Though I have been using the ColorRamp node for quite a while, I often trial and error moving the handles in the ColorRamp node around to get my desired effect. I realized that I didn't really have any intuition about how it worked, I just 'did' things until it worked the way I wanted it to. I figured its best I try to think about what it 'logically' does behind the scenes, but I can't quite understand

For instance:

enter image description here

Here this is equivalent to plugging the Noise Node directly into the Material Output/Viewer. I understand the Noise Texture is a psuedorandom texture that is PURELY greyscale, that is colors can be black, white or anything in between


enter image description here

I assume it is different here. From what I believe, this setting of the ColorRamp handles basically mean: "Since the lefthandside of the ColorRamp 'strip of colors' is wholly black, this means that any colors in the Noise texture that is darker than grey (since I assume grey is in the middle of black and white, and the black color handle here is right in the middle) are to be treated as completely black"

For this one:

enter image description here

I assume its the same as before but flipped. Anything LIGHTER than grey from the noise texture is outputted as completely white, though I am confused, since they look more grey than white to me

However, this one confuses me:

enter image description here

Anything darker than grey is to be treated as pure black, anything lighter than white is to be treated as pure white? What about the small gap between the black and white handles? What do they logically mean?

Finally, using it with a MixShader:

enter image description here

How does this work at all? From my limited intuition, this basically means where there is black on the Noise Texture, shade that area with Red, where there is white shade with Blue, but what about once again the tiny gap down the middle? What's it do here exactly?

All that being said, what exactly am I getting wrong with my intuitions of the various ColorRamp settings, what am I not understanding here?

  • $\begingroup$ I would recommend at least 2 grid cells of distance between your nodes - less than that and you may have problems connecting the nodes together. In your first 3 screenshots it's hard to tell if you connect Factor or Color output to the color ramp. $\endgroup$ Jul 10, 2021 at 10:51
  • $\begingroup$ @MarkusvonBroady My bad, apologies. All the screenshots have fac connected, not color $\endgroup$
    – Hash
    Jul 10, 2021 at 12:12
  • $\begingroup$ Your intuitions about the color ramp are correct. Your confusion is coming from color management (post-processing on the color, conversion from linear color in nodes to sRGB color for display) and samples (the screen color is the average of every sample, and if there are multiple samples per pixel, pure bw input can turn into grey output.) Do your testing with display device "None" and 1 sample and it will agree with your intuitions. $\endgroup$
    – Nathan
    Jul 10, 2021 at 16:35
  • $\begingroup$ Also reading the comments, your confusion comes from how the node tree is evaluated on each pixel of the object on the screen, and not once for the whole mesh, which in its own right is a complex question $\endgroup$
    – Gorgious
    Jul 10, 2021 at 16:40
  • $\begingroup$ @Nathan Display Device None? So if im assuming right, it renders as the colors as the linear colors you talked about? $\endgroup$
    – Hash
    Jul 15, 2021 at 9:26

4 Answers 4

  • One thing of the greyish appearance is partly because of Color Management (by default Filmic).
  • Another thing is Noise Texture itself. Using ColorRamp should results as 0 (white) - 1 (black) at some point on texture that is not happening. My explanation is - that these 0 and 1 points are somewhere in texture currently not visible on mesh surface. With simple Linear gradient texture it works fine.
  • All greys up to black handles became black ... all greys up to white handle became white, all the greys between black&white handles are blending from 0-1

enter image description here

  • Mixing colors works in the same way. Color at center is 50% Cyan and 50% Red

enter image description here

  • The same color you can get by Mic node with Fac 0.5

enter image description here


It might be best to think of this in two parts, how the ramp is created and how it is used. Let's take how it is used first:

Using a color ramp

The input to a color ramp is not a color. You can feed it the output of a color node, but internally it converts that into a single number. [If you feed it a color it computes the luminance of that color and uses it.]

In your examples, you aren't feeding a color to the color ramp, because you are feeding it the Fac output of the noise texture, by the way. Noise textures do produce color.

Think of the color ramp itself as being a strip along the X axis from 0 to 1. At any given position on the ramp, there is a color. The color ramp node takes the fac input and goes to the equivalent position on the ramp. Its output for that Fac input is simply the color that is at that position on the ramp. You can think of this as a lookup table.

The handles have nothing to do with this part of the process, nor does Blender's color management. Intuitively it is a lookup table: go to the position on the line that matches fac, and return the color that's there.

Here's a different color ramp:

constant color ramp

On this ramp, if fac is between 0 and .2, pure green will be returned; but if it is between .4 and .6, pure blue will be returned.

Here's the output of a noise texture plugged into the above color ramp:

noise texture

Creating the ramp

This is where the handles come into play. Rather than having you create a color for every possible position on the ramp, Blender interpolates between values using mathematical formula. The start and end values are set by the handles, and the interpolation method is set by the control that is set to Linear by default:

color ramp interpolation options

There are several ways to interpolate colors between handles, and I won't go into details.

