mirror of
https://github.com/jmarshall23/DoomRTX.git
synced 2026-08-19 20:19:50 +02:00
POM Relief Mapping
This commit is contained in:
+250
-104
@@ -2971,7 +2971,7 @@ cbuffer DrawCB : register(b0)
|
||||
// Pixel-shader POM depth in UV space. Keep this conservative: legacy idTech
|
||||
// normal maps often do not have a true height channel, so the POM path below
|
||||
// gates fallback height by local detail before applying any offset.
|
||||
#define gParallaxScale (clamp(gNormalMapStrength, 0.0, 4.0) * 0.020)
|
||||
#define gParallaxScale (clamp(gNormalMapStrength, 0.0, 4.0) * 0.028)
|
||||
#define gCameraWorldPos gCameraPomPad.xyz
|
||||
#define gCameraPomValid gCameraPomPad.w
|
||||
#define gUseNeuralPOM gNeuralPomPad.x
|
||||
@@ -3002,6 +3002,7 @@ cbuffer DrawCB : register(b0)
|
||||
#define QD3D12_TESS_TARGET_EDGE_PIXELS 28.0
|
||||
#define QD3D12_TESS_DISTANCE_NEAR 512.0
|
||||
#define QD3D12_TESS_DISTANCE_FAR 2200.0
|
||||
#define QD3D12_GEOMETRY_FLAG_SKELETAL 1u
|
||||
#define QD3D12_POM_DISTANCE_NEAR 384.0
|
||||
#define QD3D12_POM_DISTANCE_FAR 1800.0
|
||||
|
||||
@@ -3443,6 +3444,43 @@ float QD3D12_GetPomDepth(float2 uv)
|
||||
return saturate(1.0 - QD3D12_GetPomHeightFromSamples(uv));
|
||||
}
|
||||
|
||||
float QD3D12_GetPomDepthLOD(float2 uv, float lod)
|
||||
{
|
||||
float4 nm = gNormalMap.SampleLevel(gSamp2, uv, lod);
|
||||
float authored = QD3D12_AuthoredPomAlphaWeight(nm.a);
|
||||
if (authored > 0.5)
|
||||
return saturate(1.0 - nm.a);
|
||||
|
||||
float3 decoded = nm.xyz * 2.0 - 1.0;
|
||||
decoded.y *= gNormalMapYSign;
|
||||
|
||||
float slope = saturate(length(decoded.xy));
|
||||
float normalHeight = saturate(0.5 + (pow(slope, 0.80) - 0.35) * 0.42);
|
||||
|
||||
if (gUseTex0 > 0.5)
|
||||
{
|
||||
float normalDetailGate = saturate((slope - 0.040) * 8.0);
|
||||
if (normalDetailGate > 0.001)
|
||||
{
|
||||
float mipScale = exp2(lod);
|
||||
float2 texel = QD3D12_NormalMapTexelSize() * mipScale;
|
||||
float lumC = QD3D12_Luma(gTex0.SampleLevel(gSamp0, uv, lod).rgb);
|
||||
float lumL = QD3D12_Luma(gTex0.SampleLevel(gSamp0, uv - float2(texel.x, 0.0), lod).rgb);
|
||||
float lumR = QD3D12_Luma(gTex0.SampleLevel(gSamp0, uv + float2(texel.x, 0.0), lod).rgb);
|
||||
float lumU = QD3D12_Luma(gTex0.SampleLevel(gSamp0, uv - float2(0.0, texel.y), lod).rgb);
|
||||
float lumD = QD3D12_Luma(gTex0.SampleLevel(gSamp0, uv + float2(0.0, texel.y), lod).rgb);
|
||||
|
||||
float lumAvg = (lumL + lumR + lumU + lumD) * 0.25;
|
||||
float localContrast = abs(lumC - lumAvg);
|
||||
float diffuseWeight = saturate((localContrast - 0.018) * 16.0) * normalDetailGate;
|
||||
float diffuseHeight = saturate(0.5 + (lumC - lumAvg) * 1.85);
|
||||
normalHeight = lerp(normalHeight, diffuseHeight, diffuseWeight * 0.28);
|
||||
}
|
||||
}
|
||||
|
||||
return saturate(1.0 - normalHeight);
|
||||
}
|
||||
|
||||
float QD3D12_GetPomConfidence(float2 uv)
|
||||
{
|
||||
float minHeight = 0.5;
|
||||
@@ -3484,6 +3522,13 @@ float QD3D12_GetRegularPomFade(VSOut i, float2 baseUv)
|
||||
return saturate(confidence * distanceFade * grazingFade);
|
||||
}
|
||||
|
||||
struct QD3D12PomTraceResult
|
||||
{
|
||||
float2 uv;
|
||||
float confidence;
|
||||
float visibility;
|
||||
};
|
||||
|
||||
|
||||
// Keep the runtime network bounded. Most payloads do not need the full 128-wide
|
||||
// MLP in a fixed-function material pass; clamping evaluation here prevents a
|
||||
@@ -3750,106 +3795,145 @@ QD3D12NeuralPOMResult QD3D12_EvaluateNeuralPOM(VSOut i, float2 baseUv)
|
||||
r.active = 1.0;
|
||||
return r;
|
||||
}
|
||||
)HLSL"
|
||||
R"HLSL(
|
||||
QD3D12PomTraceResult QD3D12_TraceReliefPOM(VSOut i, float2 baseUv)
|
||||
{
|
||||
QD3D12PomTraceResult r;
|
||||
r.uv = baseUv;
|
||||
r.confidence = 0.0;
|
||||
r.visibility = 1.0;
|
||||
|
||||
if (gUseNormalMap < 0.5)
|
||||
return r;
|
||||
|
||||
if (gAlphaBlendPass > 0.5)
|
||||
return r;
|
||||
|
||||
if (gUseTex0 > 0.5)
|
||||
{
|
||||
float baseAlpha = gTex0.SampleLevel(gSamp0, baseUv, 0.0).a;
|
||||
if (baseAlpha < 0.985)
|
||||
return r;
|
||||
}
|
||||
|
||||
float minHeight = 0.5;
|
||||
float maxHeight = 0.5;
|
||||
float authoredWeight = 0.0;
|
||||
QD3D12_GetPomHeightStats(baseUv, minHeight, maxHeight, authoredWeight);
|
||||
|
||||
float heightRange = maxHeight - minHeight;
|
||||
float threshold = lerp(0.055, 0.014, authoredWeight);
|
||||
float confidence = saturate((heightRange - threshold) / max(0.18 - threshold, 0.001));
|
||||
confidence = confidence * confidence * (3.0 - 2.0 * confidence);
|
||||
if (confidence <= 0.035)
|
||||
return r;
|
||||
|
||||
float3 n, t, b;
|
||||
QD3D12_BuildPixelTBN(i, n, t, b);
|
||||
|
||||
float cameraConfidence = (gCameraPomValid >= 0.5) ? 1.0 : 0.35;
|
||||
float3 rawViewWS = (gCameraPomValid >= 0.5) ? (gCameraWorldPos - i.worldPos) : (-i.worldPos);
|
||||
float3 viewWS = QD3D12_SafeNormalize(rawViewWS, n);
|
||||
float NoV = dot(n, viewWS);
|
||||
if (NoV <= 0.025)
|
||||
return r;
|
||||
|
||||
float3 viewTS = QD3D12_SafeNormalize(float3(dot(viewWS, t), dot(viewWS, b), NoV), float3(0.0, 0.0, 1.0));
|
||||
float ndotv = saturate(viewTS.z);
|
||||
float viewDistance = (gCameraPomValid >= 0.5) ? max(length(gCameraWorldPos - i.worldPos), 1.0) : max(abs(i.currClip.w), 1.0);
|
||||
float distanceFade = 1.0 - smoothstep(QD3D12_POM_DISTANCE_NEAR, QD3D12_POM_DISTANCE_FAR, viewDistance);
|
||||
float grazingFade = smoothstep(0.055, 0.18, ndotv);
|
||||
float fade = saturate(confidence * distanceFade * grazingFade * cameraConfidence);
|
||||
if (fade <= 0.001)
|
||||
return r;
|
||||
|
||||
float2 texel = QD3D12_NormalMapTexelSize();
|
||||
float2 uvGradX = ddx(baseUv);
|
||||
float2 uvGradY = ddy(baseUv);
|
||||
float footprint = max(length(uvGradX / max(texel, float2(1.0e-6, 1.0e-6))), length(uvGradY / max(texel, float2(1.0e-6, 1.0e-6))));
|
||||
float lod = clamp(log2(max(footprint, 1.0)), 0.0, 5.0);
|
||||
|
||||
float depthScale = gParallaxScale * lerp(0.68, 1.18, authoredWeight) * confidence * distanceFade * cameraConfidence;
|
||||
float vz = max(ndotv, lerp(0.18, 0.10, authoredWeight));
|
||||
float2 parallaxVector = (viewTS.xy / vz) * depthScale;
|
||||
|
||||
float parallaxLen = length(parallaxVector);
|
||||
float maxParallaxShift = lerp(0.014, 0.046, authoredWeight) * lerp(0.85, 1.18, confidence);
|
||||
if (parallaxLen > maxParallaxShift && parallaxLen > 1.0e-6)
|
||||
parallaxVector *= maxParallaxShift / parallaxLen;
|
||||
|
||||
float layerCountF = lerp(14.0, 46.0, saturate(1.0 - ndotv));
|
||||
layerCountF = lerp(10.0, layerCountF, distanceFade);
|
||||
layerCountF = lerp(layerCountF * 0.70, layerCountF, authoredWeight);
|
||||
uint layerCount = (uint)clamp(layerCountF + 0.5, 10.0, 48.0);
|
||||
float invLayerCount = rcp((float)layerCount);
|
||||
float2 deltaUv = parallaxVector * invLayerCount;
|
||||
|
||||
float2 prevUv = baseUv;
|
||||
float2 uv = baseUv;
|
||||
float prevRayDepth = 0.0;
|
||||
float rayDepth = 0.0;
|
||||
float prevSurfaceDepth = QD3D12_GetPomDepthLOD(baseUv, lod);
|
||||
float surfaceDepth = prevSurfaceDepth;
|
||||
|
||||
[loop]
|
||||
for (uint layer = 0u; layer < 48u; ++layer)
|
||||
{
|
||||
if (layer >= layerCount || rayDepth >= surfaceDepth)
|
||||
break;
|
||||
|
||||
prevUv = uv;
|
||||
prevRayDepth = rayDepth;
|
||||
prevSurfaceDepth = surfaceDepth;
|
||||
|
||||
uv -= deltaUv;
|
||||
rayDepth += invLayerCount;
|
||||
surfaceDepth = QD3D12_GetPomDepthLOD(uv, lod);
|
||||
}
|
||||
|
||||
float after = surfaceDepth - rayDepth;
|
||||
float before = prevSurfaceDepth - prevRayDepth;
|
||||
float denom = after - before;
|
||||
float w = (abs(denom) > 1.0e-5) ? saturate(after / denom) : 0.0;
|
||||
float2 refinedUv = lerp(uv, prevUv, w);
|
||||
|
||||
float2 loUv = uv;
|
||||
float2 hiUv = prevUv;
|
||||
[unroll]
|
||||
for (uint refine = 0u; refine < 5u; ++refine)
|
||||
{
|
||||
float2 midUv = (loUv + hiUv) * 0.5;
|
||||
float midT = dot(baseUv - midUv, parallaxVector) / max(dot(parallaxVector, parallaxVector), 1.0e-8);
|
||||
float midDepth = saturate(midT);
|
||||
float midSurface = QD3D12_GetPomDepthLOD(midUv, lod);
|
||||
if (midDepth < midSurface)
|
||||
hiUv = midUv;
|
||||
else
|
||||
loUv = midUv;
|
||||
}
|
||||
|
||||
refinedUv = lerp(refinedUv, (loUv + hiUv) * 0.5, 0.65);
|
||||
|
||||
float2 finalOffset = refinedUv - baseUv;
|
||||
float maxOffset = maxParallaxShift * 1.05;
|
||||
float finalLen = length(finalOffset);
|
||||
if (finalLen > maxOffset && finalLen > 1.0e-6)
|
||||
refinedUv = baseUv + finalOffset * (maxOffset / finalLen);
|
||||
|
||||
r.uv = lerp(baseUv, refinedUv, fade);
|
||||
r.confidence = fade;
|
||||
r.visibility = saturate(1.0 - length(r.uv - baseUv) / max(maxParallaxShift, 1.0e-5) * 0.18);
|
||||
return r;
|
||||
}
|
||||
|
||||
float2 QD3D12_ComputeParallaxUVWithNeural(VSOut i, float2 baseUv, QD3D12NeuralPOMResult nr)
|
||||
{
|
||||
if (nr.active > 0.5)
|
||||
return nr.uv;
|
||||
|
||||
if (gUseNormalMap < 0.5)
|
||||
return baseUv;
|
||||
|
||||
float confidence = QD3D12_GetPomConfidence(baseUv);
|
||||
if (confidence <= 0.05)
|
||||
return baseUv;
|
||||
|
||||
float parallaxScale = gParallaxScale * confidence;
|
||||
if (abs(parallaxScale) < 1e-6)
|
||||
return baseUv;
|
||||
|
||||
float3 n, t, b;
|
||||
QD3D12_BuildPixelTBN(i, n, t, b);
|
||||
|
||||
// Correct view vector. The old code used -worldPos, which only works when
|
||||
// the camera is exactly at world origin and causes the obvious offset bugs
|
||||
// as soon as the camera moves. Keep -worldPos only as a reduced compatibility
|
||||
// fallback for older paths that cannot derive a perspective camera.
|
||||
float cameraConfidence = (gCameraPomValid >= 0.5) ? 1.0 : 0.35;
|
||||
float3 rawViewWS = (gCameraPomValid >= 0.5) ? (gCameraWorldPos - i.worldPos) : (-i.worldPos);
|
||||
float3 viewWS = QD3D12_SafeNormalize(rawViewWS, n);
|
||||
float NoV = dot(n, viewWS);
|
||||
if (NoV <= 0.035)
|
||||
return baseUv;
|
||||
|
||||
float3 viewTS = QD3D12_SafeNormalize(float3(
|
||||
dot(viewWS, t),
|
||||
dot(viewWS, b),
|
||||
NoV
|
||||
), float3(0.0, 0.0, 1.0));
|
||||
|
||||
float ndotv = saturate(viewTS.z);
|
||||
float vz = max(ndotv, 0.22);
|
||||
|
||||
// Fade out before far surfaces shimmer or when the viewing angle is too
|
||||
// grazing for estimated height maps.
|
||||
float viewDistance = (gCameraPomValid >= 0.5) ? max(length(gCameraWorldPos - i.worldPos), 1.0) : max(abs(i.currClip.w), 1.0);
|
||||
float distanceFade = 1.0 - smoothstep(QD3D12_POM_DISTANCE_NEAR, QD3D12_POM_DISTANCE_FAR, viewDistance);
|
||||
float grazingFade = smoothstep(0.08, 0.22, ndotv);
|
||||
|
||||
float scale = parallaxScale * distanceFade * grazingFade * cameraConfidence;
|
||||
if (scale <= 0.00045)
|
||||
return baseUv;
|
||||
|
||||
float layerCountF = lerp(10.0, 30.0, saturate(1.0 - ndotv));
|
||||
layerCountF = lerp(8.0, layerCountF, saturate(distanceFade));
|
||||
uint layerCount = (uint)clamp(layerCountF + 0.5, 8.0, 32.0);
|
||||
|
||||
// Offset-limited POM. Divide by a softened z term and clamp the max UV walk;
|
||||
// this removes the extreme stretched-offset artifacts on steep angles.
|
||||
// Standard POM walks opposite the view vector in tangent space. The shift
|
||||
// cap is intentionally tight for generated RGB-only height, looser for real
|
||||
// authored alpha height.
|
||||
float2 parallaxVector = (viewTS.xy / vz) * scale;
|
||||
float parallaxLen = length(parallaxVector);
|
||||
float maxParallaxShift = lerp(0.016, 0.040, confidence);
|
||||
if (parallaxLen > maxParallaxShift && parallaxLen > 1e-6)
|
||||
parallaxVector *= maxParallaxShift / parallaxLen;
|
||||
|
||||
float invLayerCount = rcp((float)layerCount);
|
||||
float2 deltaUv = parallaxVector * invLayerCount;
|
||||
|
||||
float2 uv = baseUv;
|
||||
float2 prevUv = uv;
|
||||
float currentLayerDepth = 0.0;
|
||||
float prevLayerDepth = 0.0;
|
||||
float currentDepth = QD3D12_GetPomDepth(uv);
|
||||
float prevDepth = currentDepth;
|
||||
|
||||
[loop]
|
||||
for (uint layer = 0u; layer < 32u; ++layer)
|
||||
{
|
||||
if (layer >= layerCount || currentLayerDepth >= currentDepth)
|
||||
break;
|
||||
|
||||
prevUv = uv;
|
||||
prevLayerDepth = currentLayerDepth;
|
||||
prevDepth = currentDepth;
|
||||
|
||||
uv -= deltaUv;
|
||||
currentLayerDepth += invLayerCount;
|
||||
currentDepth = QD3D12_GetPomDepth(uv);
|
||||
}
|
||||
|
||||
float afterDepth = currentDepth - currentLayerDepth;
|
||||
float beforeDepth = prevDepth - prevLayerDepth;
|
||||
float denom = afterDepth - beforeDepth;
|
||||
float weight = (abs(denom) > 1e-5) ? saturate(afterDepth / denom) : 0.0;
|
||||
float2 refinedUv = lerp(uv, prevUv, weight);
|
||||
|
||||
// Blend the final result in instead of applying a manual half-vector center
|
||||
// correction. The center correction was the source of several texture-offset
|
||||
// bugs on flat/low-confidence areas.
|
||||
return lerp(baseUv, refinedUv, saturate(distanceFade * grazingFade * confidence));
|
||||
QD3D12PomTraceResult trace = QD3D12_TraceReliefPOM(i, baseUv);
|
||||
return trace.uv;
|
||||
}
|
||||
)HLSL"
|
||||
R"HLSL(
|
||||
@@ -4006,10 +4090,7 @@ float4 BuildSpecularAlbedoCached(VSOut i, QD3D12MaterialEval m)
|
||||
{
|
||||
if (gUseSpecularMap > 0.0)
|
||||
{
|
||||
float regularPomFade = (gUseNeuralPOM <= 0.5 || m.neural.active <= 0.5)
|
||||
? QD3D12_GetRegularPomFade(i, i.uv0)
|
||||
: 0.0;
|
||||
float2 specUv = lerp(i.uv0, m.uv0, regularPomFade);
|
||||
float2 specUv = m.uv0;
|
||||
float4 spec = gSpecularMap.Sample(gSamp4, specUv);
|
||||
float strength = max(gSpecularMapStrength, 0.0);
|
||||
|
||||
@@ -4021,8 +4102,6 @@ float4 BuildSpecularAlbedoCached(VSOut i, QD3D12MaterialEval m)
|
||||
bool alphaLooksForcedOpaque = (spec.a >= 0.999);
|
||||
float alphaMask = alphaLooksForcedOpaque ? 1.0 : saturate(spec.a);
|
||||
float3 specRgb = saturate(spec.rgb) * alphaMask * strength;
|
||||
if (regularPomFade > 0.0)
|
||||
specRgb = min(specRgb, float3(0.82, 0.82, 0.82));
|
||||
return float4(specRgb, 1.0);
|
||||
}
|
||||
|
||||
@@ -4235,11 +4314,42 @@ float QD3D12_TessellationPatchEdgeFade(float3 bary)
|
||||
return smoothstep(0.0, 0.08, edgeDistance);
|
||||
}
|
||||
|
||||
uint QD3D12_DecodeGeometryFlag(float flag)
|
||||
{
|
||||
return (uint)floor(max(flag, 0.0) + 0.5);
|
||||
}
|
||||
|
||||
bool QD3D12_IsSkeletalGeometry(float flag)
|
||||
{
|
||||
return (QD3D12_DecodeGeometryFlag(flag) & QD3D12_GEOMETRY_FLAG_SKELETAL) != 0u;
|
||||
}
|
||||
|
||||
float QD3D12_ComputeCharacterTessEdgeFactor(VSOut a, VSOut b)
|
||||
{
|
||||
float distanceFade = QD3D12_TessellationEdgeDistanceFade(a, b);
|
||||
if (distanceFade <= 0.001)
|
||||
return 1.0;
|
||||
|
||||
float edgePixels = QD3D12_EdgeLengthPixels(a.currClip, b.currClip);
|
||||
float screenTerm = sqrt(max(edgePixels, 1.0) / 24.0);
|
||||
float strength = clamp(max(gNormalMapStrength, 0.0), 0.0, 4.0);
|
||||
|
||||
// Character tessellation is for silhouette/deformation smoothness, not
|
||||
// normal-map relief. Keep it bounded so animated MD5s do not turn rubbery.
|
||||
float nearFactor = 1.0 + screenTerm * 2.65 + strength * 0.22;
|
||||
nearFactor = clamp(nearFactor, 1.0, 8.0);
|
||||
|
||||
return clamp(lerp(1.0, nearFactor, distanceFade), QD3D12_TESS_MIN_FACTOR, 8.0);
|
||||
}
|
||||
|
||||
float QD3D12_ComputeNormalMapTessEdgeFactor(VSOut a, VSOut b)
|
||||
{
|
||||
if (gUseNormalMap <= 0.5)
|
||||
return 1.0;
|
||||
|
||||
if (QD3D12_IsSkeletalGeometry(a.attr.x) || QD3D12_IsSkeletalGeometry(b.attr.x))
|
||||
return QD3D12_ComputeCharacterTessEdgeFactor(a, b);
|
||||
|
||||
float distanceFade = QD3D12_TessellationEdgeDistanceFade(a, b);
|
||||
if (distanceFade <= 0.001)
|
||||
return 1.0;
|
||||
@@ -4331,6 +4441,38 @@ float4 QD3D12_Interp4(float4 a, float4 b, float4 c, float3 w)
|
||||
return a * w.x + b * w.y + c * w.z;
|
||||
}
|
||||
|
||||
float3 QD3D12_ProjectPointToTangentPlane(float3 p, float3 planePoint, float3 planeNormal)
|
||||
{
|
||||
planeNormal = QD3D12_SafeNormalize(planeNormal, float3(0.0, 0.0, 1.0));
|
||||
return p - planeNormal * dot(p - planePoint, planeNormal);
|
||||
}
|
||||
|
||||
float3 QD3D12_CharacterPhongTessellate(const OutputPatch<TessCP, 3> patch, float3 bary, float3 linearObjPos, float distanceFade)
|
||||
{
|
||||
float3 n0 = QD3D12_SafeNormalize(patch[0].objNormal, float3(0.0, 0.0, 1.0));
|
||||
float3 n1 = QD3D12_SafeNormalize(patch[1].objNormal, n0);
|
||||
float3 n2 = QD3D12_SafeNormalize(patch[2].objNormal, n0);
|
||||
|
||||
float3 q0 = QD3D12_ProjectPointToTangentPlane(linearObjPos, patch[0].objPos, n0);
|
||||
float3 q1 = QD3D12_ProjectPointToTangentPlane(linearObjPos, patch[1].objPos, n1);
|
||||
float3 q2 = QD3D12_ProjectPointToTangentPlane(linearObjPos, patch[2].objPos, n2);
|
||||
float3 phongObjPos = q0 * bary.x + q1 * bary.y + q2 * bary.z;
|
||||
|
||||
float normalAgreement = saturate((dot(n0, n1) + dot(n1, n2) + dot(n2, n0)) * 0.1667 + 0.5);
|
||||
float smoothAmount = 0.78 * distanceFade * smoothstep(0.10, 0.82, normalAgreement);
|
||||
|
||||
float3 delta = phongObjPos - linearObjPos;
|
||||
float maxEdgeLen = max(
|
||||
length(patch[0].objPos - patch[1].objPos),
|
||||
max(length(patch[1].objPos - patch[2].objPos), length(patch[2].objPos - patch[0].objPos)));
|
||||
float maxDelta = max(maxEdgeLen * 0.075, 0.01);
|
||||
float deltaLen = length(delta);
|
||||
if (deltaLen > maxDelta)
|
||||
delta *= maxDelta / max(deltaLen, 1.0e-5);
|
||||
|
||||
return linearObjPos + delta * smoothAmount;
|
||||
}
|
||||
|
||||
[domain("tri")]
|
||||
VSOut DSMain(HSConstOut tessFactors, float3 bary : SV_DomainLocation, const OutputPatch<TessCP, 3> patch)
|
||||
{
|
||||
@@ -4353,13 +4495,17 @@ VSOut DSMain(HSConstOut tessFactors, float3 bary : SV_DomainLocation, const Outp
|
||||
VSOut o;
|
||||
|
||||
float3 objNormal = QD3D12_SafeNormalize(i.objNormal, float3(0.0, 0.0, 1.0));
|
||||
bool isSkeletal = QD3D12_IsSkeletalGeometry(i.attr.x);
|
||||
float distanceFade = QD3D12_TessellationDisplacementFade(i.currClip);
|
||||
float3 baseObjPos = isSkeletal
|
||||
? QD3D12_CharacterPhongTessellate(patch, bary, i.objPos, distanceFade)
|
||||
: i.objPos;
|
||||
float height = QD3D12_GetFilteredTessHeight(i.uv0);
|
||||
float centeredHeight = QD3D12_CleanCenteredTessHeight(height);
|
||||
float displacementFade = QD3D12_TessellationDisplacementFade(i.currClip);
|
||||
displacementFade *= QD3D12_TessellationPatchEdgeFade(bary);
|
||||
float displacementFade = isSkeletal ? 0.0 : distanceFade * QD3D12_TessellationPatchEdgeFade(bary);
|
||||
float reliefConfidence = QD3D12_GetPomConfidence(i.uv0);
|
||||
float displacement = centeredHeight * gTessellationDisplacement * displacementFade * reliefConfidence;
|
||||
float3 displacedObjPos = i.objPos + objNormal * displacement;
|
||||
float3 displacedObjPos = baseObjPos + objNormal * displacement;
|
||||
|
||||
float4 worldPos = mul(gModelMatrix, float4(displacedObjPos, 1.0));
|
||||
float4 currClip = mul(gMVP, float4(displacedObjPos, 1.0));
|
||||
|
||||
Reference in New Issue
Block a user