179 lines
4.7 KiB
GLSL
179 lines
4.7 KiB
GLSL
#type vertex
|
|
#version 430
|
|
|
|
layout(location = 0) in vec3 a_Position;
|
|
layout(location = 1) in vec2 a_TexCoord;
|
|
|
|
out vec2 v_TexCoord;
|
|
|
|
void main()
|
|
{
|
|
vec4 position = vec4(a_Position.xy, 0.0, 1.0);
|
|
v_TexCoord = a_TexCoord;
|
|
gl_Position = position;
|
|
}
|
|
|
|
#type fragment
|
|
#version 430
|
|
|
|
layout(location = 0) out vec4 o_Color;
|
|
|
|
in vec2 v_TexCoord;
|
|
|
|
uniform sampler2D u_ColorTexture;
|
|
uniform sampler2D u_DepthTexture;
|
|
uniform sampler2D u_MaterialInfoTexture;
|
|
|
|
uniform mat4 u_Projection;
|
|
uniform mat4 u_View;
|
|
uniform mat4 u_InvViewProjection;
|
|
|
|
uniform vec3 u_CameraPosition;
|
|
|
|
uniform vec2 u_ScreenSize;
|
|
uniform float u_CameraNear;
|
|
uniform float u_CameraFar;
|
|
|
|
uniform int u_Steps = 32;
|
|
uniform float u_Thickness = 0.5;
|
|
uniform float u_MaxDistance = 30.0;
|
|
uniform float u_StepSize = 0.5;
|
|
uniform float u_RayOffset = 0.1;
|
|
uniform float u_Intensity = 1.0;
|
|
|
|
float saturate(float x)
|
|
{
|
|
return clamp(x, 0.0, 1.0);
|
|
}
|
|
|
|
float LinearizeDepth(float depth)
|
|
{
|
|
float z = depth * 2.0 - 1.0;
|
|
return (2.0 * u_CameraNear * u_CameraFar) / (u_CameraFar + u_CameraNear - z * (u_CameraFar - u_CameraNear));
|
|
}
|
|
|
|
vec3 ComputeWorldSpacePosition(vec2 uv, float depth)
|
|
{
|
|
vec4 clipPos = vec4(uv * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);
|
|
vec4 worldPos = u_InvViewProjection * clipPos;
|
|
return worldPos.xyz / worldPos.w;
|
|
}
|
|
|
|
vec3 ReconstructNormalFromDepth(vec2 tc, float depth)
|
|
{
|
|
vec2 texelSize = 1.0 / u_ScreenSize;
|
|
|
|
vec2 tcL = tc - vec2(texelSize.x, 0.0);
|
|
vec2 tcR = tc + vec2(texelSize.x, 0.0);
|
|
vec2 tcB = tc - vec2(0.0, texelSize.y);
|
|
vec2 tcT = tc + vec2(0.0, texelSize.y);
|
|
|
|
float depthL = texture(u_DepthTexture, tcL).r;
|
|
float depthR = texture(u_DepthTexture, tcR).r;
|
|
float depthB = texture(u_DepthTexture, tcB).r;
|
|
float depthT = texture(u_DepthTexture, tcT).r;
|
|
|
|
vec3 pC = ComputeWorldSpacePosition(tc, depth);
|
|
vec3 pR = ComputeWorldSpacePosition(tcR, depthR);
|
|
vec3 pT = ComputeWorldSpacePosition(tcT, depthT);
|
|
|
|
vec3 dx = pR - pC;
|
|
vec3 dy = pT - pC;
|
|
|
|
return normalize(cross(dx, dy));
|
|
}
|
|
|
|
vec3 ComputeNDCWithZ(vec3 worldPos)
|
|
{
|
|
vec4 clipPos = u_Projection * u_View * vec4(worldPos, 1.0);
|
|
vec3 ndc = clipPos.xyz / clipPos.w;
|
|
ndc.xy = ndc.xy * 0.5 + 0.5;
|
|
return ndc;
|
|
}
|
|
|
|
void main()
|
|
{
|
|
float depth = texture(u_DepthTexture, v_TexCoord).r;
|
|
|
|
if (depth >= 1.0)
|
|
{
|
|
o_Color = vec4(0.0);
|
|
return;
|
|
}
|
|
|
|
vec4 matInfo = texture(u_MaterialInfoTexture, v_TexCoord);
|
|
float metalness = matInfo.r;
|
|
float roughness = matInfo.g;
|
|
|
|
if (roughness > 0.9)
|
|
{
|
|
o_Color = vec4(0.0);
|
|
return;
|
|
}
|
|
|
|
vec3 positionWS = ComputeWorldSpacePosition(v_TexCoord, depth);
|
|
vec3 viewWS = normalize(u_CameraPosition - positionWS);
|
|
vec3 normalWS = ReconstructNormalFromDepth(v_TexCoord, depth);
|
|
vec3 reflectionWS = normalize(reflect(-viewWS, normalWS));
|
|
|
|
if (dot(reflectionWS, normalWS) < 0.0)
|
|
{
|
|
o_Color = vec4(0.0);
|
|
return;
|
|
}
|
|
|
|
vec3 rayWS = positionWS + normalWS * u_RayOffset;
|
|
|
|
for (int i = 0; i < u_Steps; i++)
|
|
{
|
|
rayWS += reflectionWS * u_StepSize;
|
|
|
|
vec3 rayNDC = ComputeNDCWithZ(rayWS);
|
|
float rayDepth = rayNDC.z;
|
|
|
|
vec2 raySS = rayNDC.xy * u_ScreenSize;
|
|
|
|
if (rayNDC.x < 0.0 || rayNDC.x > 1.0 || rayNDC.y < 0.0 || rayNDC.y > 1.0)
|
|
break;
|
|
|
|
float sceneDepth = texture(u_DepthTexture, rayNDC.xy).r;
|
|
float sceneDepthLinear = LinearizeDepth(sceneDepth);
|
|
float rayDepthLinear = LinearizeDepth(rayDepth * 0.5 + 0.5);
|
|
|
|
float delta = rayDepthLinear - sceneDepthLinear;
|
|
|
|
if (delta >= 0.0 && delta <= u_Thickness)
|
|
{
|
|
vec3 hitNormalWS = ReconstructNormalFromDepth(rayNDC.xy, sceneDepth);
|
|
if (dot(hitNormalWS, reflectionWS) > 0.0)
|
|
break;
|
|
|
|
float ssrStrength = saturate(1.0 - roughness * roughness);
|
|
|
|
float dist = distance(positionWS, rayWS);
|
|
float fadeFactor = 1.0 - smoothstep(u_MaxDistance * 0.3, u_MaxDistance, dist);
|
|
|
|
float edgeFade = 1.0;
|
|
edgeFade *= smoothstep(0.0, 0.1, rayNDC.x);
|
|
edgeFade *= smoothstep(0.0, 0.1, rayNDC.y);
|
|
edgeFade *= smoothstep(0.0, 0.1, 1.0 - rayNDC.x);
|
|
edgeFade *= smoothstep(0.0, 0.1, 1.0 - rayNDC.y);
|
|
|
|
float NdotV = max(dot(normalWS, viewWS), 0.0);
|
|
vec3 F0 = mix(vec3(0.04), vec3(1.0), metalness);
|
|
vec3 Fresnel = F0 + (1.0 - F0) * pow(1.0 - NdotV, 5.0);
|
|
|
|
ssrStrength *= fadeFactor * edgeFade * u_Intensity;
|
|
|
|
vec4 color = texture(u_ColorTexture, rayNDC.xy);
|
|
color.rgb *= ssrStrength * Fresnel;
|
|
color.a = ssrStrength * dot(Fresnel, vec3(0.333));
|
|
|
|
o_Color = color;
|
|
return;
|
|
}
|
|
}
|
|
|
|
o_Color = vec4(0.0);
|
|
}
|