Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // GLSL Fragment Shader "fsmain"
- // Generated by XShaderCompiler
- // 19/07/2019 12:09:16
- #version 450
- #extension GL_EXT_samplerless_texture_functions : enable
- layout(location = 0) in vec2 bs_TEXCOORD0;
- layout(location = 1) in vec3 bs_TEXCOORD1;
- layout(location = 2) in vec3 bs_NORMAL0;
- layout(location = 3) in vec4 bs_TANGENT0;
- layout(location = 0) out vec4 SV_Target0;
- layout(std140, row_major, binding = 31) uniform PerCamera
- {
- vec3 gViewDir;
- vec3 gViewOrigin;
- mat4 gMatViewProj;
- mat4 gMatView;
- mat4 gMatProj;
- mat4 gMatInvProj;
- mat4 gMatInvViewProj;
- mat4 gMatScreenToWorld;
- mat4 gNDCToPrevNDC;
- vec2 gDeviceZToWorldZ;
- vec2 gNDCZToWorldZ;
- vec2 gNDCZToDeviceZ;
- vec2 gNearFar;
- ivec4 gViewportRectangle;
- vec4 gClipToUVScaleOffset;
- vec4 gUVToClipScaleOffset;
- float gAmbientFactor;
- };
- struct VStoFS
- {
- vec4 position;
- vec2 uv0;
- vec3 worldPosition;
- vec3 tangentToWorldZ;
- vec4 tangentToWorldX;
- };
- vec3 calcWorldNormal(VStoFS xsr_input, vec3 surfaceNormal)
- {
- vec3 tangentToWorldX = xsr_input.tangentToWorldX.xyz;
- vec3 tangentToWorldZ = xsr_input.tangentToWorldZ;
- vec3 tangentToWorldY = cross(tangentToWorldZ, tangentToWorldX) * xsr_input.tangentToWorldX.w;
- mat3 tangentToWorld = mat3(tangentToWorldX, tangentToWorldY, tangentToWorldZ);
- return normalize((tangentToWorld * surfaceNormal));
- }
- struct SurfaceData
- {
- vec4 albedo;
- vec4 worldNormal;
- float depth;
- float roughness;
- float metalness;
- uint mask;
- };
- struct LightData
- {
- vec3 position;
- float boundRadius;
- vec3 direction;
- float luminance;
- vec3 spotAngles;
- float attRadiusSqrdInv;
- vec3 color;
- float srcRadius;
- vec3 shiftedLightPosition;
- float padding;
- };
- vec3 calcMicrofacetFresnelShlick(vec3 F0, float LoH)
- {
- return F0 + (vec3(1.0f) - F0) * pow(1.0f - LoH, 5.0f);
- }
- float calcMicrofacetShadowingSmithGGX(float roughness4, float NoV, float NoL)
- {
- float g1V = NoV + sqrt(NoV * (NoV - NoV * roughness4) + roughness4);
- float g1L = NoL + sqrt(NoL * (NoL - NoL * roughness4) + roughness4);
- return (float(1.0f) / (g1V * g1L));
- }
- float calcMicrofacetDistGGX(float roughness4, float NoH)
- {
- float d = (NoH * roughness4 - NoH) * NoH + 1.0f;
- return roughness4 / (3.1415926f * d * d);
- }
- vec3 calcDiffuseLambert(vec3 color)
- {
- return color * (1.0f / 3.1415926f);
- }
- float getSpotAttenuation(vec3 toLight, LightData lightData)
- {
- float xsr_output = clamp((dot(toLight, -lightData.direction) - lightData.spotAngles.y) * lightData.spotAngles.z, float(0), float(1));
- return xsr_output * xsr_output;
- }
- float getRadialAttenuation(float distance2, LightData lightData)
- {
- float radialAttenuation = distance2 * lightData.attRadiusSqrdInv;
- radialAttenuation *= radialAttenuation;
- radialAttenuation = clamp(1.0f - radialAttenuation, float(0), float(1));
- radialAttenuation *= radialAttenuation;
- return radialAttenuation;
- }
- float illuminancePointLight(float distance2, float NoL, LightData lightData)
- {
- return (lightData.luminance * NoL) / max(distance2, 0.01f * 0.01f);
- }
- float illuminanceScaleSphereDiskAreaLight(float unclampedNoL, float sinSolidAngleSqrd)
- {
- float sinSolidAngle = sqrt(sinSolidAngleSqrd);
- return 3.1415926f * sinSolidAngleSqrd * clamp(unclampedNoL, float(0), float(1));
- }
- float illuminanceSphereAreaLight(float unclampedNoL, float distToLight2, LightData lightData)
- {
- float radius2 = lightData.srcRadius * lightData.srcRadius;
- float sinSolidAngle2 = radius2 / distToLight2;
- sinSolidAngle2 = min(sinSolidAngle2, 0.9999f);
- return lightData.luminance * illuminanceScaleSphereDiskAreaLight(unclampedNoL, sinSolidAngle2);
- }
- float illuminanceDiscAreaLight(float unclampedNoL, float distToLight2, vec3 L, LightData lightData)
- {
- float radius2 = lightData.srcRadius * lightData.srcRadius;
- float sinSolidAngle2 = clamp(radius2 / (radius2 + max(radius2, distToLight2)), float(0), float(1));
- return lightData.luminance * illuminanceScaleSphereDiskAreaLight(unclampedNoL, sinSolidAngle2 * clamp(dot(lightData.direction, -L), float(0), float(1)));
- }
- vec3 getSpecularDominantDir(vec3 N, vec3 R, float roughness)
- {
- float r2 = roughness * roughness;
- return normalize(mix(N, R, vec3((1,000000f - r2) * (sqrt(1,000000f - r2) + r2))));
- }
- vec3 evaluateStandardBRDF(vec3 V, vec3 L, float specLobeEnergy, SurfaceData surfaceData)
- {
- vec3 N = surfaceData.worldNormal.xyz;
- vec3 H = normalize(V + L);
- float LoH = clamp(dot(L, H), float(0), float(1));
- float NoH = clamp(dot(N, H), float(0), float(1));
- float NoV = clamp(dot(N, V), float(0), float(1));
- float NoL = clamp(dot(N, L), float(0), float(1));
- vec3 diffuseColor = mix(surfaceData.albedo.rgb, vec3(0.0f, 0.0f, 0.0f), vec3(surfaceData.metalness));
- vec3 specularColor = mix(vec3(0.04f, 0.04f, 0.04f), surfaceData.albedo.rgb, vec3(surfaceData.metalness));
- vec3 diffuse = calcDiffuseLambert(diffuseColor);
- float roughness = max(surfaceData.roughness, 0.04f);
- float roughness2 = roughness * roughness;
- float roughness4 = roughness2 * roughness2;
- vec3 specular = calcMicrofacetFresnelShlick(specularColor, LoH) * calcMicrofacetDistGGX(roughness4, NoH) * calcMicrofacetShadowingSmithGGX(roughness4, NoV, NoL);
- return diffuse + specular * specLobeEnergy;
- }
- vec3 getLuminanceDirectional(LightData lightData, vec3 worldPos, vec3 V, vec3 R, SurfaceData surfaceData)
- {
- vec3 N = surfaceData.worldNormal.xyz;
- vec3 L = -lightData.direction;
- float NoL = clamp(dot(N, L), float(0), float(1));
- float specEnergy = 1.0f;
- if (lightData.srcRadius > 0,000000f)
- {
- float diskRadius = sin(lightData.srcRadius);
- float distanceToDisk = cos(lightData.srcRadius);
- float DoR = dot(L, R);
- vec3 S = normalize(R - DoR * L);
- L = DoR < distanceToDisk ? normalize(distanceToDisk * L + S * diskRadius) : R;
- }
- vec3 surfaceShading = evaluateStandardBRDF(V, L, specEnergy, surfaceData);
- float illuminance = lightData.luminance * NoL;
- return lightData.color * illuminance * surfaceShading;
- }
- vec3 getLuminanceRadial(LightData lightData, vec3 worldPos, vec3 V, vec3 R, float roughness2, SurfaceData surfaceData)
- {
- vec3 N = surfaceData.worldNormal.xyz;
- vec3 toLight = lightData.position - worldPos;
- float distToLightSqrd = dot(toLight, toLight);
- float invDistToLight = inversesqrt(distToLightSqrd);
- vec3 L = toLight * invDistToLight;
- float NoL = dot(N, L);
- float specEnergy = 1.0f;
- float illuminance = 0.0f;
- if (lightData.srcRadius > 0,000000f)
- {
- illuminance = illuminanceSphereAreaLight(NoL, distToLightSqrd, lightData);
- float sphereAngle = clamp(lightData.srcRadius * invDistToLight, float(0), float(1));
- specEnergy = roughness2 / clamp(roughness2 + 0.5f * sphereAngle, float(0), float(1));
- specEnergy *= specEnergy;
- vec3 closestPointOnRay = dot(toLight, R) * R;
- vec3 centerToRay = closestPointOnRay - toLight;
- float invDistToRay = inversesqrt(dot(centerToRay, centerToRay));
- vec3 closestPointOnSphere = toLight + centerToRay * clamp(lightData.srcRadius * invDistToRay, float(0), float(1));
- toLight = closestPointOnSphere;
- L = normalize(toLight);
- }
- else
- {
- NoL = clamp(NoL, float(0), float(1));
- illuminance = illuminancePointLight(distToLightSqrd, NoL, lightData);
- }
- float attenuation = getRadialAttenuation(distToLightSqrd, lightData);
- vec3 surfaceShading = evaluateStandardBRDF(V, L, specEnergy, surfaceData);
- return lightData.color * illuminance * attenuation * surfaceShading;
- }
- vec3 getLuminanceSpot(LightData lightData, vec3 worldPos, vec3 V, vec3 R, float roughness2, SurfaceData surfaceData)
- {
- vec3 N = surfaceData.worldNormal.xyz;
- vec3 toLight = lightData.position - worldPos;
- float distToLightSqrd = dot(toLight, toLight);
- float invDistToLight = inversesqrt(distToLightSqrd);
- vec3 L = toLight * invDistToLight;
- float NoL = dot(N, L);
- float specEnergy = 1.0f;
- float illuminance = 0.0f;
- float spotAttenuation = 1.0f;
- if (lightData.srcRadius > 0,000000f)
- {
- illuminance = illuminanceDiscAreaLight(NoL, distToLightSqrd, L, lightData);
- float rightDiscAngle = clamp(lightData.srcRadius * invDistToLight, float(0), float(1));
- float discAngle = rightDiscAngle * clamp(dot(lightData.direction, -L), float(0), float(1));
- specEnergy = roughness2 / clamp(roughness2 + 0.5f * discAngle, float(0), float(1));
- specEnergy *= specEnergy;
- vec3 discNormal = -lightData.direction;
- float distAlongLightDir = max(dot(R, discNormal), 1.e-6f);
- float t = dot(toLight, discNormal) / distAlongLightDir;
- vec3 closestPointOnPlane = R * t;
- vec3 centerToRay = closestPointOnPlane - toLight;
- float invDistToRay = inversesqrt(dot(centerToRay, centerToRay));
- vec3 closestPointOnDisc = toLight + centerToRay * clamp(lightData.srcRadius * invDistToRay, float(0), float(1));
- toLight = closestPointOnDisc;
- L = normalize(toLight);
- vec3 toSpotEdge = normalize(lightData.shiftedLightPosition - worldPos);
- spotAttenuation = getSpotAttenuation(toSpotEdge, lightData);
- }
- else
- {
- NoL = clamp(NoL, float(0), float(1));
- illuminance = illuminancePointLight(distToLightSqrd, NoL, lightData);
- spotAttenuation = getSpotAttenuation(L, lightData);
- }
- float radialAttenuation = getRadialAttenuation(distToLightSqrd, lightData);
- float attenuation = spotAttenuation * radialAttenuation;
- vec3 surfaceShading = evaluateStandardBRDF(V, L, specEnergy, surfaceData);
- return lightData.color * illuminance * attenuation * surfaceShading;
- }
- float mapRoughnessToMipLevel(float roughness, int numMips)
- {
- return max(0,000000f, -2.8f * log2(1.0f - roughness));
- }
- struct ReflProbeData
- {
- vec3 position;
- float radius;
- vec3 boxExtents;
- float transitionDistance;
- mat4 invBoxTransform;
- uint cubemapIdx;
- uint type;
- vec2 padding;
- };
- layout(binding = 35) uniform textureCube gSkyReflectionTex;
- layout(binding = 36) uniform sampler gSkyReflectionSamp;
- layout(binding = 37) uniform textureCubeArray gReflProbeCubemaps;
- layout(binding = 38) uniform sampler gReflProbeSamp;
- layout(binding = 39) uniform texture2D gAmbientOcclusionTex;
- layout(binding = 40) uniform sampler gAmbientOcclusionSamp;
- layout(binding = 41) uniform texture2D gSSRTex;
- layout(binding = 42) uniform sampler gSSRSamp;
- layout(binding = 43) uniform texture2D gPreintegratedEnvBRDF;
- layout(binding = 44) uniform sampler gPreintegratedEnvBRDFSamp;
- layout(std140, binding = 45) uniform ReflProbeParams
- {
- uint gReflCubemapNumMips;
- uint gNumProbes;
- uint gSkyCubemapAvailable;
- uint gUseReflectionMaps;
- uint gSkyCubemapNumMips;
- float gSkyBrightness;
- };
- float getSphereReflectionContribution(float normalizedDistance)
- {
- float t = clamp(2.5f - 2.5f * normalizedDistance, float(0), float(1));
- return t * t * (3.0f - 2.0f * t);
- }
- vec3 getLookupForSphereProxy(vec3 originWS, vec3 dirWS, vec3 centerWS, float radius)
- {
- float radius2 = radius * radius;
- vec3 originLS = originWS - centerWS;
- float a = dot(originLS, dirWS);
- float dist2 = a * a - dot(originLS, originLS) + radius2;
- vec3 lookupDir = dirWS;
- if (dist2 >= 0,000000f)
- {
- float farDist = sqrt(dist2) - a;
- lookupDir = originLS + farDist * dirWS;
- }
- return lookupDir;
- }
- float getDistBoxToPoint(vec3 pt, vec3 extents)
- {
- vec3 d = max(max(-extents - pt, vec3(0)), pt - extents);
- return length(d);
- }
- vec3 getLookupForBoxProxy(vec3 originWS, vec3 dirWS, vec3 centerWS, vec3 extents, mat4 invBoxTransform, float transitionDistance, out float contribution)
- {
- vec3 originLS = (vec4(originWS, 1) * invBoxTransform).xyz;
- vec3 dirLS = (vec4(dirWS, 0) * invBoxTransform).xyz;
- vec3 invDirLS = (vec3(vec3(1)) / (dirLS));
- vec3 intersectsMax = invDirLS - originLS * invDirLS;
- vec3 intersectsMin = -invDirLS - originLS * invDirLS;
- vec3 positiveIntersections = max(intersectsMax, intersectsMin);
- float intersectDist = min(positiveIntersections.x, min(positiveIntersections.y, positiveIntersections.z));
- vec3 intersectPositionWS = originWS + intersectDist * dirWS;
- vec3 lookupDir = intersectPositionWS - centerWS;
- vec3 reducedExtents = extents - vec3(transitionDistance, transitionDistance, transitionDistance);
- float distToBox = getDistBoxToPoint(originLS * extents, reducedExtents);
- float normalizedDistance = distToBox / transitionDistance;
- float t = clamp(3.3333f - 3.3333f * normalizedDistance, float(0), float(1));
- contribution = t * t * (3.0f - 2.0f * t);
- return lookupDir;
- }
- vec4 evaluateProbe(vec3 worldPos, vec3 dir, float mipLevel, ReflProbeData probeData)
- {
- vec3 probeToPos = worldPos - probeData.position;
- float distToProbe = length(probeToPos);
- float normalizedDist = clamp(distToProbe / probeData.radius, float(0), float(1));
- if (distToProbe <= probeData.radius)
- {
- vec3 correctedDir;
- float contribution = 0,000000f;
- if (probeData.type == 0u)
- {
- correctedDir = getLookupForSphereProxy(worldPos, dir, probeData.position, probeData.radius);
- contribution = getSphereReflectionContribution(normalizedDist);
- }
- else if (probeData.type == 1u)
- {
- correctedDir = getLookupForBoxProxy(worldPos, dir, probeData.position, probeData.boxExtents, probeData.invBoxTransform, probeData.transitionDistance, contribution);
- }
- vec4 probeSample = textureLod(samplerCubeArray(gReflProbeCubemaps, gReflProbeSamp), vec4(correctedDir, probeData.cubemapIdx), mipLevel);
- probeSample *= vec4(contribution);
- return vec4(probeSample.rgb, (1.0f - contribution));
- }
- return vec4(0, 0, 0, 1.0f);
- }
- float getSpecularOcclusion(float NoV, float r, float ao)
- {
- float r2 = r * r;
- return clamp(pow(NoV + ao, r2) - 1.0f + ao, float(0), float(1));
- }
- layout(std140, binding = 46) uniform Lights
- {
- LightData gLights[8];
- };
- vec4 getDirectLighting(vec3 worldPos, vec3 V, vec3 R, SurfaceData surfaceData, uvec4 lightOffsets)
- {
- vec3 N = surfaceData.worldNormal.xyz;
- float roughness2 = max(surfaceData.roughness, 0.08f);
- roughness2 *= roughness2;
- vec3 outLuminance = vec3(0);
- float alpha = 0.0f;
- if (surfaceData.worldNormal.w > 0.0f)
- {
- for (uint i = 0u; i < lightOffsets.x; ++i)
- {
- LightData lightData = gLights[i];
- outLuminance += getLuminanceDirectional(lightData, worldPos, V, R, surfaceData);
- }
- for (uint j = lightOffsets.y; j < lightOffsets.z; ++j)
- {
- uint lightIdx = j;
- LightData lightData = gLights[lightIdx];
- outLuminance += getLuminanceRadial(lightData, worldPos, V, R, roughness2, surfaceData);
- }
- for (uint k = lightOffsets.z; k < lightOffsets.w; ++k)
- {
- uint lightIdx = k;
- LightData lightData = gLights[lightIdx];
- outLuminance += getLuminanceSpot(lightData, worldPos, V, R, roughness2, surfaceData);
- }
- outLuminance += surfaceData.albedo.rgb * gAmbientFactor / 3.1415926f;
- alpha = 1.0f;
- }
- return vec4(outLuminance, alpha);
- }
- layout(std140, binding = 47) uniform ReflProbes
- {
- ReflProbeData gReflectionProbes[8];
- };
- vec3 gatherReflectionRadiance(vec3 worldPos, vec3 dir, float roughness, float alpha, vec3 specularColor, uint probeOffset, uint numProbes)
- {
- if (gUseReflectionMaps == 0u)
- return specularColor;
- float mipLevel = mapRoughnessToMipLevel(roughness, int(gReflCubemapNumMips));
- vec3 xsr_output = vec3(0);
- for (uint i = 0u; i < numProbes; i++)
- {
- if (alpha < 0.001f)
- break;
- uint probeIdx = probeOffset + i;
- ReflProbeData probeData = gReflectionProbes[probeIdx];
- vec4 probeValue = evaluateProbe(worldPos, dir, mipLevel, probeData);
- xsr_output += probeValue.rgb * alpha;
- alpha *= probeValue.w;
- }
- if (gSkyCubemapAvailable > 0u)
- {
- float skyMipLevel = mapRoughnessToMipLevel(roughness, int(gSkyCubemapNumMips));
- vec4 skySample = textureLod(samplerCube(gSkyReflectionTex, gSkyReflectionSamp), dir, skyMipLevel) * gSkyBrightness;
- xsr_output += skySample.rgb * alpha;
- }
- return xsr_output;
- }
- vec3 getImageBasedSpecular(vec3 worldPos, vec3 V, vec3 R, SurfaceData surfaceData, float ao, vec4 ssr, uint probeOffset, uint numProbes)
- {
- vec3 N = surfaceData.worldNormal.xyz;
- float NoV = clamp(dot(N, V), float(0), float(1));
- vec3 specularColor = mix(vec3(0.04f, 0.04f, 0.04f), surfaceData.albedo.rgb, vec3(surfaceData.metalness));
- vec3 radiance = ssr.rgb;
- float alpha = 1.0f - ssr.a;
- float specOcclusion = getSpecularOcclusion(NoV, surfaceData.roughness * surfaceData.roughness, ao);
- alpha *= specOcclusion;
- radiance += gatherReflectionRadiance(worldPos, R, surfaceData.roughness, alpha, specularColor, probeOffset, numProbes);
- vec2 envBRDF = textureLod(sampler2D(gPreintegratedEnvBRDF, gPreintegratedEnvBRDFSamp), vec2(NoV, surfaceData.roughness), 0).rg;
- return radiance * (specularColor * envBRDF.x + vec3(envBRDF.y));
- }
- layout(std140, binding = 48) uniform LightAndReflProbeParams
- {
- uvec4 gLightOffsets;
- uint gReflProbeCount;
- };
- vec3 calcLighting(vec3 worldPosition, vec3 screenPosition, vec2 uv, SurfaceData surfaceData)
- {
- uvec4 lightOffsets = gLightOffsets;
- uvec2 reflProbeOffsetAndSize = uvec2(0, gReflProbeCount);
- vec3 V = normalize(gViewOrigin - worldPosition);
- vec3 N = surfaceData.worldNormal.xyz;
- vec3 R = 2,000000f * dot(V, N) * N - V;
- vec3 specR = getSpecularDominantDir(N, R, surfaceData.roughness);
- vec4 directLighting = getDirectLighting(worldPosition, V, specR, surfaceData, lightOffsets);
- float ao = float(texture(sampler2D(gAmbientOcclusionTex, gAmbientOcclusionSamp), uv));
- vec4 ssr = texture(sampler2D(gSSRTex, gSSRSamp), uv);
- vec3 imageBasedSpecular = getImageBasedSpecular(worldPosition, V, specR, surfaceData, ao, ssr, reflProbeOffsetAndSize.x, reflProbeOffsetAndSize.y);
- vec3 totalLighting = directLighting.rgb;
- totalLighting.rgb += imageBasedSpecular;
- return totalLighting;
- }
- layout(std140, binding = 49) uniform MaterialParams
- {
- float gOpacity;
- vec3 gEmissiveColor;
- vec2 gUVOffset;
- vec2 gUVTile;
- vec4 gTint;
- float gJiggleAmount;
- float gJiggleMaxAngle;
- };
- layout(binding = 50) uniform sampler gAlbedoSamp;
- layout(binding = 51) uniform sampler gNormalSamp;
- layout(binding = 52) uniform sampler gRoughnessSamp;
- layout(binding = 53) uniform sampler gMetalnessSamp;
- layout(binding = 54) uniform sampler gEmissiveMaskSamp;
- layout(binding = 55) uniform texture2D gAlbedoTex;
- layout(binding = 56) uniform texture2D gNormalTex;
- layout(binding = 57) uniform texture2D gRoughnessTex;
- layout(binding = 58) uniform texture2D gMetalnessTex;
- layout(binding = 59) uniform texture2D gEmissiveMaskTex;
- void main()
- {
- VStoFS xsr_input;
- xsr_input.position = gl_FragCoord;
- xsr_input.uv0 = bs_TEXCOORD0;
- xsr_input.worldPosition = bs_TEXCOORD1;
- xsr_input.tangentToWorldZ = bs_NORMAL0;
- xsr_input.tangentToWorldX = bs_TANGENT0;
- vec2 uv = xsr_input.uv0 * gUVTile + gUVOffset;
- vec3 normal = normalize(texture(sampler2D(gNormalTex, gNormalSamp), uv).xyz * 2.0f - vec3(1, 1, 1));
- vec3 worldNormal = calcWorldNormal(xsr_input, normal);
- SurfaceData surfaceData;
- surfaceData.albedo = texture(sampler2D(gAlbedoTex, gAlbedoSamp), uv) * gTint;
- surfaceData.worldNormal.xyz = worldNormal;
- surfaceData.worldNormal.w = 1.0f;
- surfaceData.roughness = texture(sampler2D(gRoughnessTex, gRoughnessSamp), uv).x;
- surfaceData.metalness = texture(sampler2D(gMetalnessTex, gMetalnessSamp), uv).x;
- vec3 lighting = calcLighting(xsr_input.worldPosition.xyz, vec3(xsr_input.position), uv, surfaceData);
- vec3 emissive = gEmissiveColor * texture(sampler2D(gEmissiveMaskTex, gEmissiveMaskSamp), uv).x;
- SV_Target0 = vec4(emissive + surfaceData.albedo.rgb, surfaceData.albedo.a * gOpacity);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement