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\$ – Icy Defiance Apr 27 '15 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 '15 at 21:07

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.

|improve this answer|||||
  • \$\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 '15 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 '15 at 12:16

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.