feat: add basic forward lighting coverage

This commit is contained in:
2026-04-01 00:41:56 +08:00
parent ac2b7c1fa2
commit 3373119eee
10 changed files with 31741 additions and 7 deletions

View File

@@ -59,16 +59,21 @@ cbuffer PerObjectConstants : register(b1) {
float4x4 gProjectionMatrix;
float4x4 gViewMatrix;
float4x4 gModelMatrix;
float4x4 gNormalMatrix;
float4 gMainLightDirectionAndIntensity;
float4 gMainLightColorAndFlags;
};
struct VSInput {
float3 position : POSITION;
float3 normal : NORMAL;
float2 texcoord : TEXCOORD0;
};
struct PSInput {
float4 position : SV_POSITION;
float2 texcoord : TEXCOORD0;
float3 normalWS : TEXCOORD0;
float2 texcoord : TEXCOORD1;
};
PSInput MainVS(VSInput input) {
@@ -76,31 +81,48 @@ PSInput MainVS(VSInput input) {
float4 positionWS = mul(gModelMatrix, float4(input.position, 1.0f));
float4 positionVS = mul(gViewMatrix, positionWS);
output.position = mul(gProjectionMatrix, positionVS);
output.normalWS = mul((float3x3)gNormalMatrix, input.normal);
output.texcoord = input.texcoord;
return output;
}
float4 MainPS(PSInput input) : SV_TARGET {
return gBaseColorTexture.Sample(gLinearSampler, input.texcoord);
float4 baseColor = gBaseColorTexture.Sample(gLinearSampler, input.texcoord);
if (gMainLightColorAndFlags.a < 0.5f) {
return baseColor;
}
float3 normalWS = normalize(input.normalWS);
float3 directionToLightWS = normalize(gMainLightDirectionAndIntensity.xyz);
float diffuse = saturate(dot(normalWS, directionToLightWS));
float3 lighting = float3(0.28f, 0.28f, 0.28f) +
gMainLightColorAndFlags.rgb * (diffuse * gMainLightDirectionAndIntensity.w);
return float4(baseColor.rgb * lighting, baseColor.a);
}
)";
const char kBuiltinForwardVertexShader[] = R"(#version 430
layout(location = 0) in vec3 aPosition;
layout(location = 1) in vec2 aTexCoord;
layout(location = 1) in vec3 aNormal;
layout(location = 2) in vec2 aTexCoord;
layout(std140, binding = 1) uniform PerObjectConstants {
mat4 gProjectionMatrix;
mat4 gViewMatrix;
mat4 gModelMatrix;
mat4 gNormalMatrix;
vec4 gMainLightDirectionAndIntensity;
vec4 gMainLightColorAndFlags;
};
out vec3 vNormalWS;
out vec2 vTexCoord;
void main() {
vec4 positionWS = gModelMatrix * vec4(aPosition, 1.0);
vec4 positionVS = gViewMatrix * positionWS;
gl_Position = gProjectionMatrix * positionVS;
vNormalWS = mat3(gNormalMatrix) * aNormal;
vTexCoord = aTexCoord;
}
)";
@@ -108,12 +130,33 @@ void main() {
const char kBuiltinForwardFragmentShader[] = R"(#version 430
layout(binding = 1) uniform sampler2D uBaseColorTexture;
layout(std140, binding = 1) uniform PerObjectConstants {
mat4 gProjectionMatrix;
mat4 gViewMatrix;
mat4 gModelMatrix;
mat4 gNormalMatrix;
vec4 gMainLightDirectionAndIntensity;
vec4 gMainLightColorAndFlags;
};
in vec3 vNormalWS;
in vec2 vTexCoord;
layout(location = 0) out vec4 fragColor;
void main() {
fragColor = texture(uBaseColorTexture, vTexCoord);
vec4 baseColor = texture(uBaseColorTexture, vTexCoord);
if (gMainLightColorAndFlags.w < 0.5) {
fragColor = baseColor;
return;
}
vec3 normalWS = normalize(vNormalWS);
vec3 directionToLightWS = normalize(gMainLightDirectionAndIntensity.xyz);
float diffuse = max(dot(normalWS, directionToLightWS), 0.0);
vec3 lighting = vec3(0.28) +
gMainLightColorAndFlags.rgb * (diffuse * gMainLightDirectionAndIntensity.w);
fragColor = vec4(baseColor.rgb * lighting, baseColor.a);
}
)";
@@ -204,6 +247,14 @@ RHI::InputLayoutDesc BuiltinForwardPipeline::BuildInputLayout() {
position.alignedByteOffset = 0;
inputLayout.elements.push_back(position);
RHI::InputElementDesc normal = {};
normal.semanticName = "NORMAL";
normal.semanticIndex = 0;
normal.format = static_cast<uint32_t>(RHI::Format::R32G32B32_Float);
normal.inputSlot = 0;
normal.alignedByteOffset = static_cast<uint32_t>(offsetof(Resources::StaticMeshVertex, normal));
inputLayout.elements.push_back(normal);
RHI::InputElementDesc texcoord = {};
texcoord.semanticName = "TEXCOORD";
texcoord.semanticIndex = 0;
@@ -689,7 +740,22 @@ bool BuiltinForwardPipeline::DrawVisibleItem(
const PerObjectConstants constants = {
sceneData.cameraData.projection,
sceneData.cameraData.view,
visibleItem.localToWorld.Transpose()
visibleItem.localToWorld.Transpose(),
visibleItem.localToWorld.Inverse(),
sceneData.lighting.HasMainDirectionalLight()
? Math::Vector4(
sceneData.lighting.mainDirectionalLight.direction.x,
sceneData.lighting.mainDirectionalLight.direction.y,
sceneData.lighting.mainDirectionalLight.direction.z,
sceneData.lighting.mainDirectionalLight.intensity)
: Math::Vector4::Zero(),
sceneData.lighting.HasMainDirectionalLight()
? Math::Vector4(
sceneData.lighting.mainDirectionalLight.color.r,
sceneData.lighting.mainDirectionalLight.color.g,
sceneData.lighting.mainDirectionalLight.color.b,
1.0f)
: Math::Vector4::Zero()
};
RHI::RHIResourceView* textureView = ResolveTextureView(visibleItem);