EEVEE-Next: Add correct support for volume anisotropy from probe volumes
This adds the approximation of phase function convolution of the distant lighting captured inside probe volumes. This is based on a publication at siggraph from Bartlomiej Wronsky "Volumetric Fog: Unified compute shader based solution to atmospheric scattering" Implementation is quite straightforward. However this isn't as good as one can expect as there isn't self shadowing from the volume themself, so the lighting is still quite flat. To fix this, we have to add support for volumetrics inside probe volumes baking. But this approach would still be static so a more general solution is still to be found for dynamic volumes like smoke simulations. Pull Request: https://projects.blender.org/blender/blender/pulls/119479
This commit is contained in:
committed by
Clément Foucault
parent
a2bb547b9a
commit
893430a2c7
@@ -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;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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. */
|
||||
|
||||
Reference in New Issue
Block a user