Advertisement Jump to content
Sign in to follow this  

How to reproduce the 3ds Max Gradient Ramp effect?

This topic is 2357 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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:

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.

Share this post

Link to post
Share on other sites
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. Edited by Nik02

Share this post

Link to post
Share on other sites
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. Edited by enigmagame

Share this post

Link to post
Share on other sites
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

Share this post

Link to post
Share on other sites
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.

Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Advertisement

Important Information

By using, you agree to our community Guidelines, Terms of Use, and Privacy Policy. is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!