Search code examples
androidopengl-esglslshaderopengl-es-3.0

Cell shading effect in OpenGL ES 2.0/3.0


I applied cell shading effect to the object, like:

enter image description here

This works well, but there are many conditional checks ("if" statements) in the fragment shader:

#version 300 es
precision lowp float;

in float v_CosViewAngle;
in float v_LightIntensity;

const lowp vec3 defaultColor = vec3(0.1, 0.7, 0.9);

void main() {
    lowp float intensity = 0.0;
    if (v_CosViewAngle > 0.33) {
        intensity = 0.33;
        if (v_LightIntensity > 0.76) {
            intensity = 1.0;
        } else if (v_LightIntensity > 0.51) {
            intensity = 0.84;
        } else if (v_LightIntensity > 0.26) {
            intensity = 0.67;
        } else if (v_LightIntensity > 0.1) {
            intensity = 0.50;
        }
    }
    outColor = vec4(defaultColor * intensity, 1.0);
}

I guess so many checks in the fragment shader can ultimately affect performance. In addition, shader size is increasing. Especially if there will be even more cell shading levels.

Is there any other way to get this effect? Maybe some glsl-function can be used here?

Thanks in advance!


Solution

  • Store your color bands in a Nx1 texture, do a texture lookup using v_LightIntensity as your texture coordinate. Want a different shading level count then just change the texture.

    EDIT Store an NxM texture, doing a lookup using vLightIntensity and v_CosViewAngle as a 2D coordinate, and you can kill branches completely.