|
120 | 120 | #endif
|
121 | 121 | in vec3 vPositionW
|
122 | 122 | , in vec3 normalW
|
123 |
| - #ifdef ANISOTROPIC |
124 |
| - , in anisotropicOutParams anisotropicOut |
125 |
| - #endif |
126 | 123 | )
|
127 | 124 | {
|
128 |
| - #ifdef ANISOTROPIC |
129 |
| - vec3 reflectionVector = computeReflectionCoords(vec4(vPositionW, 1.0), anisotropicOut.anisotropicNormal); |
130 |
| - #else |
131 |
| - vec3 reflectionVector = computeReflectionCoords(vec4(vPositionW, 1.0), normalW); |
132 |
| - #endif |
| 125 | + vec3 reflectionVector = computeReflectionCoords(vec4(vPositionW, 1.0), normalW); |
133 | 126 |
|
134 | 127 | #ifdef REFLECTIONMAP_OPPOSITEZ
|
135 | 128 | reflectionVector.z *= -1.0;
|
|
154 | 147 | in float alphaG
|
155 | 148 | , in vec3 vReflectionMicrosurfaceInfos
|
156 | 149 | , in vec2 vReflectionInfos
|
157 |
| - #if defined(LODINREFLECTIONALPHA) && !defined(REFLECTIONMAP_SKYBOX) |
158 |
| - , in float NdotVUnclamped |
159 |
| - #endif |
| 150 | + , in geometryInfoOutParams geoInfo |
160 | 151 | #ifdef REFLECTIONMAP_3D
|
161 | 152 | , in samplerCube reflectionSampler
|
162 | 153 | , const vec3 reflectionCoords
|
|
172 | 163 | vec4 environmentRadiance = vec4(0., 0., 0., 0.);
|
173 | 164 | // _____________________________ 2D vs 3D Maps ________________________________
|
174 | 165 | #if defined(LODINREFLECTIONALPHA) && !defined(REFLECTIONMAP_SKYBOX)
|
175 |
| - float reflectionLOD = getLodFromAlphaG(vReflectionMicrosurfaceInfos.x, alphaG, NdotVUnclamped); |
| 166 | + float reflectionLOD = getLodFromAlphaG(vReflectionMicrosurfaceInfos.x, alphaG, geoInfo.NdotVUnclamped); |
176 | 167 | #elif defined(LINEARSPECULARREFLECTION)
|
177 | 168 | float reflectionLOD = getLinearLodFromRoughness(vReflectionMicrosurfaceInfos.x, roughness);
|
178 | 169 | #else
|
|
184 | 175 |
|
185 | 176 | #ifdef REALTIME_FILTERING
|
186 | 177 | environmentRadiance = vec4(radiance(alphaG, reflectionSampler, reflectionCoords, vReflectionFilteringInfo), 1.0);
|
| 178 | + // #elif defined(ANISOTROPIC) |
| 179 | + // vec4 radianceSample = vec4(0.0); |
| 180 | + // const int samples = 16; |
| 181 | + // for (int i = 0; i < samples; ++i) { |
| 182 | + // float t = (float(i) * (1.0f / float(max(samples - 1, 1))) - 0.5f) * 3.14159 * alphaT; |
| 183 | + // vec3 perturbed_N = geoInfo.anisotropicTangent * t; |
| 184 | + // // Add noise (mostly in the tangent direction) to smooth out sampling |
| 185 | + // // perturbed_N.xy += new_noise.xy; |
| 186 | + |
| 187 | + // vec3 newCoords = normalize(reflectionCoords + perturbed_N); |
| 188 | + // radianceSample += sampleReflectionLod(reflectionSampler, newCoords, reflectionLOD); |
| 189 | + // } |
| 190 | + // environmentRadiance = vec4(radianceSample.xyz / float(samples), 1.0); |
187 | 191 | #else
|
188 | 192 | environmentRadiance = sampleReflectionLod(reflectionSampler, reflectionCoords, reflectionLOD);
|
189 | 193 | #endif
|
|
201 | 205 | return environmentRadiance.rgb;
|
202 | 206 | }
|
203 | 207 |
|
| 208 | +#if defined(ANISOTROPIC) |
| 209 | + #define pbr_inline |
| 210 | + #define inline |
| 211 | + vec3 sampleRadianceAnisotropic( |
| 212 | + in float alphaG |
| 213 | + , in vec3 vReflectionMicrosurfaceInfos |
| 214 | + , in vec2 vReflectionInfos |
| 215 | + , in geometryInfoOutParams geoInfo |
| 216 | + , const vec3 normalW |
| 217 | + , const vec3 viewDirectionW |
| 218 | + , const vec3 positionW |
| 219 | + , const vec3 noise |
| 220 | + #ifdef REFLECTIONMAP_3D |
| 221 | + , in samplerCube reflectionSampler |
| 222 | + #else |
| 223 | + , in sampler2D reflectionSampler |
| 224 | + #endif |
| 225 | + #ifdef REALTIME_FILTERING |
| 226 | + , in vec2 vReflectionFilteringInfo |
| 227 | + #endif |
| 228 | + ) |
| 229 | + { |
| 230 | + vec4 environmentRadiance = vec4(0., 0., 0., 0.); |
| 231 | + |
| 232 | + // Calculate alpha along tangent and bitangent according to equation 21 in the OpenPBR spec. |
| 233 | + float alphaT = alphaG * sqrt(2.0 / (1.0 + (1.0 - geoInfo.anisotropy) * (1.0 - geoInfo.anisotropy))); |
| 234 | + float alphaB = (1.0 - geoInfo.anisotropy) * alphaT; |
| 235 | + alphaG = mix(alphaG, alphaB, 0.95); |
| 236 | + |
| 237 | + // _____________________________ 2D vs 3D Maps ________________________________ |
| 238 | + #if defined(LODINREFLECTIONALPHA) && !defined(REFLECTIONMAP_SKYBOX) |
| 239 | + float reflectionLOD = getLodFromAlphaG(vReflectionMicrosurfaceInfos.x, alphaG, geoInfo.NdotVUnclamped); |
| 240 | + #elif defined(LINEARSPECULARREFLECTION) |
| 241 | + float reflectionLOD = getLinearLodFromRoughness(vReflectionMicrosurfaceInfos.x, roughness); |
| 242 | + #else |
| 243 | + float reflectionLOD = getLodFromAlphaG(vReflectionMicrosurfaceInfos.x, alphaG); |
| 244 | + #endif |
| 245 | + |
| 246 | + // Apply environment convolution scale/offset filter tuning parameters to the mipmap LOD selection |
| 247 | + reflectionLOD = reflectionLOD * vReflectionMicrosurfaceInfos.y + vReflectionMicrosurfaceInfos.z; |
| 248 | + |
| 249 | + #ifdef REALTIME_FILTERING |
| 250 | + environmentRadiance = vec4(radiance(alphaG, reflectionSampler, reflectionCoords, vReflectionFilteringInfo), 1.0); |
| 251 | + #else |
| 252 | + // We will sample multiple reflections using interpolated surface normals along |
| 253 | + // the tangent direction from -tangent to +tangent. |
| 254 | + // We don't want to waste samples where the view direction is back-facing so |
| 255 | + // we'll compress samples into the valid range. |
| 256 | + const int samples = 16; |
| 257 | + // Find the maximum safe interpolation range |
| 258 | + float normalDot = dot(viewDirectionW, normalW); |
| 259 | + float tangentDot = dot(viewDirectionW, geoInfo.anisotropicTangent); |
| 260 | + float negTangentDot = dot(viewDirectionW, -geoInfo.anisotropicTangent); |
| 261 | + |
| 262 | + // Find the valid interpolation range on each side of the normal |
| 263 | + float maxPositiveT = 1.0; // Default: sample all the way to +tangent |
| 264 | + float maxNegativeT = -1.0; // Default: sample all the way to -tangent |
| 265 | + |
| 266 | + // If +tangent is back-facing, find where the interpolation becomes back-facing |
| 267 | + if (tangentDot <= 0.0) { |
| 268 | + // Find t where mix(normalW, tangentW, t) becomes perpendicular to view |
| 269 | + if (abs(tangentDot - normalDot) > 0.001) { |
| 270 | + maxPositiveT = clamp(-normalDot / (tangentDot - normalDot), 0.0, 1.0); |
| 271 | + } else { |
| 272 | + maxPositiveT = 0.0; // Can't sample towards tangent |
| 273 | + } |
| 274 | + } |
| 275 | + |
| 276 | + // If -tangent is back-facing, find where the interpolation becomes back-facing |
| 277 | + if (negTangentDot <= 0.0) { |
| 278 | + // Find t where mix(-tangentW, normalW, blend) becomes perpendicular to view |
| 279 | + // This is equivalent to mix(normalW, -tangentW, -t) for t < 0 |
| 280 | + if (abs(negTangentDot - normalDot) > 0.001) { |
| 281 | + float negT = -normalDot / (negTangentDot - normalDot); |
| 282 | + maxNegativeT = clamp(-negT, -1.0, 0.0); |
| 283 | + } else { |
| 284 | + maxNegativeT = 0.0; // Can't sample towards -tangent |
| 285 | + } |
| 286 | + } |
| 287 | + |
| 288 | + // Further compress the sampling range based on the level of anisotropic roughness |
| 289 | + float tangentRange = clamp(sqrt(sqrt(alphaT)) * geoInfo.anisotropy, 0.0, 1.0) * (0.25 * noise.x + 0.75); |
| 290 | + maxPositiveT *= maxPositiveT * tangentRange; |
| 291 | + maxNegativeT = -(maxNegativeT * maxNegativeT) * tangentRange; |
| 292 | + |
| 293 | + vec4 radianceSample = vec4(0.0); |
| 294 | + vec3 reflectionCoords = vec3(0.0); |
| 295 | + float sample_weight = 0.0; |
| 296 | + float total_weight = 0.0; |
| 297 | + for (int i = 0; i < samples; ++i) { |
| 298 | + // Find interpolation parameter in our valid range |
| 299 | + float t = mix(maxNegativeT, maxPositiveT, float(i) / float(max(samples - 1, 1))); |
| 300 | + |
| 301 | + // Generate sample direction |
| 302 | + vec3 sampleDirection; |
| 303 | + if (t < 0.0) { |
| 304 | + // Interpolate from -tangent towards normal |
| 305 | + float blend = t + 1.0; |
| 306 | + sampleDirection = normalize(mix(-geoInfo.anisotropicTangent, normalW, blend)); |
| 307 | + } else if (t > 0.0) { |
| 308 | + // Interpolate from normal towards +tangent |
| 309 | + float blend = t; |
| 310 | + sampleDirection = normalize(mix(normalW, geoInfo.anisotropicTangent, blend)); |
| 311 | + } else { |
| 312 | + // t = 0, sample the normal |
| 313 | + sampleDirection = normalW; |
| 314 | + } |
| 315 | + |
| 316 | + // Empirical approximation of geometry masking. |
| 317 | + sample_weight = pow(clamp(dot(normalW, sampleDirection), 0.0, 1.0), 16.0); |
| 318 | + reflectionCoords = createReflectionCoords(positionW, sampleDirection); |
| 319 | + radianceSample = sampleReflectionLod(reflectionSampler, reflectionCoords, reflectionLOD); |
| 320 | + #ifdef RGBDREFLECTION |
| 321 | + environmentRadiance.rgb += sample_weight * fromRGBD(radianceSample); |
| 322 | + #elif defined(GAMMAREFLECTION) |
| 323 | + environmentRadiance.rgb += sample_weight * toLinearSpace(radianceSample.rgb); |
| 324 | + #else |
| 325 | + environmentRadiance.rgb += sample_weight * radianceSample.rgb; |
| 326 | + #endif |
| 327 | + total_weight += sample_weight; |
| 328 | + } |
| 329 | + environmentRadiance = vec4(environmentRadiance.xyz / float(total_weight), 1.0); |
| 330 | + #endif |
| 331 | + |
| 332 | + // _____________________________ Levels _____________________________________ |
| 333 | + environmentRadiance.rgb *= vec3(vReflectionInfos.x); |
| 334 | + return environmentRadiance.rgb; |
| 335 | + } |
| 336 | +#endif |
| 337 | + |
204 | 338 | #define pbr_inline
|
205 | 339 | vec3 conductorIblFresnel(in ReflectanceParams reflectance, in float NdotV, in float roughness, in vec3 environmentBrdf)
|
206 | 340 | {
|
|
0 commit comments