Shader: Key-Fill-Rim Light Sources

I’ve taken models from here:

Demo

Spot 1 Blub Spot 2 Space Cruiser
Spot cruiser shroom oozey
3L-even 3L-even 3L-green 3L-even

Vertex Shader

The Vertex shader is straightforward. We compute the relative vertex position and a normal for the current view to pass it to the Fragment shader. Additionally, we pass the Texture coordinates through the shader pipeline.

#version 400

layout(location = 0) in vec3 vPosition;
layout(location = 1) in vec3 vNormal;
layout(location = 2) in vec2 vTexCoord;

uniform mat4 mViewProjection;
uniform mat4 mModel;

out vec3 position;
out vec3 normal;
out vec2 texCoord;

void main() {
    normal = vec3(mModel * vec4(vNormal, 0.0));
    position = vec3(mModel * vec4(vPosition, 1.0));
    texCoord = vTexCoord;
    gl_Position = (mViewProjection * mModel) * vec4(vPosition, 1.0);
}

Fragment Shader

The complete illumination equation:

\[I=I_{a}K_{d}+\sum_{i=1}^{L}\Bigl(I_{d_{i}}K_{d}(\vec{L}_{i} \cdot\vec{N})+I_{s_{i}}K_{s}(\vec{R}_{i} \cdot\vec{V})^{\alpha_{s}}\Bigr)\]

Where:

Shader Code:

#version 400

in vec3 position;
in vec3 normal;
in vec2 texCoord;

uniform vec3 Kd;
uniform vec3 Ks;
uniform float shininess;

uniform vec3 Ia;

struct LightSource {
    bool Enabled;
    vec3 Position;
    vec3 Id;
    vec3 Is;
};
#define NUMBER_OF_LIGHTS 3
uniform LightSource lights[NUMBER_OF_LIGHTS];

uniform vec3 cameraPosition;

uniform bool useTexture;
uniform sampler2D texSampler;

layout(location = 0) out vec4 fragColor;

vec3 getLightColor(LightSource light, vec3 diffuseColor) {
    vec3 n = normalize(normal);
    vec3 l = normalize(light.Position - position);
    vec3 v = normalize(cameraPosition - position);
    vec3 r = reflect(-l, n);

    float diff = max(dot(n, l), 0.0);
    vec3 diffuse = diff * light.Id;

    float spec = pow(max(dot(v, r), 0.0), shininess);
    vec3 specular = Ks * spec * light.Is;

    return diffuse * diffuseColor + specular;
}

vec3 getPixelColor(vec3 diffuseColor) {
    vec3 color = Ia * diffuseColor;
    for(int i = 0; i < NUMBER_OF_LIGHTS; i++)
        if(lights[i].Enabled)
            color += getLightColor(lights[i], diffuseColor);
    return color;
}

void main() {
    if(useTexture) {
        vec4 texColor = texture(texSampler, texCoord);
        fragColor = vec4(getPixelColor(texColor.rgb), 1.0);
    } else {
        fragColor = vec4(getPixelColor(Kd), 1.0);
    }
}

Real Life Demo

Hemispheric Demo

×