Decal screen space is now projection based.

This commit is contained in:
Justin Marshall
2026-05-22 09:26:03 -07:00
parent aefe08a1fc
commit 373b0cb253
5 changed files with 40 additions and 23 deletions
+6 -13
View File
@@ -4513,8 +4513,6 @@ float4 PSScreenDecals(VSOut i) : SV_Target0
{
uint2 pixel = uint2(i.pos.xy);
float3 worldPos = gScreenDecalPosition.Load(int3(pixel, 0)).xyz;
float3 normal = QD3D12_SafeNormalizeOr(gScreenDecalNormal.Load(int3(pixel, 0)).xyz, float3(0.0, 0.0, 1.0));
float3 geometricNormal = QD3D12_SafeNormalizeOr(cross(ddx(worldPos), ddy(worldPos)), normal);
float3 decalColor = 0.0;
float decalAlpha = 0.0;
uint decalIndex = (uint)gScreenDecalIndex;
@@ -4522,28 +4520,23 @@ float4 PSScreenDecals(VSOut i) : SV_Target0
return float4(0.0, 0.0, 0.0, 0.0);
ScreenSpaceDecal d = gScreenDecals[decalIndex];
float3 decalN = QD3D12_SafeNormalizeOr(d.normal, normal);
float facing = saturate(abs(dot(geometricNormal, decalN)) * 4.0);
if (facing <= 0.0)
return float4(0.0, 0.0, 0.0, 0.0);
float3 decalN = QD3D12_SafeNormalizeOr(d.normal, float3(0.0, 0.0, 1.0));
float3 rel = worldPos - d.origin;
float decalDepth = max(d.depth, 1.0e-3);
float depthDistance = abs(dot(rel, decalN));
float depthFade = 1.0 - smoothstep(decalDepth, decalDepth + max(decalDepth * 0.25, 1.0), depthDistance);
if (depthFade <= 0.0)
float projectorDepth = max(d.depth, 1.0e-3);
float projectorZ = dot(rel, decalN);
if (abs(projectorZ) > projectorDepth)
return float4(0.0, 0.0, 0.0, 0.0);
float3 axisU = QD3D12_SafeNormalizeOr(d.axisU, float3(1.0, 0.0, 0.0));
float3 axisV = QD3D12_SafeNormalizeOr(d.axisV, cross(decalN, axisU));
float2 uv = float2(dot(rel, axisU), dot(rel, axisV)) / max(d.halfSize, 1.0e-3);
if (abs(uv.x) >= 1.0 || abs(uv.y) >= 1.0)
if (abs(uv.x) > 1.0 || abs(uv.y) > 1.0)
return float4(0.0, 0.0, 0.0, 0.0);
float2 texUv = float2(uv.x * 0.5 + 0.5, -uv.y * 0.5 + 0.5);
float4 texel = gTex0.Sample(gSamp0, texUv);
float edge = smoothstep(1.0, 0.75, max(abs(uv.x), abs(uv.y)));
float mask = saturate(d.opacity) * facing * depthFade * edge * saturate(d.color.a) * saturate(texel.a);
float mask = saturate(d.opacity) * saturate(d.color.a) * saturate(texel.a);
if (d.blendMode == 1u)
{
decalColor = saturate(texel.rgb * mask);