85 lines
2.3 KiB
HLSL
85 lines
2.3 KiB
HLSL
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
|
|
|
#ifndef __SH__
|
|
#define __SH__
|
|
|
|
// The SH coefficients for the projection of a function that maps directions to scalar values
|
|
struct ThreeBandSHVector
|
|
{
|
|
half4 V0;
|
|
half4 V1;
|
|
half V2;
|
|
};
|
|
|
|
ThreeBandSHVector SHBasisFunction3(half3 v)
|
|
{
|
|
ThreeBandSHVector result;
|
|
|
|
result.V0.x = 0.282095f;
|
|
result.V0.y = -0.488603f * v.y;
|
|
result.V0.z = 0.488603f * v.z;
|
|
result.V0.w = -0.488603f * v.x;
|
|
|
|
result.V1.x = 1.092548f * v.x * v.y;
|
|
result.V1.y = -1.092548f * v.y * v.z;
|
|
result.V1.z = 0.315392f * (3.0f * v.z - 1.0f);
|
|
result.V1.w = -1.092548f * v.x * v.z;
|
|
result.V2 = 0.546274f * (v.x - v.y);
|
|
|
|
return result;
|
|
}
|
|
|
|
// Projects a direction onto SH and convolves with a cosine kernel to compute irradiance
|
|
void ProjectOntoSH3(in float3 n, in float3 color, out float3 sh[9])
|
|
{
|
|
// Cosine kernel
|
|
const float A0 = 3.141593f;
|
|
const float A1 = 2.095395f;
|
|
const float A2 = 0.785398f;
|
|
|
|
// Band 0
|
|
sh[0] = 0.282095f * A0 * color;
|
|
|
|
// Band 1
|
|
sh[1] = 0.488603f * n.y * A1 * color;
|
|
sh[2] = 0.488603f * n.z * A1 * color;
|
|
sh[3] = 0.488603f * n.x * A1 * color;
|
|
|
|
// Band 2
|
|
sh[4] = 1.092548f * n.x * n.y * A2 * color;
|
|
sh[5] = 1.092548f * n.y * n.z * A2 * color;
|
|
sh[6] = 0.315392f * (3.0f * n.z * n.z - 1.0f) * A2 * color;
|
|
sh[7] = 1.092548f * n.x * n.z * A2 * color;
|
|
sh[8] = 0.546274f * (n.x * n.x - n.y * n.y) * A2 * color;
|
|
}
|
|
|
|
// Converts from 3-band SH to 2-band H-Basis
|
|
// [Ralf Habel and Michael Wimmer, "Efficient Irradiance Normal Mapping"]
|
|
void ConvertSH3ToHBasis(in float3 sh[9], out float3 hBasis[4])
|
|
{
|
|
const float rt2 = sqrt(2.0f);
|
|
const float rt32 = sqrt(3.0f / 2.0f);
|
|
const float rt52 = sqrt(5.0f / 2.0f);
|
|
const float rt152 = sqrt(15.0f / 2.0f);
|
|
const float convMatrix[4 * 9] =
|
|
{
|
|
// @formatter:off
|
|
1.0f / rt2, 0, 0.5f * rt32, 0, 0, 0, 0, 0, 0,
|
|
0, 1.0f / rt2, 0, 0, 0, (3.0f / 8.0f) * rt52, 0, 0, 0,
|
|
0, 0, 1.0f / (2.0f * rt2), 0, 0, 0, 0.25f * rt152, 0, 0,
|
|
0, 0, 0, 1.0f / rt2, 0, 0, 0, (3.0f / 8.0f) * rt52, 0
|
|
// @formatter:on
|
|
};
|
|
|
|
UNROLL
|
|
for (uint row = 0; row < 4; row++)
|
|
{
|
|
hBasis[row] = 0.0f;
|
|
UNROLL
|
|
for (uint col = 0; col < 9; col++)
|
|
hBasis[row] += convMatrix[row * 9 + col] * sh[col];
|
|
}
|
|
}
|
|
|
|
#endif
|