R2 Core Shaders

R2ShadowVariance.h
Go to the documentation of this file.
1 #ifndef R2_SHADOW_VARIANCE_H
2 #define R2_SHADOW_VARIANCE_H
3
4 /// \file R2ShadowVariance.h
5 /// \brief Functions for variance shadows
6
7 #include "R2LogDepth.h"
8
9 /// A variance shadow
10 struct R2_shadow_variance_t {
11 /// The minimum level of attenuation by the shadow (0.0 means "completely attenuated", 1.0 means "no attenuation")
12 float factor_minimum;
13
14 /// The minimum variance level. Used to eliminate shadow bias. Typically `0.00002f` will suffice for all scenes.
15 float variance_minimum;
16
17 /// The amount of bleed reduction (typically `[0.2, 1.0]`). Setting this value too high results in loss of detail in shadows.
18 float bleed_reduction;
19
20 /// The logarithmic depth coefficient that was used to encode depth values
21 float depth_coefficient;
22
23 /// The variance shadow map
24 sampler2D map;
25 };
26
27 /// Compute an upper bound on the probability that the position at
28 /// `depth` is in shadow.
29 ///
30 /// @param s The shadow
31 /// @param moments The sampled shadow map depth moments
32 /// @param depth The current depth
33 ///
34 /// @return A value between `0.0` and `1.0`, where 1.0 indicates that the
35 /// area is certainly in shadow.
36
37 float
38 R2_varianceChebyshevUpperBound(
39 const R2_shadow_variance_t s,
40 const vec2 moments,
41 const float depth)
42 {
43 float p = float (depth <= moments.x);
44 float variance = max (s.variance_minimum, moments.y - (moments.x * moments.x));
45 float delta = depth - moments.x;
46 float p_max = variance / (variance + (delta * delta));
47 return max (p, p_max);
48 }
49
50 /// A linear step function that maps all values less than `min` to `min`, all
51 /// values greater than `max` to `max`, and linearly scales all values in `[min, max]`
52 /// to `[min, max]`.
53 ///
54 /// @param min The minimum value
55 /// @param max The maximum value
56 /// @param x The value to scale
57 ///
58 /// @return A linearly scaled value
59
60 float
61 R2_varianceLinearStep(
62 const float min,
63 const float max,
64 const float x)
65 {
66 float vsm = x - min;
67 float msm = max - min;
68 return clamp (vsm / msm, 0.0, 1.0);
69 }
70
71 /// Apply light bleed reduction to the given shadow probability.
72 ///
73 /// @param s The shadow
74 /// @param p The shadow probability
75 ///
76 /// @return `p` with light bleed reduction applied
77
78 float
79 R2_varianceLightBleedReduction(
80 const R2_shadow_variance_t s,
81 const float p_max)
82 {
83 return R2_varianceLinearStep (s.bleed_reduction, 1.0, p_max);
84 }
85
86 /// Calculate a shadow factor for the given position.
87 ///
88 /// @param s The shadow
89 /// @param v The projective light vectors, including the position in various light coordinate spaces
90 ///
91 /// @return `s.factor_minimum` if the point is fully in shadow, or `1.0` if the point is
92 // definitely not in shadow.
93
94 float
95 R2_varianceShadowFactor(
96 const R2_shadow_variance_t s,
97 const R2_light_projective_vectors_t v)
98 {
99 float pos_light_depth =
100 R2_logDepthEncodePartial(
101 R2_logDepthPrepareEyeZ (v.surface_light_eye.z),
102 s.depth_coefficient);
103
104 // Sample the variance map for the depth distribution
105 vec2 moments =
106 texture (s.map, v.surface_light_uv.xy).xy;
107
108 // Calculate the probability that the point is in shadow.
109 float p_max =
110 R2_varianceChebyshevUpperBound (s, moments, pos_light_depth);
111
112 // Apply light bleeding reduction
113 float p_reduced =
114 R2_varianceLightBleedReduction (s, p_max);
115
116 return max (p_reduced, s.factor_minimum);
117 }
118
119 #endif // R2_SHADOW_VARIANCE_H
R2_light_projective_vectors_t::surface_light_eye
vec4 surface_light_eye
The surface position in light-eye-space.
Definition: R2LightProjective.h:16
R2_logDepthEncodePartial
float R2_logDepthEncodePartial(const float z, const float depth_coefficient)
Definition: R2LogDepth.h:33
R2_light_projective_vectors_t
Vectors used when calculating projective lighting.
Definition: R2LightProjective.h:11
R2_shadow_variance_t::map
sampler2D map
The variance shadow map.
Definition: R2ShadowVariance.h:24
R2_shadow_variance_t::variance_minimum
float variance_minimum
The minimum variance level. Used to eliminate shadow bias. Typically 0.00002f will suffice for all sc...
Definition: R2ShadowVariance.h:15
R2_light_projective_vectors_t::surface_light_uv
vec2 surface_light_uv
The surface position as UV coordinates from the perspective of the light.
Definition: R2LightProjective.h:25
R2_varianceShadowFactor
float R2_varianceShadowFactor(const R2_shadow_variance_t s, const R2_light_projective_vectors_t v)
Definition: R2ShadowVariance.h:95
R2_varianceLinearStep
float R2_varianceLinearStep(const float min, const float max, const float x)
Definition: R2ShadowVariance.h:61
R2_varianceLightBleedReduction
float R2_varianceLightBleedReduction(const R2_shadow_variance_t s, const float p_max)
Definition: R2ShadowVariance.h:79
R2_shadow_variance_t::bleed_reduction
float bleed_reduction
The amount of bleed reduction (typically [0.2, 1.0]). Setting this value too high results in loss of ...
Definition: R2ShadowVariance.h:18
R2_logDepthPrepareEyeZ
float R2_logDepthPrepareEyeZ(const float z)
Definition: R2LogDepth.h:15
R2LogDepth.h
Logarithmic depth functions.
R2_shadow_variance_t::depth_coefficient
float depth_coefficient
The logarithmic depth coefficient that was used to encode depth values.
Definition: R2ShadowVariance.h:21
R2_shadow_variance_t::factor_minimum
float factor_minimum
The minimum level of attenuation by the shadow (0.0 means "completely attenuated", 1.0 means "no attenuation")
Definition: R2ShadowVariance.h:12
R2_shadow_variance_t
A variance shadow.
Definition: R2ShadowVariance.h:10
R2_varianceChebyshevUpperBound
float R2_varianceChebyshevUpperBound(const R2_shadow_variance_t s, const vec2 moments, const float depth)
Definition: R2ShadowVariance.h:38