Scene shader: Improve and document SH evaluation for light probes

This commit is contained in:
BlueCube3310 2025-04-18 16:45:28 +02:00
parent 215acd52e8
commit 5640ddd0a5
4 changed files with 58 additions and 46 deletions

View file

@ -2059,22 +2059,25 @@ void main() {
#ifndef DISABLE_LIGHTMAP
#ifdef USE_LIGHTMAP_CAPTURE
{
// The world normal.
vec3 wnormal = mat3(scene_data.inv_view_matrix) * normal;
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;
ambient_light += (c1 * lightmap_captures[8].rgb * (wnormal.x * wnormal.x - wnormal.y * wnormal.y) +
c3 * lightmap_captures[6].rgb * wnormal.z * wnormal.z +
c4 * lightmap_captures[0].rgb -
c5 * lightmap_captures[6].rgb +
2.0 * c1 * lightmap_captures[4].rgb * wnormal.x * wnormal.y +
2.0 * c1 * lightmap_captures[7].rgb * wnormal.x * wnormal.z +
2.0 * c1 * lightmap_captures[5].rgb * wnormal.y * wnormal.z +
2.0 * c2 * lightmap_captures[3].rgb * wnormal.x +
2.0 * c2 * lightmap_captures[1].rgb * wnormal.y +
2.0 * c2 * lightmap_captures[2].rgb * wnormal.z) *
// The SH coefficients used for evaluating diffuse data from SH probes.
const float c0 = 0.886227; // l0 sqrt(1.0/(4.0*PI)) * PI
const float c1 = 1.023327; // l1 sqrt(3.0/(4.0*PI)) * PI*2.0/3.0
const float c2 = 0.858086; // l2n2, l2n1, l2p1 sqrt(15.0/(4.0*PI)) * PI*1.0/4.0
const float c3 = 0.247708; // l20 sqrt(5.0/(16.0*PI)) * PI*1.0/4.0
const float c4 = 0.429043; // l2p2 sqrt(15.0/(16.0*PI))* PI*1.0/4.0
ambient_light += (c0 * lightmap_captures[0].rgb +
c1 * lightmap_captures[1].rgb * wnormal.y +
c1 * lightmap_captures[2].rgb * wnormal.z +
c1 * lightmap_captures[3].rgb * wnormal.x +
c2 * lightmap_captures[4].rgb * wnormal.x * wnormal.y +
c2 * lightmap_captures[5].rgb * wnormal.y * wnormal.z +
c3 * lightmap_captures[6].rgb * (3.0 * wnormal.z * wnormal.z - 1.0) +
c2 * lightmap_captures[7].rgb * wnormal.x * wnormal.z +
c4 * lightmap_captures[8].rgb * (wnormal.x * wnormal.x - wnormal.y * wnormal.y)) *
scene_data.emissive_exposure_normalization;
}
#else

View file

@ -1042,7 +1042,6 @@ void main() {
0.488603 * ray_dir.x, //l1p1
1.092548 * ray_dir.x * ray_dir.y, //l2n2
1.092548 * ray_dir.y * ray_dir.z, //l2n1
//0.315392 * (ray_dir.x * ray_dir.x + ray_dir.y * ray_dir.y + 2.0 * ray_dir.z * ray_dir.z), //l20
0.315392 * (3.0 * ray_dir.z * ray_dir.z - 1.0), //l20
1.092548 * ray_dir.x * ray_dir.z, //l2p1
0.546274 * (ray_dir.x * ray_dir.x - ray_dir.y * ray_dir.y) //l2p2

View file

@ -1655,22 +1655,27 @@ void fragment_shader(in SceneData scene_data) {
if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE)) { //has lightmap capture
uint index = instances.data[instance_index].gi_offset;
// The world normal.
vec3 wnormal = mat3(scene_data.inv_view_matrix) * normal;
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;
ambient_light += (c1 * lightmap_captures.data[index].sh[8].rgb * (wnormal.x * wnormal.x - wnormal.y * wnormal.y) +
c3 * lightmap_captures.data[index].sh[6].rgb * wnormal.z * wnormal.z +
c4 * lightmap_captures.data[index].sh[0].rgb -
c5 * lightmap_captures.data[index].sh[6].rgb +
2.0 * c1 * lightmap_captures.data[index].sh[4].rgb * wnormal.x * wnormal.y +
2.0 * c1 * lightmap_captures.data[index].sh[7].rgb * wnormal.x * wnormal.z +
2.0 * c1 * lightmap_captures.data[index].sh[5].rgb * wnormal.y * wnormal.z +
2.0 * c2 * lightmap_captures.data[index].sh[3].rgb * wnormal.x +
2.0 * c2 * lightmap_captures.data[index].sh[1].rgb * wnormal.y +
2.0 * c2 * lightmap_captures.data[index].sh[2].rgb * wnormal.z) *
// The SH coefficients used for evaluating diffuse data from SH probes.
const float c[5] = float[](
0.886227, // l0 sqrt(1.0/(4.0*PI)) * PI
1.023327, // l1 sqrt(3.0/(4.0*PI)) * PI*2.0/3.0
0.858086, // l2n2, l2n1, l2p1 sqrt(15.0/(4.0*PI)) * PI*1.0/4.0
0.247708, // l20 sqrt(5.0/(16.0*PI)) * PI*1.0/4.0
0.429043 // l2p2 sqrt(15.0/(16.0*PI))* PI*1.0/4.0
);
ambient_light += (c[0] * lightmap_captures.data[index].sh[0].rgb +
c[1] * lightmap_captures.data[index].sh[1].rgb * wnormal.y +
c[1] * lightmap_captures.data[index].sh[2].rgb * wnormal.z +
c[1] * lightmap_captures.data[index].sh[3].rgb * wnormal.x +
c[2] * lightmap_captures.data[index].sh[4].rgb * wnormal.x * wnormal.y +
c[2] * lightmap_captures.data[index].sh[5].rgb * wnormal.y * wnormal.z +
c[3] * lightmap_captures.data[index].sh[6].rgb * (3.0 * wnormal.z * wnormal.z - 1.0) +
c[2] * lightmap_captures.data[index].sh[7].rgb * wnormal.x * wnormal.z +
c[4] * lightmap_captures.data[index].sh[8].rgb * (wnormal.x * wnormal.x - wnormal.y * wnormal.y)) *
scene_data.emissive_exposure_normalization;
} else if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP)) { // has actual lightmap

View file

@ -1318,22 +1318,27 @@ void main() {
if (bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE)) { //has lightmap capture
uint index = instances.data[draw_call.instance_index].gi_offset;
// The world normal.
vec3 wnormal = mat3(scene_data.inv_view_matrix) * normal;
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;
ambient_light += (c1 * lightmap_captures.data[index].sh[8].rgb * (wnormal.x * wnormal.x - wnormal.y * wnormal.y) +
c3 * lightmap_captures.data[index].sh[6].rgb * wnormal.z * wnormal.z +
c4 * lightmap_captures.data[index].sh[0].rgb -
c5 * lightmap_captures.data[index].sh[6].rgb +
2.0 * c1 * lightmap_captures.data[index].sh[4].rgb * wnormal.x * wnormal.y +
2.0 * c1 * lightmap_captures.data[index].sh[7].rgb * wnormal.x * wnormal.z +
2.0 * c1 * lightmap_captures.data[index].sh[5].rgb * wnormal.y * wnormal.z +
2.0 * c2 * lightmap_captures.data[index].sh[3].rgb * wnormal.x +
2.0 * c2 * lightmap_captures.data[index].sh[1].rgb * wnormal.y +
2.0 * c2 * lightmap_captures.data[index].sh[2].rgb * wnormal.z) *
// The SH coefficients used for evaluating diffuse data from SH probes.
const float c[5] = float[](
0.886227, // l0 sqrt(1.0/(4.0*PI)) * PI
1.023327, // l1 sqrt(3.0/(4.0*PI)) * PI*2.0/3.0
0.858086, // l2n2, l2n1, l2p1 sqrt(15.0/(4.0*PI)) * PI*1.0/4.0
0.247708, // l20 sqrt(5.0/(16.0*PI)) * PI*1.0/4.0
0.429043 // l2p2 sqrt(15.0/(16.0*PI))* PI*1.0/4.0
);
ambient_light += (c[0] * lightmap_captures.data[index].sh[0].rgb +
c[1] * lightmap_captures.data[index].sh[1].rgb * wnormal.y +
c[1] * lightmap_captures.data[index].sh[2].rgb * wnormal.z +
c[1] * lightmap_captures.data[index].sh[3].rgb * wnormal.x +
c[2] * lightmap_captures.data[index].sh[4].rgb * wnormal.x * wnormal.y +
c[2] * lightmap_captures.data[index].sh[5].rgb * wnormal.y * wnormal.z +
c[3] * lightmap_captures.data[index].sh[6].rgb * (3.0 * wnormal.z * wnormal.z - 1.0) +
c[2] * lightmap_captures.data[index].sh[7].rgb * wnormal.x * wnormal.z +
c[4] * lightmap_captures.data[index].sh[8].rgb * (wnormal.x * wnormal.x - wnormal.y * wnormal.y)) *
scene_data.emissive_exposure_normalization;
} else if (bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP)) { // has actual lightmap