How to reproduce the 3ds Max Gradient Ramp effect?

Started by
3 comments, last by Nik02 11 years, 8 months ago
The material definition of a mesh is composed of these three components: Self-Illumunation, Refletcion and Refraction. Each of these components has a Gradient Ramp as a map and the mapping mode is set to spherical environment.
I'm searching for a way to reproduce these effects in a shader (the shader language doesn't matter). Is it possible?
My first idea was to save the Gradient Ramp as a texture: you can see the result in the image below:
2ebu0c2.png

It seems to be a Blinn/Newell Latitude Map instead of a Spherical Map, but using the math behind the first, the result isn't correct.
Thanks.
Advertisement
In general, gradient ramps are implemented by simply interpolating between colors, given a scalar parameter. This is very easy in shaders.

Think of a color ramp as a spline, where the control points represent colors instead of positions. The spline algorithms are literally the exact same ones in either case.

The simplest possible ramp is one that contains two control points (colors) that are used in linear interpolation:


// simple example
float4 red = float4(1,0,0,1);
float4 blue= float4(0,0,1,1);
float parameter = normal.y * 0.5f + 0.5f; // map normal's y direction to 0...1 for use as interpolation parameter
float4 finalcolor = lerp(red, blue, parameter); // when normal points down, red is used more; conversely, up means more blue
// lerp is defined as v1*(1-param) + v2*param where v1 and v2 are the original values to interpolate between


You can extend this basic idea to introduce more colors in the ramp.

Niko Suni

Nik02 thanks for the hint, you're absolutely right: thinking on the texture maps has completely moved my focus on the problem.
I've just tried with two control points and the result is correct.

Just another question: I've ramps with four, five or six control points, what is the best way to interpolate these control points and achieve a correct result? Bézier curve?
Thanks.
Any spline will do, but Bézier will provide smoother transitions between colors than linear. The "best" way depends on what you want to do with the ramp; in some cases, linear is the correct and elegant way to go, but higher-order splines tend to get more "organic" results.

You can handle any number of control points by taking n nearest control points of the parameter (where n is the degree of the curve + 1), and doing the interpolation between those found points. This effectively means that the minimum amount of control points is also defined as degree + 1.

Here is a simple example of piecewise linear handling of arbitrary number of points:

float4 colors[] = {float4(1,0,0,1), float4(0,1,0,1), float4(0,0,1,1), float4(0,0,0,1), float4(1,1,1,1)}; // red, green, blue, black, white
int numColors = 5; // must match the actual number of control points :)
float parameter; // initialized earlier to 0...1

float index = parameter * (float)numColors;
int nearestLeftIndex = (int)index; // effectively take the whole number part of the scaled parameter to find the first control point
int nearestRightIndex = nearestLeftIndex + 1; // the next control point is adjacent in the array
// If nearest indices are the same or greater than numColors or less than 0, we should take the nearest point as is, because we're past the color array.
// To extend beyond piecewise linear, find more nearest points like this and perform the next steps with those.

float4 left = colors[nearestLeftIndex];
float4 right = colors[nearestRightIndex];
float fraction = index - (float)nearestLeftIndex; // find the decimal portion of the scaled parameter in between the nearest points
float4 finalColor = lerp (left, right, fraction); // then interpolate between the nearest points

Niko Suni

Also, it is worth noting that you could pre-calculate and store the ramp as a 1-d texture, and sample it in the shader to effectively emulate any 1-dimensional function (such as a spline with parameter u).

This is useful if you want to decrease register or ALU pressure, at the cost of using a little bit of memory bandwidth. Also, textures tend to be more easy to author than arrays of shader constants.

Niko Suni

This topic is closed to new replies.

Advertisement