add material sphere preview, add ssr, improve shadow

This commit is contained in:
2026-05-14 21:37:02 +08:00
parent d11f8bb0c9
commit f50824bdb1
30 changed files with 1277 additions and 356 deletions

View File

@ -0,0 +1,207 @@
#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_InvProjection;
uniform vec2 u_ScreenSize;
uniform float u_CameraNear;
uniform float u_CameraFar;
uniform int u_Steps = 64;
uniform float u_Thickness = 0.5;
uniform float u_MaxDistance = 30.0;
uniform float u_Intensity = 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 ReconstructViewPos(vec2 tc, float depth)
{
float z = depth * 2.0 - 1.0;
vec4 clipPos = vec4(tc * 2.0 - 1.0, z, 1.0);
vec4 viewPos4 = u_InvProjection * clipPos;
return viewPos4.xyz / viewPos4.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 pL = ReconstructViewPos(tcL, depthL);
vec3 pR = ReconstructViewPos(tcR, depthR);
vec3 pB = ReconstructViewPos(tcB, depthB);
vec3 pT = ReconstructViewPos(tcT, depthT);
vec3 dx = pR - pL;
vec3 dy = pT - pB;
return normalize(cross(dx, dy));
}
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 viewPos = ReconstructViewPos(v_TexCoord, depth);
vec3 normal = ReconstructNormalFromDepth(v_TexCoord, depth);
vec3 viewDir = normalize(-viewPos);
float NdotV = max(dot(normal, viewDir), 0.0);
vec3 reflectDir = reflect(-viewDir, normal);
if (dot(reflectDir, normal) < 0.0)
{
o_Color = vec4(0.0);
return;
}
vec3 rayOrigin = viewPos + normal * 0.02;
vec3 rayEnd = rayOrigin + reflectDir * u_MaxDistance;
vec4 p0 = u_Projection * vec4(rayOrigin, 1.0);
vec4 p1 = u_Projection * vec4(rayEnd, 1.0);
float k0 = 1.0 / p0.w;
float k1 = 1.0 / p1.w;
p0.xyz *= k0;
p1.xyz *= k1;
vec3 v0 = rayOrigin * k0;
vec3 v1 = rayEnd * k1;
vec2 s0 = p0.xy * 0.5 + 0.5;
vec2 s1 = p1.xy * 0.5 + 0.5;
vec2 sDelta = s1 - s0;
float screenDist = length(sDelta * u_ScreenSize);
if (screenDist < 1.0)
{
o_Color = vec4(0.0);
return;
}
float divisions = min(screenDist, float(u_Steps));
vec3 dV = (v1 - v0) / divisions;
float dK = (k1 - k0) / divisions;
vec2 dS = sDelta / divisions;
vec3 curV = v0;
float curK = k0;
vec2 curS = s0;
vec2 hitUV = vec2(0.0);
bool found = false;
for (int i = 0; i < int(divisions); i++)
{
curV += dV;
curK += dK;
curS += dS;
if (curS.x < 0.0 || curS.x > 1.0 || curS.y < 0.0 || curS.y > 1.0)
break;
float sampleDepth = texture(u_DepthTexture, curS).r;
float surfDepth = LinearizeDepth(sampleDepth);
float rayDepth = -curV.z / curK;
float depthDiff = rayDepth - surfDepth;
if (depthDiff > 0.0 && depthDiff < u_Thickness)
{
hitUV = curS;
found = true;
break;
}
}
if (!found)
{
o_Color = vec4(0.0);
return;
}
vec3 hitNormal = ReconstructNormalFromDepth(hitUV, texture(u_DepthTexture, hitUV).r);
if (dot(hitNormal, -reflectDir) < 0.0)
{
o_Color = vec4(0.0);
return;
}
vec3 reflectColor = texture(u_ColorTexture, hitUV).rgb;
float dist = distance(viewPos, ReconstructViewPos(hitUV, texture(u_DepthTexture, hitUV).r));
float fadeFactor = 1.0 - smoothstep(u_MaxDistance * 0.5, u_MaxDistance, dist);
float edgeFade = 1.0;
edgeFade *= smoothstep(0.0, 0.15, hitUV.x);
edgeFade *= smoothstep(0.0, 0.15, hitUV.y);
edgeFade *= smoothstep(0.0, 0.15, 1.0 - hitUV.x);
edgeFade *= smoothstep(0.0, 0.15, 1.0 - hitUV.y);
vec3 F0 = mix(vec3(0.04), reflectColor, metalness);
vec3 Fresnel = F0 + (1.0 - F0) * pow(1.0 - NdotV, 5.0);
float roughnessFade = 1.0 - roughness * roughness;
vec3 ssrContrib = reflectColor * Fresnel * fadeFactor * edgeFade * roughnessFade * u_Intensity;
float ssrAlpha = length(Fresnel) * fadeFactor * edgeFade * roughnessFade;
o_Color = vec4(ssrContrib, ssrAlpha);
}