MaT
MaT

Reputation: 1606

Shader - Color blending

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).

Any idea how to do that ?

Upvotes: 1

Views: 3770

Answers (2)

Figment3D
Figment3D

Reputation: 11

To avoid branching in a shader, one technique is to use lerp (linear interpolation). That is, use the would-be conditional variable as the lerp factor, so if it's 0 it's one color and if it's 1 it's the other color.

Be sure to reverse the logic since the second argument is what it blends to if cond=1. This also allows you to blend half way.

Example:

Instead of

Color result = (cond)? A:B;

use:

Color result=lerp(cond,B,A);

Upvotes: 1

Reto Koradi
Reto Koradi

Reputation: 54652

With GLSL, the simplest approach is probably to use a branch. If colA and colB are the two vectors (of type vec4) holding your colors A and B:

if (any(lessThan(colB.xyz, vec3(1.0)))) {
    outColor = colB;
} else {
    outColor = colA;
}

Or, if you really want to avoid a branch, you could rely more on built-in functions. For example, using the observation that if all components are in the range [0.0, 1.0], the dot product of the vector with itself is 3.0 for the vector (1.0, 1.0, 1.0), and smaller for all other vectors:

outColor = mix(colB, colA, step(3.0, dot(colB.xyz, colB.xyz)))

You will have to benchmark to find out which of these is faster.

There may be some concern about floating point precision in the comparisons for both variations above. I believe it should be fine, since 1.0 can be represented as a float exactly. But if you do run into problems, you may want to allow for some imprecision by changing the constants that colB is compared against to slightly smaller values.

Upvotes: 2

Related Questions