now using deferred rendering instead of forward rendering; some little problem: grid not render, shadow not impl

This commit is contained in:
2026-03-18 14:28:02 +08:00
parent f1de5df4de
commit 57700da217
15 changed files with 731 additions and 420 deletions

View File

@ -0,0 +1,348 @@
#type vertex
#version 430 core
layout(location = 0) in vec3 a_Position;
layout(location = 1) in vec2 a_TexCoord;
out vec2 v_TexCoord;
void main()
{
v_TexCoord = a_TexCoord;
gl_Position = vec4(a_Position.xy, 0.0, 1.0);
}
#type fragment
#version 430 core
// ==================== 输入 ====================
in vec2 v_TexCoord;
// G-buffer 纹理
uniform sampler2D u_AlbedoMetallic; // RGB: albedo, A: metallic
uniform sampler2D u_NormalRoughness; // RGB: normal (encoded), A: roughness
uniform sampler2D u_EmissiveAO; // RGB: emissive, A: AO
uniform sampler2D u_Depth; // depth
// 相机参数
uniform mat4 u_InvViewProj; // 逆视图投影矩阵,用于重建世界坐标
uniform vec3 u_CameraPosition;
// 光源结构体与你的PBR着色器一致
struct DirectionalLight {
vec3 Direction;
vec3 Radiance;
float Intensity;
bool CastShadows;
};
struct PointLight {
vec3 Position;
vec3 Radiance;
float Intensity;
float Range;
bool CastShadows;
};
struct SpotLight {
vec3 Position;
vec3 Direction;
vec3 Radiance;
float Intensity;
float Range;
float InnerConeCos;
float OuterConeCos;
bool CastShadows;
};
uniform DirectionalLight u_DirectionalLights; // 仅一个方向光
uniform int u_PointLightCount;
uniform PointLight u_PointLights[16]; // 假设最多16个点光源
uniform int u_SpotLightCount;
uniform SpotLight u_SpotLights[16]; // 最多16个聚光源
// IBL 相关
uniform samplerCube u_EnvRadianceTex;
uniform samplerCube u_EnvIrradianceTex;
uniform sampler2D u_BRDFLUTTexture;
uniform float u_IBLContribution;
uniform float u_EnvMapRotation;
// 阴影相关
uniform sampler2D u_ShadowMap;
uniform float u_ShadowBias;
uniform float u_ShadowSoftness;
uniform int u_ShadowEnabled;
uniform float u_ShadowIntensity; // 阴影强度0-1
uniform mat4 u_LightSpaceMatrix; // 方向光光源空间矩阵
// 天空盒(可选)
uniform samplerCube u_Skybox; // 如果深度为1.0则采样天空盒
uniform float u_SkyIntensity;
uniform float u_SkyTextureLod;
// 输出
layout(location = 0) out vec4 o_Color;
// ==================== 常量 ====================
const float PI = 3.14159265359;
const float Epsilon = 0.00001;
const vec3 Fdielectric = vec3(0.04);
// ==================== 工具函数 ====================
// 从深度重建世界坐标
vec3 worldPosFromDepth(vec2 uv, float depth) {
vec4 clipPos = vec4(uv * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);
vec4 worldPos = u_InvViewProj * clipPos;
return worldPos.xyz / worldPos.w;
}
// 从深度重建世界空间方向(用于天空盒采样)
vec3 worldDirFromUV(vec2 uv) {
// 假设深度为1.0时,得到远平面方向
vec4 clipPos = vec4(uv * 2.0 - 1.0, 1.0, 1.0);
vec4 worldPos = u_InvViewProj * clipPos;
return normalize(worldPos.xyz / worldPos.w);
}
// 旋转向量绕Y轴
vec3 RotateVectorAboutY(float angle, vec3 vec) {
angle = radians(angle);
mat3 rotationMatrix = mat3(
vec3(cos(angle), 0.0, sin(angle)),
vec3(0.0, 1.0, 0.0),
vec3(-sin(angle), 0.0, cos(angle))
);
return rotationMatrix * vec;
}
// ==================== PBR 函数(复用你的代码) ====================
float ndfGGX(float cosLh, float roughness) {
float alpha = roughness * roughness;
float alphaSq = alpha * alpha;
float denom = (cosLh * cosLh) * (alphaSq - 1.0) + 1.0;
return alphaSq / (PI * denom * denom);
}
float GeometrySchlickGGX(float NdotV, float roughness) {
float r = (roughness + 1.0);
float k = (r * r) / 8.0;
float nom = NdotV;
float denom = NdotV * (1.0 - k) + k;
return nom / denom;
}
float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness) {
float NdotV = max(dot(N, V), 0.0);
float NdotL = max(dot(N, L), 0.0);
float ggx2 = GeometrySchlickGGX(NdotV, roughness);
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
return ggx1 * ggx2;
}
vec3 fresnelSchlick(vec3 F0, float cosTheta) {
return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
}
vec3 fresnelSchlickRoughness(vec3 F0, float cosTheta, float roughness) {
return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0);
}
// ---------- 方向光 ----------
vec3 ComputeDirectionalLight(DirectionalLight light, vec3 F0, vec3 N, vec3 V, float NdotV, vec3 albedo, float roughness, float metallic) {
vec3 L = normalize(-light.Direction);
vec3 Lradiance = light.Radiance * light.Intensity;
vec3 Lh = normalize(L + V);
float cosLi = max(dot(N, L), 0.0);
float cosLh = max(dot(N, Lh), 0.0);
vec3 F = fresnelSchlick(F0, max(dot(Lh, V), 0.0));
float D = ndfGGX(cosLh, roughness);
float G = GeometrySmith(N, V, L, roughness);
vec3 kd = (1.0 - F) * (1.0 - metallic);
vec3 diffuseBRDF = kd * albedo;
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * NdotV);
return (diffuseBRDF + specularBRDF) * Lradiance * cosLi;
}
// ---------- 点光源 ----------
vec3 ComputePointLight(PointLight light, vec3 F0, vec3 N, vec3 V, float NdotV, vec3 albedo, float roughness, float metallic, vec3 worldPos) {
vec3 lightVec = light.Position - worldPos;
float dist = length(lightVec);
if (dist > light.Range) return vec3(0.0);
vec3 L = lightVec / dist;
vec3 Lradiance = light.Radiance * light.Intensity;
float attenuation = 1.0 / (dist * dist + 0.0001);
float rangeFactor = clamp(1.0 - (dist / light.Range), 0.0, 1.0);
rangeFactor = rangeFactor * rangeFactor;
attenuation *= rangeFactor;
vec3 Lh = normalize(L + V);
float cosLi = max(dot(N, L), 0.0);
float cosLh = max(dot(N, Lh), 0.0);
vec3 F = fresnelSchlick(F0, max(dot(Lh, V), 0.0));
float D = ndfGGX(cosLh, roughness);
float G = GeometrySmith(N, V, L, roughness);
vec3 kd = (1.0 - F) * (1.0 - metallic);
vec3 diffuseBRDF = kd * albedo;
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * NdotV);
return (diffuseBRDF + specularBRDF) * Lradiance * cosLi * attenuation;
}
// ---------- 聚光源 ----------
vec3 ComputeSpotLight(SpotLight light, vec3 F0, vec3 N, vec3 V, float NdotV, vec3 albedo, float roughness, float metallic, vec3 worldPos) {
vec3 lightVec = light.Position - worldPos;
float dist = length(lightVec);
if (dist > light.Range) return vec3(0.0);
vec3 L = lightVec / dist;
vec3 Lradiance = light.Radiance * light.Intensity;
float attenuation = 1.0 / (dist * dist + 0.0001);
float rangeFactor = clamp(1.0 - (dist / light.Range), 0.0, 1.0);
rangeFactor = rangeFactor * rangeFactor;
attenuation *= rangeFactor;
float cosAngle = dot(-L, normalize(light.Direction));
if (cosAngle < light.OuterConeCos) return vec3(0.0);
float angleFalloff = (cosAngle - light.OuterConeCos) / (light.InnerConeCos - light.OuterConeCos);
angleFalloff = clamp(angleFalloff, 0.0, 1.0);
attenuation *= angleFalloff;
vec3 Lh = normalize(L + V);
float cosLi = max(dot(N, L), 0.0);
float cosLh = max(dot(N, Lh), 0.0);
vec3 F = fresnelSchlick(F0, max(dot(Lh, V), 0.0));
float D = ndfGGX(cosLh, roughness);
float G = GeometrySmith(N, V, L, roughness);
vec3 kd = (1.0 - F) * (1.0 - metallic);
vec3 diffuseBRDF = kd * albedo;
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * NdotV);
return (diffuseBRDF + specularBRDF) * Lradiance * cosLi * attenuation;
}
// ---------- IBL ----------
vec3 IBL(vec3 F0, vec3 N, vec3 V, float NdotV, float roughness, float metallic, vec3 albedo) {
vec3 irradiance = texture(u_EnvIrradianceTex, N).rgb;
vec3 F = fresnelSchlickRoughness(F0, NdotV, roughness);
vec3 kd = (1.0 - F) * (1.0 - metallic);
vec3 diffuseIBL = albedo * irradiance;
vec3 R = 2.0 * NdotV * N - V; // 反射向量
int u_EnvRadianceTexLevels = textureQueryLevels(u_EnvRadianceTex);
vec3 specularIrradiance = textureLod(
u_EnvRadianceTex,
RotateVectorAboutY(u_EnvMapRotation, R),
roughness * u_EnvRadianceTexLevels
).rgb;
vec2 specularBRDF = texture(u_BRDFLUTTexture, vec2(NdotV, 1.0 - roughness)).rg;
vec3 specularIBL = specularIrradiance * (F * specularBRDF.x + specularBRDF.y);
return kd * diffuseIBL + specularIBL;
}
// ---------- 阴影 ----------
float calculateShadow(vec4 fragPosLightSpace, vec3 normal, vec3 lightDir) {
if (u_ShadowEnabled == 0) return 0.0;
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
projCoords = projCoords * 0.5 + 0.5;
if (projCoords.z > 1.0 || projCoords.x < 0.0 || projCoords.x > 1.0 || projCoords.y < 0.0 || projCoords.y > 1.0)
return 0.0;
float closestDepth = texture(u_ShadowMap, projCoords.xy).r;
float currentDepth = projCoords.z;
float bias = max(u_ShadowBias * (1.0 - dot(normal, lightDir)), u_ShadowBias * 0.1);
float shadow = 0.0;
vec2 texelSize = 1.0 / textureSize(u_ShadowMap, 0);
int pcfRange = int(u_ShadowSoftness);
int sampleCount = 0;
for (int x = -pcfRange; x <= pcfRange; ++x) {
for (int y = -pcfRange; y <= pcfRange; ++y) {
float pcfDepth = texture(u_ShadowMap, projCoords.xy + vec2(x, y) * texelSize).r;
shadow += (currentDepth - bias > pcfDepth) ? 1.0 : 0.0;
sampleCount++;
}
}
shadow /= float(sampleCount);
return shadow * u_ShadowIntensity; // 应用阴影强度
}
// ==================== 主函数 ====================
void main() {
vec2 uv = v_TexCoord;
float depth = texture(u_Depth, uv).r;
if (depth >= 1.0) {
vec3 dir = worldDirFromUV(uv);
vec3 skyColor = textureLod(u_Skybox, dir, u_SkyTextureLod).rgb * u_SkyIntensity;
o_Color = vec4(skyColor, 1.0);
return;
}
vec4 albedoMetal = texture(u_AlbedoMetallic, uv);
vec4 normalRough = texture(u_NormalRoughness, uv);
vec4 emissiveAO = texture(u_EmissiveAO, uv);
vec3 albedo = albedoMetal.rgb;
float metallic = albedoMetal.a;
vec3 normal = normalRough.rgb * 2.0 - 1.0;
float roughness = normalRough.a;
vec3 emissive = emissiveAO.rgb;
float ao = emissiveAO.a;
vec3 worldPos = worldPosFromDepth(uv, depth);
vec3 V = normalize(u_CameraPosition - worldPos);
float NdotV = clamp(dot(normal, V), 0.0, 1.0);
vec3 F0 = mix(Fdielectric, albedo, metallic);
vec3 Lo = vec3(0.0);
// Direction Light
if (u_DirectionalLights.Intensity > 0.0) {
Lo += ComputeDirectionalLight(u_DirectionalLights, F0, normal, V, NdotV, albedo, roughness, metallic);
}
// Point Light
for (int i = 0; i < u_PointLightCount; ++i) {
Lo += ComputePointLight(u_PointLights[i], F0, normal, V, NdotV, albedo, roughness, metallic, worldPos);
}
// Spot light
for (int i = 0; i < u_SpotLightCount; ++i) {
Lo += ComputeSpotLight(u_SpotLights[i], F0, normal, V, NdotV, albedo, roughness, metallic, worldPos);
}
float shadowFactor = 1.0;
if (u_ShadowEnabled > 0 && u_DirectionalLights.CastShadows && u_DirectionalLights.Intensity > 0.0) {
vec4 fragPosLightSpace = u_LightSpaceMatrix * vec4(worldPos, 1.0);
float shadow = calculateShadow(fragPosLightSpace, normal, u_DirectionalLights.Direction);
shadowFactor = 1.0 - shadow;
}
Lo *= shadowFactor;
// 计算 IBL
vec3 ibl = IBL(F0, normal, V, NdotV, roughness, metallic, albedo) * u_IBLContribution;
vec3 finalColor = Lo + ibl + emissive;
o_Color = vec4(finalColor, 1.0);
}