I would like to know how to blend colors in a specific way.

Let's imagine that I have a color (A) and an other color (B).

I would like to blend them in such a way that if I choose white for the (B) then the output color is (A) but if have any other color for (B) it outputs a blending of (A) and (B).

  • I've tried the addition, but it doesn't give the expected result.
  • I've tried the multiplicative blending it's quite good for the (B) white value but it fail for a blue (B) and red (A) colors.

Any idea how to do that ? Thanks a lot.

  • \$\begingroup\$ You'll have to use an if statement, but if possible it's usually better to avoid branching logic in shaders. Could you expand more on the problem you're trying to solve with this method? There might be a better way to accomplish the same thing. \$\endgroup\$ Apr 27, 2015 at 20:49
  • \$\begingroup\$ Thank you for your answer, yes I would like to avoid branching. The problem is that I want to allow the user the set two color and blend them the way I explained (I hope it's well enough explained tell me if it's not good enough) but I don't find a good way to do that even with lerp... The color (A) should appear only when going to white for color (B) \$\endgroup\$
    – MaT
    Apr 27, 2015 at 21:07

1 Answer 1


You can get this behaviour without a branch using the step function:

float blendFactor = step(3.0f, dot(B.rgb, B.rgb));
return lerp(B, A, blendFactor);

When B = (1, 1, 1), dot(B, B) = 3.0f, so step returns 1, blendFactor = 1, and the lerp gives a result of A.

When B is anything less, dot(B, B) < 3.0f, so step returns 0, blendFactor drops to 0, and the lerp gives a result of B.

(Here I'm assuming B's components are in the range 0...1)


Edit: if you'd prefer a smooth blend, you can calculate blendFactor like this instead:

float blendFactor = saturate(1.0f - sharpness * (dot(B.rgb, B.rgb) - 3.0f));

Here "sharpness" is a parameter you can use to control how narrow the blend range is. Very large values will make the output jump from A to B like step(), while smaller values will let it blend out a little when B is close to white.

  • \$\begingroup\$ This is very close to what I am trying to achieve but it's like having an if statement as it "jumps" to the A color when having B = (1, 1, 1). I would like to know if it's possible to avoid this "jump" and blend smoothly. \$\endgroup\$
    – MaT
    Apr 28, 2015 at 11:55
  • \$\begingroup\$ @MaT, I've edited the answer to include a smooth blending version. Note that your question only describes outputting A & B, not intermediate colours, so you may want to edit it to describe the blending behaviour you want more precisely. \$\endgroup\$
    – DMGregory
    Apr 28, 2015 at 12:16

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .