- Material:单贴图 → 4 槽(binding=Slot 枚举),MakeCacheKey 组合键 保持材质去重(同贴图组合共享描述符集) - Model:读取 aiTextureType DIFFUSE/NORMALS/SPECULAR/EMISSIVE 四类路径; aiProcess_CalcTangentSpace 生成切线(Vertex +tangent 属性,location 3); 每槽默认纹理兜底(白/平法线(128,128,255)/黑/黑,1x1) - 纹理 sRGB 语义按槽位:颜色图 SRGB 变体,数据图(Normal/Specular)线性 UNORM——Texture 路径加载加 srgb 参数;修复 InitFromPixels 图文 format 不一致的 validation 警告 - UBO 尾部追加 cameraPos(Blinn-Phong V 向量) - simple_shader.frag:TBN 法线贴图(无切线/平法线退化回几何法线)+ Blinn-Phong 高光(specular 图强度系数)+ 自发光直加 - SunTemple 实测:148 张 DDS 全槽位加载(96 张线性变体)、1056 mesh、 validation 零警告
112 lines
3.9 KiB
GLSL
112 lines
3.9 KiB
GLSL
#version 450
|
||
|
||
const int MAX_LIGHTS = 4;
|
||
|
||
struct Light {
|
||
vec4 direction;
|
||
vec4 color;
|
||
};
|
||
|
||
layout(location = 0) in vec2 fragUV;
|
||
layout(location = 1) in vec3 fragNormal;
|
||
layout(location = 2) in vec3 fragWorldPos;
|
||
layout(location = 3) in float fragViewDepth;
|
||
layout(location = 4) in vec2 fragVelocity;
|
||
layout(location = 5) in vec3 fragTangent;
|
||
|
||
layout(location = 0) out vec4 outColor;
|
||
layout(location = 1) out vec2 outVelocity; // TAA velocity 附件
|
||
|
||
layout(set = 0, binding = 0) uniform UniformBufferObject {
|
||
mat4 view;
|
||
mat4 proj;
|
||
mat4 lightSpace[3]; // CSM 各级联光空间 VP
|
||
vec4 cascadeSplits; // xyz = 级联 0..2 远边界(视图深度)
|
||
vec4 ambientColor;
|
||
Light lights[MAX_LIGHTS];
|
||
mat4 projNoJitter;
|
||
mat4 prevView;
|
||
mat4 prevProj;
|
||
vec4 cameraPos;
|
||
} ubo;
|
||
|
||
// 材质纹理槽(binding = Material::Slot)
|
||
layout(set = 1, binding = 0) uniform sampler2D albedoMap;
|
||
layout(set = 1, binding = 1) uniform sampler2D normalMap;
|
||
layout(set = 1, binding = 2) uniform sampler2D specularMap;
|
||
layout(set = 1, binding = 3) uniform sampler2D emissiveMap;
|
||
|
||
layout(set = 2, binding = 0) uniform sampler2D shadowMap0; // CSM 级联 0(最近)
|
||
layout(set = 2, binding = 1) uniform sampler2D shadowMap1; // 级联 1
|
||
layout(set = 2, binding = 2) uniform sampler2D shadowMap2; // 级联 2(最远)
|
||
|
||
// 第 0 盏灯(KeyLight)的 CSM 阴影因子:0.3 影中 / 1.0 受光。
|
||
// 级联按视图深度选择;采样器均 clamp-to-border 白色:
|
||
// 光视锥外自动 1.0(无阴影),省出界分支。
|
||
float ShadowFactor(vec3 N, float viewDepth) {
|
||
// 级联选择:第一个 viewDepth < split 的级联
|
||
int cascade = 2;
|
||
for (int i = 0; i < 3; ++i) {
|
||
if (viewDepth < ubo.cascadeSplits[i]) { cascade = i; break; }
|
||
}
|
||
|
||
vec4 ls = ubo.lightSpace[cascade] * vec4(fragWorldPos, 1.0);
|
||
vec3 proj = ls.xyz / ls.w;
|
||
// NDC [-1,1] → UV [0,1](ortho 的 w=1)
|
||
vec2 uv = proj.xy * 0.5 + 0.5;
|
||
|
||
float closest;
|
||
if (cascade == 0) closest = texture(shadowMap0, uv).r;
|
||
else if (cascade == 1) closest = texture(shadowMap1, uv).r;
|
||
else closest = texture(shadowMap2, uv).r;
|
||
|
||
// 斜率缩放 bias:掠射面用更大的 bias 压 acne
|
||
vec3 L = normalize(-ubo.lights[0].direction.xyz);
|
||
float bias = max(0.004 * (1.0 - dot(N, L)), 0.0012);
|
||
|
||
return (proj.z - bias > closest) ? 0.3 : 1.0;
|
||
}
|
||
|
||
// 法线贴图 → 世界空间法线(TBN 构建)。
|
||
// 无切线数据(零向量)或平法线贴图时退回几何法线。
|
||
vec3 MappedNormal(vec3 geomN, vec3 T, vec2 uv) {
|
||
if (dot(T, T) < 1e-4) return geomN;
|
||
|
||
vec3 N = geomN;
|
||
vec3 nT = normalize(T - N * dot(N, T)); // 正交化
|
||
vec3 B = cross(N, nT);
|
||
vec3 sampled = texture(normalMap, uv).xyz * 2.0 - 1.0;
|
||
if (dot(sampled, sampled) < 1e-4) return geomN;
|
||
|
||
return normalize(nT * sampled.x + B * sampled.y + N * sampled.z);
|
||
}
|
||
|
||
void main() {
|
||
vec3 albedo = texture(albedoMap, fragUV).rgb;
|
||
float specIntensity = texture(specularMap, fragUV).r;
|
||
vec3 emissive = texture(emissiveMap, fragUV).rgb;
|
||
|
||
vec3 N = MappedNormal(normalize(fragNormal), fragTangent, fragUV);
|
||
vec3 V = normalize(ubo.cameraPos.xyz - fragWorldPos);
|
||
|
||
vec3 result = ubo.ambientColor.rgb * albedo;
|
||
|
||
for (int i = 0; i < MAX_LIGHTS; ++i) {
|
||
vec3 L = normalize(-ubo.lights[i].direction.xyz);
|
||
float diff = max(dot(N, L), 0.0);
|
||
// Blinn-Phong 高光(半程向量;specular 图做强度系数)
|
||
vec3 H = normalize(L + V);
|
||
float spec = pow(max(dot(N, H), 0.0), 32.0) * specIntensity;
|
||
|
||
float shade = (i == 0) ? ShadowFactor(N, fragViewDepth) : 1.0;
|
||
result += ubo.lights[i].color.rgb * ubo.lights[i].color.a *
|
||
(albedo * diff + vec3(spec)) * shade;
|
||
}
|
||
|
||
// 自发光不经光照/阴影直接叠加
|
||
result += emissive;
|
||
|
||
outColor = vec4(result, 1.0);
|
||
outVelocity = fragVelocity;
|
||
}
|