From a797428ee5311c9e5caf6037eac0403a8bace524 Mon Sep 17 00:00:00 2001 From: Justin Marshall Date: Tue, 12 May 2026 16:43:28 -0700 Subject: [PATCH] Increased tess depth --- neo/engine/opengl/gl_d3d12shim.cpp | 43 ++++++++++++++++++------------ 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/neo/engine/opengl/gl_d3d12shim.cpp b/neo/engine/opengl/gl_d3d12shim.cpp index 6a3acd41..c3737808 100644 --- a/neo/engine/opengl/gl_d3d12shim.cpp +++ b/neo/engine/opengl/gl_d3d12shim.cpp @@ -2305,7 +2305,10 @@ cbuffer DrawCB : register(b0) #define gUseSpecularMap gMaterialMapPad.x #define gSpecularMapStrength gMaterialMapPad.y #define gAlphaBlendPass gMaterialMapPad.z -#define gTessellationDisplacement max(gMaterialMapPad.w, 0.0) +// Full object-space displacement amplitude for the tessellation domain shader. +// The CPU side keeps this conservative, but clamp here too so a bad material +// strength cannot explode the mesh. +#define gTessellationDisplacement clamp(gMaterialMapPad.w, 0.0, 0.35) Texture2D gTex0 : register(t0); Texture2D gTex1 : register(t1); @@ -2540,12 +2543,14 @@ float QD3D12_HeightFromNormalSample(float4 nm) { // Many legacy normal maps are RGB/DXT uploads with an implicitly forced // opaque alpha channel. Treat alpha as height only when it looks like real - // authored data; otherwise derive a conservative pseudo-height from the - // normal itself. A flat normal (0.5, 0.5, 1.0) stays centered at 0.5, so - // RGB-only normal maps do not push whole surfaces outward. + // authored data; otherwise derive a stronger pseudo-height from the normal + // itself. A flat normal (0.5, 0.5, 1.0) stays centered at 0.5, while steep + // normal-map detail now gets a much larger positive lift so tessellation + // visibly pops instead of barely moving the silhouette. bool hasAuthoredHeight = (nm.a > 0.0001 && nm.a < 0.999); float3 decoded = nm.xyz * 2.0 - 1.0; - float slopeHeight = 0.5 + (1.0 - saturate(abs(decoded.z))) * 0.25; + float slope = 1.0 - saturate(abs(decoded.z)); + float slopeHeight = 0.5 + pow(slope, 0.65) * 0.5; float h = hasAuthoredHeight ? nm.a : slopeHeight; return saturate(h); } @@ -2840,12 +2845,12 @@ float QD3D12_ComputeNormalMapTessFactor(InputPatch patch) float h2 = QD3D12_GetHeightFromNormalMapLOD(patch[2].uv0, 0.0); float heightRange = max(abs(h0 - h1), max(abs(h1 - h2), abs(h2 - h0))); - // Keep the factor conservative. Most legacy normal maps are not authored as - // height maps, so aggressive tessellation creates cracks and flickering without - // adding useful detail. Height variation still nudges the factor upward. - float strength = saturate(max(gNormalMapStrength, 0.0)); - float factor = 1.0 + strength + heightRange * 4.0; - return (gUseNormalMap > 0.5) ? clamp(factor, 1.0, 4.0) : 1.0; + // Give displaced normal-mapped surfaces enough subdivision to show the larger + // height push. fractional_odd will quantize these into stable odd partitions, + // so 3/5/7 are the practical quality tiers for default/strong materials. + float strength = clamp(max(gNormalMapStrength, 0.0), 0.0, 4.0); + float factor = 2.0 + strength * 1.0 + heightRange * 8.0; + return (gUseNormalMap > 0.5) ? clamp(factor, 2.0, 7.0) : 1.0; } HSConstOut HSMainConstants(InputPatch patch) @@ -2907,7 +2912,8 @@ VSOut DSMain(HSConstOut tessFactors, float3 bary : SV_DomainLocation, const Outp float3 objNormal = QD3D12_SafeNormalize(i.objNormal, float3(0.0, 0.0, 1.0)); float height = QD3D12_GetHeightFromNormalMapLOD(i.uv0, 0.0); - float displacement = (height - 0.5) * gTessellationDisplacement; + float centeredHeight = (height - 0.5) * 2.0; + float displacement = centeredHeight * gTessellationDisplacement; float3 displacedObjPos = i.objPos + objNormal * displacement; float4 worldPos = mul(gModelMatrix, float4(displacedObjPos, 1.0)); @@ -8928,12 +8934,15 @@ static void QD3D12_FlushQueuedBatches() dc->materialMapPad[0] = batch.key.useSpecularMap; dc->materialMapPad[1] = batch.key.specularMapStrength; dc->materialMapPad[2] = QD3D12_PipelineUsesAlphaBlend(batch.key.pipeline) ? 1.0f : 0.0f; - // Normal-map strength is a shading control, not an object-space height in - // Quake/idTech units. Use it only as a small scalar for displacement so the - // tessellation pass cannot shove surfaces through walls or the near plane. - const float tessDisplacementScale = 0.03f; + // Normal-map strength now drives a visibly stronger object-space displacement. + // Keep a hard upper bound because old RGB-only normal maps are often noisy and + // are not authored as true height maps. Default strength 1.0 gives about + // +/-0.08 object units for authored alpha-height maps and outward lift for + // RGB-only bump detail; glNormalMapStrengthf() can push it higher. + const float tessStrength = ClampValue(batch.key.normalMapStrength, 0.0f, 4.0f); + const float tessDisplacementScale = 0.08f; dc->materialMapPad[3] = QD3D12_UseNormalMapTessellationPSO(batch.key, nativeColorOnly) ? - (ClampValue(batch.key.normalMapStrength, 0.0f, 4.0f) * tessDisplacementScale) : 0.0f; + ClampValue(tessStrength * tessDisplacementScale, 0.0f, 0.35f) : 0.0f; if (batch.key.useARBPrograms) {