Saturday 31 August 2013

Remap

This operation can also be referred to as a fit operation because it takes the low and high value of x (referred as a1and b1) and fits them in a linear fashion into a new low and high value (referred to as a2 and b2). If you use the call remap(x,0,1,1,0), the value of x will be inverted. Setting the function to remap(x,0,1,0.25,0.75) will remap the output to 0.25–0.75

float remap(float x,float a1,float b1,float a2,float b2) {
                   return (x*(b2-a2) - a1*b2 + b1*a2) / (b1-a1);


s with a remap() of (0,1,1,0) inverts the image



















remap() of (0,1,0.25,0.75) limits the image to 0.25 - 0.75.

Expand

The expand() function does the exact opposite of compress(): It remaps the values by pushing the values to a higher position in a value graph.

float expand(float x, float lo, float hi) {
                     float retval = 0;
                     if (lo == hi)
                         retval = x < lo ? 0 : 1;
                    else
                         retval = (x-lo) / (hi-lo);
                    

                    return retval;
}



s with no compression



















Applying an expand() function with the values expand(s,0.5,1) will leave 0 and 1 untouched, remapping 0.5 to 0. This means that the value of 0 is shifted up to the position of 0.5, therefore remapping 0.5 to 0.

s with (0.5,1) expanded. what used to be 0.5 is now 0



















Using the values expand(s,0,2) will leave 0 untouched while remapping 1 to 0.5, because the value of 1 will be shifted up to the position of 2.

s with (0,2) expanded. what used to be 1 is now 0.5






Compress

The compress() functions allow you to manipulate the dynamic range of the 0 to 1 values.

The compress() function allows you to tighten the dynamic range of the texture. It adheres to the following syntax:

compress(value,lo,hi) 

lo represents the lowest value that will be remapped to and hi the highest.

s with no compression


















Setting the compress() values to compress(s,0,2) will remap a value of 1 to 2 and 0.5 to 1 while leaving 0 unchanged.

s with (0,2) compression. what used to be 1 is now 2


















Changing the values to compress(s,0.5,1) will remap the value of 0 to 0.5 and 0.5 to 0.75 while leaving 1 untouched.

s with (0.5,1) compression. what used to be 0 is now 0.5


Gain

The gain() function (also known as a contrast function) has very different behavior. It leaves the values at 0, 0.5, and 1 unchanged and manipulates the values in the first segment (0 to 0.5) and the second segment (0.5, 1). Internally, it is calculated as two bias() operations applied to the first and second segments. The visual result of the gain()function is the increase or decrease of the value’s contrast.

Here is the function followed by Figure 5.7 and Figure 5.8, which are graphs of gain() at 0.25 and 0.85.

float gain(float val,g){
              return 0.5 * ((val < 0.5) ? bias(2 * val,1 - g) :
              (2 - bias(2 - 2 * val,1 - g)));
}



Bias

The bias() function behaves like a weight modifier: it allows you to control which part of the 0 to 1 range has more weight. Here is the bias() function, followed by Figures 5.5 and 5.6, which illustrate the output of applying the values 0.25 and 0.85 to the bias() function.


Parametrizing a value

Sometimes you will need the user to enter a value range 20 - 40 without telling user. You set this formula:

#define parametrizeVal(x,lo,hi) lo+x*(hi-lo)
float specVal = parametrizeVal(specParam, 20 ,40);

This way the user will have the input between 0 -1 and remap it to 20 -40

Divide by zero

Sometimes you will run into "divide by zero" error. To avoid this, you can:

float ss = s/txscale;
float tt = t/txscale;

//return a value either 0.00001 or greater)
float scaler = max(1/txscale, 0.00001);

float ss = s * scaler;
float tt = s * scaler;

As you develop your shaders, you will sometimes need to use a certain value within your shaders, but that value would make no sense at all as a shader parameter. One such example is when you are scaling a texture. Remember that texture spaces (s, t) are usually within the 0 to 1 range. To scale the texture, you could take a shader input txscaleand divide by the s or t value.

The problem with this approach is that you will run into a “divide by zero” error when the texture coordinate is 0 (you can’t divide a value by 0). The following code will more than likely generate rendering errors:
float ss = s/txscale;
float tt = t/txscale;


To get around this problem, we will invert our approach and add the logic to avoid division by zero. To do this, we will multiply the sand tvalues by 1/txscale. What this does is scale down the texture coordinates, resulting in the texture scaling up.

To prevent division by zero, we will use the max()shadeop to restrict the value to drop below a very small number. Here is the modified code.
float scaler = max(1/txscale,0.000001);
float ss = s * scaler;
float tt = t * scaler;

Signing a value

y = 2(x) -1

Turn 0 - 1 into -1 - 1.

Sometimes, you have a 0 to 1 range that you need to turn into –1 to 1. This operation is known as signing. To sign a 0 to 1 value, you need to multiply the value by 2 and then subtract 1 from it, such as y = (2 x) –1;. Signing can be very useful when dealing with noise values. noise()returns values that average around 0.5. Sometimes, you need the noise values to average between –0.5 and 0.5. In such cases, all you need to do is sign the noise value.

Inverting a value

Inverting a value
If x is in the range of 0 - 1:
y = 1 - x

If x is in the range of -1 - 1:
y = -1(x)