Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl')
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl153
1 files changed, 153 insertions, 0 deletions
diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl
new file mode 100644
index 00000000000..5f641c5d490
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl
@@ -0,0 +1,153 @@
+
+/* Based on Frosbite Unified Volumetric.
+ * https://www.ea.com/frostbite/news/physically-based-unified-volumetric-rendering-in-frostbite */
+
+/* Volume slice to view space depth. */
+float volume_z_to_view_z(float z)
+{
+ if (ProjectionMatrix[3][3] == 0.0) {
+ /* Exponential distribution */
+ return (exp2(z / volDepthParameters.z) - volDepthParameters.x) / volDepthParameters.y;
+ }
+ else {
+ /* Linear distribution */
+ return mix(volDepthParameters.x, volDepthParameters.y, z);
+ }
+}
+
+float view_z_to_volume_z(float depth)
+{
+ if (ProjectionMatrix[3][3] == 0.0) {
+ /* Exponential distribution */
+ return volDepthParameters.z * log2(depth * volDepthParameters.y + volDepthParameters.x);
+ }
+ else {
+ /* Linear distribution */
+ return (depth - volDepthParameters.x) * volDepthParameters.z;
+ }
+}
+
+/* Volume texture normalized coordinates to NDC (special range [0, 1]). */
+vec3 volume_to_ndc(vec3 cos)
+{
+ cos.z = volume_z_to_view_z(cos.z);
+ cos.z = get_depth_from_view_z(cos.z);
+ cos.xy /= volCoordScale.xy;
+ return cos;
+}
+
+vec3 ndc_to_volume(vec3 cos)
+{
+ cos.z = get_view_z_from_depth(cos.z);
+ cos.z = view_z_to_volume_z(cos.z);
+ cos.xy *= volCoordScale.xy;
+ return cos;
+}
+
+float phase_function_isotropic()
+{
+ return 1.0 / (4.0 * M_PI);
+}
+
+float phase_function(vec3 v, vec3 l, float g)
+{
+ /* Henyey-Greenstein */
+ float cos_theta = dot(v, l);
+ g = clamp(g, -1.0 + 1e-3, 1.0 - 1e-3);
+ float sqr_g = g * g;
+ return (1- sqr_g) / max(1e-8, 4.0 * M_PI * pow(1 + sqr_g - 2 * g * cos_theta, 3.0 / 2.0));
+}
+
+#ifdef LAMPS_LIB
+vec3 light_volume(LightData ld, vec4 l_vector)
+{
+ float power;
+ /* TODO : Area lighting ? */
+ /* XXX : Removing Area Power. */
+ /* TODO : put this out of the shader. */
+ /* See eevee_light_setup(). */
+ if (ld.l_type == AREA_RECT || ld.l_type == AREA_ELLIPSE) {
+ power = (ld.l_sizex * ld.l_sizey * 4.0 * M_PI) * (1.0 / 80.0);
+ if (ld.l_type == AREA_ELLIPSE) {
+ power *= M_PI * 0.25;
+ }
+ power *= 20.0 * max(0.0, dot(-ld.l_forward, l_vector.xyz / l_vector.w)); /* XXX ad hoc, empirical */
+ }
+ else if (ld.l_type == SUN) {
+ power = (4.0f * ld.l_radius * ld.l_radius * M_2PI) * (1.0 / 12.5); /* Removing area light power*/
+ power *= M_2PI * 0.78; /* Matching cycles with point light. */
+ }
+ else {
+ power = (4.0 * ld.l_radius * ld.l_radius) * (1.0 /10.0);
+ }
+
+ /* OPTI: find a better way than calculating this on the fly */
+ float lum = dot(ld.l_color, vec3(0.3, 0.6, 0.1)); /* luminance approx. */
+ vec3 tint = (lum > 0.0) ? ld.l_color / lum : vec3(1.0); /* normalize lum. to isolate hue+sat */
+
+ power /= (l_vector.w * l_vector.w);
+
+ lum = min(lum * power, volLightClamp);
+
+ return tint * lum;
+}
+
+#define VOLUMETRIC_SHADOW_MAX_STEP 32.0
+
+vec3 participating_media_extinction(vec3 wpos, sampler3D volume_extinction)
+{
+ /* Waiting for proper volume shadowmaps and out of frustum shadow map. */
+ vec3 ndc = project_point(ViewProjectionMatrix, wpos);
+ vec3 volume_co = ndc_to_volume(ndc * 0.5 + 0.5);
+
+ /* Let the texture be clamped to edge. This reduce visual glitches. */
+ return texture(volume_extinction, volume_co).rgb;
+}
+
+vec3 light_volume_shadow(LightData ld, vec3 ray_wpos, vec4 l_vector, sampler3D volume_extinction)
+{
+#if defined(VOLUME_SHADOW)
+ /* Heterogeneous volume shadows */
+ float dd = l_vector.w / volShadowSteps;
+ vec3 L = l_vector.xyz * l_vector.w;
+ vec3 shadow = vec3(1.0);
+ for (float s = 0.5; s < VOLUMETRIC_SHADOW_MAX_STEP && s < (volShadowSteps - 0.1); s += 1.0) {
+ vec3 pos = ray_wpos + L * (s / volShadowSteps);
+ vec3 s_extinction = participating_media_extinction(pos, volume_extinction);
+ shadow *= exp(-s_extinction * dd);
+ }
+ return shadow;
+#else
+ return vec3(1.0);
+#endif /* VOLUME_SHADOW */
+}
+#endif
+
+#ifdef IRRADIANCE_LIB
+vec3 irradiance_volumetric(vec3 wpos)
+{
+#ifdef IRRADIANCE_HL2
+ IrradianceData ir_data = load_irradiance_cell(0, vec3(1.0));
+ vec3 irradiance = ir_data.cubesides[0] + ir_data.cubesides[1] + ir_data.cubesides[2];
+ ir_data = load_irradiance_cell(0, vec3(-1.0));
+ irradiance += ir_data.cubesides[0] + ir_data.cubesides[1] + ir_data.cubesides[2];
+ irradiance *= 0.16666666; /* 1/6 */
+ return irradiance;
+#else
+ return vec3(0.0);
+#endif
+}
+#endif
+
+uniform sampler3D inScattering;
+uniform sampler3D inTransmittance;
+
+vec4 volumetric_resolve(vec4 scene_color, vec2 frag_uvs, float frag_depth)
+{
+ vec3 volume_cos = ndc_to_volume(vec3(frag_uvs, frag_depth));
+
+ vec3 scattering = texture(inScattering, volume_cos).rgb;
+ vec3 transmittance = texture(inTransmittance, volume_cos).rgb;
+
+ return vec4(scene_color.rgb * transmittance + scattering, scene_color.a);
+}