1
0
Fork 0

LightmapGI: Use Geometrics technique for retrieving irradiance from SH

This commit is contained in:
BlueCube3310 2025-01-04 22:59:51 +01:00
parent bdf625bd54
commit 90b5a3682a
1 changed files with 36 additions and 19 deletions

View File

@ -895,6 +895,22 @@ vec4 textureArray_bicubic(texture2DArray tex, vec3 uv, vec2 texture_size) {
return (g0(fuv.y) * (g0x * texture(sampler2DArray(tex, SAMPLER_LINEAR_CLAMP), vec3(p0, uv.z)) + g1x * texture(sampler2DArray(tex, SAMPLER_LINEAR_CLAMP), vec3(p1, uv.z)))) +
(g1(fuv.y) * (g0x * texture(sampler2DArray(tex, SAMPLER_LINEAR_CLAMP), vec3(p2, uv.z)) + g1x * texture(sampler2DArray(tex, SAMPLER_LINEAR_CLAMP), vec3(p3, uv.z))));
}
// https://github.com/kayru/Probulator/blob/4a97a2b021eb2ca7ef696f4ddf36ba9a9432cbb6/Source/Probulator/SphericalHarmonics.h#L136-L151
// http://www.geomerics.com/wp-content/uploads/2015/08/CEDEC_Geomerics_ReconstructingDiffuseLighting1.pdf
float shEvaluateDiffuseL1Geomerics(vec4 sh, vec3 n) {
float R0 = sh.x;
vec3 R1 = 0.5f * sh.wyz;
float lenR1 = length(R1);
float q = 0.5f * (1.0f + dot(R1 / lenR1, n));
float p = 1.0f + 2.0f * lenR1 / R0;
float a = (1.0f - lenR1 / R0) / (1.0f + lenR1 / R0);
return R0 * (a + (1.0f - a) * (p + 1.0f) * pow(q, p));
}
#endif //USE_LIGHTMAP
#ifdef USE_MULTIVIEW
@ -1675,31 +1691,32 @@ void fragment_shader(in SceneData scene_data) {
uvw.z = float(slice);
if (uses_sh) {
uvw.z *= 4.0; //SH textures use 4 times more data
vec3 lm_light_l0;
vec3 lm_light_l1n1;
vec3 lm_light_l1_0;
vec3 lm_light_l1p1;
uvw.z *= 4.0; // SH textures use 4 times more data.
vec3 lm_sh[4];
if (sc_use_lightmap_bicubic_filter()) {
lm_light_l0 = textureArray_bicubic(lightmap_textures[ofs], uvw + vec3(0.0, 0.0, 0.0), lightmaps.data[ofs].light_texture_size).rgb;
lm_light_l1n1 = (textureArray_bicubic(lightmap_textures[ofs], uvw + vec3(0.0, 0.0, 1.0), lightmaps.data[ofs].light_texture_size).rgb - vec3(0.5)) * 2.0;
lm_light_l1_0 = (textureArray_bicubic(lightmap_textures[ofs], uvw + vec3(0.0, 0.0, 2.0), lightmaps.data[ofs].light_texture_size).rgb - vec3(0.5)) * 2.0;
lm_light_l1p1 = (textureArray_bicubic(lightmap_textures[ofs], uvw + vec3(0.0, 0.0, 3.0), lightmaps.data[ofs].light_texture_size).rgb - vec3(0.5)) * 2.0;
lm_sh[0] = textureArray_bicubic(lightmap_textures[ofs], uvw + vec3(0.0, 0.0, 0.0), lightmaps.data[ofs].light_texture_size).rgb;
lm_sh[1] = (textureArray_bicubic(lightmap_textures[ofs], uvw + vec3(0.0, 0.0, 1.0), lightmaps.data[ofs].light_texture_size).rgb - vec3(0.5)) * 2.0;
lm_sh[2] = (textureArray_bicubic(lightmap_textures[ofs], uvw + vec3(0.0, 0.0, 2.0), lightmaps.data[ofs].light_texture_size).rgb - vec3(0.5)) * 2.0;
lm_sh[3] = (textureArray_bicubic(lightmap_textures[ofs], uvw + vec3(0.0, 0.0, 3.0), lightmaps.data[ofs].light_texture_size).rgb - vec3(0.5)) * 2.0;
} else {
lm_light_l0 = textureLod(sampler2DArray(lightmap_textures[ofs], SAMPLER_LINEAR_CLAMP), uvw + vec3(0.0, 0.0, 0.0), 0.0).rgb;
lm_light_l1n1 = (textureLod(sampler2DArray(lightmap_textures[ofs], SAMPLER_LINEAR_CLAMP), uvw + vec3(0.0, 0.0, 1.0), 0.0).rgb - vec3(0.5)) * 2.0;
lm_light_l1_0 = (textureLod(sampler2DArray(lightmap_textures[ofs], SAMPLER_LINEAR_CLAMP), uvw + vec3(0.0, 0.0, 2.0), 0.0).rgb - vec3(0.5)) * 2.0;
lm_light_l1p1 = (textureLod(sampler2DArray(lightmap_textures[ofs], SAMPLER_LINEAR_CLAMP), uvw + vec3(0.0, 0.0, 3.0), 0.0).rgb - vec3(0.5)) * 2.0;
lm_sh[0] = textureLod(sampler2DArray(lightmap_textures[ofs], SAMPLER_LINEAR_CLAMP), uvw + vec3(0.0, 0.0, 0.0), 0.0).rgb;
lm_sh[1] = (textureLod(sampler2DArray(lightmap_textures[ofs], SAMPLER_LINEAR_CLAMP), uvw + vec3(0.0, 0.0, 1.0), 0.0).rgb - vec3(0.5)) * 2.0;
lm_sh[2] = (textureLod(sampler2DArray(lightmap_textures[ofs], SAMPLER_LINEAR_CLAMP), uvw + vec3(0.0, 0.0, 2.0), 0.0).rgb - vec3(0.5)) * 2.0;
lm_sh[3] = (textureLod(sampler2DArray(lightmap_textures[ofs], SAMPLER_LINEAR_CLAMP), uvw + vec3(0.0, 0.0, 3.0), 0.0).rgb - vec3(0.5)) * 2.0;
}
vec3 n = normalize(lightmaps.data[ofs].normal_xform * normal);
float en = lightmaps.data[ofs].exposure_normalization;
lm_sh[1] *= lm_sh[0] * 4.0;
lm_sh[2] *= lm_sh[0] * 4.0;
lm_sh[3] *= lm_sh[0] * 4.0;
ambient_light += lm_light_l0 * en;
ambient_light += lm_light_l1n1 * n.y * (lm_light_l0 * en * 4.0);
ambient_light += lm_light_l1_0 * n.z * (lm_light_l0 * en * 4.0);
ambient_light += lm_light_l1p1 * n.x * (lm_light_l0 * en * 4.0);
vec3 sampleIrradianceSh;
for (uint i = 0; i < 3; i++) {
sampleIrradianceSh[i] = shEvaluateDiffuseL1Geomerics(vec4(lm_sh[0][i], lm_sh[1][i], lm_sh[2][i], lm_sh[3][i]), normalize(lightmaps.data[ofs].normal_xform * normal));
}
ambient_light += sampleIrradianceSh * lightmaps.data[ofs].exposure_normalization;
} else {
if (sc_use_lightmap_bicubic_filter()) {