summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorclayjohn <claynjohn@gmail.com>2024-08-21 00:30:59 -0700
committerclayjohn <claynjohn@gmail.com>2024-08-21 10:24:32 -0700
commitf4ccba7508fe6fbbbda92df855ad59a63a205b17 (patch)
treec7cd5206100ae9e00df267657dd4822e4375f9d6
parentda5f39889f155658cef7f7ec3cc1abb94e17d815 (diff)
downloadredot-engine-f4ccba7508fe6fbbbda92df855ad59a63a205b17.tar.gz
Use correct lightmap coefficients to ensure that the directional lightmap mode looks correct
Also remove the metallic option from directional lightmap as it is guaranteed to return negative numbers in many cases
-rw-r--r--drivers/gles3/shaders/scene.glsl14
-rw-r--r--modules/lightmapper_rd/lightmapper_rd.cpp17
-rw-r--r--modules/lightmapper_rd/lightmapper_rd.h2
-rw-r--r--modules/lightmapper_rd/lm_compute.glsl30
-rw-r--r--servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl14
-rw-r--r--servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl15
6 files changed, 48 insertions, 44 deletions
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index 04ba98a420..955f3e0206 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -1729,16 +1729,10 @@ void main() {
vec3 n = normalize(lightmap_normal_xform * normal);
- ambient_light += lm_light_l0 * 0.282095f;
- ambient_light += lm_light_l1n1 * 0.32573 * n.y * lightmap_exposure_normalization;
- ambient_light += lm_light_l1_0 * 0.32573 * n.z * lightmap_exposure_normalization;
- ambient_light += lm_light_l1p1 * 0.32573 * n.x * lightmap_exposure_normalization;
- if (metallic > 0.01) { // Since the more direct bounced light is lost, we can kind of fake it with this trick.
- vec3 r = reflect(normalize(-vertex), normal);
- specular_light += lm_light_l1n1 * 0.32573 * r.y * lightmap_exposure_normalization;
- specular_light += lm_light_l1_0 * 0.32573 * r.z * lightmap_exposure_normalization;
- specular_light += lm_light_l1p1 * 0.32573 * r.x * lightmap_exposure_normalization;
- }
+ ambient_light += lm_light_l0 * lightmap_exposure_normalization;
+ ambient_light += lm_light_l1n1 * n.y * lightmap_exposure_normalization;
+ ambient_light += lm_light_l1_0 * n.z * lightmap_exposure_normalization;
+ ambient_light += lm_light_l1p1 * n.x * lightmap_exposure_normalization;
#else
ambient_light += textureLod(lightmap_textures, uvw, 0.0).rgb * lightmap_exposure_normalization;
#endif
diff --git a/modules/lightmapper_rd/lightmapper_rd.cpp b/modules/lightmapper_rd/lightmapper_rd.cpp
index 33b0b0d015..41ac6ee0ec 100644
--- a/modules/lightmapper_rd/lightmapper_rd.cpp
+++ b/modules/lightmapper_rd/lightmapper_rd.cpp
@@ -915,7 +915,7 @@ LightmapperRD::BakeError LightmapperRD::_denoise_oidn(RenderingDevice *p_rd, RID
return BAKE_OK;
}
-LightmapperRD::BakeError LightmapperRD::_denoise(RenderingDevice *p_rd, Ref<RDShaderFile> &p_compute_shader, const RID &p_compute_base_uniform_set, PushConstant &p_push_constant, RID p_source_light_tex, RID p_source_normal_tex, RID p_dest_light_tex, float p_denoiser_strength, int p_denoiser_range, const Size2i &p_atlas_size, int p_atlas_slices, bool p_bake_sh, BakeStepFunc p_step_function) {
+LightmapperRD::BakeError LightmapperRD::_denoise(RenderingDevice *p_rd, Ref<RDShaderFile> &p_compute_shader, const RID &p_compute_base_uniform_set, PushConstant &p_push_constant, RID p_source_light_tex, RID p_source_normal_tex, RID p_dest_light_tex, float p_denoiser_strength, int p_denoiser_range, const Size2i &p_atlas_size, int p_atlas_slices, bool p_bake_sh, BakeStepFunc p_step_function, void *p_bake_userdata) {
RID denoise_params_buffer = p_rd->uniform_buffer_create(sizeof(DenoiseParams));
DenoiseParams denoise_params;
denoise_params.spatial_bandwidth = 5.0f;
@@ -978,6 +978,11 @@ LightmapperRD::BakeError LightmapperRD::_denoise(RenderingDevice *p_rd, Ref<RDSh
p_rd->sync();
}
}
+ if (p_step_function) {
+ int percent = (s + 1) * 100 / p_atlas_slices;
+ float p = float(s) / p_atlas_slices * 0.1;
+ p_step_function(0.8 + p, vformat(RTR("Denoising %d%%"), percent), p_bake_userdata, false);
+ }
}
p_rd->free(compute_shader_denoise);
@@ -1581,6 +1586,14 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
Ref<Image> img = Image::create_from_data(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s);
img->save_exr("res://2_light_primary_" + itos(i) + ".exr", false);
}
+
+ if (p_bake_sh) {
+ for (int i = 0; i < atlas_slices * 4; i++) {
+ Vector<uint8_t> s = rd->texture_get_data(light_accum_tex, i);
+ Ref<Image> img = Image::create_from_data(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s);
+ img->save_exr("res://2_light_primary_accum_" + itos(i) + ".exr", false);
+ }
+ }
#endif
/* SECONDARY (indirect) LIGHT PASS(ES) */
@@ -1803,7 +1816,7 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
} else {
// JNLM (built-in).
SWAP(light_accum_tex, light_accum_tex2);
- error = _denoise(rd, compute_shader, compute_base_uniform_set, push_constant, light_accum_tex2, normal_tex, light_accum_tex, p_denoiser_strength, p_denoiser_range, atlas_size, atlas_slices, p_bake_sh, p_step_function);
+ error = _denoise(rd, compute_shader, compute_base_uniform_set, push_constant, light_accum_tex2, normal_tex, light_accum_tex, p_denoiser_strength, p_denoiser_range, atlas_size, atlas_slices, p_bake_sh, p_step_function, p_bake_userdata);
}
if (unlikely(error != BAKE_OK)) {
return error;
diff --git a/modules/lightmapper_rd/lightmapper_rd.h b/modules/lightmapper_rd/lightmapper_rd.h
index 487c44a480..59c2d52e69 100644
--- a/modules/lightmapper_rd/lightmapper_rd.h
+++ b/modules/lightmapper_rd/lightmapper_rd.h
@@ -272,7 +272,7 @@ class LightmapperRD : public Lightmapper {
void _raster_geometry(RenderingDevice *rd, Size2i atlas_size, int atlas_slices, int grid_size, AABB bounds, float p_bias, Vector<int> slice_triangle_count, RID position_tex, RID unocclude_tex, RID normal_tex, RID raster_depth_buffer, RID rasterize_shader, RID raster_base_uniform);
BakeError _dilate(RenderingDevice *rd, Ref<RDShaderFile> &compute_shader, RID &compute_base_uniform_set, PushConstant &push_constant, RID &source_light_tex, RID &dest_light_tex, const Size2i &atlas_size, int atlas_slices);
- BakeError _denoise(RenderingDevice *p_rd, Ref<RDShaderFile> &p_compute_shader, const RID &p_compute_base_uniform_set, PushConstant &p_push_constant, RID p_source_light_tex, RID p_source_normal_tex, RID p_dest_light_tex, float p_denoiser_strength, int p_denoiser_range, const Size2i &p_atlas_size, int p_atlas_slices, bool p_bake_sh, BakeStepFunc p_step_function);
+ BakeError _denoise(RenderingDevice *p_rd, Ref<RDShaderFile> &p_compute_shader, const RID &p_compute_base_uniform_set, PushConstant &p_push_constant, RID p_source_light_tex, RID p_source_normal_tex, RID p_dest_light_tex, float p_denoiser_strength, int p_denoiser_range, const Size2i &p_atlas_size, int p_atlas_slices, bool p_bake_sh, BakeStepFunc p_step_function, void *p_bake_userdata);
Error _store_pfm(RenderingDevice *p_rd, RID p_atlas_tex, int p_index, const Size2i &p_atlas_size, const String &p_name);
Ref<Image> _read_pfm(const String &p_name);
diff --git a/modules/lightmapper_rd/lm_compute.glsl b/modules/lightmapper_rd/lm_compute.glsl
index 9424d5a4c1..6320d3afa7 100644
--- a/modules/lightmapper_rd/lm_compute.glsl
+++ b/modules/lightmapper_rd/lm_compute.glsl
@@ -588,15 +588,20 @@ void main() {
light_for_texture += light;
#ifdef USE_SH_LIGHTMAPS
+ // These coefficients include the factored out SH evaluation, diffuse convolution, and final application, as well as the BRDF 1/PI and the spherical monte carlo factor.
+ // LO: 1/(2*sqrtPI) * 1/(2*sqrtPI) * PI * PI * 1/PI = 0.25
+ // L1: sqrt(3/(4*pi)) * sqrt(3/(4*pi)) * (PI*2/3) * (2 * PI) * 1/PI = 1.0
+ // Note: This only works because we aren't scaling, rotating, or combing harmonics, we are just directing applying them in the shader.
+
float c[4] = float[](
- 0.282095, //l0
- 0.488603 * light_dir.y, //l1n1
- 0.488603 * light_dir.z, //l1n0
- 0.488603 * light_dir.x //l1p1
+ 0.25, //l0
+ light_dir.y, //l1n1
+ light_dir.z, //l1n0
+ light_dir.x //l1p1
);
for (uint j = 0; j < 4; j++) {
- sh_accum[j].rgb += light * c[j] * 8.0;
+ sh_accum[j].rgb += light * c[j] * bake_params.exposure_normalization;
}
#endif
}
@@ -646,15 +651,20 @@ void main() {
vec3 light = trace_indirect_light(position, ray_dir, noise);
#ifdef USE_SH_LIGHTMAPS
+ // These coefficients include the factored out SH evaluation, diffuse convolution, and final application, as well as the BRDF 1/PI and the spherical monte carlo factor.
+ // LO: 1/(2*sqrtPI) * 1/(2*sqrtPI) * PI * PI * 1/PI = 0.25
+ // L1: sqrt(3/(4*pi)) * sqrt(3/(4*pi)) * (PI*2/3) * (2 * PI) * 1/PI = 1.0
+ // Note: This only works because we aren't scaling, rotating, or combing harmonics, we are just directing applying them in the shader.
+
float c[4] = float[](
- 0.282095, //l0
- 0.488603 * ray_dir.y, //l1n1
- 0.488603 * ray_dir.z, //l1n0
- 0.488603 * ray_dir.x //l1p1
+ 0.25, //l0
+ ray_dir.y, //l1n1
+ ray_dir.z, //l1n0
+ ray_dir.x //l1p1
);
for (uint j = 0; j < 4; j++) {
- sh_accum[j].rgb += light * c[j] * 8.0;
+ sh_accum[j].rgb += light * c[j];
}
#else
light_accum += light;
diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl
index cf15497c8c..203ddd6610 100644
--- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl
+++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl
@@ -1450,16 +1450,10 @@ void fragment_shader(in SceneData scene_data) {
vec3 n = normalize(lightmaps.data[ofs].normal_xform * normal);
float en = lightmaps.data[ofs].exposure_normalization;
- ambient_light += lm_light_l0 * 0.282095f * en;
- ambient_light += lm_light_l1n1 * 0.32573 * n.y * en;
- ambient_light += lm_light_l1_0 * 0.32573 * n.z * en;
- ambient_light += lm_light_l1p1 * 0.32573 * n.x * en;
- if (metallic > 0.01) { // since the more direct bounced light is lost, we can kind of fake it with this trick
- vec3 r = reflect(normalize(-vertex), normal);
- specular_light += lm_light_l1n1 * 0.32573 * r.y * en;
- specular_light += lm_light_l1_0 * 0.32573 * r.z * en;
- specular_light += lm_light_l1p1 * 0.32573 * r.x * en;
- }
+ ambient_light += lm_light_l0 * en;
+ ambient_light += lm_light_l1n1 * n.y * en;
+ ambient_light += lm_light_l1_0 * n.z * en;
+ ambient_light += lm_light_l1p1 * n.x * en;
} else {
ambient_light += textureLod(sampler2DArray(lightmap_textures[ofs], SAMPLER_LINEAR_CLAMP), uvw, 0.0).rgb * lightmaps.data[ofs].exposure_normalization;
diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl
index e7623e0062..2a250bfb34 100644
--- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl
+++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl
@@ -1210,17 +1210,10 @@ void main() {
vec3 n = normalize(lightmaps.data[ofs].normal_xform * normal);
float exposure_normalization = lightmaps.data[ofs].exposure_normalization;
- ambient_light += lm_light_l0 * 0.282095f;
- ambient_light += lm_light_l1n1 * 0.32573 * n.y * exposure_normalization;
- ambient_light += lm_light_l1_0 * 0.32573 * n.z * exposure_normalization;
- ambient_light += lm_light_l1p1 * 0.32573 * n.x * exposure_normalization;
- if (metallic > 0.01) { // since the more direct bounced light is lost, we can kind of fake it with this trick
- vec3 r = reflect(normalize(-vertex), normal);
- specular_light += lm_light_l1n1 * 0.32573 * r.y * exposure_normalization;
- specular_light += lm_light_l1_0 * 0.32573 * r.z * exposure_normalization;
- specular_light += lm_light_l1p1 * 0.32573 * r.x * exposure_normalization;
- }
-
+ ambient_light += lm_light_l0 * exposure_normalization;
+ ambient_light += lm_light_l1n1 * n.y * exposure_normalization;
+ ambient_light += lm_light_l1_0 * n.z * exposure_normalization;
+ ambient_light += lm_light_l1p1 * n.x * exposure_normalization;
} else {
ambient_light += textureLod(sampler2DArray(lightmap_textures[ofs], SAMPLER_LINEAR_CLAMP), uvw, 0.0).rgb * lightmaps.data[ofs].exposure_normalization;
}