What do the gaps mean?

They mean whatever the interpolation mode tells them to mean. In your example, you are using linear interpolation, so the range between black and white is evenly distributed between the two handles, gradually going from black to white. In my example above, the range is constant.

What about using it as the factor in a mix shader?

Since the color ramp node outputs a color, but the mix shader uses a number, the mix shader internally converts the 3 numbers that make up the color value into a single number in the range of 0 to 1. It then performs its mix operation as usual.


Going step by step through your node setup:

First Blender compiles your node setup to a shader and uploads it to the GPU. The compiled shader could (I don't know the actual algorithm) convert the nodes to functions in the order marked on the screenshot. Then for each lightray hit in Cycles or each pixel in Eevee, whole shader program will be run which in Python [in reality GLSL is used] would look something like this:

def shader(col1, rough1, norm1, col2, rough2, norm2, noise_mode, noise_vec, noise_scale,
    noise_detail, noise_roughness, noise_distortion, color_ramp_swatches):

    diff_bsdf1 = diffuse(col1, rough1, norm1)  # 1
    diff_bsdf2 = diffuse(col2, rough2, norm2)  # 2
    noise_fac, noise_color = noise(noise_mode, noise_vec, noise_scale, noise_detail, noise_roughness, noise_distortion)  # 3
    ramp_col = ramp(noise_fac, color_ramp_swatches)  # 4
    mix_bsdf = (ramp_col, diff_bsdf1, diff_bsdf2)  # 5
    return mix_bsdf  # 6

Then in Eevee this program is run for each pixel of the render once the render engine finds out what triangle is hit by the ray shot from that pixel of the camera, and gathers data like this triangle's normal. In cycles this program is run for each lightray, however many there are.

  1. Diffuse BSDF: since nothing is connected to inputs, the default values are used: specified red color, specified roughness and implied normal: the normal of the triangle the current point belongs to. Based on that, the function calculates the color based on the light ray hitting it (for example it will be black to a green light ray), the roughness (which simulates subpixel inconsistency of the material), the input color and the normal (a normal parallel to the lightray means a face perpendicular to the lightray, which catches more light and results in a brighter color).

  2. Diffuse BSDF: as above, but for a different color (it will be green to a green light ray)

  3. Noise Texture - use some maths to turn the inputs to 4 values: factor and RGB. The Vector passed here, since there's no link, is the default Vector - the UV coordinate of the current point.

  4. Color Ramp - take the input - in your case it's just a number, so you don't have to convert it to a number. Out of the "swatches" with a lesser value than the input value, find 1 that has the highest value. Out of the "swatches" with a higher value than the input value, find 1 that has the lowest value. If there's only 1 swatch found, return (output) that swatch'es color and alpha. If there's 2 swatches found, return an interpolation of their colors and alphas. For example, the linear interpolation is: red = s1.red * d1/(d1+d2) + s2.red * d2/(d1+d2) - where d1 is distance from s1 (swatch #1), and d2 is distance from s2 (swatch #2).

  5. Mix Shader - take the first input - in your case it's color, so convert it to a number by using the color's luminance (0.3 R + 0.59 G + 0.11 B). Now make a linear interpolation like in Color ramp, but instead of swatches, interpolate between shaders: here d1 = Fac and d2 = 1 - Fac.

  • $\begingroup$ I have 2 questions: 1) You said the color ramp takes in a number as input? But does it not take the Noise's factor as the input actually? Or is the factor of the Noise itself some number? 2) You had also said the default vector is the UV Coordinates of the current point. Does that mean the mix shader and everything is executed for every pixel of the mesh to which a ray is casted with differing values each time since the coordinates are different at different points on the mesh? $\endgroup$
    – Hash
    Jul 10, 2021 at 13:27
  • $\begingroup$ @Hash Noise Texture node, or any other node, doesn't actually output a texture. It only outputs a value (the number!) associated with currently evaluated context (in Eevee that's pixel, in Cycles a lightray hitting a given point). It's easier to explain on the Gradient Texture node vklidu used: in linear mode it simply outputs x as a result. So for x:0 y:whatever it outputs the number 0, for x:0.5 y:whatever it outputs the number 0.5 and so on. You only get the actual gradient by displaying many such numbers, converted to the color form. $\endgroup$ Jul 10, 2021 at 14:30
  • $\begingroup$ So the texture node outputs a value for every pixel/lightray that 'hits' the mesh,one at a time, at that point? $\endgroup$
    – Hash
    Jul 15, 2021 at 15:28
  • $\begingroup$ @Hash other than perhaps caching the value at a given coordinate - no idea if it actually is cached - yea, that's pretty much what happens, this is why a procedural texture is so sharp: i.imgur.com/k9njkED.png whereas for an image texture to be so sharp on an object so big (without repeating it) you would need a ridiculously big image. For example here's an image texture of 51200x512 dimensions: i.imgur.com/FsrI2yC.png - the "C" is still not sharp! $\endgroup$ Jul 15, 2021 at 17:15
  • $\begingroup$ So the reason as to why procedural textures are sharp is because Blender maps and CALCULATES the exact color to be applied as a texture at the time of rendering, while in regular textures, the values are precalculated and stretched over the mesh leading to loss of detail? $\endgroup$
    – Hash
    Jul 15, 2021 at 20:20

