Programming of Spherical Harmonics Lighting (1)
This time I have decoded the SH lighting parameters of Grace Cathedral by GLSL fragment shader, mapped the upper and lower hemisphere to the disk.
今回は Grace Cathedral の SH のパラメータをデコードしたものについて, 上半球と下半球をそれぞれ円盤に対してマッピングしてみました.
Some part of upper hemisphere seems quite bright.
上半球のライティングが部分的に結構まぶしい感じです.
Decoding the Grace Cathedral SH lighting parameters ( upper hemisphere ).

Decoding the Grace Cathedral SH lighting parameters ( lower hemisphere ).

I have pasted part of my source code below.
下に今回, 僕が書いたソースコードの一部を貼り付けました.
//////////////////////////////////////////////////
// GLSL fragment shader to decode SH lighting
// ( l_max = 2, 9 coefficients )
// hanecci
//
//////////////////////////////////////////////////
varying vec3 v_normal;
const int SH_NUM = 9;
uniform vec3 sh_light_array[ SH_NUM ];
float
computeSH( const vec4 normal4, const int colorIndex )
{
const float SH_C1 = 0.429043;
const float SH_C2 = 0.511664;
const float SH_C3 = 0.743125;
const float SH_C4 = 0.886227;
const float SH_C5 = 0.247708;
const int SH_L_0_0 = 0;
const int SH_L_1_M1 = 1;
const int SH_L_1_0 = 2;
const int SH_L_1_1 = 3;
const int SH_L_2_M2 = 4;
const int SH_L_2_M1 = 5;
const int SH_L_2_0 = 6;
const int SH_L_2_1 = 7;
const int SH_L_2_2 = 8;
mat4 m44 = mat4(
SH_C1 * sh_light_array[ SH_L_2_2 ][ colorIndex ],
SH_C1 * sh_light_array[ SH_L_2_M2 ][ colorIndex ],
SH_C1 * sh_light_array[ SH_L_2_1 ][ colorIndex ],
SH_C2 * sh_light_array[ SH_L_1_1 ][ colorIndex ],
//
SH_C1 * sh_light_array[ SH_L_2_M2 ][ colorIndex ],
- SH_C1 * sh_light_array[ SH_L_2_2 ][ colorIndex ],
SH_C1 * sh_light_array[ SH_L_2_M1 ][ colorIndex ],
SH_C2 * sh_light_array[ SH_L_1_M1 ][ colorIndex ],
//
SH_C1 * sh_light_array[ SH_L_2_1 ][ colorIndex ],
SH_C1 * sh_light_array[ SH_L_2_M1 ][ colorIndex ],
SH_C3 * sh_light_array[ SH_L_2_0 ][ colorIndex ],
SH_C2 * sh_light_array[ SH_L_1_0 ][ colorIndex ],
//
SH_C2 * sh_light_array[ SH_L_1_1 ][ colorIndex ],
SH_C2 * sh_light_array[ SH_L_1_M1 ][ colorIndex ],
SH_C2 * sh_light_array[ SH_L_1_0 ][ colorIndex ],
SH_C4 * sh_light_array[ SH_L_0_0 ][ colorIndex ] -
SH_C5 * sh_light_array[ SH_L_2_0 ][ colorIndex ]
);
vec4 tmpNormal4 = m44 * normal4;
return dot( normal4, tmpNormal4 );
}
void main (void)
{
const int redColorIndex = 0;
const int greenColorIndex = 1;
const int blueColorIndex = 2;
vec3 normal = normalize( v_normal );
vec4 normal4 = vec4( normal, 1.0 );
float red = computeSH( normal4, redColorIndex );
float green = computeSH( normal4, greenColorIndex );
float blue = computeSH( normal4, blueColorIndex );
gl_FragColor = vec4( red, green, blue, 1.0 );
}//////////////////////////////////////////////////
//
// Setting SH parameters of Grace Cathedral as GLSL uniform
// ( l_max = 2, 9 coefficients )
// hanecci
//
//////////////////////////////////////////////////
const int SH_NUM = 9;
const int RGB_NUM = 3;
const int SH_ARRAY_NUM = SH_NUM * RGB_NUM;
float g_sh_light_array[ SH_ARRAY_NUM ];
GLint g_sh_light_array_location = -1;
void initSHLightArray()
{
const int SH_L_0_0 = 0;
const int SH_L_1_M1 = 1;
const int SH_L_1_0 = 2;
const int SH_L_1_1 = 3;
const int SH_L_2_M2 = 4;
const int SH_L_2_M1 = 5;
const int SH_L_2_0 = 6;
const int SH_L_2_1 = 7;
const int SH_L_2_2 = 8;
// SH parameters of Grace cathedral
// L 0 0 ( rgb )
g_sh_light_array[ 3 * SH_L_0_0 + 0 ] = 0.79f;
g_sh_light_array[ 3 * SH_L_0_0 + 1 ] = 0.44f;
g_sh_light_array[ 3 * SH_L_0_0 + 2 ] = 0.54f;
// L 1 -1
g_sh_light_array[ 3 * SH_L_1_M1 + 0 ] = 0.39f;
g_sh_light_array[ 3 * SH_L_1_M1 + 1 ] = 0.35f;
g_sh_light_array[ 3 * SH_L_1_M1 + 2 ] = 0.60f;
// L 1 0
g_sh_light_array[ 3 * SH_L_1_0 + 0 ] = -0.34f;
g_sh_light_array[ 3 * SH_L_1_0 + 1 ] = -0.18f;
g_sh_light_array[ 3 * SH_L_1_0 + 2 ] = -0.27f;
// L 1 1
g_sh_light_array[ 3 * SH_L_1_1 + 0 ] = -0.29f;
g_sh_light_array[ 3 * SH_L_1_1 + 1 ] = -0.06f;
g_sh_light_array[ 3 * SH_L_1_1 + 2 ] = 0.01f;
// L 2 -2
g_sh_light_array[ 3 * SH_L_2_M2 + 0 ] = -0.11f;
g_sh_light_array[ 3 * SH_L_2_M2 + 1 ] = -0.05f;
g_sh_light_array[ 3 * SH_L_2_M2 + 2 ] = 0.12f;
// L 2 -1
g_sh_light_array[ 3 * SH_L_2_M1 + 0 ] = -0.26f;
g_sh_light_array[ 3 * SH_L_2_M1 + 1 ] = -0.22f;
g_sh_light_array[ 3 * SH_L_2_M1 + 2 ] = -0.47f;
// L 2 0
g_sh_light_array[ 3 * SH_L_2_0 + 0 ] = -0.16f;
g_sh_light_array[ 3 * SH_L_2_0 + 1 ] = -0.09f;
g_sh_light_array[ 3 * SH_L_2_0 + 2 ] = -0.15f;
// L 2 1
g_sh_light_array[ 3 * SH_L_2_1 + 0 ] = 0.56f;
g_sh_light_array[ 3 * SH_L_2_1 + 1 ] = 0.21f;
g_sh_light_array[ 3 * SH_L_2_1 + 2 ] = 0.14f;
// L 2 2
g_sh_light_array[ 3 * SH_L_2_2 + 0 ] = 0.21f;
g_sh_light_array[ 3 * SH_L_2_2 + 1 ] = -0.05f;
g_sh_light_array[ 3 * SH_L_2_2 + 2 ] = -0.30f;
g_sh_light_array_location =
glGetUniformLocation( g_ProgramId,
"sh_light_array" );
}
void setSHUniform()
{
glUniform3fv( g_sh_light_array_location,
SH_NUM,
g_sh_light_array );
}