diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2017-10-24 15:49:00 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2017-10-27 23:49:15 +0300 |
commit | 66d8f82b832b58cba3273c0a4196fae6db0e1efd (patch) | |
tree | 682a3aba8fbd23ccd72a4e4f2a02fb36ad0a0d01 /source/blender/draw/engines/eevee/shaders/volumetric_scatter_frag.glsl | |
parent | 1c0c63ce5b3914be2d0828260e5ac777a7596d36 (diff) |
Eevee: Overhaul the volumetric system.
The system now uses several 3D textures in order to decouple every steps of the volumetric rendering.
See https://www.ea.com/frostbite/news/physically-based-unified-volumetric-rendering-in-frostbite for more details.
On the technical side, instead of using a compute shader to populate the 3D textures we use layered rendering with a geometry shader to render 1 fullscreen triangle per 3D texture slice.
Diffstat (limited to 'source/blender/draw/engines/eevee/shaders/volumetric_scatter_frag.glsl')
-rw-r--r-- | source/blender/draw/engines/eevee/shaders/volumetric_scatter_frag.glsl | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_scatter_frag.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_scatter_frag.glsl new file mode 100644 index 00000000000..ec695b2f0ac --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/volumetric_scatter_frag.glsl @@ -0,0 +1,83 @@ + +/* Based on Frosbite Unified Volumetric. + * https://www.ea.com/frostbite/news/physically-based-unified-volumetric-rendering-in-frostbite */ + +/* Step 2 : Evaluate all light scattering for each froxels. + * Also do the temporal reprojection to fight aliasing artifacts. */ + +uniform sampler3D volumeScattering; +uniform sampler3D volumeExtinction; +uniform sampler3D volumeEmission; +uniform sampler3D volumePhase; + +uniform sampler3D historyScattering; +uniform sampler3D historyTransmittance; + +uniform vec3 volume_jitter; +uniform float volume_history_alpha; +uniform int light_count; +uniform mat4 PastViewProjectionMatrix; + +flat in int slice; + +layout(location = 0) out vec4 outScattering; +layout(location = 1) out vec4 outTransmittance; + +#define VOLUME_LIGHTING + +void main() +{ + vec3 volume_tex_size = vec3(textureSize(volumeScattering, 0)); + ivec3 volume_cell = ivec3(gl_FragCoord.xy, slice); + + /* Emission */ + outScattering = texelFetch(volumeEmission, volume_cell, 0); + outTransmittance = texelFetch(volumeExtinction, volume_cell, 0); + vec3 s_scattering = texelFetch(volumeScattering, volume_cell, 0).rgb; + vec3 volume_ndc = volume_to_ndc((vec3(volume_cell) + volume_jitter) / volume_tex_size); + vec3 worldPosition = get_world_space_from_depth(volume_ndc.xy, volume_ndc.z); + vec3 wdir = cameraVec; + + vec2 phase = texelFetch(volumePhase, volume_cell, 0).rg; + float s_anisotropy = phase.x / phase.y; + + /* Environment : Average color. */ + outScattering.rgb += irradiance_volumetric(worldPosition) * s_scattering * phase_function_isotropic(); + +#ifdef VOLUME_LIGHTING /* Lights */ + for (int i = 0; i < MAX_LIGHT && i < light_count; ++i) { + + LightData ld = lights_data[i]; + + vec4 l_vector; + l_vector.xyz = ld.l_position - worldPosition; + l_vector.w = length(l_vector.xyz); + + float Vis = light_visibility(ld, worldPosition, l_vector); + + vec3 Li = light_volume(ld, l_vector) * light_volume_shadow(ld, worldPosition, l_vector, volumeExtinction); + + outScattering.rgb += Li * Vis * s_scattering * phase_function(-wdir, l_vector.xyz / l_vector.w, s_anisotropy); + } +#endif + + /* Temporal supersampling */ + /* Note : this uses the cell non-jittered position (texel center). */ + vec3 curr_ndc = volume_to_ndc(vec3(gl_FragCoord.xy, float(slice) + 0.5) / volume_tex_size); + vec3 wpos = get_world_space_from_depth(curr_ndc.xy, curr_ndc.z); + vec3 prev_ndc = project_point(PastViewProjectionMatrix, wpos); + vec3 prev_volume = ndc_to_volume(prev_ndc * 0.5 + 0.5); + + if ((volume_history_alpha > 0.0) && all(greaterThan(prev_volume, vec3(0.0))) && all(lessThan(prev_volume, vec3(1.0)))) { + vec4 h_Scattering = texture(historyScattering, prev_volume); + vec4 h_Transmittance = texture(historyTransmittance, prev_volume); + outScattering = mix(outScattering, h_Scattering, volume_history_alpha); + outTransmittance = mix(outTransmittance, h_Transmittance, volume_history_alpha); + } + + /* Catch NaNs */ + if (any(isnan(outScattering)) || any(isnan(outTransmittance))) { + outScattering = vec4(0.0); + outTransmittance = vec4(0.0); + } +} |