Someone correct me if this is wrong but you said;

"Anything darker than grey is to be treated as pure black, anything lighter than white is to be treated as pure white? What about the small gap between the black and white handles? What do they logically mean?"

As a response, I'll try and break it down the best I can but the Noise node added that cloudy looking effect to it. Obviously, it's made up of the selected colour of handle 0 and 1 along with every colour in between.

enter image description here

For example, this is a noise texture the same as yours with handle 0 set to #2A256F and 1 to #65FF3A but if we look in the middle of the two we see the colour #4EBD59 along with others such as (but not limited to) #3F8C65 and #5AE14B

enter image description here

Ignoring how scuffed this looks blender adds the colour in between as a gradient while like you said outside of the handles is the associated colour and then we can push those handles super close together. In doing this we effectively removing the gradient replacing it with just two colours:

enter image description here

We can also remove this gradient by changing how the colour ramp works. If you look above the colour ramp (still on the node just next to the RGB drop-down) there is another drop-down that often will be set to Linear. Setting this to Constant we see that everything before and after handle 0 is the selected colour until it reaches handle 1 and it will then change to that colour and continue to the end of the ramp.

(I cant put in another link but it is identical, trust me ;)

Giving us the same result!

Finally on the mix shader with red and blue controlled by the colour ramp;

You have two colours one being red this goes into the mix-shader. If the mix shaders Fac is set to a value of 0 it whill show red.

enter image description here

Now if we set the value to 1 it will turn blue.

enter image description here

By conecting the colour ramp to the mix-shaders Fac then we can control the value but when a noise goes into the colour ramp fac (along with everything else before mentioned) we can control what parts of the noise will be asinged to what value and everything in between. In other words we can do the same thing as changing the colours of the handles.

enter image description here

This again gives us the same picture as before (red and blue where altered to the blue and green from above). I didn't dile in the exct same results as before so it looks a tiny bit diffrent at some parts but it does the same thing in this context.

Orignal falvor! enter image description here


The new flavour! enter image description here

I hope that wasn't condecending but I tried to make it simple for everyone! I also hope that made sense

PS. I think that going straight from a mix-shader into the output will make it dark, to fix this I think you can just chuck in principle BSDF or something similar (not 100% sure on that).

Have a good day! :)

  • $\begingroup$ I have 2 questions: 1) In the case of the color ramp having colored handles like purple and green in your pic and having a Noise Node plugged into it, what exactly is happening? With regular greyscale colorramp, its intuitive, grey on ramp = grey in noise, white on ramp = white on noise and so on, but how does it work with purple/green color ramps? How does Blender map the black white and grey of the Noise to Purple and Green of the ColorRamp? 2) When ONLY ColorRamp is used as Fac of Red and Blue diffuse, how are the Reds and Blues mixed? Colors on ColorRamp and Diffuse arent same right? $\endgroup$
    – Hash
    Jul 10, 2021 at 12:59
  • 1
    $\begingroup$ I hope I understand what you mean, if not just re-ask! But 1) I used colours but it's the same as if it was monochrome. So in this case the blue was the black and the green the white. So like you said "grey on ramp = grey in noise..." So the noise gives us a black and white image, this then goes into the ramp and blender says that 100% black is purple and then 100% white is green it then says that grey that is 50% black and 50% white will be a mix of half purple and half green. I hope that makes sense and answers your question. I'll mak another comment for question 2 :) $\endgroup$ Jul 10, 2021 at 13:19
  • $\begingroup$ 2) If I use the colour ramp without noise and have it set to linear when I drag the white as close as I can before it overlaps the black (set 0.000001) it shows the blue similar to the Value node set to 1, the opposite happens when I set black to 0.999999 and it shows Red. If I have the black handles on 0.5 it will show perfect Red but if I set the white handle to 0.5 it shows blue. It doesn't matter where or what side the other handle it is on. The handle in the middle wins. The two colours can be mixed with the handle that's closer to the middle will show through more. And i dont think so? $\endgroup$ Jul 10, 2021 at 13:46
  • $\begingroup$ Just looked it up apparently colour ramps output "Standard image output" I'm not sure if that something similar to diffuse or not. I'm sorry I'm not 100% sure about that final thing but I hope that helped! :) $\endgroup$ Jul 10, 2021 at 13:47
  • $\begingroup$ Thank you for all the answers! Though I have a lingering doubt. Is there a specific reason in 2) that Blender assumes the color in the middle to apply to whatever object has that material? Why specifically the middle? $\endgroup$
    – Hash
    Jul 15, 2021 at 13:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.