Jump to content

  • Log In with Google      Sign In   
  • Create Account

We need your help!

We need 1 more developer from Canada and 12 more from Australia to help us complete a research survey.

Support our site by taking a quick sponsored survey and win a chance at a $50 Amazon gift card. Click here to get started!

How to reproduce the 3ds Max Gradient Ramp effect?

Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
4 replies to this topic

#1 enigmagame   Members   -  Reputation: 138


Posted 07 August 2012 - 01:27 AM

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:
Posted Image

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.


#2 Nik02   Crossbones+   -  Reputation: 3436


Posted 07 August 2012 - 04:55 AM

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, 07 August 2012 - 05:09 AM.

Niko Suni

#3 enigmagame   Members   -  Reputation: 138


Posted 07 August 2012 - 09:14 AM

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?

Edited by enigmagame, 07 August 2012 - 09:42 AM.

#4 Nik02   Crossbones+   -  Reputation: 3436


Posted 07 August 2012 - 11:03 PM

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 <img src='http://public.gamedev.net//public/style_emoticons/<#EMO_DIR#>/smile.png' class='bbc_emoticon' alt=':)' />
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

#5 Nik02   Crossbones+   -  Reputation: 3436


Posted 08 August 2012 - 12:08 AM

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

Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.