Remapping Ranges - Shader Basics - Shader Learning

Shader Basics

Remapping Ranges

Task

Use remapping to build the pixel color from its uv coordinates:

  • red is 0.0 at uv.x = 0.25 and grows to 1.0 at uv.x = 0.75 (left of 0.25 the red is 0.0, right of 0.75 it is full - the screen does this for you);
  • green is 1.0 at the bottom of the screen and 0.0 at the top;
  • blue is 0.0, alpha is 1.0.
Hint 1

Red: which uv.x should give 0.0? Subtract it, and the range starts at zero. How wide is the range? Divide by the width, and it ends at one.

Hint 2

Check your formula at the edges: at uv.x = 0.25 it must give 0.0, at 0.75 - 1.0, and halfway, at 0.5, - 0.5.

Hint 3

Green goes the other way: 1.0 at the bottom, 0.0 at the top. Look for the reversed range in the table of common remaps.

Theory

Values often come in one range, but you need them in another:

  • uv goes from 0 to 1, but you want 0 in the center of the screen and -1 / 1 at the edges;
  • a wave goes from -1 to 1, but a color must be from 0 to 1;
  • you want a gradient only between x = 0.25 and x = 0.75, not across the whole screen.

Converting a value from one range to another is called remapping. It needs nothing but subtraction, division, multiplication and addition.


From any range to 0..1


To turn x from the range [a, b] into [0, 1]:

  1. subtract the start, x - a: now the range starts at 0 and goes to b - a;
  2. divide by the length, (x - a) / (b - a): now it ends at 1.
// x from 0.25 to 0.75  ->  t from 0.0 to 1.0
float t = (uv.x - 0.25) / (0.75 - 0.25);

Drag a and b and watch the line: it crosses 0 at a and 1 at b.

::plot[f="(x - a) / (b - a)", a=0.25 0..1, b=0.75 0..1, y=-0.5..1.5]

Outside [a, b] the result keeps going: below 0 left of a, above 1 right of b. The screen shows every value below 0 as black and every value above 1 as full brightness, so for colors that's often just what you want. Later you'll learn functions that cut these values off exactly where you need.


From 0..1 to any range


The other way around: multiply by the new length, then add the new start.

// t from 0.0 to 1.0  ->  from -1.0 to 1.0
float centered = t * 2.0 - 1.0;

Common remaps


From To Code
0..1 -1..1 x * 2.0 - 1.0
-1..1 0..1 x * 0.5 + 0.5
0..1 1..0 (reversed) 1.0 - x
0..1 -0.5..0.5 (centered) x - 0.5
a..b 0..1 (x - a) / (b - a)

It works on vectors too: uv * 2.0 - 1.0 remaps both x and y, so the center of the screen becomes (0.0, 0.0). You'll use this in almost every shader.