- UniformBuffer ring 支持 eStorageBuffer usage(GPUDriven 实例矩阵 per-frame-slot,正确性保证与 UBO 一致:fence 等待后写入) - DescriptorManager 加 UpdateStorageBuffer;池补 STORAGE_BUFFER 类型 - Set0 新增 binding1 = 实例矩阵 SSBO(vertex 读取,std430) - Forward pass 重写:每帧从 ECS 收集实例矩阵(按 mesh 聚合 batch, 两趟遍历保证 batch 区间连续),同 mesh 的 N 个实体合并为 一次 drawIndexed(instanceCount=N),firstInstance 指向 batch 起点; vertex shader 经 gl_InstanceIndex 取模型矩阵,forward 不再用 push - draw 数 = 唯一 mesh 数,与实体数量解耦(4096 实例上限, 超出截断告警;聚合改哈希为后续 TODO) 验证:8 pass 全活,validation 0 error 0 warning,GPU Timings 面板 实测各 pass 毫秒,场景渲染与阴影正确
48 lines
1.4 KiB
GLSL
48 lines
1.4 KiB
GLSL
#version 450
|
||
|
||
const int MAX_LIGHTS = 4;
|
||
|
||
struct Light {
|
||
vec4 direction;
|
||
vec4 color;
|
||
};
|
||
|
||
layout(location = 0) in vec3 inPosition;
|
||
layout(location = 1) in vec3 inNormal;
|
||
layout(location = 2) in vec2 inUV;
|
||
|
||
layout(location = 0) out vec2 fragUV;
|
||
layout(location = 1) out vec3 fragNormal;
|
||
layout(location = 2) out vec3 fragWorldPos;
|
||
layout(location = 3) out vec3 fragLightSpacePos;
|
||
|
||
// 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;
|
||
|
||
layout(set = 0, binding = 0) uniform UniformBufferObject {
|
||
mat4 view;
|
||
mat4 proj;
|
||
mat4 lightSpace;
|
||
vec4 ambientColor;
|
||
Light lights[MAX_LIGHTS];
|
||
} ubo;
|
||
|
||
void main() {
|
||
mat4 model = objects.models[gl_InstanceIndex];
|
||
|
||
vec4 worldPos = model * vec4(inPosition, 1.0);
|
||
gl_Position = ubo.proj * ubo.view * worldPos;
|
||
|
||
fragWorldPos = worldPos.xyz;
|
||
// 光空间坐标(含 Vulkan [0,1] 深度重映射,与 shadow pass 写入端共用同一矩阵)
|
||
fragLightSpacePos = (ubo.lightSpace * worldPos).xyz;
|
||
|
||
mat3 normalMatrix = mat3(transpose(inverse(model)));
|
||
fragNormal = normalize(normalMatrix * inNormal);
|
||
|
||
fragUV = inUV;
|
||
} |