|
@@ -0,0 +1,339 @@
|
|
|
+struct subSurfaceOutParams
|
|
|
+{
|
|
|
+ vec3 specularEnvironmentReflectance;
|
|
|
+#ifdef SS_REFRACTION
|
|
|
+ vec3 finalRefraction;
|
|
|
+ vec3 surfaceAlbedo;
|
|
|
+ #ifdef SS_LINKREFRACTIONTOTRANSPARENCY
|
|
|
+ float alpha;
|
|
|
+ #endif
|
|
|
+ #ifdef REFLECTION
|
|
|
+ float refractionFactorForIrradiance;
|
|
|
+ #endif
|
|
|
+#endif
|
|
|
+#ifdef SS_TRANSLUCENCY
|
|
|
+ vec3 transmittance;
|
|
|
+ #ifdef REFLECTION
|
|
|
+ vec3 refractionIrradiance;
|
|
|
+ #endif
|
|
|
+#endif
|
|
|
+#if DEBUGMODE > 0
|
|
|
+ vec4 thicknessMap;
|
|
|
+ vec4 environmentRefraction;
|
|
|
+ vec3 refractionTransmittance;
|
|
|
+#endif
|
|
|
+};
|
|
|
+
|
|
|
+#ifdef SUBSURFACE
|
|
|
+ void subSurfaceBlock(
|
|
|
+ const in vec2 vThicknessParam,
|
|
|
+ const in vec4 vTintColor,
|
|
|
+ const in vec3 normalW,
|
|
|
+ const in vec3 specularEnvironmentReflectance,
|
|
|
+ #ifdef SS_THICKNESSANDMASK_TEXTURE
|
|
|
+ const in vec2 vThicknessUV,
|
|
|
+ const in vec2 uvOffset,
|
|
|
+ const in sampler2D thicknessSampler,
|
|
|
+ #endif
|
|
|
+ #ifdef REFLECTION
|
|
|
+ #ifdef SS_TRANSLUCENCY
|
|
|
+ const in mat4 reflectionMatrix,
|
|
|
+ #ifdef USESPHERICALFROMREFLECTIONMAP
|
|
|
+ #if !defined(NORMAL) || !defined(USESPHERICALINVERTEX)
|
|
|
+ const in vec3 irradianceVector_,
|
|
|
+ #endif
|
|
|
+ #endif
|
|
|
+ #ifdef USEIRRADIANCEMAP
|
|
|
+ #ifdef REFLECTIONMAP_3D
|
|
|
+ const in samplerCube irradianceSampler,
|
|
|
+ #else
|
|
|
+ const in sampler2D irradianceSampler,
|
|
|
+ #endif
|
|
|
+ #endif
|
|
|
+ #endif
|
|
|
+ #endif
|
|
|
+ #ifdef SS_REFRACTION
|
|
|
+ const in vec3 vPositionW,
|
|
|
+ const in vec3 viewDirectionW,
|
|
|
+ const in mat4 view,
|
|
|
+ const in vec3 surfaceAlbedo,
|
|
|
+ const in vec4 vRefractionInfos,
|
|
|
+ const in mat4 refractionMatrix,
|
|
|
+ const in vec3 vRefractionMicrosurfaceInfos,
|
|
|
+ const in vec4 vLightingIntensity,
|
|
|
+ #ifdef SS_LINKREFRACTIONTOTRANSPARENCY
|
|
|
+ const in float alpha,
|
|
|
+ #endif
|
|
|
+ #ifdef SS_LODINREFRACTIONALPHA
|
|
|
+ const in float NdotVUnclamped,
|
|
|
+ #endif
|
|
|
+ #ifdef SS_LINEARSPECULARREFRACTION
|
|
|
+ const in float roughness,
|
|
|
+ #else
|
|
|
+ const in float alphaG,
|
|
|
+ #endif
|
|
|
+ #ifdef SS_REFRACTIONMAP_3D
|
|
|
+ const in samplerCube refractionSampler,
|
|
|
+ #ifndef LODBASEDMICROSFURACE
|
|
|
+ const in samplerCube refractionSamplerLow,
|
|
|
+ const in samplerCube refractionSamplerHigh,
|
|
|
+ #endif
|
|
|
+ #else
|
|
|
+ const in sampler2D refractionSampler,
|
|
|
+ #ifndef LODBASEDMICROSFURACE
|
|
|
+ const in sampler2D refractionSamplerLow,
|
|
|
+ const in sampler2D refractionSamplerHigh,
|
|
|
+ #endif
|
|
|
+ #endif
|
|
|
+ #ifdef ANISOTROPIC
|
|
|
+ const in anisotropicOutParams anisotropicOut,
|
|
|
+ #endif
|
|
|
+ #endif
|
|
|
+ #ifdef SS_TRANSLUCENCY
|
|
|
+ const in vec3 vDiffusionDistance,
|
|
|
+ #endif
|
|
|
+ out subSurfaceOutParams outParams
|
|
|
+ )
|
|
|
+ {
|
|
|
+ outParams.specularEnvironmentReflectance = specularEnvironmentReflectance;
|
|
|
+
|
|
|
+ // ______________________________________________________________________________________
|
|
|
+ // _____________________________ Intensities & thickness ________________________________
|
|
|
+ // ______________________________________________________________________________________
|
|
|
+ #ifdef SS_REFRACTION
|
|
|
+ float refractionIntensity = vSubSurfaceIntensity.x;
|
|
|
+ #ifdef SS_LINKREFRACTIONTOTRANSPARENCY
|
|
|
+ refractionIntensity *= (1.0 - alpha);
|
|
|
+ // Put alpha back to 1;
|
|
|
+ outParams.alpha = 1.0;
|
|
|
+ #endif
|
|
|
+ #endif
|
|
|
+ #ifdef SS_TRANSLUCENCY
|
|
|
+ float translucencyIntensity = vSubSurfaceIntensity.y;
|
|
|
+ #endif
|
|
|
+ #ifdef SS_SCATTERING
|
|
|
+ float scatteringIntensity = vSubSurfaceIntensity.z;
|
|
|
+ #endif
|
|
|
+
|
|
|
+ #ifdef SS_THICKNESSANDMASK_TEXTURE
|
|
|
+ vec4 thicknessMap = texture2D(thicknessSampler, vThicknessUV + uvOffset);
|
|
|
+ float thickness = thicknessMap.r * vThicknessParam.y + vThicknessParam.x;
|
|
|
+
|
|
|
+ #if DEBUGMODE > 0
|
|
|
+ outParams.thicknessMap = thicknessMap;
|
|
|
+ #endif
|
|
|
+
|
|
|
+ #ifdef SS_MASK_FROM_THICKNESS_TEXTURE
|
|
|
+ #ifdef SS_REFRACTION
|
|
|
+ refractionIntensity *= thicknessMap.g;
|
|
|
+ #endif
|
|
|
+ #ifdef SS_TRANSLUCENCY
|
|
|
+ translucencyIntensity *= thicknessMap.b;
|
|
|
+ #endif
|
|
|
+ #ifdef SS_SCATTERING
|
|
|
+ scatteringIntensity *= thicknessMap.a;
|
|
|
+ #endif
|
|
|
+ #endif
|
|
|
+ #else
|
|
|
+ float thickness = vThicknessParam.y;
|
|
|
+ #endif
|
|
|
+
|
|
|
+ // _________________________________________________________________________________________
|
|
|
+ // _____________________________ Translucency transmittance ________________________________
|
|
|
+ // _________________________________________________________________________________________
|
|
|
+ #ifdef SS_TRANSLUCENCY
|
|
|
+ thickness = maxEps(thickness);
|
|
|
+ vec3 transmittance = transmittanceBRDF_Burley(vTintColor.rgb, vDiffusionDistance, thickness);
|
|
|
+ transmittance *= translucencyIntensity;
|
|
|
+ outParams.transmittance = transmittance;
|
|
|
+ #endif
|
|
|
+
|
|
|
+ // _____________________________________________________________________________________
|
|
|
+ // _____________________________ Refraction environment ________________________________
|
|
|
+ // _____________________________________________________________________________________
|
|
|
+ #ifdef SS_REFRACTION
|
|
|
+ vec4 environmentRefraction = vec4(0., 0., 0., 0.);
|
|
|
+
|
|
|
+ #ifdef ANISOTROPIC
|
|
|
+ vec3 refractionVector = refract(-viewDirectionW, anisotropicOut.anisotropicNormal, vRefractionInfos.y);
|
|
|
+ #else
|
|
|
+ vec3 refractionVector = refract(-viewDirectionW, normalW, vRefractionInfos.y);
|
|
|
+ #endif
|
|
|
+
|
|
|
+ #ifdef SS_REFRACTIONMAP_OPPOSITEZ
|
|
|
+ refractionVector.z *= -1.0;
|
|
|
+ #endif
|
|
|
+
|
|
|
+ // _____________________________ 2D vs 3D Maps ________________________________
|
|
|
+ #ifdef SS_REFRACTIONMAP_3D
|
|
|
+ refractionVector.y = refractionVector.y * vRefractionInfos.w;
|
|
|
+ vec3 refractionCoords = refractionVector;
|
|
|
+ refractionCoords = vec3(refractionMatrix * vec4(refractionCoords, 0));
|
|
|
+ #else
|
|
|
+ vec3 vRefractionUVW = vec3(refractionMatrix * (view * vec4(vPositionW + refractionVector * vRefractionInfos.z, 1.0)));
|
|
|
+ vec2 refractionCoords = vRefractionUVW.xy / vRefractionUVW.z;
|
|
|
+ refractionCoords.y = 1.0 - refractionCoords.y;
|
|
|
+ #endif
|
|
|
+
|
|
|
+ #ifdef SS_LODINREFRACTIONALPHA
|
|
|
+ float refractionLOD = getLodFromAlphaG(vRefractionMicrosurfaceInfos.x, alphaG, NdotVUnclamped);
|
|
|
+ #elif defined(SS_LINEARSPECULARREFRACTION)
|
|
|
+ float refractionLOD = getLinearLodFromRoughness(vRefractionMicrosurfaceInfos.x, roughness);
|
|
|
+ #else
|
|
|
+ float refractionLOD = getLodFromAlphaG(vRefractionMicrosurfaceInfos.x, alphaG);
|
|
|
+ #endif
|
|
|
+
|
|
|
+ #ifdef LODBASEDMICROSFURACE
|
|
|
+ // Apply environment convolution scale/offset filter tuning parameters to the mipmap LOD selection
|
|
|
+ refractionLOD = refractionLOD * vRefractionMicrosurfaceInfos.y + vRefractionMicrosurfaceInfos.z;
|
|
|
+
|
|
|
+ #ifdef SS_LODINREFRACTIONALPHA
|
|
|
+ // Automatic LOD adjustment to ensure that the smoothness-based environment LOD selection
|
|
|
+ // is constrained to appropriate LOD levels in order to prevent aliasing.
|
|
|
+ // The environment map is first sampled without custom LOD selection to determine
|
|
|
+ // the hardware-selected LOD, and this is then used to constrain the final LOD selection
|
|
|
+ // so that excessive surface smoothness does not cause aliasing (e.g. on curved geometry
|
|
|
+ // where the normal is varying rapidly).
|
|
|
+
|
|
|
+ // Note: Shader Model 4.1 or higher can provide this directly via CalculateLevelOfDetail(), and
|
|
|
+ // manual calculation via derivatives is also possible, but for simplicity we use the
|
|
|
+ // hardware LOD calculation with the alpha channel containing the LOD for each mipmap.
|
|
|
+ float automaticRefractionLOD = UNPACK_LOD(sampleRefraction(refractionSampler, refractionCoords).a);
|
|
|
+ float requestedRefractionLOD = max(automaticRefractionLOD, refractionLOD);
|
|
|
+ #else
|
|
|
+ float requestedRefractionLOD = refractionLOD;
|
|
|
+ #endif
|
|
|
+
|
|
|
+ environmentRefraction = sampleRefractionLod(refractionSampler, refractionCoords, requestedRefractionLOD);
|
|
|
+ #else
|
|
|
+ float lodRefractionNormalized = saturate(refractionLOD / log2(vRefractionMicrosurfaceInfos.x));
|
|
|
+ float lodRefractionNormalizedDoubled = lodRefractionNormalized * 2.0;
|
|
|
+
|
|
|
+ vec4 environmentRefractionMid = sampleRefraction(refractionSampler, refractionCoords);
|
|
|
+ if (lodRefractionNormalizedDoubled < 1.0){
|
|
|
+ environmentRefraction = mix(
|
|
|
+ sampleRefraction(refractionSamplerHigh, refractionCoords),
|
|
|
+ environmentRefractionMid,
|
|
|
+ lodRefractionNormalizedDoubled
|
|
|
+ );
|
|
|
+ } else {
|
|
|
+ environmentRefraction = mix(
|
|
|
+ environmentRefractionMid,
|
|
|
+ sampleRefraction(refractionSamplerLow, refractionCoords),
|
|
|
+ lodRefractionNormalizedDoubled - 1.0
|
|
|
+ );
|
|
|
+ }
|
|
|
+ #endif
|
|
|
+
|
|
|
+ #ifdef SS_RGBDREFRACTION
|
|
|
+ environmentRefraction.rgb = fromRGBD(environmentRefraction);
|
|
|
+ #endif
|
|
|
+
|
|
|
+ #ifdef SS_GAMMAREFRACTION
|
|
|
+ environmentRefraction.rgb = toLinearSpace(environmentRefraction.rgb);
|
|
|
+ #endif
|
|
|
+
|
|
|
+ // _____________________________ Levels _____________________________________
|
|
|
+ environmentRefraction.rgb *= vRefractionInfos.x;
|
|
|
+ #endif
|
|
|
+
|
|
|
+ // _______________________________________________________________________________
|
|
|
+ // _____________________________ Final Refraction ________________________________
|
|
|
+ // _______________________________________________________________________________
|
|
|
+ #ifdef SS_REFRACTION
|
|
|
+ vec3 refractionTransmittance = vec3(refractionIntensity);
|
|
|
+ #ifdef SS_THICKNESSANDMASK_TEXTURE
|
|
|
+ vec3 volumeAlbedo = computeColorAtDistanceInMedia(vTintColor.rgb, vTintColor.w);
|
|
|
+
|
|
|
+ // // Simulate Flat Surface
|
|
|
+ // thickness /= dot(refractionVector, -normalW);
|
|
|
+
|
|
|
+ // // Simulate Curved Surface
|
|
|
+ // float NdotRefract = dot(normalW, refractionVector);
|
|
|
+ // thickness *= -NdotRefract;
|
|
|
+
|
|
|
+ refractionTransmittance *= cocaLambert(volumeAlbedo, thickness);
|
|
|
+ #elif defined(SS_LINKREFRACTIONTOTRANSPARENCY)
|
|
|
+ // Tint the material with albedo.
|
|
|
+ float maxChannel = max(max(surfaceAlbedo.r, surfaceAlbedo.g), surfaceAlbedo.b);
|
|
|
+ vec3 volumeAlbedo = saturate(maxChannel * surfaceAlbedo);
|
|
|
+
|
|
|
+ // Tint reflectance
|
|
|
+ environmentRefraction.rgb *= volumeAlbedo;
|
|
|
+ #else
|
|
|
+ // Compute tint from min distance only.
|
|
|
+ vec3 volumeAlbedo = computeColorAtDistanceInMedia(vTintColor.rgb, vTintColor.w);
|
|
|
+ refractionTransmittance *= cocaLambert(volumeAlbedo, vThicknessParam.y);
|
|
|
+ #endif
|
|
|
+
|
|
|
+ // Decrease Albedo Contribution
|
|
|
+ outParams.surfaceAlbedo = surfaceAlbedo * (1. - refractionIntensity);
|
|
|
+
|
|
|
+ #ifdef REFLECTION
|
|
|
+ // Decrease irradiance Contribution
|
|
|
+ outParams.refractionFactorForIrradiance = (1. - refractionIntensity);
|
|
|
+ //environmentIrradiance *= (1. - refractionIntensity);
|
|
|
+ #endif
|
|
|
+
|
|
|
+ // Add Multiple internal bounces.
|
|
|
+ vec3 bounceSpecularEnvironmentReflectance = (2.0 * specularEnvironmentReflectance) / (1.0 + specularEnvironmentReflectance);
|
|
|
+ outParams.specularEnvironmentReflectance = mix(bounceSpecularEnvironmentReflectance, specularEnvironmentReflectance, refractionIntensity);
|
|
|
+
|
|
|
+ // In theory T = 1 - R.
|
|
|
+ refractionTransmittance *= 1.0 - outParams.specularEnvironmentReflectance;
|
|
|
+
|
|
|
+ #if DEBUGMODE > 0
|
|
|
+ outParams.refractionTransmittance = refractionTransmittance;
|
|
|
+ #endif
|
|
|
+
|
|
|
+ outParams.finalRefraction = environmentRefraction.rgb * refractionTransmittance * vLightingIntensity.z;
|
|
|
+
|
|
|
+ #if DEBUGMODE > 0
|
|
|
+ outParams.environmentRefraction = environmentRefraction;
|
|
|
+ #endif
|
|
|
+ #endif
|
|
|
+
|
|
|
+ // __________________________________________________________________________________
|
|
|
+ // _______________________________ IBL Translucency ________________________________
|
|
|
+ // __________________________________________________________________________________
|
|
|
+ #if defined(REFLECTION) && defined(SS_TRANSLUCENCY)
|
|
|
+ #if defined(NORMAL) && defined(USESPHERICALINVERTEX) || !defined(USESPHERICALFROMREFLECTIONMAP)
|
|
|
+ vec3 irradianceVector = vec3(reflectionMatrix * vec4(normalW, 0)).xyz;
|
|
|
+ #ifdef REFLECTIONMAP_OPPOSITEZ
|
|
|
+ irradianceVector.z *= -1.0;
|
|
|
+ #endif
|
|
|
+ #else
|
|
|
+ vec3 irradianceVector = irradianceVector_;
|
|
|
+ #endif
|
|
|
+
|
|
|
+ #if defined(USESPHERICALFROMREFLECTIONMAP)
|
|
|
+ vec3 refractionIrradiance = computeEnvironmentIrradiance(-irradianceVector);
|
|
|
+ #elif defined(USEIRRADIANCEMAP)
|
|
|
+ #ifdef REFLECTIONMAP_3D
|
|
|
+ vec3 irradianceCoords = irradianceVector;
|
|
|
+ #else
|
|
|
+ vec2 irradianceCoords = irradianceVector.xy;
|
|
|
+ #ifdef REFLECTIONMAP_PROJECTION
|
|
|
+ irradianceCoords /= irradianceVector.z;
|
|
|
+ #endif
|
|
|
+ irradianceCoords.y = 1.0 - irradianceCoords.y;
|
|
|
+ #endif
|
|
|
+
|
|
|
+ vec4 refractionIrradiance = sampleReflection(irradianceSampler, -irradianceCoords);
|
|
|
+ #ifdef RGBDREFLECTION
|
|
|
+ refractionIrradiance.rgb = fromRGBD(refractionIrradiance);
|
|
|
+ #endif
|
|
|
+
|
|
|
+ #ifdef GAMMAREFLECTION
|
|
|
+ refractionIrradiance.rgb = toLinearSpace(refractionIrradiance.rgb);
|
|
|
+ #endif
|
|
|
+ #else
|
|
|
+ vec4 refractionIrradiance = vec4(0.);
|
|
|
+ #endif
|
|
|
+
|
|
|
+ refractionIrradiance.rgb *= transmittance;
|
|
|
+ outParams.refractionIrradiance = refractionIrradiance.rgb;
|
|
|
+ #endif
|
|
|
+ }
|
|
|
+#endif
|
|
|
+
|