This little demo experiments with Spherical Harmonics. I won’t explain what Spherical Harmonics lighting is about, though, because I’m not an expert on the field and there are many people all over the network that have already done a better job explaining what spherical harmonics are than what I could do here.

For this demo I used the values for some environments taken from the book OpenGL Shading Language 3rd Edition (buy), only to try out some effects I could achieve with a model.

The shaders are pretty simple:

Vertex:

#version 330

// Attributes per position: position and normal
in vec4 position;
in vec3 normal;

uniform mat4   MVP;
uniform mat4   MV;
uniform mat3   normal_matrix;
uniform float  scale_factor;

struct SHFactors
{
    vec3 L00;
    vec3 L1m1;
    vec3 L10;
    vec3 L11;
    vec3 L2m2;
    vec3 L2m1;
    vec3 L20;
    vec3 L21;
    vec3 L22;
};

uniform SH
{
    SHFactors sh_array[10];
} sh;

uniform int sh_idx;

const float C1 = 0.429043;
const float C2 = 0.511664;
const float C3 = 0.743125;
const float C4 = 0.886227;
const float C5 = 0.247708;

smooth out vec3 v_diffuse_color;

void main(void)
{
    // Get surface normal in eye coordinates
    vec3 tnorm = normal_matrix * normal;

    v_diffuse_color = C1 * sh.sh_array[sh_idx].L22 * (tnorm.x * tnorm.x - tnorm.y * tnorm.y) +
                      C3 * sh.sh_array[sh_idx].L20 *  tnorm.z * tnorm.z +
                      C4 * sh.sh_array[sh_idx].L00 -
                      C5 * sh.sh_array[sh_idx].L20 +
                      2.f * C1 * sh.sh_array[sh_idx].L2m2 * tnorm.x * tnorm.y +
                      2.f * C1 * sh.sh_array[sh_idx].L21  * tnorm.x * tnorm.z +
                      2.f * C1 * sh.sh_array[sh_idx].L2m1 * tnorm.y * tnorm.z +
                      2.f * C2 * sh.sh_array[sh_idx].L11  * tnorm.x +
                      2.f * C2 * sh.sh_array[sh_idx].L1m1 * tnorm.y +
                      2.f * C2 * sh.sh_array[sh_idx].L10  * tnorm.z;

    v_diffuse_color *= scale_factor;

    // Don't forget to transform the geometry!
    gl_Position = MVP * position;
}

Fragment:

#version 330

out vec4 fragmentColor;

smooth in vec3 v_diffuse_color;

void main(void)
{
    fragmentColor = vec4 (v_diffuse_color, 1.f);
}

And here are some screenshots from the results:

About these ads