diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_spherical_harmonics_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_spherical_harmonics_lib.glsl index fc237387b7a..6f1e10305e4 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_spherical_harmonics_lib.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_spherical_harmonics_lib.glsl @@ -562,3 +562,22 @@ SphericalHarmonicL2 spherical_harmonics_add(SphericalHarmonicL2 a, SphericalHarm } /** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Dot + * \{ */ + +vec4 spherical_harmonics_dot(SphericalHarmonicL1 a, SphericalHarmonicL1 b) +{ + /* Convert coefficients to per channel column. */ + mat4x4 a_mat = transpose(mat4x4(a.L0.M0, a.L1.Mn1, a.L1.M0, a.L1.Mp1)); + mat4x4 b_mat = transpose(mat4x4(b.L0.M0, b.L1.Mn1, b.L1.M0, b.L1.Mp1)); + vec4 result; + result[0] = dot(a_mat[0], b_mat[0]); + result[1] = dot(a_mat[1], b_mat[1]); + result[2] = dot(a_mat[2], b_mat[2]); + result[3] = dot(a_mat[3], b_mat[3]); + return result; +} + +/** \} */ diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_volume_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_volume_lib.glsl index 04731eaac80..8a91235d7e7 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_volume_lib.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_volume_lib.glsl @@ -10,6 +10,7 @@ #pragma BLENDER_REQUIRE(draw_view_lib.glsl) #pragma BLENDER_REQUIRE(eevee_light_lib.glsl) #pragma BLENDER_REQUIRE(eevee_shadow_lib.glsl) +#pragma BLENDER_REQUIRE(eevee_spherical_harmonics_lib.glsl) /* Based on Frosbite Unified Volumetric. * https://www.ea.com/frostbite/news/physically-based-unified-volumetric-rendering-in-frostbite */ @@ -68,6 +69,22 @@ float volume_phase_function(vec3 V, vec3 L, float g) return (1 - sqr_g) / max(1e-8, 4.0 * M_PI * pow(1 + sqr_g - 2 * g * cos_theta, 3.0 / 2.0)); } +SphericalHarmonicL1 volume_phase_function_as_sh_L1(vec3 V, float g) +{ + /* Compute rotated zonal harmonic. + * From Bartlomiej Wronsky + * "Volumetric Fog: Unified compute shader based solution to atmospheric scattering" page 55 + * Siggraph 2014 + * https://bartwronski.files.wordpress.com/2014/08/bwronski_volumetric_fog_siggraph2014.pdf + */ + SphericalHarmonicL1 sh; + sh.L0.M0 = spherical_harmonics_L0_M0(V) * vec4(1.0); + sh.L1.Mn1 = spherical_harmonics_L1_Mn1(V) * vec4(g); + sh.L1.M0 = spherical_harmonics_L1_M0(V) * vec4(g); + sh.L1.Mp1 = spherical_harmonics_L1_Mp1(V) * vec4(g); + return sh; +} + vec3 volume_light(LightData light, const bool is_directional, LightVector lv) { float power = 1.0; @@ -153,16 +170,6 @@ vec3 volume_shadow( #endif /* VOLUME_SHADOW */ } -vec3 volume_irradiance(vec3 P) -{ -#ifdef VOLUME_IRRADIANCE - SphericalHarmonicL1 irradiance = lightprobe_irradiance_sample(P); - return irradiance.L0.M0.rgb * M_PI; -#else - return vec3(0.0); -#endif -} - struct VolumeResolveSample { vec3 transmittance; vec3 scattering; diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_volume_scatter_comp.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_volume_scatter_comp.glsl index 301ee19ac9e..ddde3e64f8c 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_volume_scatter_comp.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_volume_scatter_comp.glsl @@ -78,10 +78,13 @@ void main() float s_anisotropy = phase.x / max(1.0, phase.y); #ifdef VOLUME_LIGHTING - scattering += volume_irradiance(P) * s_scattering * volume_phase_function_isotropic(); + SphericalHarmonicL1 phase_sh = volume_phase_function_as_sh_L1(V, s_anisotropy); + SphericalHarmonicL1 volume_radiance_sh = lightprobe_irradiance_sample(P); + + vec3 light_scattering = spherical_harmonics_dot(volume_radiance_sh, phase_sh).xyz; LIGHT_FOREACH_BEGIN_DIRECTIONAL (light_cull_buf, l_idx) { - scattering += volume_scatter_light_eval(true, P, V, l_idx, s_anisotropy) * s_scattering; + light_scattering += volume_scatter_light_eval(true, P, V, l_idx, s_anisotropy); } LIGHT_FOREACH_END @@ -89,10 +92,11 @@ void main() uniform_buf.volumes.viewport_size_inv; LIGHT_FOREACH_BEGIN_LOCAL (light_cull_buf, light_zbin_buf, light_tile_buf, pixel, vP.z, l_idx) { - scattering += volume_scatter_light_eval(false, P, V, l_idx, s_anisotropy) * s_scattering; + light_scattering += volume_scatter_light_eval(false, P, V, l_idx, s_anisotropy); } LIGHT_FOREACH_END + scattering += light_scattering * s_scattering; #endif /* Catch NaNs. */