5. Spherical Harmonics 5
return float4( irradiance, 1.f );
}
????????Irradiance Map????????.
?????Irradiance Map????????????????.
float3 ImageBasedLight( float3 normal )
{
return IrradianceMap.Sample( LinearSampler, normal ).rgb;
}
// ...
float4 lightColor = float4( ImageBasedLight( normal ), 1.f ) * MoveLinearSpace( Diffuse );
??????????????????Irradiance Map???. ??????Irradiance Map????24KB( 32 *
32 * 6 * 4Byte )????????????. ?????????????????108Byte( 3 * 9 * 4Byte )????
??????????????????. ???????????????????????.
?????????(Associated Legendre Polynomials)
?????????????????????????????????????. ????????????
????????????????.
??????????????? ?
?????????? ?
? ?
?????????????????.
??? ?
?-1 ~ 1????????????????????????.
? ????????????????????????????????.
????? ?
? ?
??????????(Bands)???????? ?
?Band Index???0??????????
??????. ??? ?
?0 ~ ???????????????.
??????? Irradiance Map
P l m
P ?
(x)
l
m
x
l m l
m l
P ?
0
0
P ?
P ?
1
0
1
1
P ?
P ?
P ?
2
0
2
1
2
2
6. Spherical Harmonics 6
???????????????????????????????????????????. ????3??
????????????.
?????????????????????????????????????????. ??? ?
?????
?????????????????????.
????????????????.
?
???1?????????????????3?????????????????????????.
???3??????????????????????????.
double P(int l, int m, double x)
{
// evaluate an Associated Legendre Polynomial P(l,m,x) at x
double pmm = 1.0;
if (m > 0)
{
double somx2 = sqrt((1.0 - x) * (1.0 + x))
double fact = 1.0;
for (int i = 1; i <= m; i++)
{
pmm *= (-fact) * somx2;
fact += 2.0;
}
}
if (l == m) return pmm;
double pmmp1 = x * (2.0 * m + 1.0) * pmm;
if (l == m + 1) return pmmp1;
double pll = 0.0;
for (int ll = m + 2; ll <= l; ++ll)
{
pll = ((2.0 * ll - 1.0) * x * pmmp1 - (ll + m - 1.0) * pmm) / (ll - m);
pmm = pmmp1;
pmmp1 = pll;
}
return pll;
}
??????
Spherical Harmonics???????????????????????????.
???????????????????????????????????????????????????
?. ??????????????????????????.
????????????????.
1 P ? =
m
m
(?1) (2m ?
m
1)!!(1 ? x )
2 m/2
!!
n!! = { ?
n ? (n ? 2)...5 ? 3 ? 1, n > 0 odd
n ? (n ? 2)...6 ? 4 ? 2, n > 0 even
2 P ? =
m+1
m
x(2m + 1)P ?
m
m
3 (l ? m)P ?
=
l
m
x(2l ? 1)P ?
?
l?1
m
(l + m ? 1)P ?
l?2
m
P ?
(x)
0
0
Y ?
(¦È,?) :=
l
m
AP ?
(cos¦È)e
l
m im?
7. Spherical Harmonics 7
??? ?
?????????????????? ?
??????????????.
?????????? ?
? ?
?????????????????????. ?
????0???????????
?? ?
? ?
? ?
????????.
?????????????????.
??????????????????????????????????????????????????
????.
??????????????????.
double K(int l, int m)
{
// renormalisation constant for SH function
double temp = ((2.0 * l + 1.0) * factorial(l - m)) / (4.0 * PI * factorial(l + m));
return sqrt(temp);
}
double SH(int l, int m, double theta, double phi)
{
// return a point sample of a Spherical Harmonic basis function
// l is the band, range [0..N]
// m in the range [-l..l]
// theta in the range [0..Pi]
y ?
(¦È,¦Õ) =
l
m
{ ?
?
K ?
cos(m¦Õ)P ?
(cos¦È), m > 0
2 l
m
l
m
?
K ?
sin(?m¦Õ)P ?
(cos¦È), m < 0
2 l
m
l
m
K ?
P ?
(cos¦È), m = 0
l
0
l
0
P K
K ? =
l
m
?
?
4¦Ð
(2l + 1)
(l + ¨Om¨O)!
(l ? ¨Om¨O)!
l m l
m ?l l
y ?
0
0
y y ? y ?
1
?1
1
0
1
1
y ? y ? y ? y ? y ?
2
?2
2
?1
2
0
2
1
2
2
??: https://users.soe.ucsc.edu/~pang/160/s13/projects/bgabin/Final/report/Spherical Harmonic Lighting Comparison.htm
8. Spherical Harmonics 8
// phi in the range [0..2*Pi]
const double sqrt2 = sqrt(2.0);
if (m == 0) return K(l, 0) * P(l, m, cos(theta));
else if (m > 0) return sqrt2 * K(l, m) * cos(m * phi) * P(l, m, cos(theta));
else return sqrt2 * K(l, -m) * sin(-m * phi) * P(l, -m, cos(theta));
}
???????????????????????????????????. ???????????????
????????????????????????????????. ?????????????????
??????????????.
???????????????????????????????. ??? ?
????????????.
??(Projection)
???????????????????. ??????????????????Irradiance Map?????
????????????????? ???????(Basis Function)???(Projection)???????????
??.
????????????????????????????????. ?????????????????
???????????????????.
?????????????????????????. ????????????????????????
?????????????????.
????????????????????.
(x,y,z) = (sin¦Ècos?,sin¦Èsin?,cos¦È)
l = 2
y ?
( ) =
0
0
n 0.282095
y ?
( ) =
1
?1
n 0.488603y
y ?
( ) =
1
0
n 0.488603z
y ?
( ) =
1
1
n 0.488603x
y ?
( ) =
2
?2
n 1.092548xy
y ?
( ) =
2
?1
n 1.092548yz
y ?
( ) =
2
0
n 0.315392(3z ?
2
1)
y ?
( ) =
2
1
n 1.092548xz
y ?
( ) =
2
2
n 0.546274(x ?
2
y )
2
f(x) = c ?
b ?
(x) +
1 1 c ?
b ?
(x) +
2 2 c ?
b ?
(x) +
3 3 c ?
b ?
(x) +
4 4 ...
c ? =
i f(x)b ?
(x)
¡Ò i
9. Spherical Harmonics 9
??????????????????????????????.
???????????????????Irradiance Map??????????.
??????????Irradiance Map
??????????Irradiance Map ??????????.
??: Spherical Harmonic Lighting: The Gritty Details
??: Spherical Harmonic Lighting: The Gritty Details
??: Spherical Harmonic Lighting: The Gritty Details
? ? L ?
(x,¦Ø ?
)cos(¦È)sin(¦È)d¦Èd?
¦Ð
1
¡Ò
?=0
2¦Ð
¡Ò
¦È=0
?
2
¦Ð
i i
10. Spherical Harmonics 10
?????????2???????.
1. ?¡ú ??????????????????????????.
2. ?¡ú ???????????. ??????Radiance???????????????0??
??????Radiance??????.
???????????????????????????.
??? ?
????(Zenith Angle)?????????? ?
???0????. ???????? ? ?
??
?Irradiance?????????. Irradiance?????????? ?
????Irradiance?????????
??.
?? ?
? ?
? ?
??????????????.
??? ?
?????????? ?
?????????????????????????????. ?
???????????4??4.A??????????.
?????????? ?
???????????.
?
????????????????????.
???????????????????????????????????????.
? ? L ?
(x,¦Ø ?
)sin(¦È)d¦Èd?
¡Ò?=0
2¦Ð
¡Ò¦È=0
¦Ð
i i
max(cos(¦È),0)
L ? =
lm ? ? L(¦È,?)y ?
(¦È,?)sin(¦È)d¦Èd?
¡Ò
?=0
2¦Ð
¡Ò
¦È=0
¦Ð
l
m
A ? =
l ? max(cos(¦È),0)y ?
(¦È,0)d¦È
¡Ò
¦È=0
¦Ð
l
0
cos(¦È) m Llm A ?
l
E ?
lm
E(¦È,?) = ? E ?
y ?
(¦È,?)
l,m
¡Æ lm l
m
E ?
lm L ?
lm A ?
l
E ?
=
lm ?
A ?
L ?
?
2l + 1
4¦Ð
l lm
?
?
2l+1
4¦Ð
cos(¦È)
?
A ?
l
^
?
=
A ?
l
^ ?
A ?
?
2l + 1
4¦Ð
l
?
A ?
l
^
? =
A ?
0
^ 3.1415
? =
A ?
1
^ 2.0943
? =
A ?
2
^ 0.7853
? =
A ?
3
^ 0
?
=
A ?
4
^ ?0.1309
? =
A ?
5
^ 0
?
=
A ?
6
^ 0.0490
11. Spherical Harmonics 11
??? ?
??????????????????????27????(RGB ??3?* SH ??9?)???
Irradiance Map?????????. ???????????????? ?
???????????????
??.
void ShFunctionL2( float3 v, out float Y[9] )
{
// L0
Y[0] = 0.282095f; // Y_00
// L1
Y[1] = 0.488603f * v.y; // Y_1-1
Y[2] = 0.488603f * v.z; // Y_10
Y[3] = 0.488603f * v.x; // Y_11
// L2
Y[4] = 1.092548f * v.x * v.y; // Y_2-2
Y[5] = 1.092548f * v.y * v.z; // Y_2-1
Y[6] = 0.315392f * ( 3.f * v.z * v.z - 1.f ) ; // Y_20
Y[7] = 1.092548f * v.x * v.z; // Y_21
Y[8] = 0.546274f * ( v.x * v.x - v.y * v.y ); // Y_22
}
??? ?
????????????????????. ?????????????????????.
#include "Common/Constants.fxh"
#include "SH/SphericalHarmonics.fxh"
??: On the relationship between radiance and irradiance: determining the illumination from images of a convex Lambertian object
l ¡Ü 2
y ?
( )
l
m
n
L ?
lm
L ?
=
lm ? ? ? L(¦È,?)y ?
(¦È,?)sin(¦È)d¦Èd?
¦Ð
1
¡Ò
?=0
2¦Ð
¡Ò
¦È=0
¦Ð
l
m
= ? ? ? ? ? L(¦È,?)y ?
(¦È,?)sin(¦È)
¦Ð
1
n1
2¦Ð
n2
¦Ð
?=0
¡Æ
n1
¦È=0
¡Æ
n2
l
m
= ? ? ?
L(¦È,?)y ?
(¦È,?)sin(¦È)
n1n2
2¦Ð
?=0
¡Æ
n1
¦È=0
¡Æ
n2
l
m
12. Spherical Harmonics 12
TextureCube CubeMap : register( t0 );
SamplerState LinearSampler : register( s0 );
RWStructuredBuffer<float3> Coeffs : register( u0 );
static const int ThreadGroupX = 16;
static const int ThreadGroupY = 16;
static const float3 Black = (float3)0;
static const float SampleDelta = 0.025f;
static const float DeltaPhi = SampleDelta * ThreadGroupX;
static const float DeltaTheta = SampleDelta * ThreadGroupY;
groupshared float3 SharedCoeffs[ThreadGroupX * ThreadGroupY][9];
groupshared int TotalSample;
[numthreads(ThreadGroupX, ThreadGroupY, 1)]
void main( uint3 GTid: SV_GroupThreadID, uint GI : SV_GroupIndex)
{
if ( GI == 0 )
{
TotalSample = 0;
}
GroupMemoryBarrierWithGroupSync();
float3 coeffs[9] = { Black, Black, Black, Black, Black, Black, Black, Black, Black };
int numSample = 0;
for ( float phi = GTid.x * SampleDelta; phi < 2.f * PI; phi += DeltaPhi )
{
for ( float theta = GTid.y * SampleDelta; theta < PI; theta += DeltaTheta )
{
float3 sampleDir = normalize( float3( sin( theta ) * cos( phi ), sin( theta ) * sin( phi ), cos( theta ) ) );
float3 radiance = CubeMap.SampleLevel( LinearSampler, sampleDir, 0 ).rgb;
float y[9];
ShFunctionL2( sampleDir, y );
[unroll]
for ( int i = 0; i < 9; ++i )
{
coeffs[i] += radiance * y[i] * sin( theta );
}
++numSample;
}
}
int sharedIndex = GTid.y * ThreadGroupX + GTid.x;
[unroll]
for ( int i = 0; i < 9; ++i )
{
SharedCoeffs[sharedIndex][i] = coeffs[i];
coeffs[i] = Black;
}
InterlockedAdd( TotalSample, numSample );
GroupMemoryBarrierWithGroupSync();
if ( GI == 0 )
{
for ( int i = 0; i < ThreadGroupX * ThreadGroupY; ++i )
{
[unroll]
for ( int j = 0; j < 9; ++j )
{
coeffs[j] += SharedCoeffs[i][j];
}
}
float dOmega = 2.f * PI / float( TotalSample );
[unroll]
for ( int i = 0; i < 9; ++i )
{
14. Spherical Harmonics 14
???
?????????????.
???????????????????.
GitHub - xtozero/SSR at irradiance_map
Screen Space Reflection. Contribute to xtozero/SSR development by creating an account on
GitHub.
https://github.com/xtozero/ssr/tree/irradiance_map
Reference
1. Diffuse irradiance
2. Spherical Harmonic Lighting: The Gritty Details
3. An Efficient Representation for Irradiance Environment Maps
4. On the relationship between radiance and irradiance: determining the illumination from images of a convex
Lambertian object
5. Diffuse IrradianceMap?Spherical harmonics??????
?
??
?
??