Files
render/assets/shaders/skybox.hlsl
T
2026-08-17 06:31:43 +09:00

94 lines
3.4 KiB
HLSL

// [新增] 相机背景天空盒。
// CPU 不创建天空盒网格;VS 使用 SV_VertexID 读取内置 36 个顶点。
#pragma pack_matrix(row_major)
#include "include/pbr_brdf.hlsli"
cbuffer CBScene : register(b0) {
row_major float4x4 gView;
row_major float4x4 gProjection;
float4 gCameraPosition;
float4 gLightDirection;
float4 gLightColorIntensity;
float4 gAmbientColorIntensity;
float4 gRenderParams; // x=exposure
};
cbuffer CBIBL : register(b4) {
// x=intensity, y=prefilter max mip, z=Y rotation, w=enabled
float4 gIblParams;
};
TextureCube<float4> gSkyboxCube : register(t12);
SamplerState gSkyboxSampler : register(s4);
static const float3 gCubeVertices[36] = {
// -Z
float3(-1.0f, -1.0f, -1.0f), float3(-1.0f, 1.0f, -1.0f), float3( 1.0f, 1.0f, -1.0f),
float3(-1.0f, -1.0f, -1.0f), float3( 1.0f, 1.0f, -1.0f), float3( 1.0f, -1.0f, -1.0f),
// +Z
float3(-1.0f, -1.0f, 1.0f), float3( 1.0f, 1.0f, 1.0f), float3(-1.0f, 1.0f, 1.0f),
float3(-1.0f, -1.0f, 1.0f), float3( 1.0f, -1.0f, 1.0f), float3( 1.0f, 1.0f, 1.0f),
// -X
float3(-1.0f, -1.0f, -1.0f), float3(-1.0f, -1.0f, 1.0f), float3(-1.0f, 1.0f, 1.0f),
float3(-1.0f, -1.0f, -1.0f), float3(-1.0f, 1.0f, 1.0f), float3(-1.0f, 1.0f, -1.0f),
// +X
float3( 1.0f, -1.0f, -1.0f), float3( 1.0f, 1.0f, 1.0f), float3( 1.0f, -1.0f, 1.0f),
float3( 1.0f, -1.0f, -1.0f), float3( 1.0f, 1.0f, -1.0f), float3( 1.0f, 1.0f, 1.0f),
// -Y
float3(-1.0f, -1.0f, -1.0f), float3( 1.0f, -1.0f, 1.0f), float3(-1.0f, -1.0f, 1.0f),
float3(-1.0f, -1.0f, -1.0f), float3( 1.0f, -1.0f, -1.0f), float3( 1.0f, -1.0f, 1.0f),
// +Y
float3(-1.0f, 1.0f, -1.0f), float3(-1.0f, 1.0f, 1.0f), float3( 1.0f, 1.0f, 1.0f),
float3(-1.0f, 1.0f, -1.0f), float3( 1.0f, 1.0f, 1.0f), float3( 1.0f, 1.0f, -1.0f)
};
struct VSOutput {
float4 positionCS : SV_POSITION;
float3 directionWS : TEXCOORD0;
};
VSOutput VSMain(uint vertexId : SV_VertexID) {
VSOutput output;
const float3 positionWS = gCubeVertices[vertexId];
// [修改] w=0 只应用相机旋转,不应用相机平移;天空盒因此始终以相机为中心。
const float3 positionVS = mul(float4(positionWS, 0.0f), gView).xyz;
float4 positionCS = mul(float4(positionVS, 1.0f), gProjection);
// [新增] 固定到远平面;配合 LESS_EQUAL 和深度不写入,仅覆盖背景像素。
positionCS.z = positionCS.w;
output.positionCS = positionCS;
output.directionWS = positionWS;
return output;
}
float3 RotateAroundY(float3 direction, float radians) {
float sineValue;
float cosineValue;
sincos(radians, sineValue, cosineValue);
return float3(
cosineValue * direction.x + sineValue * direction.z,
direction.y,
-sineValue * direction.x + cosineValue * direction.z);
}
float4 PSMain(VSOutput input) : SV_TARGET {
const float3 sampleDirection = RotateAroundY(
normalize(input.directionWS), gIblParams.z);
float3 color = gSkyboxCube.SampleLevel(
gSkyboxSampler, sampleDirection, 0.0f).rgb;
// [修改] enabled 只控制物体 IBL;天空背景在 Cube 已加载时始终显示。
color *= max(gIblParams.x, 0.0f);
// 与 PBR 物体使用相同曝光、色调映射和显示编码。
color *= max(gRenderParams.x, 0.0f);
color = ToneMapACES(color);
color = pow(max(color, 0.0f), 1.0f / 2.2f);
return float4(color, 1.0f);
}