mirror of
https://github.com/jmarshall23/DoomRTX.git
synced 2026-08-12 08:11:10 +02:00
Spec fixes
This commit is contained in:
@@ -2983,6 +2983,13 @@ float4 LoadSceneNormal(uint2 pixel)
|
||||
return nSample;
|
||||
}
|
||||
|
||||
float LoadSceneSurfaceRoughness(float4 normalSample)
|
||||
{
|
||||
// The raster G-buffer stores authored/material roughness in normal.w.
|
||||
// Keep a small floor so glossy materials do not become perfect mirrors.
|
||||
return clamp(normalSample.w, 0.05, 1.0);
|
||||
}
|
||||
|
||||
float SafeLengthSq(float3 v)
|
||||
{
|
||||
return max(dot(v, v), 1e-8);
|
||||
@@ -3234,7 +3241,8 @@ void BounceClosestHit(inout BouncePayload payload, in BuiltInTriangleIntersectio
|
||||
payload.meshIndex = InstanceID() & GL_RAYTRACING_INSTANCE_USER_ID_MASK;
|
||||
DecodeRayMaterialAtHit(payload.meshIndex, attr, payload.hitNormal, payload.hitTexCoord);
|
||||
}
|
||||
|
||||
)"
|
||||
R"(
|
||||
[shader("closesthit")]
|
||||
void ReflectionClosestHit(inout BouncePayload payload, in BuiltInTriangleIntersectionAttributes attr)
|
||||
{
|
||||
@@ -4014,6 +4022,17 @@ float EstimateSpecularNormalVariance(uint2 pixel, float3 centerN)
|
||||
return saturate(v * 1.70);
|
||||
}
|
||||
|
||||
float StabilizeSpecularSurfaceRoughness(uint2 pixel, float3 N, float surfaceRoughness)
|
||||
{
|
||||
float normalVariance = EstimateSpecularNormalVariance(pixel, N);
|
||||
|
||||
// Doom 3 normal maps can be extremely high contrast. Let clean painted metal
|
||||
// and wet floors stay glossy, but force rougher lobes on noisy pixels so GGX
|
||||
// does not turn texel-scale normal detail into broken sparkles.
|
||||
float varianceFloor = lerp(0.12, 0.46, smoothstep(0.08, 0.42, normalVariance));
|
||||
return clamp(max(surfaceRoughness, varianceFloor), 0.05, 1.0);
|
||||
}
|
||||
|
||||
float3 Doom3SyntheticSpecularMask(uint2 pixel, float3 baseAlbedo)
|
||||
{
|
||||
// Missing Doom 3 specular maps used to get a bright Phong-era fallback. Build
|
||||
@@ -4034,8 +4053,8 @@ float3 Doom3SyntheticSpecularMask(uint2 pixel, float3 baseAlbedo)
|
||||
float cavityDamping = lerp(1.0, 0.48, smoothstep(0.03, 0.32, normalVariance));
|
||||
float roughSurfaceDamping = lerp(1.0, 0.58, smoothstep(0.08, 0.45, normalVariance));
|
||||
|
||||
float f0 = 0.04 * cleanDiffuse * cavityDamping * roughSurfaceDamping;
|
||||
f0 = clamp(f0, 0.010, 0.055);
|
||||
float f0 = 0.045 * cleanDiffuse * cavityDamping * roughSurfaceDamping;
|
||||
f0 = clamp(f0, 0.012, 0.070);
|
||||
|
||||
float tintAmount = 0.10 * saturate(saturation);
|
||||
float3 neutralSpec = float3(f0, f0, f0);
|
||||
@@ -4058,17 +4077,17 @@ float3 ShapeAuthoredDoom3Specular(uint2 pixel, float3 baseAlbedo, float3 authore
|
||||
// Doom/idTech spec maps were painted for Phong, often as broad intensity masks.
|
||||
// Treat them as strength/tint hints over a physical dielectric baseline instead
|
||||
// of feeding their RGB straight into F0.
|
||||
float authoredStrength = smoothstep(0.025, 0.72, authoredPeak);
|
||||
float strengthScale = lerp(0.65, 2.85, authoredStrength);
|
||||
float authoredStrength = smoothstep(0.018, 0.68, authoredPeak);
|
||||
float strengthScale = lerp(0.85, 4.65, authoredStrength);
|
||||
float3 shaped = synthetic * strengthScale;
|
||||
|
||||
float3 authoredTint = authored / max(authoredPeak, 1.0e-4);
|
||||
float tintTrust = saturate((authoredPeak - 0.08) * 0.55);
|
||||
float tintTrust = saturate((authoredPeak - 0.05) * 0.85);
|
||||
shaped = lerp(shaped, authoredTint * SpecularPeak3(shaped), tintTrust);
|
||||
|
||||
float peak = SpecularPeak3(shaped);
|
||||
if (peak > 0.16 && peak > 1.0e-5)
|
||||
shaped *= 0.16 / peak;
|
||||
if (peak > 0.30 && peak > 1.0e-5)
|
||||
shaped *= 0.30 / peak;
|
||||
|
||||
return max(shaped, float3(0.004, 0.004, 0.004));
|
||||
}
|
||||
@@ -4108,15 +4127,17 @@ float ComputeDiffuseLightingTerm(float3 N, float3 L)
|
||||
return saturate(rawNoL);
|
||||
}
|
||||
|
||||
float EstimateSpecularRoughness(float3 specularAlbedo)
|
||||
float EstimateSpecularRoughness(float3 specularAlbedo, float surfaceRoughness)
|
||||
{
|
||||
// No roughness map is available in this G-buffer path, so infer a stable
|
||||
// perceptual roughness from the specular map strength. Brighter spec maps
|
||||
// get tighter highlights, but keep a floor high enough that POM/normal-map
|
||||
// detail cannot collapse into one-pixel GGX fireflies.
|
||||
// Doom 3 spec maps are art-directed intensity/tint masks, not roughness maps.
|
||||
// Use the authored/material roughness packed by the raster path, with spec
|
||||
// strength only nudging the lobe sharper for bright painted highlights.
|
||||
float peak = SpecularPeak3(saturate(specularAlbedo));
|
||||
float strength = smoothstep(0.010, 0.145, peak);
|
||||
return clamp(lerp(0.70, 0.42, strength), 0.38, 0.76);
|
||||
float specDrivenRoughness = lerp(0.68, 0.22, strength);
|
||||
float materialRoughness = clamp(surfaceRoughness, 0.05, 1.0);
|
||||
float roughness = lerp(specDrivenRoughness, min(specDrivenRoughness, materialRoughness), 0.72);
|
||||
return clamp(roughness, 0.18, 0.86);
|
||||
}
|
||||
|
||||
float3 LimitSpecularPeak(float3 c, float peakLimit)
|
||||
@@ -4142,7 +4163,8 @@ float3 ComputeSpecularShaped(
|
||||
float f0Blend,
|
||||
float fresnelToWhiteScale,
|
||||
float energyScale,
|
||||
float peakLimit)
|
||||
float peakLimit,
|
||||
float surfaceRoughness)
|
||||
{
|
||||
if (gEnableSpecular == 0)
|
||||
return 0.0;
|
||||
@@ -4175,7 +4197,7 @@ float3 ComputeSpecularShaped(
|
||||
if (specPeak <= 0.001)
|
||||
return 0.0;
|
||||
|
||||
float roughness = clamp(EstimateSpecularRoughness(specMask) + roughnessBias, 0.38, 0.90);
|
||||
float roughness = clamp(EstimateSpecularRoughness(specMask, surfaceRoughness) + roughnessBias, 0.18, 0.92);
|
||||
float a = roughness * roughness;
|
||||
float a2 = max(a * a, 1.0e-4);
|
||||
|
||||
@@ -4197,9 +4219,9 @@ float3 ComputeSpecularShaped(
|
||||
float3 F = F0 + (1.0 - F0) * (pow(1.0 - VoH, 5.0) * saturate(fresnelToWhiteScale));
|
||||
|
||||
float specTerm = (D * G) / max(4.0 * NoL * NoV, 1.0e-4);
|
||||
specTerm = min(specTerm, 3.6);
|
||||
specTerm = min(specTerm, 2.85);
|
||||
|
||||
const float SPECULAR_ENERGY_SCALE = 2.35;
|
||||
const float SPECULAR_ENERGY_SCALE = 3.15;
|
||||
|
||||
float3 specular =
|
||||
lightColor *
|
||||
@@ -4211,6 +4233,42 @@ float3 ComputeSpecularShaped(
|
||||
specTerm *
|
||||
(SPECULAR_ENERGY_SCALE * max(energyScale, 0.0));
|
||||
|
||||
float legacyLobe = Doom3SpecularLookup(NoH) * saturate(1.0 - roughness * 0.55);
|
||||
specular +=
|
||||
lightColor *
|
||||
lightIntensity *
|
||||
atten *
|
||||
shadow *
|
||||
NoL *
|
||||
specMask *
|
||||
legacyLobe *
|
||||
(0.72 * max(energyScale, 0.0));
|
||||
|
||||
float clearcoatMask = smoothstep(0.075, 0.22, specPeak) * saturate((0.58 - roughness) / 0.42);
|
||||
if (clearcoatMask > 0.0)
|
||||
{
|
||||
float coatRoughness = clamp(roughness * 0.55, 0.14, 0.36);
|
||||
float coatA = coatRoughness * coatRoughness;
|
||||
float coatA2 = max(coatA * coatA, 1.0e-4);
|
||||
float coatDenom = NoH * NoH * (coatA2 - 1.0) + 1.0;
|
||||
float coatD = coatA2 / max(PI * coatDenom * coatDenom, 1.0e-4);
|
||||
float coatK = ((coatRoughness + 1.0) * (coatRoughness + 1.0)) * 0.125;
|
||||
float coatGv = NoV / max(NoV * (1.0 - coatK) + coatK, 1.0e-4);
|
||||
float coatGl = NoL / max(NoL * (1.0 - coatK) + coatK, 1.0e-4);
|
||||
float coatF = 0.04 + 0.96 * pow(1.0 - VoH, 5.0);
|
||||
float coatTerm = min((coatD * coatGv * coatGl) / max(4.0 * NoL * NoV, 1.0e-4), 2.75);
|
||||
|
||||
specular +=
|
||||
lightColor *
|
||||
lightIntensity *
|
||||
atten *
|
||||
shadow *
|
||||
NoL *
|
||||
coatF *
|
||||
coatTerm *
|
||||
(0.30 * clearcoatMask * max(energyScale, 0.0));
|
||||
}
|
||||
|
||||
return LimitSpecularPeak(specular, peakLimit);
|
||||
}
|
||||
|
||||
@@ -4222,7 +4280,8 @@ float3 ComputeSpecular(
|
||||
float lightIntensity,
|
||||
float atten,
|
||||
float shadow,
|
||||
float3 specularAlbedo)
|
||||
float3 specularAlbedo,
|
||||
float surfaceRoughness)
|
||||
{
|
||||
return ComputeSpecularShaped(
|
||||
N,
|
||||
@@ -4237,8 +4296,9 @@ float3 ComputeSpecular(
|
||||
0.12,
|
||||
0.82,
|
||||
1.0,
|
||||
1.42,
|
||||
4.8);
|
||||
1.70,
|
||||
6.5,
|
||||
surfaceRoughness);
|
||||
}
|
||||
|
||||
float EstimateSkeletalSubsurfaceMask(float3 baseAlbedo, float3 specularAlbedo)
|
||||
@@ -4256,7 +4316,8 @@ float EstimateSkeletalSubsurfaceMask(float3 baseAlbedo, float3 specularAlbedo)
|
||||
|
||||
return saturate((0.08 + warm * 0.42 + redBias * 0.38) * fleshRange * lerp(0.55, 1.0, matte));
|
||||
}
|
||||
|
||||
)"
|
||||
R"(
|
||||
float3 ComputeSkeletalSpecularAlbedo(float3 baseAlbedo, float3 specularAlbedo)
|
||||
{
|
||||
float subsurfaceMask = EstimateSkeletalSubsurfaceMask(baseAlbedo, specularAlbedo);
|
||||
@@ -4269,7 +4330,8 @@ float3 ComputeSkeletalSpecularAlbedo(float3 baseAlbedo, float3 specularAlbedo)
|
||||
float cap = lerp(0.16, 0.075, subsurfaceMask);
|
||||
return min(softSpec, float3(cap, cap, cap));
|
||||
}
|
||||
|
||||
)"
|
||||
R"(
|
||||
float3 ComputeSkeletalSpecular(
|
||||
float3 N,
|
||||
float3 V,
|
||||
@@ -4279,7 +4341,8 @@ float3 ComputeSkeletalSpecular(
|
||||
float lightIntensity,
|
||||
float atten,
|
||||
float shadow,
|
||||
float3 specularAlbedo)
|
||||
float3 specularAlbedo,
|
||||
float surfaceRoughness)
|
||||
{
|
||||
float subsurfaceMask = EstimateSkeletalSubsurfaceMask(baseAlbedo, specularAlbedo);
|
||||
float3 characterSpec = ComputeSkeletalSpecularAlbedo(baseAlbedo, specularAlbedo);
|
||||
@@ -4301,7 +4364,8 @@ float3 ComputeSkeletalSpecular(
|
||||
0.58,
|
||||
lerp(0.32, 0.14, subsurfaceMask),
|
||||
lerp(0.40, 0.24, subsurfaceMask),
|
||||
lerp(0.55, 0.18, subsurfaceMask));
|
||||
lerp(0.55, 0.18, subsurfaceMask),
|
||||
max(surfaceRoughness, 0.48));
|
||||
}
|
||||
|
||||
float ComputeSubsurfaceShape(float3 N, float3 V, float3 L)
|
||||
@@ -4817,7 +4881,7 @@ float3 EstimatePathTracedSky(float3 worldPos, float3 N, inout uint rng)
|
||||
}
|
||||
)"
|
||||
R"(
|
||||
float3 PathTraceDirectPointLight(uint2 pixel, float3 worldPos, float3 N, float3 V, float3 baseAlbedo, float3 specularAlbedo, bool isSkeletal, float subsurfaceMask, Light Lgt, inout uint rng, out float3 specularOut, out float3 subsurfaceOut)
|
||||
float3 PathTraceDirectPointLight(uint2 pixel, float3 worldPos, float3 N, float3 V, float3 baseAlbedo, float3 specularAlbedo, float surfaceRoughness, bool isSkeletal, float subsurfaceMask, Light Lgt, inout uint rng, out float3 specularOut, out float3 subsurfaceOut)
|
||||
{
|
||||
specularOut = 0.0;
|
||||
subsurfaceOut = 0.0;
|
||||
@@ -4870,8 +4934,8 @@ float3 PathTraceDirectPointLight(uint2 pixel, float3 worldPos, float3 N, float3
|
||||
shadow = TraceVisibilityBiased(worldPos, N, L, dist);
|
||||
|
||||
specAccum += isSkeletal
|
||||
? ComputeSkeletalSpecular(N, V, L, baseAlbedo, Lgt.color, Lgt.intensity, atten, shadow, specularAlbedo)
|
||||
: ComputeSpecular(N, V, L, Lgt.color, Lgt.intensity, atten, shadow, specularAlbedo);
|
||||
? ComputeSkeletalSpecular(N, V, L, baseAlbedo, Lgt.color, Lgt.intensity, atten, shadow, specularAlbedo, surfaceRoughness)
|
||||
: ComputeSpecular(N, V, L, Lgt.color, Lgt.intensity, atten, shadow, specularAlbedo, surfaceRoughness);
|
||||
|
||||
sssAccum += ComputeSkeletalSubsurfaceRadiance(N, V, L, baseAlbedo, Lgt.color, Lgt.intensity, atten, shadow, subsurfaceMask);
|
||||
diffuseAccum += Lgt.color * (Lgt.intensity * atten * diffuseNoL * shadow);
|
||||
@@ -4884,7 +4948,7 @@ float3 PathTraceDirectPointLight(uint2 pixel, float3 worldPos, float3 N, float3
|
||||
}
|
||||
)"
|
||||
R"(
|
||||
float3 PathTraceDirectSpotLight(float3 worldPos, float3 N, float3 V, float3 baseAlbedo, float3 specularAlbedo, bool isSkeletal, float subsurfaceMask, Light Lgt, inout uint rng, out float3 specularOut, out float3 subsurfaceOut)
|
||||
float3 PathTraceDirectSpotLight(float3 worldPos, float3 N, float3 V, float3 baseAlbedo, float3 specularAlbedo, float surfaceRoughness, bool isSkeletal, float subsurfaceMask, Light Lgt, inout uint rng, out float3 specularOut, out float3 subsurfaceOut)
|
||||
{
|
||||
specularOut = 0.0;
|
||||
subsurfaceOut = 0.0;
|
||||
@@ -4904,15 +4968,15 @@ float3 PathTraceDirectSpotLight(float3 worldPos, float3 N, float3 V, float3 base
|
||||
shadow = TraceVisibilityBiased(worldPos, N, L, dist);
|
||||
|
||||
specularOut = isSkeletal
|
||||
? ComputeSkeletalSpecular(N, V, L, baseAlbedo, Lgt.color, Lgt.intensity, atten, shadow, specularAlbedo)
|
||||
: ComputeSpecular(N, V, L, Lgt.color, Lgt.intensity, atten, shadow, specularAlbedo);
|
||||
? ComputeSkeletalSpecular(N, V, L, baseAlbedo, Lgt.color, Lgt.intensity, atten, shadow, specularAlbedo, surfaceRoughness)
|
||||
: ComputeSpecular(N, V, L, Lgt.color, Lgt.intensity, atten, shadow, specularAlbedo, surfaceRoughness);
|
||||
|
||||
subsurfaceOut = ComputeSkeletalSubsurfaceRadiance(N, V, L, baseAlbedo, Lgt.color, Lgt.intensity, atten, shadow, subsurfaceMask);
|
||||
return Lgt.color * (Lgt.intensity * atten * diffuseNoL * shadow);
|
||||
}
|
||||
)"
|
||||
R"(
|
||||
float3 PathTraceDirectRectLight(uint2 pixel, float3 worldPos, float3 N, float3 V, float3 baseAlbedo, float3 specularAlbedo, bool isSkeletal, float subsurfaceMask, Light Lgt, inout uint rng, out float3 specularOut, out float3 subsurfaceOut)
|
||||
float3 PathTraceDirectRectLight(uint2 pixel, float3 worldPos, float3 N, float3 V, float3 baseAlbedo, float3 specularAlbedo, float surfaceRoughness, bool isSkeletal, float subsurfaceMask, Light Lgt, inout uint rng, out float3 specularOut, out float3 subsurfaceOut)
|
||||
{
|
||||
specularOut = 0.0;
|
||||
subsurfaceOut = 0.0;
|
||||
@@ -4981,7 +5045,8 @@ float3 PathTraceDirectRectLight(uint2 pixel, float3 worldPos, float3 N, float3 V
|
||||
Lgt.intensity * faceTerm,
|
||||
1.0,
|
||||
shadow,
|
||||
specularAlbedo)
|
||||
specularAlbedo,
|
||||
surfaceRoughness)
|
||||
: ComputeSpecular(
|
||||
N,
|
||||
V,
|
||||
@@ -4990,7 +5055,8 @@ float3 PathTraceDirectRectLight(uint2 pixel, float3 worldPos, float3 N, float3 V
|
||||
Lgt.intensity * faceTerm,
|
||||
1.0,
|
||||
shadow,
|
||||
specularAlbedo)) * atten;
|
||||
specularAlbedo,
|
||||
surfaceRoughness)) * atten;
|
||||
|
||||
sssAccum += ComputeSkeletalSubsurfaceRadiance(
|
||||
N,
|
||||
@@ -5294,6 +5360,7 @@ float3 EstimateShadowedBounceLight(uint2 hitPixel, float3 hitPos, float3 hitN, f
|
||||
float3 sss = 0.0;
|
||||
float3 diffuse = 0.0;
|
||||
float3 hitSpecularAlbedo = LoadSceneSpecularAlbedo(hitPixel, hitAlbedo);
|
||||
float hitSurfaceRoughness = StabilizeSpecularSurfaceRoughness(hitPixel, hitN, LoadSceneSurfaceRoughness(LoadSceneNormal(hitPixel)));
|
||||
float subsurfaceMask = hitIsSkeletal ? EstimateSkeletalSubsurfaceMask(hitAlbedo, hitSpecularAlbedo) * 0.45 : 0.0;
|
||||
|
||||
// Use the same visibility-capable direct-light samplers as the primary hit.
|
||||
@@ -5301,15 +5368,15 @@ float3 EstimateShadowedBounceLight(uint2 hitPixel, float3 hitPos, float3 hitN, f
|
||||
// old unoccluded light-list approximation.
|
||||
if (Lgt.type == GL_RAYTRACING_LIGHT_TYPE_POINT)
|
||||
{
|
||||
diffuse = PathTraceDirectPointLight(hitPixel, hitPos, hitN, hitV, hitAlbedo, hitSpecularAlbedo, hitIsSkeletal, subsurfaceMask, Lgt, rng, spec, sss);
|
||||
diffuse = PathTraceDirectPointLight(hitPixel, hitPos, hitN, hitV, hitAlbedo, hitSpecularAlbedo, hitSurfaceRoughness, hitIsSkeletal, subsurfaceMask, Lgt, rng, spec, sss);
|
||||
}
|
||||
else if (Lgt.type == GL_RAYTRACING_LIGHT_TYPE_SPOT)
|
||||
{
|
||||
diffuse = PathTraceDirectSpotLight(hitPos, hitN, hitV, hitAlbedo, hitSpecularAlbedo, hitIsSkeletal, subsurfaceMask, Lgt, rng, spec, sss);
|
||||
diffuse = PathTraceDirectSpotLight(hitPos, hitN, hitV, hitAlbedo, hitSpecularAlbedo, hitSurfaceRoughness, hitIsSkeletal, subsurfaceMask, Lgt, rng, spec, sss);
|
||||
}
|
||||
else if (Lgt.type == GL_RAYTRACING_LIGHT_TYPE_RECT)
|
||||
{
|
||||
diffuse = PathTraceDirectRectLight(hitPixel, hitPos, hitN, hitV, hitAlbedo, hitSpecularAlbedo, hitIsSkeletal, subsurfaceMask, Lgt, rng, spec, sss);
|
||||
diffuse = PathTraceDirectRectLight(hitPixel, hitPos, hitN, hitV, hitAlbedo, hitSpecularAlbedo, hitSurfaceRoughness, hitIsSkeletal, subsurfaceMask, Lgt, rng, spec, sss);
|
||||
}
|
||||
|
||||
return clamp(diffuse + sss * 0.35, 0.0, 12.0);
|
||||
@@ -5848,7 +5915,7 @@ float3 ApplyPrimarySpecularPost(float3 specularAccum, float ao, bool isSkeletal)
|
||||
// AO is a diffuse/ambient visibility term here. Multiplying specular by AO
|
||||
// directly made highlights disappear on creases, props, and normal-mapped
|
||||
// surfaces. Keep a mild occlusion tint, but let direct-light specular read.
|
||||
float specAo = lerp(0.58, 1.0, saturate(ao));
|
||||
float specAo = lerp(0.76, 1.0, saturate(ao));
|
||||
if (isSkeletal)
|
||||
{
|
||||
specAo = lerp(specAo, 1.0, 0.50);
|
||||
@@ -5869,6 +5936,7 @@ float3 PathTraceDeterministicLighting(
|
||||
float3 V,
|
||||
float3 baseAlbedo,
|
||||
float3 specularAlbedo,
|
||||
float surfaceRoughness,
|
||||
bool isSkeletal,
|
||||
float cavity,
|
||||
float ao,
|
||||
@@ -5915,15 +5983,15 @@ float3 PathTraceDeterministicLighting(
|
||||
|
||||
if (Lgt.type == GL_RAYTRACING_LIGHT_TYPE_POINT)
|
||||
{
|
||||
diffuse = PathTraceDirectPointLight(pixel, worldPos, N, V, baseAlbedo, specularAlbedo, isSkeletal, subsurfaceMask, Lgt, directRng, spec, sss);
|
||||
diffuse = PathTraceDirectPointLight(pixel, worldPos, N, V, baseAlbedo, specularAlbedo, surfaceRoughness, isSkeletal, subsurfaceMask, Lgt, directRng, spec, sss);
|
||||
}
|
||||
else if (Lgt.type == GL_RAYTRACING_LIGHT_TYPE_SPOT)
|
||||
{
|
||||
diffuse = PathTraceDirectSpotLight(worldPos, N, V, baseAlbedo, specularAlbedo, isSkeletal, subsurfaceMask, Lgt, directRng, spec, sss);
|
||||
diffuse = PathTraceDirectSpotLight(worldPos, N, V, baseAlbedo, specularAlbedo, surfaceRoughness, isSkeletal, subsurfaceMask, Lgt, directRng, spec, sss);
|
||||
}
|
||||
else if (Lgt.type == GL_RAYTRACING_LIGHT_TYPE_RECT)
|
||||
{
|
||||
diffuse = PathTraceDirectRectLight(pixel, worldPos, N, V, baseAlbedo, specularAlbedo, isSkeletal, subsurfaceMask, Lgt, directRng, spec, sss);
|
||||
diffuse = PathTraceDirectRectLight(pixel, worldPos, N, V, baseAlbedo, specularAlbedo, surfaceRoughness, isSkeletal, subsurfaceMask, Lgt, directRng, spec, sss);
|
||||
}
|
||||
|
||||
lightingAccum += diffuse;
|
||||
@@ -6057,6 +6125,7 @@ float3 EstimateRayTracedSpecularReflection(
|
||||
float3 V,
|
||||
float3 baseAlbedo,
|
||||
float3 specularAlbedo,
|
||||
float surfaceRoughness,
|
||||
float cavity,
|
||||
bool isSkeletal,
|
||||
inout uint rng)
|
||||
@@ -6097,8 +6166,8 @@ float3 EstimateRayTracedSpecularReflection(
|
||||
? saturate(specularAlbedo)
|
||||
: saturate(lerp(float3(0.02, 0.02, 0.02), specularAlbedo, 0.38));
|
||||
float3 fresnel = F0 + (1.0 - F0) * pow(1.0 - NoV, 5.0);
|
||||
float roughness = EstimateSpecularRoughness(specularAlbedo);
|
||||
roughness = clamp(lerp(roughness, 0.78, smoothstep(0.12, 0.46, normalVariance)), 0.38, 0.82);
|
||||
float roughness = EstimateSpecularRoughness(specularAlbedo, surfaceRoughness);
|
||||
roughness = clamp(lerp(roughness, 0.78, smoothstep(0.12, 0.46, normalVariance)), 0.16, 0.84);
|
||||
|
||||
// Do not multiply by specPeak again here. specularAlbedo is already F0, and
|
||||
// double-penalizing it made normal dielectric floors fall below the ray gate.
|
||||
@@ -6273,9 +6342,12 @@ void RayGen()
|
||||
uint geoFlag = DecodeGeometryFlag(positionSample.w);
|
||||
bool isSkeletal = (geoFlag & GEOMETRY_FLAG_SKELETAL) != 0u;
|
||||
bool isUnlit = (geoFlag & GEOMETRY_FLAG_UNLIT) != 0u;
|
||||
float4 normalSample = LoadSceneNormal(pixel);
|
||||
float surfaceRoughness = LoadSceneSurfaceRoughness(normalSample);
|
||||
float3 N = EnhanceBumpNormal(pixel, worldPos, baseAlbedo, isSkeletal);
|
||||
if (isSkeletal)
|
||||
N = StabilizeSkeletalNormal(pixel, worldPos, N);
|
||||
surfaceRoughness = StabilizeSpecularSurfaceRoughness(pixel, N, surfaceRoughness);
|
||||
float3 V = normalize(gCameraPos.xyz - worldPos);
|
||||
|
||||
if (isUnlit)
|
||||
@@ -6325,6 +6397,7 @@ void RayGen()
|
||||
V,
|
||||
baseAlbedo,
|
||||
specularAlbedo,
|
||||
surfaceRoughness,
|
||||
isSkeletal,
|
||||
cavity,
|
||||
ao,
|
||||
@@ -6370,6 +6443,7 @@ void RayGen()
|
||||
V,
|
||||
baseAlbedo,
|
||||
specularAlbedo,
|
||||
surfaceRoughness,
|
||||
cavity,
|
||||
isSkeletal,
|
||||
reflectionRng);
|
||||
@@ -6384,7 +6458,6 @@ void RayGen()
|
||||
finalColor += baseAlbedo * reactiveFinalGather * gGiAmount;
|
||||
}
|
||||
|
||||
float outputAo = isSkeletal ? lerp(ao, 1.0, 0.55) : ao;
|
||||
finalColor += subsurfaceAccum;
|
||||
|
||||
// Volumetric light scattering is radiance in the camera ray, not surface
|
||||
@@ -6400,7 +6473,7 @@ void RayGen()
|
||||
// the eventual swap-chain/backbuffer is LDR.
|
||||
finalColor += emissiveSurface + emissiveBloom;
|
||||
|
||||
gOutputTex[pixel] = float4(PreparePathTraceOutputColor(finalColor) * outputAo, primaryHitDistance);
|
||||
gOutputTex[pixel] = float4(PreparePathTraceOutputColor(finalColor), primaryHitDistance);
|
||||
}
|
||||
)";
|
||||
|
||||
|
||||
@@ -292,6 +292,8 @@ void APIENTRY glTextureSpecularMap(GLuint texture, GLboolean isSpecularMap);
|
||||
void APIENTRY glBindSpecularMapTexture(GLuint texture);
|
||||
void APIENTRY glSpecularMapTexture(GLuint texture);
|
||||
void APIENTRY glSpecularMapStrengthf(GLfloat strength);
|
||||
void APIENTRY glSurfaceRoughnessf(GLfloat roughness);
|
||||
void APIENTRY glMaterialTypef(GLfloat materialType);
|
||||
void APIENTRY glTextureAverageColorQD3D12(GLuint texture, GLfloat r, GLfloat g, GLfloat b, GLfloat a);
|
||||
void APIENTRY glTerrainBlendEnableQD3D12(GLboolean enable);
|
||||
void APIENTRY glEnableTerrainBlendQD3D12(GLboolean enable);
|
||||
@@ -18725,6 +18727,8 @@ PROC WINAPI qd3d12_wglGetProcAddress(LPCSTR name) {
|
||||
{ "glBindSpecularMapTexture", (PROC)glBindSpecularMapTexture },
|
||||
{ "glSpecularMapTexture", (PROC)glSpecularMapTexture },
|
||||
{ "glSpecularMapStrengthf", (PROC)glSpecularMapStrengthf },
|
||||
{ "glSurfaceRoughnessf", (PROC)glSurfaceRoughnessf },
|
||||
{ "glMaterialTypef", (PROC)glMaterialTypef },
|
||||
{ "glTerrainBlendEnableQD3D12", (PROC)glTerrainBlendEnableQD3D12 },
|
||||
{ "glEnableTerrainBlendQD3D12", (PROC)glEnableTerrainBlendQD3D12 },
|
||||
{ "glTerrainLayerTextureQD3D12", (PROC)glTerrainLayerTextureQD3D12 },
|
||||
|
||||
@@ -2329,6 +2329,8 @@ void APIENTRY glTextureSpecularMap(GLuint texture, GLboolean isSpecularMap);
|
||||
void APIENTRY glBindSpecularMapTexture(GLuint texture);
|
||||
void APIENTRY glSpecularMapTexture(GLuint texture);
|
||||
void APIENTRY glSpecularMapStrengthf(GLfloat strength);
|
||||
void APIENTRY glSurfaceRoughnessf(GLfloat roughness);
|
||||
void APIENTRY glMaterialTypef(GLfloat materialType);
|
||||
void APIENTRY glTextureAverageColorQD3D12(GLuint texture, GLfloat r, GLfloat g, GLfloat b, GLfloat a);
|
||||
|
||||
void glUpdateTopLevelAceelStructure(
|
||||
|
||||
@@ -32,6 +32,92 @@ If you have questions concerning this license or the applicable additional terms
|
||||
|
||||
idCVar r_renderNeuralMaterial("r_renderNeuralMaterial", "0", CVAR_BOOL, "");
|
||||
|
||||
static bool RB_MaterialNameHasToken( const idMaterial *shader, const char *token ) {
|
||||
if ( !shader || !token || !token[0] ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
idStr name = shader->GetName();
|
||||
name.ToLower();
|
||||
return name.Find( token ) >= 0;
|
||||
}
|
||||
|
||||
static float RB_EstimatePathTraceRoughness( const idMaterial *shader, const idImage *specImage, const idImage *glowMapImage ) {
|
||||
const bool hasSpec = ( specImage != NULL );
|
||||
const bool hasGlow = ( glowMapImage != NULL );
|
||||
float roughness = hasSpec ? 0.44f : 0.72f;
|
||||
|
||||
if ( RB_MaterialNameHasToken( shader, "glass" ) ||
|
||||
RB_MaterialNameHasToken( shader, "window" ) ||
|
||||
RB_MaterialNameHasToken( shader, "screen" ) ||
|
||||
RB_MaterialNameHasToken( shader, "monitor" ) ||
|
||||
RB_MaterialNameHasToken( shader, "computer" ) ) {
|
||||
roughness = hasGlow ? 0.22f : 0.28f;
|
||||
}
|
||||
else if ( RB_MaterialNameHasToken( shader, "blood" ) ||
|
||||
RB_MaterialNameHasToken( shader, "slime" ) ||
|
||||
RB_MaterialNameHasToken( shader, "water" ) ||
|
||||
RB_MaterialNameHasToken( shader, "wet" ) ) {
|
||||
roughness = 0.24f;
|
||||
}
|
||||
else if ( RB_MaterialNameHasToken( shader, "floor" ) ||
|
||||
RB_MaterialNameHasToken( shader, "tile" ) ||
|
||||
RB_MaterialNameHasToken( shader, "plate" ) ) {
|
||||
roughness = hasSpec ? 0.34f : 0.52f;
|
||||
}
|
||||
else if ( RB_MaterialNameHasToken( shader, "metal" ) ||
|
||||
RB_MaterialNameHasToken( shader, "panel" ) ||
|
||||
RB_MaterialNameHasToken( shader, "pipe" ) ||
|
||||
RB_MaterialNameHasToken( shader, "door" ) ||
|
||||
RB_MaterialNameHasToken( shader, "trim" ) ||
|
||||
RB_MaterialNameHasToken( shader, "machine" ) ) {
|
||||
roughness = hasSpec ? 0.36f : 0.58f;
|
||||
}
|
||||
else if ( RB_MaterialNameHasToken( shader, "skin" ) ||
|
||||
RB_MaterialNameHasToken( shader, "flesh" ) ||
|
||||
RB_MaterialNameHasToken( shader, "monster" ) ||
|
||||
RB_MaterialNameHasToken( shader, "char" ) ) {
|
||||
roughness = 0.62f;
|
||||
}
|
||||
else if ( RB_MaterialNameHasToken( shader, "wall" ) ||
|
||||
RB_MaterialNameHasToken( shader, "ceil" ) ||
|
||||
RB_MaterialNameHasToken( shader, "concrete" ) ||
|
||||
RB_MaterialNameHasToken( shader, "rock" ) ||
|
||||
RB_MaterialNameHasToken( shader, "stone" ) ) {
|
||||
roughness = hasSpec ? 0.56f : 0.78f;
|
||||
}
|
||||
|
||||
return idMath::ClampFloat( 0.08f, 0.92f, roughness );
|
||||
}
|
||||
|
||||
static float RB_EstimatePathTraceSpecularStrength( const idMaterial *shader, const idImage *specImage, const idImage *glowMapImage ) {
|
||||
if ( !specImage ) {
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
float strength = 1.35f;
|
||||
if ( RB_MaterialNameHasToken( shader, "floor" ) ||
|
||||
RB_MaterialNameHasToken( shader, "tile" ) ||
|
||||
RB_MaterialNameHasToken( shader, "metal" ) ||
|
||||
RB_MaterialNameHasToken( shader, "panel" ) ||
|
||||
RB_MaterialNameHasToken( shader, "door" ) ) {
|
||||
strength = 1.85f;
|
||||
}
|
||||
if ( glowMapImage ||
|
||||
RB_MaterialNameHasToken( shader, "glass" ) ||
|
||||
RB_MaterialNameHasToken( shader, "screen" ) ||
|
||||
RB_MaterialNameHasToken( shader, "monitor" ) ) {
|
||||
strength = 2.10f;
|
||||
}
|
||||
if ( RB_MaterialNameHasToken( shader, "skin" ) ||
|
||||
RB_MaterialNameHasToken( shader, "flesh" ) ||
|
||||
RB_MaterialNameHasToken( shader, "monster" ) ) {
|
||||
strength = 0.75f;
|
||||
}
|
||||
|
||||
return idMath::ClampFloat( 0.5f, 2.4f, strength );
|
||||
}
|
||||
|
||||
static idDrawVert *RB_BindAmbientBuffer( const srfTriangles_t *tri ) {
|
||||
if ( tri->ambientVbo ) {
|
||||
glBindBufferARB( GL_ARRAY_BUFFER_ARB, tri->ambientVbo );
|
||||
@@ -498,6 +584,8 @@ void RB_T_FillDepthBuffer(const drawSurf_t* surf) {
|
||||
idImage* bumpImage = shader->GetBumpImage();
|
||||
idImage* specImage = shader->GetSpecImage();
|
||||
idImage* glowMapImage = shader->GetGlowImage(regs);
|
||||
const float pathTraceRoughness = RB_EstimatePathTraceRoughness( shader, specImage, glowMapImage );
|
||||
const float pathTraceSpecularStrength = RB_EstimatePathTraceSpecularStrength( shader, specImage, glowMapImage );
|
||||
|
||||
// Make sure the material has tried to load/upload its NeuralPOM payload.
|
||||
// If no neural files exist, this should leave the handle as 0.
|
||||
@@ -542,11 +630,14 @@ void RB_T_FillDepthBuffer(const drawSurf_t* surf) {
|
||||
if (specImage) {
|
||||
specImage->Bind();
|
||||
glBindSpecularMapTexture(specImage->texnum);
|
||||
glSpecularMapStrengthf(pathTraceSpecularStrength);
|
||||
}
|
||||
else {
|
||||
globalImages->BindNull();
|
||||
glBindSpecularMapTexture(0);
|
||||
glSpecularMapStrengthf(1.0f);
|
||||
}
|
||||
glSurfaceRoughnessf(pathTraceRoughness);
|
||||
|
||||
// glow fallback
|
||||
if (glowMapImage) {
|
||||
@@ -580,6 +671,8 @@ void RB_T_FillDepthBuffer(const drawSurf_t* surf) {
|
||||
|
||||
GL_SelectTexture(2);
|
||||
glBindSpecularMapTexture(0);
|
||||
glSpecularMapStrengthf(1.0f);
|
||||
glSurfaceRoughnessf(0.5f);
|
||||
globalImages->BindNull();
|
||||
|
||||
GL_SelectTexture(1);
|
||||
|
||||
Reference in New Issue
Block a user