#version 450 // 天空盒像素:NDC → 世界方向 → cube 采样。 // invVP = inverse(projNoJitter × mat4(mat3(view))):去掉平移的视图, // 反投影结果即"相机相对"的世界方向,normalize 后直接采样 cube。 layout(location = 0) in vec2 fragUV; layout(location = 0) out vec4 outColor; layout(location = 1) out vec2 outVelocity; // TAA velocity 附件 layout(set = 0, binding = 0) uniform samplerCube envMap; // push 与 skybox.vert 一致声明(VUID-08878) layout(push_constant) uniform PushConstants { mat4 invVP; // 当前帧反投影(方向重建) mat4 prevVP; // 上一帧 proj×view(去平移):天空 velocity } pc; void main() { vec4 target = pc.invVP * vec4(fragUV * 2.0 - 1.0, 1.0, 1.0); vec3 dir = normalize(target.xyz / target.w); outColor = vec4(texture(envMap, dir).rgb, 1.0); // 天空 velocity:天空是无限远表面,方向不随相机平移变化(w=0 忽略 // 平移),过上一帧 proj×view 得上一帧屏幕位置,与当前 fragUV 之差即 // 运动向量。相机移动时天空/背景因此正确重投影,不再闪烁 vec4 prevClip = pc.prevVP * vec4(dir, 0.0); vec2 prevUV = abs(prevClip.w) > 1e-6 ? (prevClip.xy / prevClip.w) * 0.5 + 0.5 : fragUV; outVelocity = fragUV - prevUV; }