Files
HelloVulkan/shaders/simple_shader.vert
T
atdunbg 2c4efc5165 feat: 多光源——点光源类型(距离衰减,位置来自 Transform)
- LightComponent 加 Type(Directional/Point)+ radius;点光位置取
  实体 Transform(固有组件首次实际受益)
- LightData shader 契约扩为 4×vec4(color/direction/position/params,
  每灯 64B,未用字段置零);UBO 688→816B
- 光照循环按类型分支:方向光无衰减;点光 L 指向光源 + 平方距离衰减,
  衰减半径外跳过;CSM 阴影只来自第 0 盏方向光
- main.cpp:SunTemple 场景加暖橙火坑光 + 冷蓝填充光(点光);
  KeyLight/FillLight 改 designated initializer
2026-09-23 17:46:25 +08:00

75 lines
3.0 KiB
GLSL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#version 450
const int MAX_LIGHTS = 4;
struct Light {
vec4 color; // rgb = 颜色,a = 强度
vec4 direction; // 方向光:xyz = 方向(已归一)
vec4 position; // 点光:xyz = 世界位置
vec4 params; // x = 类型(0=方向,1=点),y = 衰减半径
};
layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inNormal;
layout(location = 2) in vec2 inUV;
layout(location = 3) in vec3 inTangent;
layout(location = 0) out vec2 fragUV;
layout(location = 1) out vec3 fragNormal;
layout(location = 2) out vec3 fragWorldPos;
layout(location = 3) out float fragViewDepth; // CSM:视图深度(级联选择)
layout(location = 4) out vec2 fragVelocity; // TAA:clip 空间运动向量
layout(location = 5) out vec3 fragTangent; // 世界空间切线(法线贴图)
// GPUDriven:模型矩阵从实例缓冲按实例索引取。
// 同一 mesh 的 N 个实体 = 1 次 drawIndexed(instanceCount=N),
// draw 侧用 firstInstance 指向该 batch 在实例数组中的起始下标。
layout(std430, set = 0, binding = 1) readonly buffer ObjectBuffer {
mat4 models[]; // 连续 mat4 数组(16B 对齐,std430/std140 布局一致)
} objects;
// 上一帧实例矩阵(与 ObjectBuffer 同下标 = 同一实例的上一帧姿态)
layout(std430, set = 0, binding = 2) readonly buffer PrevObjectBuffer {
mat4 prevModels[];
} prevObjects;
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;
void main() {
mat4 model = objects.models[gl_InstanceIndex];
vec4 worldPos = model * vec4(inPosition, 1.0);
gl_Position = ubo.proj * ubo.view * worldPos;
// ---- TAA velocity:当前帧与上一帧的 clip 空间位置差(UV 空间)----
// 抖动只进光栅化 gl_Position,不进 velocity(否则抖动本身被当成运动)
vec4 currClip = ubo.projNoJitter * ubo.view * worldPos;
vec4 prevWorldPos = prevObjects.prevModels[gl_InstanceIndex] * vec4(inPosition, 1.0);
vec4 prevClip = ubo.prevProj * ubo.prevView * prevWorldPos;
fragVelocity = (currClip.xy / currClip.w - prevClip.xy / prevClip.w) * 0.5;
fragWorldPos = worldPos.xyz;
// CSM:视图深度(正值,与 cascadeSplits 同尺度)
fragViewDepth = -(ubo.view * worldPos).z;
mat3 normalMatrix = mat3(transpose(inverse(model)));
fragNormal = normalize(normalMatrix * inNormal);
// 切线随模型变换(法线贴图 TBN;无切线数据保持零,frag 侧退回几何法线)
fragTangent = normalize(mat3(model) * inTangent);
// 零向量 normalize 产生 NaN,这里直接透传零,frag 判长度
fragTangent = dot(inTangent, inTangent) > 0.0 ? fragTangent : vec3(0.0);
fragUV = inUV;
}