| const vertexShaderWSL1 = ` |
| struct Output { |
| float3 vPositionW : attribute(0); |
| float3 vNormalW : attribute(1); |
| float2 vMainUV1 : attribute(2); |
| float4 position : SV_Position; |
| } |
| |
| struct Scene { |
| float4x4 viewProjection; |
| float4x4 view; |
| } |
| |
| struct Material { |
| float2 vAlbedoInfos; |
| float4 vAmbientInfos; |
| float2 vOpacityInfos; |
| float2 vEmissiveInfos; |
| float2 vLightmapInfos; |
| float3 vReflectivityInfos; |
| float2 vMicroSurfaceSamplerInfos; |
| float2 vReflectionInfos; |
| float3 vReflectionPosition; |
| float3 vReflectionSize; |
| float3 vBumpInfos; |
| float4x4 albedoMatrix; |
| float4x4 ambientMatrix; |
| float4x4 opacityMatrix; |
| float4x4 emissiveMatrix; |
| float4x4 lightmapMatrix; |
| float4x4 reflectivityMatrix; |
| float4x4 microSurfaceSamplerMatrix; |
| float4x4 bumpMatrix; |
| float2 vTangentSpaceParams; |
| float4x4 reflectionMatrix; |
| float3 vReflectionColor; |
| float4 vAlbedoColor; |
| float4 vLightingIntensity; |
| float3 vReflectionMicrosurfaceInfos; |
| float pointSize; |
| float4 vReflectivityColor; |
| float3 vEmissiveColor; |
| float4 vEyePosition; |
| float3 vAmbientColor; |
| float2 vDebugMode; |
| float2 vClearCoatParams; |
| float4 vClearCoatRefractionParams; |
| float2 vClearCoatInfos; |
| float4x4 clearCoatMatrix; |
| float2 vClearCoatBumpInfos; |
| float2 vClearCoatTangentSpaceParams; |
| float4x4 clearCoatBumpMatrix; |
| float4 vClearCoatTintParams; |
| float clearCoatColorAtDistance; |
| float2 vClearCoatTintInfos; |
| float4x4 clearCoatTintMatrix; |
| float3 vAnisotropy; |
| float2 vAnisotropyInfos; |
| float4x4 anisotropyMatrix; |
| float4 vSheenColor; |
| float2 vSheenInfos; |
| float4x4 sheenMatrix; |
| float3 vRefractionMicrosurfaceInfos; |
| float4 vRefractionInfos; |
| float4x4 refractionMatrix; |
| float2 vThicknessInfos; |
| float4x4 thicknessMatrix; |
| float2 vThicknessParam; |
| float3 vDiffusionDistance; |
| float4 vTintColor; |
| float3 vSubSurfaceIntensity; |
| float3 vSphericalL00; |
| float3 vSphericalL1_1; |
| float3 vSphericalL10; |
| float3 vSphericalL11; |
| float3 vSphericalL2_2; |
| float3 vSphericalL2_1; |
| float3 vSphericalL20; |
| float3 vSphericalL21; |
| float3 vSphericalL22; |
| float3 vSphericalX; |
| float3 vSphericalY; |
| float3 vSphericalZ; |
| float3 vSphericalXX_ZZ; |
| float3 vSphericalYY_ZZ; |
| float3 vSphericalZZ; |
| float3 vSphericalXY; |
| float3 vSphericalYZ; |
| float3 vSphericalZX; |
| } |
| |
| struct Mesh { |
| float4x4 world; |
| float visibility; |
| } |
| |
| float3x3 transposeMat3(float3x3 inMatrix) { |
| float3 i0 = inMatrix[0]; |
| float3 i1 = inMatrix[1]; |
| float3 i2 = inMatrix[2]; |
| float3x3 outMatrix = float3x3( |
| float3(i0.x, i1.x, i2.x), |
| float3(i0.y, i1.y, i2.y), |
| float3(i0.z, i1.z, i2.z) |
| ); |
| return outMatrix; |
| } |
| |
| float3x3 inverseMat3(float3x3 inMatrix) { |
| float a00 = inMatrix[0][0], a01 = inMatrix[0][1], a02 = inMatrix[0][2]; |
| float a10 = inMatrix[1][0], a11 = inMatrix[1][1], a12 = inMatrix[1][2]; |
| float a20 = inMatrix[2][0], a21 = inMatrix[2][1], a22 = inMatrix[2][2]; |
| float b01 = a22 * a11 - a12 * a21; |
| float b11 = -a22 * a10 + a12 * a20; |
| float b21 = a21 * a10 - a11 * a20; |
| float det = a00 * b01 + a01 * b11 + a02 * b21; |
| return float3x3(b01, -a22 * a01 + a02 * a21, a12 * a01 - a02 * a11, |
| b11, a22 * a00 - a02 * a20, -a12 * a00 + a02 * a10, |
| b21, -a21 * a00 + a01 * a20, a11 * a00 - a01 * a10) / det; |
| } |
| |
| float3 toLinearSpace(float3 color) { |
| return pow(color, float3(2.2, 2.2, 2.2)); |
| } |
| |
| float3 toGammaSpace(float3 color) { |
| return pow(color, float3(1.0 / 2.2, 1.0 / 2.2, 1.0 / 2.2)); |
| } |
| |
| float square(float value) { |
| return value * value; |
| } |
| |
| float pow5(float value) { |
| float sq = value * value; |
| return sq * sq * value; |
| } |
| |
| float getLuminance(float3 color) { |
| return clamp(dot(color, float3(0.2126, 0.7152, 0.0722)), 0., 1.); |
| } |
| |
| float getRand(float2 seed) { |
| return frac(sin(dot(seed.xy, float2(12.9898, 78.233))) * 43758.5453); |
| } |
| |
| float dither(float2 seed, float varianceAmount) { |
| float rand = getRand(seed); |
| float dither = lerp(-varianceAmount / 255.0, varianceAmount / 255.0, rand); |
| return dither; |
| } |
| |
| float4 toRGBD(float3 color) { |
| float maxRGB = max(max(color.x, max(color.y, color.z)), 0.0000001); |
| float D = max(255.0 / maxRGB, 1.); |
| D = clamp(floor(D) / 255.0, 0., 1.); |
| float3 rgb = color * D; |
| rgb = toGammaSpace(rgb); |
| return float4(rgb, D); |
| } |
| |
| float3 fromRGBD(float4 rgbd) { |
| rgbd.xyz = toLinearSpace(rgbd.xyz); |
| return rgbd.xyz / rgbd.w; |
| } |
| |
| vertex Output main(float3 position : attribute(0), float3 normal : attribute(1), float2 uv : attribute(2), |
| constant Scene[] scene : register(b0, space0), |
| Texture2D<float4> environmentBrdfSamplerTexture : register(t1, space0), |
| sampler environmentBrdfSamplerSampler : register(s2, space0), |
| constant Material[] material : register(b0, space1), |
| constant Mesh[] mesh : register(b1, space1), |
| Texture2D<float4> reflectionSamplerTexture : register(t0, space2), |
| sampler reflectionSamplerSampler : register(s1, space2), |
| Texture2D<float4> albedoSamplerTexture : register(t2, space2), |
| sampler albedoSamplerSampler : register(s3, space2), |
| Texture2D<float4> reflectivitySamplerTexture : register(t4, space2), |
| sampler reflectivitySamplerSampler : register(s5, space2), |
| Texture2D<float4> ambientSamplerTexture : register(t6, space2), |
| sampler ambientSamplerSampler : register(s7, space2), |
| Texture2D<float4> emissiveSamplerTexture : register(t8, space2), |
| sampler emissiveSamplerSampler : register(s9, space2), |
| Texture2D<float4> bumpSamplerTexture : register(t10, space2), |
| sampler bumpSamplerSampler : register(s11, space2)) { |
| Output output; |
| float3 positionUpdated = position; |
| float3 normalUpdated = normal; |
| float2 uvUpdated = uv; |
| float4x4 finalWorld = mesh[0].world; |
| output.position = mul(mul(scene[0].viewProjection, finalWorld), float4(positionUpdated, 1.0)); |
| float4 worldPos = mul(finalWorld, float4(positionUpdated, 1.0)); |
| output.vPositionW = worldPos.xyz; |
| float3x3 normalWorld; |
| normalWorld[0] = finalWorld[0].xyz; |
| normalWorld[1] = finalWorld[1].xyz; |
| normalWorld[2] = finalWorld[2].xyz; |
| output.vNormalW = normalize(mul(normalWorld, normalUpdated)); |
| float2 uv2 = float2(0., 0.); |
| output.vMainUV1 = uvUpdated; |
| return output; |
| } |
| `; |
| |
| const fragmentShaderWSL1 = ` |
| struct Scene { |
| float4x4 viewProjection; |
| float4x4 view; |
| } |
| |
| struct Material { |
| float2 vAlbedoInfos; |
| float4 vAmbientInfos; |
| float2 vOpacityInfos; |
| float2 vEmissiveInfos; |
| float2 vLightmapInfos; |
| float3 vReflectivityInfos; |
| float2 vMicroSurfaceSamplerInfos; |
| float2 vReflectionInfos; |
| float3 vReflectionPosition; |
| float3 vReflectionSize; |
| float3 vBumpInfos; |
| float4x4 albedoMatrix; |
| float4x4 ambientMatrix; |
| float4x4 opacityMatrix; |
| float4x4 emissiveMatrix; |
| float4x4 lightmapMatrix; |
| float4x4 reflectivityMatrix; |
| float4x4 microSurfaceSamplerMatrix; |
| float4x4 bumpMatrix; |
| float2 vTangentSpaceParams; |
| float4x4 reflectionMatrix; |
| float3 vReflectionColor; |
| float4 vAlbedoColor; |
| float4 vLightingIntensity; |
| float3 vReflectionMicrosurfaceInfos; |
| float pointSize; |
| float4 vReflectivityColor; |
| float3 vEmissiveColor; |
| float4 vEyePosition; |
| float3 vAmbientColor; |
| float2 vDebugMode; |
| float2 vClearCoatParams; |
| float4 vClearCoatRefractionParams; |
| float2 vClearCoatInfos; |
| float4x4 clearCoatMatrix; |
| float2 vClearCoatBumpInfos; |
| float2 vClearCoatTangentSpaceParams; |
| float4x4 clearCoatBumpMatrix; |
| float4 vClearCoatTintParams; |
| float clearCoatColorAtDistance; |
| float2 vClearCoatTintInfos; |
| float4x4 clearCoatTintMatrix; |
| float3 vAnisotropy; |
| float2 vAnisotropyInfos; |
| float4x4 anisotropyMatrix; |
| float4 vSheenColor; |
| float2 vSheenInfos; |
| float4x4 sheenMatrix; |
| float3 vRefractionMicrosurfaceInfos; |
| float4 vRefractionInfos; |
| float4x4 refractionMatrix; |
| float2 vThicknessInfos; |
| float4x4 thicknessMatrix; |
| float2 vThicknessParam; |
| float3 vDiffusionDistance; |
| float4 vTintColor; |
| float3 vSubSurfaceIntensity; |
| float3 vSphericalL00; |
| float3 vSphericalL1_1; |
| float3 vSphericalL10; |
| float3 vSphericalL11; |
| float3 vSphericalL2_2; |
| float3 vSphericalL2_1; |
| float3 vSphericalL20; |
| float3 vSphericalL21; |
| float3 vSphericalL22; |
| float3 vSphericalX; |
| float3 vSphericalY; |
| float3 vSphericalZ; |
| float3 vSphericalXX_ZZ; |
| float3 vSphericalYY_ZZ; |
| float3 vSphericalZZ; |
| float3 vSphericalXY; |
| float3 vSphericalYZ; |
| float3 vSphericalZX; |
| } |
| |
| struct Mesh { |
| float4x4 world; |
| float visibility; |
| } |
| |
| float3x3 transposeMat3(float3x3 inMatrix) { |
| float3 i0 = inMatrix[0]; |
| float3 i1 = inMatrix[1]; |
| float3 i2 = inMatrix[2]; |
| float3x3 outMatrix = float3x3( |
| float3(i0.x, i1.x, i2.x), |
| float3(i0.y, i1.y, i2.y), |
| float3(i0.z, i1.z, i2.z) |
| ); |
| return outMatrix; |
| } |
| |
| float3x3 inverseMat3(float3x3 inMatrix) { |
| float a00 = inMatrix[0][0], a01 = inMatrix[0][1], a02 = inMatrix[0][2]; |
| float a10 = inMatrix[1][0], a11 = inMatrix[1][1], a12 = inMatrix[1][2]; |
| float a20 = inMatrix[2][0], a21 = inMatrix[2][1], a22 = inMatrix[2][2]; |
| float b01 = a22 * a11 - a12 * a21; |
| float b11 = -a22 * a10 + a12 * a20; |
| float b21 = a21 * a10 - a11 * a20; |
| float det = a00 * b01 + a01 * b11 + a02 * b21; |
| return float3x3(b01, -a22 * a01 + a02 * a21, a12 * a01 - a02 * a11, |
| b11, a22 * a00 - a02 * a20, -a12 * a00 + a02 * a10, |
| b21, -a21 * a00 + a01 * a20, a11 * a00 - a01 * a10) / det; |
| } |
| |
| float3 toLinearSpace(float3 color) { |
| return pow(color, float3(2.2, 2.2, 2.2)); |
| } |
| |
| float3 toGammaSpace(float3 color) { |
| return pow(color, float3(1.0 / 2.2, 1.0 / 2.2, 1.0 / 2.2)); |
| } |
| |
| float square(float value) { |
| return value * value; |
| } |
| |
| float pow5(float value) { |
| float sq = value * value; |
| return sq * sq * value; |
| } |
| |
| float getLuminance(float3 color) { |
| return clamp(dot(color, float3(0.2126, 0.7152, 0.0722)), 0., 1.); |
| } |
| |
| float getRand(float2 seed) { |
| return frac(sin(dot(seed.xy, float2(12.9898, 78.233))) * 43758.5453); |
| } |
| |
| float dither(float2 seed, float varianceAmount) { |
| float rand = getRand(seed); |
| float dither = lerp(-varianceAmount / 255.0, varianceAmount / 255.0, rand); |
| return dither; |
| } |
| |
| float4 toRGBD(float3 color) { |
| float maxRGB = max(max(color.x, max(color.y, color.z)), 0.0000001); |
| float D = max(255.0 / maxRGB, 1.); |
| D = clamp(floor(D) / 255.0, 0., 1.); |
| float3 rgb = color * D; |
| rgb = toGammaSpace(rgb); |
| return float4(rgb, D); |
| } |
| |
| float3 fromRGBD(float4 rgbd) { |
| rgbd.xyz = toLinearSpace(rgbd.xyz); |
| return rgbd.xyz / rgbd.w; |
| } |
| |
| float convertRoughnessToAverageSlope(float roughness) { |
| return square(roughness) + 0.0005; |
| } |
| |
| float fresnelGrazingReflectance(float reflectance0) { |
| float reflectance90 = clamp(reflectance0 * 25.0, 0.0, 1.0); |
| return reflectance90; |
| } |
| |
| float2 getAARoughnessFactors(float3 normalVector) { |
| return float2(0., 0.); |
| } |
| |
| float4 applyImageProcessing(float4 result) { |
| result.xyz = toGammaSpace(result.xyz); |
| result.xyz = clamp(result.xyz, float3(0.0, 0.0, 0.0), float3(1.0, 1.0, 1.0)); |
| return result; |
| } |
| |
| float3 computeEnvironmentIrradiance(float3 normal, constant Material* material) { |
| return material->vSphericalL00 |
| + material->vSphericalL1_1 * (normal.y) |
| + material->vSphericalL10 * (normal.z) |
| + material->vSphericalL11 * (normal.x) |
| + material->vSphericalL2_2 * (normal.y * normal.x) |
| + material->vSphericalL2_1 * (normal.y * normal.z) |
| + material->vSphericalL20 * ((3.0 * normal.z * normal.z) - 1.0) |
| + material->vSphericalL21 * (normal.z * normal.x) |
| + material->vSphericalL22 * (normal.x * normal.x - (normal.y * normal.y)); |
| } |
| |
| struct PreLightingInfo { |
| float3 lightOffset; |
| float lightDistanceSquared; |
| float lightDistance; |
| float attenuation; |
| float3 L; |
| float3 H; |
| float NdotV; |
| float NdotLUnclamped; |
| float NdotL; |
| float VdotH; |
| float roughness; |
| } |
| |
| PreLightingInfo computePointAndSpotPreLightingInfo(float4 lightData, float3 V, float3 N, float3 vPositionW) { |
| PreLightingInfo result; |
| result.lightOffset = lightData.xyz - vPositionW; |
| result.lightDistanceSquared = dot(result.lightOffset, result.lightOffset); |
| result.lightDistance = sqrt(result.lightDistanceSquared); |
| result.L = normalize(result.lightOffset); |
| result.H = normalize(V + result.L); |
| result.VdotH = clamp(dot(V, result.H), 0.0, 1.0); |
| result.NdotLUnclamped = dot(N, result.L); |
| result.NdotL = clamp(result.NdotLUnclamped, 0.0000001, 1.0); |
| return result; |
| } |
| |
| PreLightingInfo computeDirectionalPreLightingInfo(float4 lightData, float3 V, float3 N) { |
| PreLightingInfo result; |
| result.lightDistance = length(-lightData.xyz); |
| result.L = normalize(-lightData.xyz); |
| result.H = normalize(V + result.L); |
| result.VdotH = clamp(dot(V, result.H), 0.0, 1.0); |
| result.NdotLUnclamped = dot(N, result.L); |
| result.NdotL = clamp(result.NdotLUnclamped, 0.0000001, 1.0); |
| return result; |
| } |
| |
| PreLightingInfo computeHemisphericPreLightingInfo(float4 lightData, float3 V, float3 N) { |
| PreLightingInfo result; |
| result.NdotL = dot(N, lightData.xyz) * 0.5 + 0.5; |
| result.NdotL = clamp(result.NdotL, 0.0000001, 1.0); |
| result.NdotLUnclamped = result.NdotL; |
| return result; |
| } |
| |
| float computeDistanceLightFalloff_Standard(float3 lightOffset, float range) { |
| return max(0., 1.0 - length(lightOffset) / range); |
| } |
| |
| float computeDistanceLightFalloff_Physical(float lightDistanceSquared) { |
| return 1.0 / max(lightDistanceSquared, 0.0000001); |
| } |
| |
| float computeDistanceLightFalloff_GLTF(float lightDistanceSquared, float inverseSquaredRange) { |
| float lightDistanceFalloff = 1.0 / max(lightDistanceSquared, 0.0000001); |
| float factor = lightDistanceSquared * inverseSquaredRange; |
| float attenuation = clamp(1.0 - factor * factor, 0.0, 1.0); |
| attenuation *= attenuation; |
| lightDistanceFalloff *= attenuation; |
| return lightDistanceFalloff; |
| } |
| |
| float computeDistanceLightFalloff(float3 lightOffset, float lightDistanceSquared, float range, float inverseSquaredRange) { |
| return computeDistanceLightFalloff_Physical(lightDistanceSquared); |
| } |
| |
| float computeDirectionalLightFalloff_Standard(float3 lightDirection, float3 directionToLightCenterW, float cosHalfAngle, float exponent) { |
| float falloff = 0.0; |
| float cosAngle = max(dot(-lightDirection, directionToLightCenterW), 0.0000001); |
| if (cosAngle >= cosHalfAngle) { |
| falloff = max(0., pow(cosAngle, exponent)); |
| } |
| return falloff; |
| } |
| |
| float computeDirectionalLightFalloff_Physical(float3 lightDirection, float3 directionToLightCenterW, float cosHalfAngle) { |
| float kMinusLog2ConeAngleIntensityRatio = 6.64385618977; |
| float concentrationKappa = kMinusLog2ConeAngleIntensityRatio / (1.0 - cosHalfAngle); |
| float4 lightDirectionSpreadSG = float4(-lightDirection * concentrationKappa, -concentrationKappa); |
| float falloff = exp2(dot(float4(directionToLightCenterW, 1.0), lightDirectionSpreadSG)); |
| return falloff; |
| } |
| |
| float computeDirectionalLightFalloff_GLTF(float3 lightDirection, float3 directionToLightCenterW, float lightAngleScale, float lightAngleOffset) { |
| float cd = dot(-lightDirection, directionToLightCenterW); |
| float falloff = clamp(cd * lightAngleScale + lightAngleOffset, 0.0, 1.0); |
| falloff *= falloff; |
| return falloff; |
| } |
| |
| float computeDirectionalLightFalloff(float3 lightDirection, float3 directionToLightCenterW, float cosHalfAngle, float exponent, float lightAngleScale, float lightAngleOffset) { |
| return computeDirectionalLightFalloff_Physical(lightDirection, directionToLightCenterW, cosHalfAngle); |
| } |
| |
| float3 getEnergyConservationFactor(float3 specularEnvironmentR0, float3 environmentBrdf) { |
| return float3(1.0, 1.0, 1.0) + specularEnvironmentR0 * (1.0 / environmentBrdf.y - 1.0); |
| } |
| |
| float3 getBRDFLookup(float NdotV, float perceptualRoughness, Texture2D<float4> environmentBrdfSamplerTexture, sampler environmentBrdfSamplerSampler) { |
| float2 UV = float2(NdotV, perceptualRoughness); |
| float4 brdfLookup = Sample(environmentBrdfSamplerTexture, environmentBrdfSamplerSampler, UV); |
| return brdfLookup.xyz; |
| } |
| |
| float3 getReflectanceFromBRDFLookup(float3 specularEnvironmentR0, float3 environmentBrdf) { |
| float3 reflectance = lerp(environmentBrdf.xxx, environmentBrdf.yyy, specularEnvironmentR0); |
| return reflectance; |
| } |
| |
| float3 fresnelSchlickGGX(float VdotH, float3 reflectance0, float3 reflectance90) { |
| return reflectance0 + (reflectance90 - reflectance0) * pow5(1.0 - VdotH); |
| } |
| |
| float fresnelSchlickGGX(float VdotH, float reflectance0, float reflectance90) { |
| return reflectance0 + (reflectance90 - reflectance0) * pow5(1.0 - VdotH); |
| } |
| |
| float normalDistributionFunction_TrowbridgeReitzGGX(float NdotH, float alphaG) { |
| float a2 = square(alphaG); |
| float d = NdotH * NdotH * (a2 - 1.0) + 1.0; |
| return a2 / (3.1415926535897932384626433832795 * d * d); |
| } |
| |
| float smithVisibility_GGXCorrelated(float NdotL, float NdotV, float alphaG) { |
| float a2 = alphaG * alphaG; |
| float GGXV = NdotL * sqrt(NdotV * (NdotV - a2 * NdotV) + a2); |
| float GGXL = NdotV * sqrt(NdotL * (NdotL - a2 * NdotL) + a2); |
| return 0.5 / (GGXV + GGXL); |
| } |
| |
| float diffuseBRDF_Burley(float NdotL, float NdotV, float VdotH, float roughness) { |
| float diffuseFresnelNV = pow5(clamp(1.0 - NdotL, 0.0000001, 1.0)); |
| float diffuseFresnelNL = pow5(clamp(1.0 - NdotV, 0.0000001, 1.0)); |
| float diffuseFresnel90 = 0.5 + 2.0 * VdotH * VdotH * roughness; |
| float fresnel = (1.0 + (diffuseFresnel90 - 1.0) * diffuseFresnelNL) * |
| (1.0 + (diffuseFresnel90 - 1.0) * diffuseFresnelNV); |
| return fresnel / 3.1415926535897932384626433832795; |
| } |
| |
| struct LightingInfo { |
| float3 diffuse; |
| } |
| |
| float adjustRoughnessFromLightProperties(float roughness, float lightRadius, float lightDistance) { |
| float lightRoughness = lightRadius / lightDistance; |
| float totalRoughness = clamp(lightRoughness + roughness, 0.0, 1.0); |
| return totalRoughness; |
| } |
| |
| float3 computeHemisphericDiffuseLighting(PreLightingInfo info, float3 lightColor, float3 groundColor) { |
| return lerp(groundColor, lightColor, float3(info.NdotL, info.NdotL, info.NdotL)); |
| } |
| |
| float3 computeDiffuseLighting(PreLightingInfo info, float3 lightColor) { |
| float diffuseTerm = diffuseBRDF_Burley(info.NdotL, info.NdotV, info.VdotH, info.roughness); |
| return diffuseTerm * info.attenuation * info.NdotL * lightColor; |
| } |
| |
| float2 computeProjectionTextureDiffuseLightingUV(float4x4 textureProjectionMatrix, float3 vPositionW) { |
| float4 strq = mul(textureProjectionMatrix, float4(vPositionW, 1.0)); |
| strq /= strq.w; |
| return strq.xy; |
| } |
| |
| float getLodFromAlphaG(float cubeMapDimensionPixels, float microsurfaceAverageSlope) { |
| float microsurfaceAverageSlopeTexels = cubeMapDimensionPixels * microsurfaceAverageSlope; |
| float lod = log2(microsurfaceAverageSlopeTexels); |
| return lod; |
| } |
| |
| float getLinearLodFromRoughness(float cubeMapDimensionPixels, float roughness) { |
| float lod = log2(cubeMapDimensionPixels) * roughness; |
| return lod; |
| } |
| |
| float environmentRadianceOcclusion(float ambientOcclusion, float NdotVUnclamped) { |
| float temp = NdotVUnclamped + ambientOcclusion; |
| return clamp(square(temp) - 1.0 + ambientOcclusion, 0.0, 1.0); |
| } |
| |
| float environmentHorizonOcclusion(float3 view, float3 normal) { |
| float3 reflection = reflect(view, normal); |
| float temp = clamp(1.0 + 1.1 * dot(reflection, normal), 0.0, 1.0); |
| return square(temp); |
| } |
| |
| float3 perturbNormal(float3x3 cotangentFrame, float3 textureSample, float scale) { |
| textureSample = textureSample * 2.0 - 1.0; |
| textureSample = normalize(textureSample * float3(scale, scale, 1.0)); |
| return normalize(mul(cotangentFrame, textureSample)); |
| } |
| |
| float3x3 cotangent_frame(float3 normal, float3 p, float2 uv, float2 tangentSpaceParams, bool frontFace) { |
| uv = frontFace ? uv : -uv; |
| float3 dp1 = ddx(p); |
| float3 dp2 = ddy(p); |
| float2 duv1 = ddx(uv); |
| float2 duv2 = ddy(uv); |
| float3 dp2perp = cross(dp2, normal); |
| float3 dp1perp = cross(normal, dp1); |
| float3 tangent = dp2perp * duv1.x + dp1perp * duv2.x; |
| float3 bitangent = dp2perp * duv1.y + dp1perp * duv2.y; |
| tangent *= tangentSpaceParams.x; |
| bitangent *= tangentSpaceParams.y; |
| float invmax = rsqrt(max(dot(tangent, tangent), dot(bitangent, bitangent))); |
| return float3x3(tangent * invmax, bitangent * invmax, normal); |
| } |
| |
| float3 perturbNormal(float3x3 cotangentFrame, float2 uv, Texture2D<float4> bumpSamplerTexture, sampler bumpSamplerSampler, float3 vBumpInfos) { |
| return perturbNormal(cotangentFrame, Sample(bumpSamplerTexture, bumpSamplerSampler, uv).xyz, vBumpInfos.y); |
| } |
| |
| float3 perturbNormal(float3x3 cotangentFrame, float3 color, float3 vBumpInfos) { |
| return perturbNormal(cotangentFrame, color, vBumpInfos.y); |
| } |
| |
| float3 parallaxCorrectNormal(float3 vertexPos, float3 origVec, float3 cubeSize, float3 cubePos) { |
| float3 invOrigVec = float3(1.0, 1.0, 1.0) / origVec; |
| float3 halfSize = cubeSize * 0.5; |
| float3 intersecAtMaxPlane = (cubePos + halfSize - vertexPos) * invOrigVec; |
| float3 intersecAtMinPlane = (cubePos - halfSize - vertexPos) * invOrigVec; |
| float3 largestIntersec = max(intersecAtMaxPlane, intersecAtMinPlane); |
| float distance = min(min(largestIntersec.x, largestIntersec.y), largestIntersec.z); |
| float3 intersectPositionWS = vertexPos + origVec * distance; |
| return intersectPositionWS - cubePos; |
| } |
| |
| float3 computeFixedEquirectangularCoords(float4 worldPos, float3 worldNormal, float3 direction) { |
| float lon = atan2(direction.z, direction.x); |
| float lat = acos(direction.y); |
| float2 sphereCoords = float2(lon, lat) * 0.15915494 * 2.0; |
| float s = sphereCoords.x * 0.5 + 0.5; |
| float t = sphereCoords.y; |
| return float3(s, t, 0); |
| } |
| |
| float3 computeMirroredFixedEquirectangularCoords(float4 worldPos, float3 worldNormal, float3 direction) { |
| float lon = atan2(direction.z, direction.x); |
| float lat = acos(direction.y); |
| float2 sphereCoords = float2(lon, lat) * 0.15915494 * 2.0; |
| float s = sphereCoords.x * 0.5 + 0.5; |
| float t = sphereCoords.y; |
| return float3(1.0 - s, t, 0); |
| } |
| |
| float3 computeEquirectangularCoords(float4 worldPos, float3 worldNormal, float3 eyePosition, float4x4 reflectionMatrix) { |
| float3 cameraToVertex = normalize(worldPos.xyz - eyePosition); |
| float3 r = normalize(reflect(cameraToVertex, worldNormal)); |
| r = mul(reflectionMatrix, float4(r, 0)).xyz; |
| float lon = atan2(r.z, r.x); |
| float lat = acos(r.y); |
| float2 sphereCoords = float2(lon, lat) * 0.15915494 * 2.0; |
| float s = sphereCoords.x * 0.5 + 0.5; |
| float t = sphereCoords.y; |
| return float3(s, t, 0); |
| } |
| |
| float3 computeSphericalCoords(float4 worldPos, float3 worldNormal, float4x4 view, float4x4 reflectionMatrix) { |
| float3 viewDir = normalize(mul(view, worldPos).xyz); |
| float3 viewNormal = normalize(mul(view, float4(worldNormal, 0.0)).xyz); |
| float3 r = reflect(viewDir, viewNormal); |
| r = mul(reflectionMatrix, float4(r, 0)).xyz; |
| r.z = r.z - 1.0; |
| float m = 2.0 * length(r); |
| return float3(r.x / m + 0.5, 1.0 - r.y / m - 0.5, 0); |
| } |
| |
| float3 computePlanarCoords(float4 worldPos, float3 worldNormal, float3 eyePosition, float4x4 reflectionMatrix) { |
| float3 viewDir = worldPos.xyz - eyePosition; |
| float3 coords = normalize(reflect(viewDir, worldNormal)); |
| return mul(reflectionMatrix, float4(coords, 1)).xyz; |
| } |
| |
| float3 computeCubicCoords(float4 worldPos, float3 worldNormal, float3 eyePosition, float4x4 reflectionMatrix) { |
| float3 viewDir = normalize(worldPos.xyz - eyePosition); |
| float3 coords = reflect(viewDir, worldNormal); |
| coords = mul(reflectionMatrix, float4(coords, 0)).xyz; |
| return coords; |
| } |
| |
| float3 computeCubicLocalCoords(float4 worldPos, float3 worldNormal, float3 eyePosition, float4x4 reflectionMatrix, float3 reflectionSize, float3 reflectionPosition) { |
| float3 viewDir = normalize(worldPos.xyz - eyePosition); |
| float3 coords = reflect(viewDir, worldNormal); |
| coords = parallaxCorrectNormal(worldPos.xyz, coords, reflectionSize, reflectionPosition); |
| coords = mul(reflectionMatrix, float4(coords, 0)).xyz; |
| return coords; |
| } |
| |
| float3 computeProjectionCoords(float4 worldPos, float4x4 view, float4x4 reflectionMatrix) { |
| return mul(reflectionMatrix, mul(view, worldPos)).xyz; |
| } |
| |
| float3 computeSkyBoxCoords(float3 positionW, float4x4 reflectionMatrix) { |
| return mul(reflectionMatrix, float4(positionW, 0)).xyz; |
| } |
| |
| float3 computeReflectionCoords(float4 worldPos, float3 worldNormal, float4 vEyePosition, float4x4 reflectionMatrix) { |
| return computeCubicCoords(worldPos, worldNormal, vEyePosition.xyz, reflectionMatrix); |
| } |
| |
| fragment float4 main(float3 vPositionW : attribute(0), float3 vNormalW : attribute(1), float2 vMainUV1 : attribute(2), |
| constant Scene[] scene : register(b0, space0), |
| Texture2D<float4> environmentBrdfSamplerTexture : register(t1, space0), |
| sampler environmentBrdfSamplerSampler : register(s2, space0), |
| constant Material[] material : register(b0, space1), |
| constant Mesh[] mesh : register(b1, space1), |
| Texture2D<float4> reflectionSamplerTexture : register(t0, space2), |
| sampler reflectionSamplerSampler : register(s1, space2), |
| Texture2D<float4> albedoSamplerTexture : register(t2, space2), |
| sampler albedoSamplerSampler : register(s3, space2), |
| Texture2D<float4> reflectivitySamplerTexture : register(t4, space2), |
| sampler reflectivitySamplerSampler : register(s5, space2), |
| Texture2D<float4> ambientSamplerTexture : register(t6, space2), |
| sampler ambientSamplerSampler : register(s7, space2), |
| Texture2D<float4> emissiveSamplerTexture : register(t8, space2), |
| sampler emissiveSamplerSampler : register(s9, space2), |
| Texture2D<float4> bumpSamplerTexture : register(t10, space2), |
| sampler bumpSamplerSampler : register(s11, space2), |
| bool frontFace : SV_IsFrontFace) : SV_Target 0 { |
| float3 viewDirectionW = normalize(material[0].vEyePosition.xyz - vPositionW); |
| float3 normalW = normalize(vNormalW); |
| float2 uvOffset = float2(0.0, 0.0); |
| float normalScale = 1.0; |
| float3x3 TBN = cotangent_frame(normalW * normalScale, vPositionW, vMainUV1, material[0].vTangentSpaceParams, frontFace); |
| normalW = perturbNormal(TBN, vMainUV1 + uvOffset, bumpSamplerTexture, bumpSamplerSampler, material[0].vBumpInfos); |
| float3 surfaceAlbedo = material[0].vAlbedoColor.xyz; |
| float alpha = material[0].vAlbedoColor.w; |
| float4 albedoTexture = Sample(albedoSamplerTexture, albedoSamplerSampler, vMainUV1 + uvOffset); |
| surfaceAlbedo *= toLinearSpace(albedoTexture.xyz); |
| surfaceAlbedo *= material[0].vAlbedoInfos.y; |
| float3 ambientOcclusionColor = float3(1., 1., 1.); |
| float3 ambientOcclusionColorMap = Sample(ambientSamplerTexture, ambientSamplerSampler, vMainUV1 + uvOffset).xyz * material[0].vAmbientInfos.y; |
| ambientOcclusionColorMap = float3(ambientOcclusionColorMap.x, ambientOcclusionColorMap.x, ambientOcclusionColorMap.x); |
| ambientOcclusionColor = lerp(ambientOcclusionColor, ambientOcclusionColorMap, float3(material[0].vAmbientInfos.z, material[0].vAmbientInfos.z, material[0].vAmbientInfos.z)); |
| float microSurface = material[0].vReflectivityColor.w; |
| float3 surfaceReflectivityColor = material[0].vReflectivityColor.xyz; |
| float2 metallicRoughness = surfaceReflectivityColor.xy; |
| float4 surfaceMetallicColorMap = Sample(reflectivitySamplerTexture, reflectivitySamplerSampler, vMainUV1 + uvOffset); |
| metallicRoughness.x *= surfaceMetallicColorMap.z; |
| metallicRoughness.y *= surfaceMetallicColorMap.y; |
| microSurface = 1.0 - metallicRoughness.y; |
| float3 baseColor = surfaceAlbedo; |
| float3 DefaultSpecularReflectanceDielectric = float3(0.04, 0.04, 0.04); |
| surfaceAlbedo = lerp(baseColor * (1.0 - DefaultSpecularReflectanceDielectric.x), float3(0., 0., 0.), float3(metallicRoughness.x, metallicRoughness.x, metallicRoughness.x)); |
| surfaceReflectivityColor = lerp(DefaultSpecularReflectanceDielectric, baseColor, float3(metallicRoughness.x, metallicRoughness.x, metallicRoughness.x)); |
| microSurface = clamp(microSurface, 0.0, 1.0); |
| float roughness = 1. - microSurface; |
| float NdotVUnclamped = dot(normalW, viewDirectionW); |
| float NdotV = abs(NdotVUnclamped) + 0.0000001; |
| float alphaG = convertRoughnessToAverageSlope(roughness); |
| float2 AARoughnessFactors = getAARoughnessFactors(normalW.xyz); |
| alphaG += AARoughnessFactors.y; |
| float4 environmentRadiance = float4(0.,0., 0., 0.); |
| float3 environmentIrradiance = float3(0., 0., 0.); |
| float3 reflectionVector = computeReflectionCoords(float4(vPositionW, 1.0), normalW, material[0].vEyePosition, material[0].reflectionMatrix); |
| float3 reflectionCoords = reflectionVector; |
| float reflectionLOD = getLodFromAlphaG(material[0].vReflectionMicrosurfaceInfos.x, alphaG); |
| reflectionLOD = reflectionLOD * material[0].vReflectionMicrosurfaceInfos.y + material[0].vReflectionMicrosurfaceInfos.z; |
| float requestedReflectionLOD = reflectionLOD; |
| environmentRadiance = Sample(reflectionSamplerTexture, reflectionSamplerSampler, reflectionCoords.xy); //SampleLevel(reflectionSamplerTexture, reflectionSamplerSampler, reflectionCoords, requestedReflectionLOD); |
| environmentRadiance.xyz = fromRGBD(environmentRadiance); |
| float3 irradianceVector = mul(material[0].reflectionMatrix, float4(normalW, 0)).xyz; |
| environmentIrradiance = computeEnvironmentIrradiance(irradianceVector, &material[0]); |
| environmentRadiance.xyz *= material[0].vReflectionInfos.x; |
| environmentRadiance.xyz *= material[0].vReflectionColor.xyz; |
| environmentIrradiance *= material[0].vReflectionColor.xyz; |
| float reflectance = max(max(surfaceReflectivityColor.x, surfaceReflectivityColor.y), surfaceReflectivityColor.z); |
| float reflectance90 = fresnelGrazingReflectance(reflectance); |
| float3 specularEnvironmentR0 = surfaceReflectivityColor.xyz; |
| float3 specularEnvironmentR90 = float3(1.0, 1.0, 1.0) * reflectance90; |
| float3 environmentBrdf = getBRDFLookup(NdotV, roughness, environmentBrdfSamplerTexture, environmentBrdfSamplerSampler); |
| float3 energyConservationFactor = getEnergyConservationFactor(specularEnvironmentR0, environmentBrdf); |
| float3 diffuseBase = float3(0., 0., 0.); |
| PreLightingInfo preInfo; |
| LightingInfo info; |
| float shadow = 1.; |
| float3 specularEnvironmentReflectance = getReflectanceFromBRDFLookup(specularEnvironmentR0, environmentBrdf); |
| float ambientMonochrome = ambientOcclusionColor.x; |
| float seo = environmentRadianceOcclusion(ambientMonochrome, NdotVUnclamped); |
| specularEnvironmentReflectance *= seo; |
| float eho = environmentHorizonOcclusion(-viewDirectionW, normalW); |
| specularEnvironmentReflectance *= eho; |
| float3 finalIrradiance = environmentIrradiance; |
| finalIrradiance *= surfaceAlbedo.xyz; |
| float3 finalRadiance = environmentRadiance.xyz; |
| finalRadiance *= specularEnvironmentReflectance; |
| float3 finalRadianceScaled = finalRadiance * material[0].vLightingIntensity.z; |
| finalRadianceScaled *= energyConservationFactor; |
| float3 finalDiffuse = diffuseBase; |
| finalDiffuse *= surfaceAlbedo.xyz; |
| finalDiffuse = max(finalDiffuse, float3(0.0, 0.0, 0.0)); |
| float3 finalAmbient = material[0].vAmbientColor; |
| finalAmbient *= surfaceAlbedo.xyz; |
| float3 finalEmissive = material[0].vEmissiveColor; |
| float3 emissiveColorTex = Sample(emissiveSamplerTexture, emissiveSamplerSampler, vMainUV1 + uvOffset).xyz; |
| finalEmissive *= toLinearSpace(emissiveColorTex); |
| finalEmissive *= material[0].vEmissiveInfos.y; |
| float3 ambientOcclusionForDirectDiffuse = lerp(float3(1., 1., 1.), ambientOcclusionColor, float3(material[0].vAmbientInfos.w, material[0].vAmbientInfos.w, material[0].vAmbientInfos.w)); |
| float4 finalColor = float4( |
| finalAmbient * ambientOcclusionColor + |
| finalDiffuse * ambientOcclusionForDirectDiffuse * material[0].vLightingIntensity.x + |
| finalIrradiance * ambientOcclusionColor * material[0].vLightingIntensity.z + |
| finalRadianceScaled + |
| finalEmissive * material[0].vLightingIntensity.y, |
| alpha); |
| finalColor = max(finalColor, float4(0.0, 0.0, 0.0, 0.0)); |
| finalColor = applyImageProcessing(finalColor); |
| finalColor.w *= mesh[0].visibility; |
| return finalColor; |
| } |
| `; |
| |
| const vertexShaderWSL2 = ` |
| struct Output { |
| float3 vPositionW : attribute(0); |
| float3 vNormalW : attribute(1); |
| float3 vPositionUVW : attribute(2); |
| float4 position : SV_Position; |
| } |
| |
| struct Scene { |
| float4x4 viewProjection; |
| float4x4 view; |
| } |
| |
| struct Material { |
| float2 vAlbedoInfos; |
| float4 vAmbientInfos; |
| float2 vOpacityInfos; |
| float2 vEmissiveInfos; |
| float2 vLightmapInfos; |
| float3 vReflectivityInfos; |
| float2 vMicroSurfaceSamplerInfos; |
| float2 vReflectionInfos; |
| float3 vReflectionPosition; |
| float3 vReflectionSize; |
| float3 vBumpInfos; |
| float4x4 albedoMatrix; |
| float4x4 ambientMatrix; |
| float4x4 opacityMatrix; |
| float4x4 emissiveMatrix; |
| float4x4 lightmapMatrix; |
| float4x4 reflectivityMatrix; |
| float4x4 microSurfaceSamplerMatrix; |
| float4x4 bumpMatrix; |
| float2 vTangentSpaceParams; |
| float4x4 reflectionMatrix; |
| float3 vReflectionColor; |
| float4 vAlbedoColor; |
| float4 vLightingIntensity; |
| float3 vReflectionMicrosurfaceInfos; |
| float pointSize; |
| float4 vReflectivityColor; |
| float3 vEmissiveColor; |
| float4 vEyePosition; |
| float3 vAmbientColor; |
| float2 vDebugMode; |
| float2 vClearCoatParams; |
| float4 vClearCoatRefractionParams; |
| float2 vClearCoatInfos; |
| float4x4 clearCoatMatrix; |
| float2 vClearCoatBumpInfos; |
| float2 vClearCoatTangentSpaceParams; |
| float4x4 clearCoatBumpMatrix; |
| float4 vClearCoatTintParams; |
| float clearCoatColorAtDistance; |
| float2 vClearCoatTintInfos; |
| float4x4 clearCoatTintMatrix; |
| float3 vAnisotropy; |
| float2 vAnisotropyInfos; |
| float4x4 anisotropyMatrix; |
| float4 vSheenColor; |
| float2 vSheenInfos; |
| float4x4 sheenMatrix; |
| float3 vRefractionMicrosurfaceInfos; |
| float4 vRefractionInfos; |
| float4x4 refractionMatrix; |
| float2 vThicknessInfos; |
| float4x4 thicknessMatrix; |
| float2 vThicknessParam; |
| float3 vDiffusionDistance; |
| float4 vTintColor; |
| float3 vSubSurfaceIntensity; |
| float3 vSphericalL00; |
| float3 vSphericalL1_1; |
| float3 vSphericalL10; |
| float3 vSphericalL11; |
| float3 vSphericalL2_2; |
| float3 vSphericalL2_1; |
| float3 vSphericalL20; |
| float3 vSphericalL21; |
| float3 vSphericalL22; |
| float3 vSphericalX; |
| float3 vSphericalY; |
| float3 vSphericalZ; |
| float3 vSphericalXX_ZZ; |
| float3 vSphericalYY_ZZ; |
| float3 vSphericalZZ; |
| float3 vSphericalXY; |
| float3 vSphericalYZ; |
| float3 vSphericalZX; |
| } |
| |
| struct Mesh { |
| float4x4 world; |
| float visibility; |
| } |
| |
| float3x3 transposeMat3(float3x3 inMatrix) { |
| float3 i0 = inMatrix[0]; |
| float3 i1 = inMatrix[1]; |
| float3 i2 = inMatrix[2]; |
| float3x3 outMatrix = float3x3( |
| float3(i0.x, i1.x, i2.x), |
| float3(i0.y, i1.y, i2.y), |
| float3(i0.z, i1.z, i2.z) |
| ); |
| return outMatrix; |
| } |
| |
| float3x3 inverseMat3(float3x3 inMatrix) { |
| float a00 = inMatrix[0][0], a01 = inMatrix[0][1], a02 = inMatrix[0][2]; |
| float a10 = inMatrix[1][0], a11 = inMatrix[1][1], a12 = inMatrix[1][2]; |
| float a20 = inMatrix[2][0], a21 = inMatrix[2][1], a22 = inMatrix[2][2]; |
| float b01 = a22 * a11 - a12 * a21; |
| float b11 = -a22 * a10 + a12 * a20; |
| float b21 = a21 * a10 - a11 * a20; |
| float det = a00 * b01 + a01 * b11 + a02 * b21; |
| return float3x3(b01, -a22 * a01 + a02 * a21, a12 * a01 - a02 * a11, |
| b11, a22 * a00 - a02 * a20, -a12 * a00 + a02 * a10, |
| b21, -a21 * a00 + a01 * a20, a11 * a00 - a01 * a10) / det; |
| } |
| |
| float3 toLinearSpace(float3 color) { |
| return pow(color, float3(2.2, 2.2, 2.2)); |
| } |
| |
| float3 toGammaSpace(float3 color) { |
| return pow(color, float3(1.0 / 2.2, 1.0 / 2.2, 1.0 / 2.2)); |
| } |
| |
| float square(float value) { |
| return value * value; |
| } |
| |
| float pow5(float value) { |
| float sq = value * value; |
| return sq * sq * value; |
| } |
| |
| float getLuminance(float3 color) { |
| return clamp(dot(color, float3(0.2126, 0.7152, 0.0722)), 0., 1.); |
| } |
| |
| float getRand(float2 seed) { |
| return frac(sin(dot(seed.xy, float2(12.9898, 78.233))) * 43758.5453); |
| } |
| |
| float dither(float2 seed, float varianceAmount) { |
| float rand = getRand(seed); |
| float dither = lerp(-varianceAmount / 255.0, varianceAmount / 255.0, rand); |
| return dither; |
| } |
| |
| float4 toRGBD(float3 color) { |
| float maxRGB = max(max(color.x, max(color.y, color.z)), 0.0000001); |
| float D = max(255.0 / maxRGB, 1.); |
| D = clamp(floor(D) / 255.0, 0., 1.); |
| float3 rgb = color * D; |
| rgb = toGammaSpace(rgb); |
| return float4(rgb, D); |
| } |
| |
| float3 fromRGBD(float4 rgbd) { |
| rgbd.xyz = toLinearSpace(rgbd.xyz); |
| return rgbd.xyz / rgbd.w; |
| } |
| |
| vertex Output main(float3 position : attribute(0), float3 normal : attribute(1), |
| constant Scene[] scene : register(b0, space0), |
| Texture2D<float4> environmentBrdfSamplerTexture : register(t1, space0), |
| sampler environmentBrdfSamplerSampler : register(s2, space0), |
| constant Material[] material : register(b0, space1), |
| constant Mesh[] mesh : register(b1, space1), |
| Texture2D<float4> reflectionSamplerTexture : register(t0, space2), |
| sampler reflectionSamplerSampler : register(s1, space2)) { |
| Output output; |
| float3 positionUpdated = position; |
| float3 normalUpdated = normal; |
| output.vPositionUVW = positionUpdated; |
| float4x4 finalWorld = mesh[0].world; |
| output.position = mul(mul(scene[0].viewProjection, finalWorld), float4(positionUpdated, 1.0)); |
| float4 worldPos = mul(finalWorld, float4(positionUpdated, 1.0)); |
| output.vPositionW = worldPos.xyz; |
| float3x3 normalWorld; |
| normalWorld[0] = finalWorld[0].xyz; |
| normalWorld[1] = finalWorld[1].xyz; |
| normalWorld[2] = finalWorld[2].xyz; |
| output.vNormalW = normalize(mul(normalWorld, normalUpdated)); |
| float2 uvUpdated; |
| float2 uv2; |
| return output; |
| } |
| `; |
| |
| const fragmentShaderWSL2 = ` |
| struct Scene { |
| float4x4 viewProjection; |
| float4x4 view; |
| } |
| |
| struct Material { |
| float2 vAlbedoInfos; |
| float4 vAmbientInfos; |
| float2 vOpacityInfos; |
| float2 vEmissiveInfos; |
| float2 vLightmapInfos; |
| float3 vReflectivityInfos; |
| float2 vMicroSurfaceSamplerInfos; |
| float2 vReflectionInfos; |
| float3 vReflectionPosition; |
| float3 vReflectionSize; |
| float3 vBumpInfos; |
| float4x4 albedoMatrix; |
| float4x4 ambientMatrix; |
| float4x4 opacityMatrix; |
| float4x4 emissiveMatrix; |
| float4x4 lightmapMatrix; |
| float4x4 reflectivityMatrix; |
| float4x4 microSurfaceSamplerMatrix; |
| float4x4 bumpMatrix; |
| float2 vTangentSpaceParams; |
| float4x4 reflectionMatrix; |
| float3 vReflectionColor; |
| float4 vAlbedoColor; |
| float4 vLightingIntensity; |
| float3 vReflectionMicrosurfaceInfos; |
| float pointSize; |
| float4 vReflectivityColor; |
| float3 vEmissiveColor; |
| float4 vEyePosition; |
| float3 vAmbientColor; |
| float2 vDebugMode; |
| float2 vClearCoatParams; |
| float4 vClearCoatRefractionParams; |
| float2 vClearCoatInfos; |
| float4x4 clearCoatMatrix; |
| float2 vClearCoatBumpInfos; |
| float2 vClearCoatTangentSpaceParams; |
| float4x4 clearCoatBumpMatrix; |
| float4 vClearCoatTintParams; |
| float clearCoatColorAtDistance; |
| float2 vClearCoatTintInfos; |
| float4x4 clearCoatTintMatrix; |
| float3 vAnisotropy; |
| float2 vAnisotropyInfos; |
| float4x4 anisotropyMatrix; |
| float4 vSheenColor; |
| float2 vSheenInfos; |
| float4x4 sheenMatrix; |
| float3 vRefractionMicrosurfaceInfos; |
| float4 vRefractionInfos; |
| float4x4 refractionMatrix; |
| float2 vThicknessInfos; |
| float4x4 thicknessMatrix; |
| float2 vThicknessParam; |
| float3 vDiffusionDistance; |
| float4 vTintColor; |
| float3 vSubSurfaceIntensity; |
| float3 vSphericalL00; |
| float3 vSphericalL1_1; |
| float3 vSphericalL10; |
| float3 vSphericalL11; |
| float3 vSphericalL2_2; |
| float3 vSphericalL2_1; |
| float3 vSphericalL20; |
| float3 vSphericalL21; |
| float3 vSphericalL22; |
| float3 vSphericalX; |
| float3 vSphericalY; |
| float3 vSphericalZ; |
| float3 vSphericalXX_ZZ; |
| float3 vSphericalYY_ZZ; |
| float3 vSphericalZZ; |
| float3 vSphericalXY; |
| float3 vSphericalYZ; |
| float3 vSphericalZX; |
| } |
| |
| struct Mesh { |
| float4x4 world; |
| float visibility; |
| } |
| |
| float3x3 transposeMat3(float3x3 inMatrix) { |
| float3 i0 = inMatrix[0]; |
| float3 i1 = inMatrix[1]; |
| float3 i2 = inMatrix[2]; |
| float3x3 outMatrix = float3x3( |
| float3(i0.x, i1.x, i2.x), |
| float3(i0.y, i1.y, i2.y), |
| float3(i0.z, i1.z, i2.z) |
| ); |
| return outMatrix; |
| } |
| |
| float3x3 inverseMat3(float3x3 inMatrix) { |
| float a00 = inMatrix[0][0], a01 = inMatrix[0][1], a02 = inMatrix[0][2]; |
| float a10 = inMatrix[1][0], a11 = inMatrix[1][1], a12 = inMatrix[1][2]; |
| float a20 = inMatrix[2][0], a21 = inMatrix[2][1], a22 = inMatrix[2][2]; |
| float b01 = a22 * a11 - a12 * a21; |
| float b11 = -a22 * a10 + a12 * a20; |
| float b21 = a21 * a10 - a11 * a20; |
| float det = a00 * b01 + a01 * b11 + a02 * b21; |
| return float3x3(b01, -a22 * a01 + a02 * a21, a12 * a01 - a02 * a11, |
| b11, a22 * a00 - a02 * a20, -a12 * a00 + a02 * a10, |
| b21, -a21 * a00 + a01 * a20, a11 * a00 - a01 * a10) / det; |
| } |
| |
| float3 toLinearSpace(float3 color) { |
| return pow(color, float3(2.2, 2.2, 2.2)); |
| } |
| |
| float3 toGammaSpace(float3 color) { |
| return pow(color, float3(1.0 / 2.2, 1.0 / 2.2, 1.0 / 2.2)); |
| } |
| |
| float square(float value) { |
| return value * value; |
| } |
| |
| float pow5(float value) { |
| float sq = value * value; |
| return sq * sq * value; |
| } |
| |
| float getLuminance(float3 color) { |
| return clamp(dot(color, float3(0.2126, 0.7152, 0.0722)), 0., 1.); |
| } |
| |
| float getRand(float2 seed) { |
| return frac(sin(dot(seed.xy, float2(12.9898, 78.233))) * 43758.5453); |
| } |
| |
| float dither(float2 seed, float varianceAmount) { |
| float rand = getRand(seed); |
| float dither = lerp(-varianceAmount / 255.0, varianceAmount / 255.0, rand); |
| return dither; |
| } |
| |
| float4 toRGBD(float3 color) { |
| float maxRGB = max(max(color.x, max(color.y, color.z)), 0.0000001); |
| float D = max(255.0 / maxRGB, 1.); |
| D = clamp(floor(D) / 255.0, 0., 1.); |
| float3 rgb = color * D; |
| rgb = toGammaSpace(rgb); |
| return float4(rgb, D); |
| } |
| |
| float3 fromRGBD(float4 rgbd) { |
| rgbd.xyz = toLinearSpace(rgbd.xyz); |
| return rgbd.xyz / rgbd.w; |
| } |
| |
| float convertRoughnessToAverageSlope(float roughness) { |
| return square(roughness) + 0.0005; |
| } |
| |
| float fresnelGrazingReflectance(float reflectance0) { |
| float reflectance90 = clamp(reflectance0 * 25.0, 0.0, 1.0); |
| return reflectance90; |
| } |
| |
| float2 getAARoughnessFactors(float3 normalVector) { |
| return float2(0., 0.); |
| } |
| |
| float4 applyImageProcessing(float4 result) { |
| result.xyz = toGammaSpace(result.xyz); |
| result.xyz = clamp(result.xyz, float3(0.0, 0.0, 0.0), float3(1.0, 1.0, 1.0)); |
| return result; |
| } |
| |
| struct PreLightingInfo { |
| float3 lightOffset; |
| float lightDistanceSquared; |
| float lightDistance; |
| float attenuation; |
| float3 L; |
| float3 H; |
| float NdotV; |
| float NdotLUnclamped; |
| float NdotL; |
| float VdotH; |
| float roughness; |
| } |
| |
| PreLightingInfo computePointAndSpotPreLightingInfo(float4 lightData, float3 V, float3 N, float3 vPositionW) { |
| PreLightingInfo result; |
| result.lightOffset = lightData.xyz - vPositionW; |
| result.lightDistanceSquared = dot(result.lightOffset, result.lightOffset); |
| result.lightDistance = sqrt(result.lightDistanceSquared); |
| result.L = normalize(result.lightOffset); |
| result.H = normalize(V + result.L); |
| result.VdotH = clamp(dot(V, result.H), 0.0, 1.0); |
| result.NdotLUnclamped = dot(N, result.L); |
| result.NdotL = clamp(result.NdotLUnclamped, 0.0000001, 1.0); |
| return result; |
| } |
| |
| PreLightingInfo computeDirectionalPreLightingInfo(float4 lightData, float3 V, float3 N) { |
| PreLightingInfo result; |
| result.lightDistance = length(-lightData.xyz); |
| result.L = normalize(-lightData.xyz); |
| result.H = normalize(V + result.L); |
| result.VdotH = clamp(dot(V, result.H), 0.0, 1.0); |
| result.NdotLUnclamped = dot(N, result.L); |
| result.NdotL = clamp(result.NdotLUnclamped, 0.0000001, 1.0); |
| return result; |
| } |
| |
| PreLightingInfo computeHemisphericPreLightingInfo(float4 lightData, float3 V, float3 N) { |
| PreLightingInfo result; |
| result.NdotL = dot(N, lightData.xyz) * 0.5 + 0.5; |
| result.NdotL = clamp(result.NdotL, 0.0000001, 1.0); |
| result.NdotLUnclamped = result.NdotL; |
| return result; |
| } |
| |
| float computeDistanceLightFalloff_Standard(float3 lightOffset, float range) { |
| return max(0., 1.0 - length(lightOffset) / range); |
| } |
| |
| float computeDistanceLightFalloff_Physical(float lightDistanceSquared) { |
| return 1.0 / max(lightDistanceSquared, 0.0000001); |
| } |
| |
| float computeDistanceLightFalloff_GLTF(float lightDistanceSquared, float inverseSquaredRange) { |
| float lightDistanceFalloff = 1.0 / max(lightDistanceSquared, 0.0000001); |
| float factor = lightDistanceSquared * inverseSquaredRange; |
| float attenuation = clamp(1.0 - factor * factor, 0.0, 1.0); |
| attenuation *= attenuation; |
| lightDistanceFalloff *= attenuation; |
| return lightDistanceFalloff; |
| } |
| |
| float computeDistanceLightFalloff(float3 lightOffset, float lightDistanceSquared, float range, float inverseSquaredRange) { |
| return computeDistanceLightFalloff_Physical(lightDistanceSquared); |
| } |
| |
| float computeDirectionalLightFalloff_Standard(float3 lightDirection, float3 directionToLightCenterW, float cosHalfAngle, float exponent) { |
| float falloff = 0.0; |
| float cosAngle = max(dot(-lightDirection, directionToLightCenterW), 0.0000001); |
| if (cosAngle >= cosHalfAngle) { |
| falloff = max(0., pow(cosAngle, exponent)); |
| } |
| return falloff; |
| } |
| |
| float computeDirectionalLightFalloff_Physical(float3 lightDirection, float3 directionToLightCenterW, float cosHalfAngle) { |
| float kMinusLog2ConeAngleIntensityRatio = 6.64385618977; |
| float concentrationKappa = kMinusLog2ConeAngleIntensityRatio / (1.0 - cosHalfAngle); |
| float4 lightDirectionSpreadSG = float4(-lightDirection * concentrationKappa, -concentrationKappa); |
| float falloff = exp2(dot(float4(directionToLightCenterW, 1.0), lightDirectionSpreadSG)); |
| return falloff; |
| } |
| |
| float computeDirectionalLightFalloff_GLTF(float3 lightDirection, float3 directionToLightCenterW, float lightAngleScale, float lightAngleOffset) { |
| float cd = dot(-lightDirection, directionToLightCenterW); |
| float falloff = clamp(cd * lightAngleScale + lightAngleOffset, 0.0, 1.0); |
| falloff *= falloff; |
| return falloff; |
| } |
| |
| float computeDirectionalLightFalloff(float3 lightDirection, float3 directionToLightCenterW, float cosHalfAngle, float exponent, float lightAngleScale, float lightAngleOffset) { |
| return computeDirectionalLightFalloff_Physical(lightDirection, directionToLightCenterW, cosHalfAngle); |
| } |
| |
| float3 getEnergyConservationFactor(float3 specularEnvironmentR0, float3 environmentBrdf) { |
| return float3(1.0, 1.0, 1.0) + specularEnvironmentR0 * (1.0 / environmentBrdf.y - 1.0); |
| } |
| |
| float3 getBRDFLookup(float NdotV, float perceptualRoughness, Texture2D<float4> environmentBrdfSamplerTexture, sampler environmentBrdfSamplerSampler) { |
| float2 UV = float2(NdotV, perceptualRoughness); |
| float4 brdfLookup = Sample(environmentBrdfSamplerTexture, environmentBrdfSamplerSampler, UV); |
| return brdfLookup.xyz; |
| } |
| |
| float3 getReflectanceFromBRDFLookup(float3 specularEnvironmentR0, float3 environmentBrdf) { |
| float3 reflectance = lerp(environmentBrdf.xxx, environmentBrdf.yyy, specularEnvironmentR0); |
| return reflectance; |
| } |
| |
| float3 getReflectanceFromAnalyticalBRDFLookup_Jones(float VdotN, float3 reflectance0, float3 reflectance90, float smoothness) { |
| float weight = lerp(0.25, 1.0, smoothness); |
| return reflectance0 + weight * (reflectance90 - reflectance0) * pow5(clamp(1.0 - VdotN, 0.0, 1.0)); |
| } |
| |
| float3 fresnelSchlickGGX(float VdotH, float3 reflectance0, float3 reflectance90) { |
| return reflectance0 + (reflectance90 - reflectance0) * pow5(1.0 - VdotH); |
| } |
| |
| float fresnelSchlickGGX(float VdotH, float reflectance0, float reflectance90) { |
| return reflectance0 + (reflectance90 - reflectance0) * pow5(1.0 - VdotH); |
| } |
| |
| float normalDistributionFunction_TrowbridgeReitzGGX(float NdotH, float alphaG) { |
| float a2 = square(alphaG); |
| float d = NdotH * NdotH * (a2 - 1.0) + 1.0; |
| return a2 / (3.1415926535897932384626433832795 * d * d); |
| } |
| |
| float smithVisibility_GGXCorrelated(float NdotL, float NdotV, float alphaG) { |
| float a2 = alphaG * alphaG; |
| float GGXV = NdotL * sqrt(NdotV * (NdotV - a2 * NdotV) + a2); |
| float GGXL = NdotV * sqrt(NdotL * (NdotL - a2 * NdotL) + a2); |
| return 0.5 / (GGXV + GGXL); |
| } |
| |
| float diffuseBRDF_Burley(float NdotL, float NdotV, float VdotH, float roughness) { |
| float diffuseFresnelNV = pow5(clamp(1.0 - NdotL, 0.0000001, 1.0)); |
| float diffuseFresnelNL = pow5(clamp(1.0 - NdotV, 0.0000001, 1.0)); |
| float diffuseFresnel90 = 0.5 + 2.0 * VdotH * VdotH * roughness; |
| float fresnel = (1.0 + (diffuseFresnel90 - 1.0) * diffuseFresnelNL) * |
| (1.0 + (diffuseFresnel90 - 1.0) * diffuseFresnelNV); |
| return fresnel / 3.1415926535897932384626433832795; |
| } |
| |
| struct LightingInfo { |
| float3 diffuse; |
| } |
| |
| float adjustRoughnessFromLightProperties(float roughness, float lightRadius, float lightDistance) { |
| float lightRoughness = lightRadius / lightDistance; |
| float totalRoughness = clamp(lightRoughness + roughness, 0.0, 1.0); |
| return totalRoughness; |
| } |
| |
| float3 computeHemisphericDiffuseLighting(PreLightingInfo info, float3 lightColor, float3 groundColor) { |
| return lerp(groundColor, lightColor, float3(info.NdotL, info.NdotL, info.NdotL)); |
| } |
| |
| float3 computeDiffuseLighting(PreLightingInfo info, float3 lightColor) { |
| float diffuseTerm = diffuseBRDF_Burley(info.NdotL, info.NdotV, info.VdotH, info.roughness); |
| return diffuseTerm * info.attenuation * info.NdotL * lightColor; |
| } |
| |
| float2 computeProjectionTextureDiffuseLightingUV(float4x4 textureProjectionMatrix, float3 vPositionW) { |
| float4 strq = mul(textureProjectionMatrix, float4(vPositionW, 1.0)); |
| strq /= strq.w; |
| return strq.xy; |
| } |
| |
| float getLodFromAlphaG(float cubeMapDimensionPixels, float microsurfaceAverageSlope) { |
| float microsurfaceAverageSlopeTexels = cubeMapDimensionPixels * microsurfaceAverageSlope; |
| float lod = log2(microsurfaceAverageSlopeTexels); |
| return lod; |
| } |
| |
| float getLinearLodFromRoughness(float cubeMapDimensionPixels, float roughness) { |
| float lod = log2(cubeMapDimensionPixels) * roughness; |
| return lod; |
| } |
| |
| float environmentRadianceOcclusion(float ambientOcclusion, float NdotVUnclamped) { |
| float temp = NdotVUnclamped + ambientOcclusion; |
| return clamp(square(temp) - 1.0 + ambientOcclusion, 0.0, 1.0); |
| } |
| |
| float environmentHorizonOcclusion(float3 view, float3 normal) { |
| float3 reflection = reflect(view, normal); |
| float temp = clamp(1.0 + 1.1 * dot(reflection, normal), 0.0, 1.0); |
| return square(temp); |
| } |
| |
| float3 parallaxCorrectNormal(float3 vertexPos, float3 origVec, float3 cubeSize, float3 cubePos) { |
| float3 invOrigVec = float3(1.0, 1.0, 1.0) / origVec; |
| float3 halfSize = cubeSize * 0.5; |
| float3 intersecAtMaxPlane = (cubePos + halfSize - vertexPos) * invOrigVec; |
| float3 intersecAtMinPlane = (cubePos - halfSize - vertexPos) * invOrigVec; |
| float3 largestIntersec = max(intersecAtMaxPlane, intersecAtMinPlane); |
| float distance = min(min(largestIntersec.x, largestIntersec.y), largestIntersec.z); |
| float3 intersectPositionWS = vertexPos + origVec * distance; |
| return intersectPositionWS - cubePos; |
| } |
| |
| float3 computeFixedEquirectangularCoords(float4 worldPos, float3 worldNormal, float3 direction) { |
| float lon = atan2(direction.z, direction.x); |
| float lat = acos(direction.y); |
| float2 sphereCoords = float2(lon, lat) * 0.15915494 * 2.0; |
| float s = sphereCoords.x * 0.5 + 0.5; |
| float t = sphereCoords.y; |
| return float3(s, t, 0); |
| } |
| |
| float3 computeMirroredFixedEquirectangularCoords(float4 worldPos, float3 worldNormal, float3 direction) { |
| float lon = atan2(direction.z, direction.x); |
| float lat = acos(direction.y); |
| float2 sphereCoords = float2(lon, lat) * 0.15915494 * 2.0; |
| float s = sphereCoords.x * 0.5 + 0.5; |
| float t = sphereCoords.y; |
| return float3(1.0 - s, t, 0); |
| } |
| |
| float3 computeEquirectangularCoords(float4 worldPos, float3 worldNormal, float3 eyePosition, float4x4 reflectionMatrix) { |
| float3 cameraToVertex = normalize(worldPos.xyz - eyePosition); |
| float3 r = normalize(reflect(cameraToVertex, worldNormal)); |
| r = mul(reflectionMatrix, float4(r, 0)).xyz; |
| float lon = atan2(r.z, r.x); |
| float lat = acos(r.y); |
| float2 sphereCoords = float2(lon, lat) * 0.15915494 * 2.0; |
| float s = sphereCoords.x * 0.5 + 0.5; |
| float t = sphereCoords.y; |
| return float3(s, t, 0); |
| } |
| |
| float3 computeSphericalCoords(float4 worldPos, float3 worldNormal, float4x4 view, float4x4 reflectionMatrix) { |
| float3 viewDir = normalize(mul(view, worldPos).xyz); |
| float3 viewNormal = normalize(mul(view, float4(worldNormal, 0.0)).xyz); |
| float3 r = reflect(viewDir, viewNormal); |
| r = mul(reflectionMatrix, float4(r, 0)).xyz; |
| r.z = r.z - 1.0; |
| float m = 2.0 * length(r); |
| return float3(r.x / m + 0.5, 1.0 - r.y / m - 0.5, 0); |
| } |
| |
| float3 computePlanarCoords(float4 worldPos, float3 worldNormal, float3 eyePosition, float4x4 reflectionMatrix) { |
| float3 viewDir = worldPos.xyz - eyePosition; |
| float3 coords = normalize(reflect(viewDir, worldNormal)); |
| return mul(reflectionMatrix, float4(coords, 1)).xyz; |
| } |
| |
| float3 computeCubicCoords(float4 worldPos, float3 worldNormal, float3 eyePosition, float4x4 reflectionMatrix) { |
| float3 viewDir = normalize(worldPos.xyz - eyePosition); |
| float3 coords = reflect(viewDir, worldNormal); |
| coords = mul(reflectionMatrix, float4(coords, 0)).xyz; |
| return coords; |
| } |
| |
| float3 computeCubicLocalCoords(float4 worldPos, float3 worldNormal, float3 eyePosition, float4x4 reflectionMatrix, float3 reflectionSize, float3 reflectionPosition) { |
| float3 viewDir = normalize(worldPos.xyz - eyePosition); |
| float3 coords = reflect(viewDir, worldNormal); |
| coords = parallaxCorrectNormal(worldPos.xyz, coords, reflectionSize, reflectionPosition); |
| coords = mul(reflectionMatrix, float4(coords, 0)).xyz; |
| return coords; |
| } |
| |
| float3 computeProjectionCoords(float4 worldPos, float4x4 view, float4x4 reflectionMatrix) { |
| return mul(reflectionMatrix, mul(view, worldPos)).xyz; |
| } |
| |
| float3 computeSkyBoxCoords(float3 positionW, float4x4 reflectionMatrix) { |
| return mul(reflectionMatrix, float4(positionW, 0)).xyz; |
| } |
| |
| float3 computeReflectionCoords(float4 worldPos, float3 worldNormal, float3 vPositionUVW, float4x4 reflectionMatrix) { |
| float r = length(vPositionUVW); |
| float gamma = atan2(vPositionUVW.x, vPositionUVW.z); |
| float theta = acos(vPositionUVW.y / r); |
| return float3(gamma / 3.1415926535897932384626433832795 + 0.5, theta / 3.1415926535897932384626433832795, r); |
| } |
| |
| fragment float4 main(float3 vPositionW : attribute(0), float3 vNormalW : attribute(1), float3 vPositionUVW : attribute(2), |
| constant Scene[] scene : register(b0, space0), |
| Texture2D<float4> environmentBrdfSamplerTexture : register(t1, space0), |
| sampler environmentBrdfSamplerSampler : register(s2, space0), |
| constant Material[] material : register(b0, space1), |
| constant Mesh[] mesh : register(b1, space1), |
| Texture2D<float4> reflectionSamplerTexture : register(t0, space2), |
| sampler reflectionSamplerSampler : register(s1, space2), |
| bool frontFace : SV_IsFrontFace) : SV_Target 0 { |
| float3 viewDirectionW = normalize(material[0].vEyePosition.xyz - vPositionW); |
| float3 normalW = normalize(vNormalW); |
| float2 uvOffset = float2(0.0, 0.0); |
| normalW = frontFace ? normalW : -normalW; |
| float3 surfaceAlbedo = material[0].vAlbedoColor.xyz; |
| float alpha = material[0].vAlbedoColor.w; |
| float3 ambientOcclusionColor = float3(1., 1., 1.); |
| float microSurface = material[0].vReflectivityColor.w; |
| float3 surfaceReflectivityColor = material[0].vReflectivityColor.xyz; |
| microSurface = clamp(microSurface, 0.0, 1.0); |
| float roughness = 1. - microSurface; |
| float NdotVUnclamped = dot(normalW, viewDirectionW); |
| float NdotV = abs(NdotVUnclamped) + 0.0000001; |
| float alphaG = convertRoughnessToAverageSlope(roughness); |
| float2 AARoughnessFactors = getAARoughnessFactors(normalW); |
| float4 environmentRadiance = float4(0., 0., 0., 0.); |
| float3 environmentIrradiance = float3(0., 0., 0.); |
| float3 reflectionVector = computeReflectionCoords(float4(vPositionW, 1.0), normalW, vPositionUVW, material[0].reflectionMatrix); |
| float3 reflectionCoords = reflectionVector; |
| float reflectionLOD = getLodFromAlphaG(material[0].vReflectionMicrosurfaceInfos.x, alphaG); |
| reflectionLOD = reflectionLOD * material[0].vReflectionMicrosurfaceInfos.y + material[0].vReflectionMicrosurfaceInfos.z; |
| float requestedReflectionLOD = reflectionLOD; |
| environmentRadiance = Sample(reflectionSamplerTexture, reflectionSamplerSampler, reflectionCoords.xy); //SampleLevel(reflectionSamplerTexture, reflectionSamplerSampler, reflectionCoords, requestedReflectionLOD); |
| environmentRadiance.xyz = fromRGBD(environmentRadiance); |
| environmentRadiance.xyz *= material[0].vReflectionInfos.x; |
| environmentRadiance.xyz *= material[0].vReflectionColor.xyz; |
| environmentIrradiance *= material[0].vReflectionColor.xyz; |
| float reflectance = max(max(surfaceReflectivityColor.x, surfaceReflectivityColor.y), surfaceReflectivityColor.z); |
| float reflectance90 = fresnelGrazingReflectance(reflectance); |
| float3 specularEnvironmentR0 = surfaceReflectivityColor.xyz; |
| float3 specularEnvironmentR90 = float3(1.0, 1.0, 1.0) * reflectance90; |
| float3 environmentBrdf = getBRDFLookup(NdotV, roughness, environmentBrdfSamplerTexture, environmentBrdfSamplerSampler); |
| float3 energyConservationFactor = getEnergyConservationFactor(specularEnvironmentR0, environmentBrdf); |
| float3 diffuseBase = float3(0., 0., 0.); |
| PreLightingInfo preInfo; |
| LightingInfo info; |
| float shadow = 1.; |
| float3 specularEnvironmentReflectance = getReflectanceFromAnalyticalBRDFLookup_Jones(NdotV, specularEnvironmentR0, specularEnvironmentR90, sqrt(microSurface)); |
| surfaceAlbedo.xyz = (1. - reflectance) * surfaceAlbedo.xyz; |
| float3 finalIrradiance = environmentIrradiance; |
| finalIrradiance *= surfaceAlbedo.xyz; |
| float3 finalRadiance = environmentRadiance.xyz; |
| finalRadiance *= specularEnvironmentReflectance; |
| float3 finalRadianceScaled = finalRadiance * material[0].vLightingIntensity.z; |
| finalRadianceScaled *= energyConservationFactor; |
| float3 finalDiffuse = diffuseBase; |
| finalDiffuse *= surfaceAlbedo.xyz; |
| finalDiffuse = max(finalDiffuse, float3(0.0, 0.0, 0.0)); |
| float3 finalAmbient = material[0].vAmbientColor; |
| finalAmbient *= surfaceAlbedo.xyz; |
| float3 finalEmissive = material[0].vEmissiveColor; |
| float3 ambientOcclusionForDirectDiffuse = ambientOcclusionColor; |
| float4 finalColor = float4( |
| finalAmbient * ambientOcclusionColor + |
| finalDiffuse * ambientOcclusionForDirectDiffuse * material[0].vLightingIntensity.x + |
| finalIrradiance * ambientOcclusionColor * material[0].vLightingIntensity.z + |
| finalRadianceScaled + |
| finalEmissive * material[0].vLightingIntensity.y, |
| alpha); |
| finalColor = max(finalColor, float4(0.0, 0.0, 0.0, 0.0)); |
| finalColor = applyImageProcessing(finalColor); |
| finalColor.w *= mesh[0].visibility; |
| return finalColor; |
| } |
| `; |