@@ -134,15 +134,57 @@ Shader "Hidden/HDRenderPipeline/CombineSubsurfaceScattering"
134134 // TODO: ask Morten if there is a better way to do this.
135135 float3 totalWeight = sampleWeight;
136136
137- [unroll]
138- for (int i = 1 ; i < N_SAMPLES; i++)
137+ uint i; // Sample index
138+
139+ [unroll] // Gather samples from the center to the left (up).
140+ for (i = 1 ; i <= N_SAMPLES / 2 ; i++)
139141 {
140142 samplePosition = posInput.unPositionSS + rotatedDirection * _FilterKernels[profileID][i].a;
141143 sampleWeight = _FilterKernels[profileID][i].rgb;
142144
143145 rawDepth = LOAD_TEXTURE2D (_MainDepthTexture, samplePosition).r;
144146 sampleIrradiance = LOAD_TEXTURE2D (_IrradianceSource, samplePosition).rgb;
145147
148+ if (any (sampleIrradiance) == false )
149+ {
150+ // The irradiance is 0. There could be two reasons for this.
151+ // Most likely, the surface fragment does not have an SSS material.
152+ // Alternatively, the surface fragment could be completely shadowed.
153+ // Our blur is energy-preserving, so 'sampleWeight' should be 0.
154+ // We can save some bandwidth by terminating the loop early.
155+ break ;
156+ }
157+
158+ // Apply bilateral weighting.
159+ // Ref #1: Skin Rendering by Pseudo–Separable Cross Bilateral Filtering.
160+ // Ref #2: Separable SSS, Supplementary Materials, Section E.
161+ float sampleDepth = LinearEyeDepth (rawDepth, _ZBufferParams );
162+ float zDistance = invDistScale * sampleDepth - (invDistScale * centerPosVS.z);
163+ sampleWeight *= exp (-zDistance * zDistance * halfRcpVariance);
164+
165+ totalIrradiance += sampleWeight * sampleIrradiance;
166+ totalWeight += sampleWeight;
167+ }
168+
169+ [unroll] // Gather samples from the center to the right (down).
170+ for (; i < N_SAMPLES; i++)
171+ {
172+ samplePosition = posInput.unPositionSS + rotatedDirection * _FilterKernels[profileID][i].a;
173+ sampleWeight = _FilterKernels[profileID][i].rgb;
174+
175+ rawDepth = LOAD_TEXTURE2D (_MainDepthTexture, samplePosition).r;
176+ sampleIrradiance = LOAD_TEXTURE2D (_IrradianceSource, samplePosition).rgb;
177+
178+ if (any (sampleIrradiance) == false )
179+ {
180+ // The irradiance is 0. There could be two reasons for this.
181+ // Most likely, the surface fragment does not have an SSS material.
182+ // Alternatively, the surface fragment could be completely shadowed.
183+ // Our blur is energy-preserving, so 'sampleWeight' should be 0.
184+ // We can save some bandwidth by terminating the loop early.
185+ break ;
186+ }
187+
146188 // Apply bilateral weighting.
147189 // Ref #1: Skin Rendering by Pseudo–Separable Cross Bilateral Filtering.
148190 // Ref #2: Separable SSS, Supplementary Materials, Section E.
0 commit comments