I’ve taken models from here:
Spot 1 | Blub | Spot 2 | Space Cruiser |
---|---|---|---|
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);
}
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);
}
}