Fixed MD5 models.

GI now bounces off textures properly.
This commit is contained in:
Justin Marshall
2026-05-21 18:58:43 -07:00
parent 1f5f0733fe
commit 345e6bfc81
10 changed files with 384 additions and 70 deletions
+1
View File
@@ -4015,6 +4015,7 @@ static classVariableInfo_t glRaytracingMeshDesc_t_typeInfo[] = {
{ "uint32_t", "indexCount", (intptr_t)(&((glRaytracingMeshDesc_t *)0)->indexCount), sizeof( ((glRaytracingMeshDesc_t *)0)->indexCount ) },
{ "int", "allowUpdate", (intptr_t)(&((glRaytracingMeshDesc_t *)0)->allowUpdate), sizeof( ((glRaytracingMeshDesc_t *)0)->allowUpdate ) },
{ "int", "opaque", (intptr_t)(&((glRaytracingMeshDesc_t *)0)->opaque), sizeof( ((glRaytracingMeshDesc_t *)0)->opaque ) },
{ "float[4]", "averageColor", (intptr_t)(&((glRaytracingMeshDesc_t *)0)->averageColor), sizeof( ((glRaytracingMeshDesc_t *)0)->averageColor ) },
{ NULL, 0 }
};
+2 -2
View File
@@ -15,9 +15,9 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LocalDebuggerCommand>D:\projects\Doom3\Doom3.exe</LocalDebuggerCommand>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerCommandArguments>+set r_fullscreen 0 +set r_mode 9 +set sv_pure 0 </LocalDebuggerCommandArguments>
<LocalDebuggerCommandArguments>+set r_fullscreen 0 +set r_mode 11 +set sv_pure 0 </LocalDebuggerCommandArguments>
<LocalDebuggerWorkingDirectory>D:\projects\Doom3</LocalDebuggerWorkingDirectory>
<LocalDebuggerCommandArgumentsHistory>+set r_fullscreen 0 +set r_mode 9|+set r_fullscreen 1 +set r_mode 9 +set sv_pure 0 +set fs_game e3|+set r_fullscreen 0 +set r_mode 9 +set sv_pure 0|+set r_fullscreen 0 +set r_mode 9 +set sv_pure 0 +set fs_game e3|+set r_fullscreen 0 +set r_mode 9 +set sv_pure 0 |</LocalDebuggerCommandArgumentsHistory>
<LocalDebuggerCommandArgumentsHistory>+set r_fullscreen 1 +set r_mode 9 +set sv_pure 0 +set fs_game e3|+set r_fullscreen 0 +set r_mode 9 +set sv_pure 0|+set r_fullscreen 0 +set r_mode 9 +set sv_pure 0 +set fs_game e3|+set r_fullscreen 0 +set r_mode 9 +set sv_pure 0 |+set r_fullscreen 0 +set r_mode 11 +set sv_pure 0 |</LocalDebuggerCommandArgumentsHistory>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Q4 Debug|x64'">
<LocalDebuggerCommand>D:\projects\Doom3\Quake4.exe</LocalDebuggerCommand>
+3 -1
View File
@@ -31,6 +31,7 @@ If you have questions concerning this license or the applicable additional terms
void SCR_DrawTextLeftAlign( float &y, const char *text, ... ) id_attribute((format(printf,2,3)));
void SCR_DrawTextRightAlign( float &y, const char *text, ... ) id_attribute((format(printf,2,3)));
extern int QD3D12_GetActiveFrameGenerationMultiplier( void );
#define LINE_WIDTH 78
#define NUM_CON_TIMES 4
@@ -219,7 +220,8 @@ float SCR_DrawFPS( float y ) {
fps = (fps + 5)/10;
const int averageFrameTime = ( total + ( FPS_FRAMES / 2 ) ) / FPS_FRAMES;
const int frameGenMultiplier = idMath::ClampInt( 1, 4, cvarSystem->GetCVarInteger( "r_frameGen" ) );
const int requestedFrameGenMultiplier = idMath::ClampInt( 1, 4, cvarSystem->GetCVarInteger( "r_frameGen" ) );
const int frameGenMultiplier = ( requestedFrameGenMultiplier >= 2 ) ? idMath::ClampInt( 1, 4, QD3D12_GetActiveFrameGenerationMultiplier() ) : 1;
const int displayFps = fps * frameGenMultiplier;
const int displayFrameTime = ( averageFrameTime + ( frameGenMultiplier / 2 ) ) / frameGenMultiplier;
const idVec4 &frameColor = SCR_FrameTimeColor( displayFrameTime );
+24 -5
View File
@@ -568,10 +568,12 @@ void idRenderModelStatic::UpdateDXR(uint32_t& dxrBottomAcel, int onlySurface)
continue;
modelSurface_t* surf = &surfaces[i];
if (!surf->geometry || surf->geometry->numVerts <= 0 || surf->geometry->numIndexes <= 0)
continue;
if (onlySurface == -1)
{
if (!surf->shader->IsLitMaterial()) {
if (!surf->shader || !surf->shader->IsLitMaterial()) {
continue;
}
}
@@ -591,14 +593,21 @@ void idRenderModelStatic::UpdateDXR(uint32_t& dxrBottomAcel, int onlySurface)
continue;
modelSurface_t* surf = &surfaces[i];
if (!surf->geometry || surf->geometry->numVerts <= 0 || surf->geometry->numIndexes <= 0)
continue;
if (onlySurface == -1)
{
if (!surf->shader->IsLitMaterial()) {
if (!surf->shader || !surf->shader->IsLitMaterial()) {
continue;
}
}
if (!surf->geometry->tangentsCalculated)
{
R_DeriveTangents(surf->geometry);
}
for (int d = 0; d < surf->geometry->numIndexes; ++d)
{
indices[indexId++] = vertexId + surf->geometry->indexes[d];
@@ -606,9 +615,15 @@ void idRenderModelStatic::UpdateDXR(uint32_t& dxrBottomAcel, int onlySurface)
for (int d = 0; d < surf->geometry->numVerts; ++d)
{
vertices[vertexId].xyz[0] = surf->geometry->verts[d].xyz.x;
vertices[vertexId].xyz[1] = surf->geometry->verts[d].xyz.y;
vertices[vertexId].xyz[2] = surf->geometry->verts[d].xyz.z;
const idDrawVert& src = surf->geometry->verts[d];
vertices[vertexId].xyz[0] = src.xyz.x;
vertices[vertexId].xyz[1] = src.xyz.y;
vertices[vertexId].xyz[2] = src.xyz.z;
vertices[vertexId].normal[0] = src.normal.x;
vertices[vertexId].normal[1] = src.normal.y;
vertices[vertexId].normal[2] = src.normal.z;
vertices[vertexId].st[0] = src.st.x;
vertices[vertexId].st[1] = src.st.y;
vertexId++;
}
}
@@ -625,6 +640,10 @@ void idRenderModelStatic::UpdateDXR(uint32_t& dxrBottomAcel, int onlySurface)
desc.indexCount = (uint32_t)numDXRIndexes;
desc.allowUpdate = 1;
desc.opaque = 1;
desc.averageColor[0] = 1.0f;
desc.averageColor[1] = 1.0f;
desc.averageColor[2] = 1.0f;
desc.averageColor[3] = 1.0f;
if (!dxrBottomAcel)
{
+3 -3
View File
@@ -262,9 +262,9 @@ Special transform to make the mesh seem fat or skinny. May be used for zombie d
====================
*/
void idMD5Mesh::TransformScaledVerts( idDrawVert *verts, const idJointMat *entJoints, float scale ) {
idVec4 *scaledWeights = (idVec4 *) _alloca16( numWeights * sizeof( scaledWeights[0] ) );
SIMDProcessor->Mul( scaledWeights[0].ToFloatPtr(), scale, scaledWeights[0].ToFloatPtr(), numWeights * 4 );
SIMDProcessor->TransformVerts( verts, texCoords.Num(), entJoints, scaledWeights, weightIndex, numWeights );
idVec4 *scaledWeightsLocal = (idVec4 *) _alloca16( numWeights * sizeof( scaledWeightsLocal[0] ) );
SIMDProcessor->Mul( scaledWeightsLocal[0].ToFloatPtr(), scale, scaledWeights[0].ToFloatPtr(), numWeights * 4 );
SIMDProcessor->TransformVerts( verts, texCoords.Num(), entJoints, scaledWeightsLocal, weightIndex, numWeights );
}
/*
+224 -46
View File
@@ -796,6 +796,7 @@ struct glRaytracingMeshRecord_t
UINT64 blasBuildFenceValue;
int currentBlasIndex;
uint32_t materialFlags;
float averageColor[4];
glRaytracingMeshRecord_t()
{
@@ -809,6 +810,7 @@ struct glRaytracingMeshRecord_t
blasBuildFenceValue = 0;
currentBlasIndex = 0;
materialFlags = 0;
averageColor[0] = averageColor[1] = averageColor[2] = averageColor[3] = 1.0f;
}
};
@@ -1055,6 +1057,27 @@ static void glRaytracingMarkAllWorldsNeedRebuild(void)
glRaytracingLightingResetDenoiseHistory();
}
static void glRaytracingCopyMeshAverageColor(float outAverageColor[4], const glRaytracingMeshDesc_t* desc)
{
if (!outAverageColor)
return;
outAverageColor[0] = outAverageColor[1] = outAverageColor[2] = outAverageColor[3] = 1.0f;
if (!desc)
return;
const bool hasExplicitAverage =
desc->averageColor[0] != 0.0f ||
desc->averageColor[1] != 0.0f ||
desc->averageColor[2] != 0.0f ||
desc->averageColor[3] != 0.0f;
if (!hasExplicitAverage)
return;
for (int i = 0; i < 4; ++i)
outAverageColor[i] = glRaytracingClamp<float>(desc->averageColor[i], 0.0f, 1.0f);
}
static uint32_t glRaytracingCountAliveInstances(const glRaytracingRenderWorld_t* world)
{
if (!world)
@@ -1330,19 +1353,20 @@ static int glRaytracingEnsureMeshResultBuffers(glRaytracingMeshRecord_t* mesh, U
static inline void glRaytracingBuildInstanceDesc(
D3D12_RAYTRACING_INSTANCE_DESC* outDesc,
const glRaytracingInstanceRecord_t& inst,
uint32_t meshHandle,
uint32_t meshMaterialFlags,
D3D12_GPU_VIRTUAL_ADDRESS blasGpuVA)
{
memcpy(outDesc->Transform, inst.descCpu.transform, sizeof(float) * 12);
// InstanceID is 24-bit in D3D12_RAYTRACING_INSTANCE_DESC. Preserve the
// caller's lower 16 bits, then pack material flags into bits 16-23 so the
// InstanceID is 24-bit in D3D12_RAYTRACING_INSTANCE_DESC. The lower 16 bits
// carry the mesh metadata index, and bits 16-23 carry material flags so the
// any-hit shader can decide whether visibility rays pass through the hit.
//
// Accept both sources:
// - meshMaterialFlags set by glRaytracingSetMeshMaterialFlags()/shim mesh tags
// - already-encoded high InstanceID bits for direct low-level callers
const uint32_t userInstanceId = inst.descCpu.instanceID & GL_RAYTRACING_INSTANCE_USER_ID_MASK;
const uint32_t userInstanceId = meshHandle & GL_RAYTRACING_INSTANCE_USER_ID_MASK;
const uint32_t instanceMaterialFlags =
(inst.descCpu.instanceID >> GL_RAYTRACING_INSTANCE_MATERIAL_SHIFT) & GL_RAYTRACING_INSTANCE_MATERIAL_MASK;
const uint32_t combinedMaterialFlags =
@@ -1382,7 +1406,7 @@ static int glRaytracingResolveInstanceDesc(
return 0;
if (outDesc)
glRaytracingBuildInstanceDesc(outDesc, *inst, mesh->materialFlags, blas->gpuVA);
glRaytracingBuildInstanceDesc(outDesc, *inst, mesh->handle, mesh->materialFlags, blas->gpuVA);
if (outBlasGpuVA)
*outBlasGpuVA = blas->gpuVA;
return 1;
@@ -2015,6 +2039,7 @@ glRaytracingMeshHandle_t glRaytracingCreateMesh(const glRaytracingMeshDesc_t* de
mesh.indicesCpu.assign(desc->indices, desc->indices + desc->indexCount);
mesh.descCpu.vertices = nullptr;
mesh.descCpu.indices = nullptr;
glRaytracingCopyMeshAverageColor(mesh.averageColor, desc);
mesh.dirty = 1;
g_glRaytracingScene.meshes.push_back(mesh);
@@ -2052,9 +2077,19 @@ int glRaytracingUpdateMesh(glRaytracingMeshHandle_t meshHandle, const glRaytraci
mesh->descCpu.indexCount == desc->indexCount &&
mesh->descCpu.allowUpdate == desc->allowUpdate &&
mesh->descCpu.opaque == desc->opaque;
float descAverageColor[4];
glRaytracingCopyMeshAverageColor(descAverageColor, desc);
const bool sameAverageColor = memcmp(mesh->averageColor, descAverageColor, sizeof(mesh->averageColor)) == 0;
if (sameDesc && sameVertexData && sameIndexData)
{
if (!sameAverageColor)
{
memcpy(mesh->averageColor, descAverageColor, sizeof(mesh->averageColor));
glRaytracingLightingResetDenoiseHistory();
}
return 1;
}
const bool canUpdateExistingBuffers =
desc->allowUpdate != 0 &&
@@ -2073,6 +2108,7 @@ int glRaytracingUpdateMesh(glRaytracingMeshHandle_t meshHandle, const glRaytraci
mesh->indicesCpu.assign(desc->indices, desc->indices + desc->indexCount);
mesh->descCpu.vertices = nullptr;
mesh->descCpu.indices = nullptr;
memcpy(mesh->averageColor, descAverageColor, sizeof(mesh->averageColor));
if (canUpdateExistingBuffers)
{
@@ -2152,6 +2188,29 @@ void glRaytracingSetMeshGlass(glRaytracingMeshHandle_t meshHandle, int isGlass)
glRaytracingSetMeshMaterialFlags(meshHandle, flags);
}
void glRaytracingSetMeshAverageColor(glRaytracingMeshHandle_t meshHandle, float r, float g, float b, float a)
{
std::lock_guard<std::mutex> lock(g_glRaytracingMutex);
glRaytracingMeshRecord_t* mesh = glRaytracingFindMesh(meshHandle);
if (!mesh)
return;
const float averageColor[4] =
{
glRaytracingClamp<float>(r, 0.0f, 1.0f),
glRaytracingClamp<float>(g, 0.0f, 1.0f),
glRaytracingClamp<float>(b, 0.0f, 1.0f),
glRaytracingClamp<float>(a, 0.0f, 1.0f)
};
if (memcmp(mesh->averageColor, averageColor, sizeof(averageColor)) == 0)
return;
memcpy(mesh->averageColor, averageColor, sizeof(mesh->averageColor));
glRaytracingLightingResetDenoiseHistory();
}
void glRaytracingDeleteMesh(glRaytracingMeshHandle_t meshHandle)
{
std::lock_guard<std::mutex> lock(g_glRaytracingMutex);
@@ -2404,6 +2463,11 @@ struct glRaytracingLightingConstants_t
float bumpStrength;
};
struct glRaytracingMeshMetadata_t
{
float averageColor[4];
};
struct glRaytracingLightingState_t
{
std::vector<glRaytracingLight_t> cpuLights;
@@ -2415,12 +2479,16 @@ struct glRaytracingLightingState_t
glRaytracingBuffer_t constantBuffer;
glRaytracingBuffer_t lightBuffer;
glRaytracingBuffer_t meshMetadataBuffer;
void* constantBufferMapped;
void* lightBufferMapped;
void* meshMetadataBufferMapped;
glRaytracingBuffer_t constantBufferRing[GL_RAYTRACING_CMD_RING_SIZE];
glRaytracingBuffer_t lightBufferRing[GL_RAYTRACING_CMD_RING_SIZE];
glRaytracingBuffer_t meshMetadataBufferRing[GL_RAYTRACING_CMD_RING_SIZE];
void* constantBufferMappedRing[GL_RAYTRACING_CMD_RING_SIZE];
void* lightBufferMappedRing[GL_RAYTRACING_CMD_RING_SIZE];
void* meshMetadataBufferMappedRing[GL_RAYTRACING_CMD_RING_SIZE];
ComPtr<ID3D12RootSignature> globalRootSig;
ComPtr<ID3D12RootSignature> localRootSig;
@@ -2462,10 +2530,12 @@ struct glRaytracingLightingState_t
descriptorStride = 0;
constantBufferMapped = nullptr;
lightBufferMapped = nullptr;
meshMetadataBufferMapped = nullptr;
for (UINT frame = 0; frame < GL_RAYTRACING_CMD_RING_SIZE; ++frame)
{
constantBufferMappedRing[frame] = nullptr;
lightBufferMappedRing[frame] = nullptr;
meshMetadataBufferMappedRing[frame] = nullptr;
for (int i = 0; i < 3; ++i)
denoiseConstantBufferMappedRing[frame][i] = nullptr;
}
@@ -2506,14 +2576,15 @@ enum glRaytracingLightingDescriptorIndex_t
GLR_DESC_TEMPORAL_SRV = 10,
GLR_DESC_EMISSIVE_SRV = 11,
GLR_DESC_SPECULAR_SRV = 12,
GLR_DESC_PATHTRACE_UAV = 13,
GLR_DESC_DENOISE_A_UAV = 14,
GLR_DESC_DENOISE_B_UAV = 15,
GLR_DESC_OUTPUT_UAV = 16,
GLR_DESC_TEMPORAL_UAV = 17,
GLR_DESC_HISTORY_UAV = 18,
GLR_DESC_COUNT = 19,
GLR_DESC_SRV_COUNT = 13,
GLR_DESC_MESH_METADATA_SRV = 13,
GLR_DESC_PATHTRACE_UAV = 14,
GLR_DESC_DENOISE_A_UAV = 15,
GLR_DESC_DENOISE_B_UAV = 16,
GLR_DESC_OUTPUT_UAV = 17,
GLR_DESC_TEMPORAL_UAV = 18,
GLR_DESC_HISTORY_UAV = 19,
GLR_DESC_COUNT = 20,
GLR_DESC_SRV_COUNT = 14,
GLR_DESC_UAV_COUNT = 6
};
@@ -2562,6 +2633,11 @@ struct Light
float pointRadiusPad; // non-zero disables specular for this light
};
struct MeshMetadata
{
float4 averageColor;
};
struct ShadowPayload
{
uint hit;
@@ -2572,7 +2648,7 @@ struct BouncePayload
uint hit;
float hitT;
uint materialFlags;
uint pad0;
uint meshIndex;
};
cbuffer LightingCB : register(b0)
@@ -2609,6 +2685,7 @@ Texture2D<float4> gPositionTex : register(t4);
RaytracingAccelerationStructure gSceneBVH : register(t5);
Texture2D<float4> gEmissiveTex : register(t11);
Texture2D<float4> gSpecularTex : register(t12);
StructuredBuffer<MeshMetadata> gMeshMetadata : register(t13);
RWTexture2D<float4> gOutputTex : register(u0);
static const uint GL_RAYTRACING_LIGHT_TYPE_POINT = 0;
@@ -2639,6 +2716,12 @@ bool CurrentRayHitIsGlass()
return (DecodeInstanceMaterialFlags() & GL_RAYTRACING_MATERIAL_FLAG_GLASS) != 0u;
}
float3 GetMeshAverageColor(uint meshIndex)
{
float3 c = gMeshMetadata[meshIndex].averageColor.rgb;
return max(saturate(c), float3(0.04, 0.04, 0.04));
}
uint DecodeGeometryFlag(float geoFlag)
{
// position.w comes from a render target / buffer path, so do not require exact
@@ -2689,10 +2772,16 @@ float BumpLuminance(float3 c)
return dot(c, float3(0.299, 0.587, 0.114));
}
float3 EnhanceBumpNormal(uint2 pixel, float3 worldPos, float3 baseAlbedo)
float3 EnhanceBumpNormal(uint2 pixel, float3 worldPos, float3 baseAlbedo, bool isSkeletal)
{
float3 N = SafeNormalizeLocal(LoadSceneNormal(pixel).xyz, float3(0.0, 0.0, 1.0));
// Character albedo has skin, cloth, and painted detail that should not be
// interpreted as height. The synthetic bump pass looks good on old walls,
// but it makes animated models crawl and self-shadow like noisy relief maps.
if (isSkeletal)
return N;
float strength = max(gBumpStrength, 0.0);
if (strength <= 0.001)
return N;
@@ -2796,7 +2885,7 @@ void BounceMiss(inout BouncePayload payload)
payload.hit = 0;
payload.hitT = 0.0;
payload.materialFlags = 0;
payload.pad0 = 0;
payload.meshIndex = 0;
}
[shader("anyhit")]
@@ -2822,14 +2911,14 @@ void BounceClosestHit(inout BouncePayload payload, in BuiltInTriangleIntersectio
payload.hit = 0;
payload.hitT = 0.0;
payload.materialFlags = DecodeInstanceMaterialFlags();
payload.pad0 = 0;
payload.meshIndex = InstanceID() & GL_RAYTRACING_INSTANCE_USER_ID_MASK;
return;
}
payload.hit = 1;
payload.hitT = RayTCurrent();
payload.materialFlags = DecodeInstanceMaterialFlags();
payload.pad0 = 0;
payload.meshIndex = InstanceID() & GL_RAYTRACING_INSTANCE_USER_ID_MASK;
}
[shader("closesthit")]
@@ -2841,7 +2930,7 @@ void ReflectionClosestHit(inout BouncePayload payload, in BuiltInTriangleInterse
payload.hit = 1;
payload.hitT = RayTCurrent();
payload.materialFlags = DecodeInstanceMaterialFlags();
payload.pad0 = 0;
payload.meshIndex = InstanceID() & GL_RAYTRACING_INSTANCE_USER_ID_MASK;
}
float TraceShadow(float3 origin, float3 dir, float maxT)
@@ -2868,7 +2957,7 @@ float TraceShadow(float3 origin, float3 dir, float maxT)
return (payload.hit != 0) ? 0.0 : 1.0;
}
bool TraceBounce(float3 origin, float3 dir, float maxT, out float hitT, out uint materialFlags)
bool TraceBounce(float3 origin, float3 dir, float maxT, out float hitT, out uint materialFlags, out uint meshIndex)
{
RayDesc ray;
ray.Origin = origin;
@@ -2880,7 +2969,7 @@ bool TraceBounce(float3 origin, float3 dir, float maxT, out float hitT, out uint
payload.hit = 0;
payload.hitT = 0.0;
payload.materialFlags = 0;
payload.pad0 = 0;
payload.meshIndex = 0;
TraceRay(
gSceneBVH,
@@ -2894,10 +2983,11 @@ bool TraceBounce(float3 origin, float3 dir, float maxT, out float hitT, out uint
hitT = payload.hitT;
materialFlags = payload.materialFlags;
meshIndex = payload.meshIndex;
return payload.hit != 0;
}
bool TraceSpecularReflection(float3 origin, float3 dir, float maxT, out float hitT, out uint materialFlags)
bool TraceSpecularReflection(float3 origin, float3 dir, float maxT, out float hitT, out uint materialFlags, out uint meshIndex)
{
RayDesc ray;
ray.Origin = origin;
@@ -2909,7 +2999,7 @@ bool TraceSpecularReflection(float3 origin, float3 dir, float maxT, out float hi
payload.hit = 0;
payload.hitT = 0.0;
payload.materialFlags = 0;
payload.pad0 = 0;
payload.meshIndex = 0;
TraceRay(
gSceneBVH,
@@ -2923,6 +3013,7 @@ bool TraceSpecularReflection(float3 origin, float3 dir, float maxT, out float hi
hitT = payload.hitT;
materialFlags = payload.materialFlags;
meshIndex = payload.meshIndex;
return payload.hit != 0;
}
@@ -3252,10 +3343,10 @@ float RectLightShadow(float3 worldPos, float3 N, Light Lgt, uint2 pixel)
return visibility / (float)sampleCount;
}
float ComputeAmbientOcclusion(float3 worldPos, float3 N, uint2 pixel)
float ComputeAmbientOcclusion(float3 worldPos, float3 N, uint2 pixel, bool isSkeletal)
{
const uint AO_SAMPLES = 8;
const float AO_RADIUS = 32.0;
float aoRadius = isSkeletal ? 18.0 : 32.0;
float3 tangent, bitangent;
BuildOrthonormalBasis(N, tangent, bitangent);
@@ -3277,14 +3368,17 @@ float ComputeAmbientOcclusion(float3 worldPos, float3 N, uint2 pixel)
aoDir = normalize(aoDir);
float3 aoOrigin = worldPos + N * (gShadowBias * 0.15);
float3 aoOrigin = worldPos + N * (gShadowBias * (isSkeletal ? 0.75 : 0.15));
visibility += TraceShadow(aoOrigin, aoDir, AO_RADIUS);
visibility += TraceShadow(aoOrigin, aoDir, aoRadius);
}
visibility /= (float)AO_SAMPLES;
visibility = saturate(pow(visibility, 1.5));
if (isSkeletal)
visibility = lerp(visibility, 1.0, 0.45);
return visibility;
}
@@ -4562,7 +4656,8 @@ float3 TraceOneIndirectBouncePath(uint2 pixel, float3 worldPos, float3 N, float3
float hitT = 0.0;
uint materialFlags = 0;
bool hit = TraceBounce(bounceOrigin, bounceDir, BOUNCE_TMAX, hitT, materialFlags);
uint meshIndex = 0;
bool hit = TraceBounce(bounceOrigin, bounceDir, BOUNCE_TMAX, hitT, materialFlags, meshIndex);
if (!hit)
{
@@ -4580,6 +4675,7 @@ float3 TraceOneIndirectBouncePath(uint2 pixel, float3 worldPos, float3 N, float3
float3 hitNormal = SafeNormalizeOr(-bounceDir, pathNormal);
float3 hitAlbedo = float3(0.55, 0.55, 0.55);
uint hitGeoFlag = GEOMETRY_FLAG_NONE;
float3 meshAverageColor = GetMeshAverageColor(meshIndex);
bool hasGBufferMaterial = TryFetchGBufferAtRayHit(
rayHitPos,
@@ -4614,6 +4710,7 @@ float3 TraceOneIndirectBouncePath(uint2 pixel, float3 worldPos, float3 N, float3
bouncedRadiance += skyTint * 0.045;
}
bouncedRadiance *= meshAverageColor * 1.12;
bouncedRadiance = CompressEmissiveRadiance(bouncedRadiance, depth == 0u ? 8.0 : 5.0);
accum += throughput * bouncedRadiance;
@@ -4624,7 +4721,7 @@ float3 TraceOneIndirectBouncePath(uint2 pixel, float3 worldPos, float3 N, float3
// the remaining throughput is just the secondary surface albedo. Use a
// conservative energy scale because material data for off-screen hits is a
// G-buffer approximation.
throughput *= saturate(hitAlbedo) * 0.72;
throughput *= saturate(hitAlbedo) * 0.84;
float continuation = clamp(max(max(throughput.x, throughput.y), throughput.z), 0.12, 0.92);
if (depth >= 1u)
@@ -4661,6 +4758,12 @@ float3 EstimatePathTracedIndirectBounce(uint2 pixel, float3 worldPos, float3 N,
float3 ApplyPrimaryDiffusePost(float3 lightingAccum, float ao, float microShadow, bool isSkeletal)
{
if (isSkeletal)
{
ao = lerp(ao, 1.0, 0.35);
microShadow = lerp(microShadow, 1.0, 0.65);
}
lightingAccum *= ao;
lightingAccum *= microShadow;
@@ -4676,6 +4779,8 @@ float3 ApplyPrimarySpecularPost(float3 specularAccum, float ao, bool isSkeletal)
// 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));
if (isSkeletal)
specAo = lerp(specAo, 1.0, 0.50);
specularAccum *= specAo;
//if (isSkeletal)
@@ -4927,7 +5032,8 @@ float3 EstimateRayTracedSpecularReflection(
float hitT = 0.0;
uint materialFlags = 0u;
bool hit = TraceSpecularReflection(reflectionOrigin, R, reflectionMaxT, hitT, materialFlags);
uint meshIndex = 0u;
bool hit = TraceSpecularReflection(reflectionOrigin, R, reflectionMaxT, hitT, materialFlags, meshIndex);
float3 reflectedRadiance = 0.0;
float distanceFade = 1.0;
@@ -4989,6 +5095,7 @@ float3 EstimateRayTracedSpecularReflection(
}
reflectedRadiance = CompressEmissiveRadiance(reflectedRadiance, hasSpecularMap ? 5.0 : 3.5);
reflectedRadiance *= hit ? GetMeshAverageColor(meshIndex) : 1.0;
float cavityFade = lerp(0.42, 1.0, saturate(cavity));
float reflectionStrength = hasSpecularMap
@@ -5055,13 +5162,12 @@ void RayGen()
float3 specularAlbedo = LoadSceneSpecularAlbedo(pixel, baseAlbedo);
float4 positionSample = gPositionTex.Load(int3(pixel, 0));
float3 worldPos = positionSample.xyz;
float4 normalSample = LoadSceneNormal(pixel);
float3 N = EnhanceBumpNormal(pixel, worldPos, baseAlbedo);
float3 V = normalize(gCameraPos.xyz - worldPos);
uint geoFlag = DecodeGeometryFlag(positionSample.w);
bool isSkeletal = (geoFlag & GEOMETRY_FLAG_SKELETAL) != 0u;
bool isUnlit = (geoFlag & GEOMETRY_FLAG_UNLIT) != 0u;
float4 normalSample = LoadSceneNormal(pixel);
float3 N = EnhanceBumpNormal(pixel, worldPos, baseAlbedo, isSkeletal);
float3 V = normalize(gCameraPos.xyz - worldPos);
if (isUnlit)
{
@@ -5075,7 +5181,9 @@ void RayGen()
// All four of these are deterministic for this pixel. Compute them once,
// then reuse them for every stochastic GI sample.
float cavity = ComputeCavity(pixel, worldPos, N);
float ao = ComputeAmbientOcclusion(worldPos, N, pixel);
if (isSkeletal)
cavity = lerp(cavity, 1.0, 0.65);
float ao = ComputeAmbientOcclusion(worldPos, N, pixel, isSkeletal);
float skyVis = 0; //ComputeSkyVisibility(worldPos, N, pixel);
float ambientSkyVis = 0; //TraceStraightUpToSky(worldPos, N);
float microShadow = lerp(0.75, 1.0, cavity);
@@ -5160,7 +5268,8 @@ void RayGen()
finalColor += baseAlbedo * reactiveFinalGather;
}
finalColor *= clamp(ao + 0.6, 0.0, 1.0);
float outputAo = isSkeletal ? lerp(ao, 1.0, 0.55) : ao;
finalColor *= clamp(outputAo + 0.6, 0.0, 1.0);
// Volumetric light scattering is radiance in the camera ray, not surface
// reflectance, so add it after surface albedo/specular composition. Because
@@ -5806,8 +5915,10 @@ static void glRaytracingLightingSelectFrameResources(UINT frameSlot)
g_glRaytracingLighting.descriptorHeap = g_glRaytracingLighting.descriptorHeapRing[frameSlot];
g_glRaytracingLighting.constantBuffer = g_glRaytracingLighting.constantBufferRing[frameSlot];
g_glRaytracingLighting.lightBuffer = g_glRaytracingLighting.lightBufferRing[frameSlot];
g_glRaytracingLighting.meshMetadataBuffer = g_glRaytracingLighting.meshMetadataBufferRing[frameSlot];
g_glRaytracingLighting.constantBufferMapped = g_glRaytracingLighting.constantBufferMappedRing[frameSlot];
g_glRaytracingLighting.lightBufferMapped = g_glRaytracingLighting.lightBufferMappedRing[frameSlot];
g_glRaytracingLighting.meshMetadataBufferMapped = g_glRaytracingLighting.meshMetadataBufferMappedRing[frameSlot];
for (int i = 0; i < 3; ++i)
{
@@ -5836,8 +5947,16 @@ static int glRaytracingLightingCreateBuffers(void)
D3D12_RESOURCE_STATE_GENERIC_READ,
D3D12_RESOURCE_FLAG_NONE);
g_glRaytracingLighting.meshMetadataBufferRing[frame] = glRaytracingCreateBuffer(
g_glRaytracingCmd.device.Get(),
sizeof(glRaytracingMeshMetadata_t) * 65536ull,
D3D12_HEAP_TYPE_UPLOAD,
D3D12_RESOURCE_STATE_GENERIC_READ,
D3D12_RESOURCE_FLAG_NONE);
if (!g_glRaytracingLighting.constantBufferRing[frame].resource ||
!g_glRaytracingLighting.lightBufferRing[frame].resource)
!g_glRaytracingLighting.lightBufferRing[frame].resource ||
!g_glRaytracingLighting.meshMetadataBufferRing[frame].resource)
{
return 0;
}
@@ -5873,6 +5992,13 @@ static int glRaytracingLightingCreateBuffers(void)
return 0;
}
if (!glRaytracingMapUploadBufferPersistent(
g_glRaytracingLighting.meshMetadataBufferRing[frame],
&g_glRaytracingLighting.meshMetadataBufferMappedRing[frame]))
{
return 0;
}
for (int i = 0; i < 3; ++i)
{
if (!glRaytracingMapUploadBufferPersistent(
@@ -5955,6 +6081,41 @@ static void glRaytracingLightingUpdateLights(void)
bytes);
}
static void glRaytracingLightingUpdateMeshMetadata(void)
{
if (!g_glRaytracingLighting.uploadToCurrentFrameResource)
return;
if (!g_glRaytracingLighting.meshMetadataBuffer.resource)
return;
glRaytracingMeshMetadata_t fallback = {};
fallback.averageColor[0] = fallback.averageColor[1] = fallback.averageColor[2] = fallback.averageColor[3] = 1.0f;
void* mapped = g_glRaytracingLighting.meshMetadataBufferMapped;
if (!mapped)
{
glRaytracingMapCopy(
g_glRaytracingLighting.meshMetadataBuffer.resource.Get(),
&fallback,
sizeof(fallback));
return;
}
glRaytracingMeshMetadata_t* metadata = (glRaytracingMeshMetadata_t*)mapped;
metadata[0] = fallback;
for (size_t i = 0; i < g_glRaytracingScene.meshes.size(); ++i)
{
const glRaytracingMeshRecord_t& mesh = g_glRaytracingScene.meshes[i];
if (!mesh.alive)
continue;
const uint32_t metadataIndex = mesh.handle & GL_RAYTRACING_INSTANCE_USER_ID_MASK;
memcpy(metadata[metadataIndex].averageColor, mesh.averageColor, sizeof(metadata[metadataIndex].averageColor));
}
}
static void glRaytracingLightingUnmapUploadBuffers(void)
{
for (UINT frame = 0; frame < GL_RAYTRACING_CMD_RING_SIZE; ++frame)
@@ -5973,6 +6134,13 @@ static void glRaytracingLightingUnmapUploadBuffers(void)
g_glRaytracingLighting.lightBufferMappedRing[frame] = nullptr;
}
if (g_glRaytracingLighting.meshMetadataBufferRing[frame].resource &&
g_glRaytracingLighting.meshMetadataBufferMappedRing[frame])
{
g_glRaytracingLighting.meshMetadataBufferRing[frame].resource->Unmap(0, nullptr);
g_glRaytracingLighting.meshMetadataBufferMappedRing[frame] = nullptr;
}
for (int i = 0; i < 3; ++i)
{
if (g_glRaytracingLighting.denoiseConstantBufferRing[frame][i].resource &&
@@ -5986,35 +6154,44 @@ static void glRaytracingLightingUnmapUploadBuffers(void)
g_glRaytracingLighting.constantBufferMapped = nullptr;
g_glRaytracingLighting.lightBufferMapped = nullptr;
g_glRaytracingLighting.meshMetadataBufferMapped = nullptr;
for (int i = 0; i < 3; ++i)
g_glRaytracingLighting.denoiseConstantBufferMapped[i] = nullptr;
}
static void glRaytracingLightingCreatePersistentLightSRV(void)
{
D3D12_SHADER_RESOURCE_VIEW_DESC srv = {};
srv.ViewDimension = D3D12_SRV_DIMENSION_BUFFER;
srv.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
srv.Format = DXGI_FORMAT_UNKNOWN;
srv.Buffer.FirstElement = 0;
srv.Buffer.NumElements = GL_RAYTRACING_MAX_LIGHTS;
srv.Buffer.StructureByteStride = sizeof(glRaytracingLight_t);
srv.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_NONE;
for (UINT frame = 0; frame < GL_RAYTRACING_CMD_RING_SIZE; ++frame)
{
if (!g_glRaytracingLighting.descriptorHeapRing[frame] ||
!g_glRaytracingLighting.lightBufferRing[frame].resource)
!g_glRaytracingLighting.lightBufferRing[frame].resource ||
!g_glRaytracingLighting.meshMetadataBufferRing[frame].resource)
{
continue;
}
D3D12_CPU_DESCRIPTOR_HANDLE base =
g_glRaytracingLighting.descriptorHeapRing[frame]->GetCPUDescriptorHandleForHeapStart();
D3D12_SHADER_RESOURCE_VIEW_DESC srv = {};
srv.ViewDimension = D3D12_SRV_DIMENSION_BUFFER;
srv.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
srv.Format = DXGI_FORMAT_UNKNOWN;
srv.Buffer.FirstElement = 0;
srv.Buffer.NumElements = GL_RAYTRACING_MAX_LIGHTS;
srv.Buffer.StructureByteStride = sizeof(glRaytracingLight_t);
srv.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_NONE;
g_glRaytracingCmd.device->CreateShaderResourceView(
g_glRaytracingLighting.lightBufferRing[frame].resource.Get(),
&srv,
glRaytracingOffsetCpu(base, g_glRaytracingLighting.descriptorStride, GLR_DESC_LIGHTS_SRV));
srv.Buffer.NumElements = 65536;
srv.Buffer.StructureByteStride = sizeof(glRaytracingMeshMetadata_t);
g_glRaytracingCmd.device->CreateShaderResourceView(
g_glRaytracingLighting.meshMetadataBufferRing[frame].resource.Get(),
&srv,
glRaytracingOffsetCpu(base, g_glRaytracingLighting.descriptorStride, GLR_DESC_MESH_METADATA_SRV));
}
}
@@ -6514,6 +6691,7 @@ static bool glRaytracingLightingExecuteInternal(
g_glRaytracingLighting.uploadToCurrentFrameResource = true;
glRaytracingLightingUpdateLights();
glRaytracingLightingUpdateMeshMetadata();
glRaytracingLightingUpdateConstants();
for (uint32_t passIndex = 0; passIndex < 3u; ++passIndex)
+59 -12
View File
@@ -287,6 +287,7 @@ void APIENTRY glTextureSpecularMap(GLuint texture, GLboolean isSpecularMap);
void APIENTRY glBindSpecularMapTexture(GLuint texture);
void APIENTRY glSpecularMapTexture(GLuint texture);
void APIENTRY glSpecularMapStrengthf(GLfloat strength);
void APIENTRY glTextureAverageColorQD3D12(GLuint texture, GLfloat r, GLfloat g, GLfloat b, GLfloat a);
void APIENTRY glRaytracingMaterialFlagsQD3D12(GLuint flags);
void APIENTRY glRaytracingMaterialFlagQD3D12(GLuint flag, GLboolean enable);
@@ -301,6 +302,7 @@ void glRaytracingLightingSetSpecularInput(ID3D12Resource* texture, DXGI_FORMAT f
void glRaytracingSetMeshMaterialFlags(glRaytracingMeshHandle_t meshHandle, uint32_t materialFlags);
void glRaytracingSetMeshGlass(glRaytracingMeshHandle_t meshHandle, int isGlass);
uint32_t glRaytracingGetMeshMaterialFlags(glRaytracingMeshHandle_t meshHandle);
void glRaytracingSetMeshAverageColor(glRaytracingMeshHandle_t meshHandle, float r, float g, float b, float a);
// Fast TLAS instance visibility controls are implemented in gl_raytracing.cpp.
// They flip the D3D12_RAYTRACING_INSTANCE_DESC InstanceMask via the existing
@@ -334,6 +336,7 @@ void QD3D12_SetToneMapBrightness(float brightness);
float QD3D12_GetToneMapBrightness(void);
void QD3D12_SetFrameGenerationMultiplier(int multiplier);
int QD3D12_GetFrameGenerationMultiplier(void);
int QD3D12_GetActiveFrameGenerationMultiplier(void);
void APIENTRY glToneMapBrightnessQD3D12(GLfloat brightness);
void APIENTRY glToneMapBrightnessfQD3D12(GLfloat brightness);
void APIENTRY glTonemapBrightnessQD3D12(GLfloat brightness);
@@ -628,6 +631,7 @@ struct TextureResource
bool isNormalMap = false;
bool isGlowMap = false;
bool isSpecularMap = false;
float averageColor[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
ComPtr<ID3D12Resource> texture;
D3D12_RESOURCE_STATES state = D3D12_RESOURCE_STATE_COPY_DEST;
@@ -1504,7 +1508,7 @@ struct GLState
bool motionHistoryReset = true;
QD3D12UpscalerBackend upscalerBackend = QD3D12_UPSCALER_DLSS;
QD3D12UpscalerQuality upscalerQuality = QD3D12_QUALITY_DLAA;
QD3D12UpscalerQuality upscalerQuality = QD3D12_QUALITY_QUALITY;
bool enableInternalTAA = false;
bool enableRayAIDenoise = false;
bool enableDLSSRayReconstruction = false;
@@ -1512,7 +1516,7 @@ struct GLState
uint32_t frameGenerationMultiplier = 2;
uint32_t pathTracingSamplesPerPixel = 1;
uint32_t pathTracingFallbackSamplesPerPixel = 2;
uint32_t pathTracingMaxBounces = 3;
uint32_t pathTracingMaxBounces = 2;
float jitterX = 0.0f;
float jitterY = 0.0f;
@@ -6764,6 +6768,7 @@ struct QD3D12StreamlineState
uint32_t lastDlssGEligibilityMaskLogged = 0xffffffffu;
uint32_t lastDlssGFramesToGenerateLogged = 0xffffffffu;
uint32_t lastDlssGPresentedFramesLogged = 0xffffffffu;
uint32_t dlssGActiveFrameMultiplier = 1;
uint32_t dlssGConfiguredFramesToGenerate = 0xffffffffu;
uint32_t dlssGConfiguredRenderWidth = 0xffffffffu;
uint32_t dlssGConfiguredRenderHeight = 0xffffffffu;
@@ -6941,7 +6946,7 @@ static sl::DLSSMode QD3D12_MapDLSSMode(QD3D12UpscalerQuality quality)
{
switch (quality)
{
case QD3D12_QUALITY_QUALITY: return sl::DLSSMode::eUltraQuality;
case QD3D12_QUALITY_QUALITY: return sl::DLSSMode::eMaxQuality;
case QD3D12_QUALITY_BALANCED: return sl::DLSSMode::eBalanced;
case QD3D12_QUALITY_PERFORMANCE: return sl::DLSSMode::eMaxPerformance;
case QD3D12_QUALITY_ULTRA_PERFORMANCE: return sl::DLSSMode::eUltraPerformance;
@@ -7219,15 +7224,15 @@ static void QD3D12_LogDLSSFrameGenerationEligibility(const QD3D12Window& w, uint
static void QD3D12_SetDLSSFrameGenerationOff()
{
if (!g_qd3d12Sl.deviceBound || !g_qd3d12Sl.dlssGSupported || !g_qd3d12Sl.dlssGActive)
return;
sl::DLSSGOptions options{};
options.mode = sl::DLSSGMode::eOff;
options.flags = sl::DLSSGFlags::eRetainResourcesWhenOff;
const sl::Result result = slDLSSGSetOptions(g_qd3d12Sl.viewport, options);
if (result != sl::Result::eOk)
QD3D12_Log("slDLSSGSetOptions(off) failed (%d).", int(result));
if (g_qd3d12Sl.deviceBound && g_qd3d12Sl.dlssGSupported && g_qd3d12Sl.dlssGActive)
{
sl::DLSSGOptions options{};
options.mode = sl::DLSSGMode::eOff;
options.flags = sl::DLSSGFlags::eRetainResourcesWhenOff;
const sl::Result result = slDLSSGSetOptions(g_qd3d12Sl.viewport, options);
if (result != sl::Result::eOk)
QD3D12_Log("slDLSSGSetOptions(off) failed (%d).", int(result));
}
if (g_qd3d12Sl.reflexSupported)
{
@@ -7237,6 +7242,7 @@ static void QD3D12_SetDLSSFrameGenerationOff()
}
g_qd3d12Sl.dlssGActive = false;
g_qd3d12Sl.dlssGActiveFrameMultiplier = 1;
g_qd3d12Sl.dlssGConfiguredFramesToGenerate = 0xffffffffu;
g_qd3d12Sl.dlssGConfiguredRenderWidth = 0xffffffffu;
g_qd3d12Sl.dlssGConfiguredRenderHeight = 0xffffffffu;
@@ -7421,6 +7427,7 @@ static void QD3D12_ConfigureDLSSFrameGeneration(QD3D12Window& w, sl::FrameToken*
}
g_qd3d12Sl.dlssGActive = true;
g_qd3d12Sl.dlssGActiveFrameMultiplier = options.numFramesToGenerate + 1;
}
static void QD3D12_LogDLSSFrameGenerationPresentResult()
@@ -7537,6 +7544,13 @@ static void QD3D12_SelectRenderResolution(QD3D12Window& w, UINT outputWidth, UIN
w.renderWidth = outputWidth;
w.renderHeight = outputHeight;
if (outputWidth == 0 || outputHeight == 0)
{
w.renderWidth = 1;
w.renderHeight = 1;
return;
}
if (g_gl.upscalerBackend == QD3D12_UPSCALER_NONE || g_gl.upscalerQuality == QD3D12_QUALITY_NATIVE)
return;
@@ -13154,6 +13168,19 @@ void APIENTRY glSpecularMapStrengthf(GLfloat strength)
g_gl.currentSpecularMapStrength = (strength < 0.0f) ? 0.0f : strength;
}
void APIENTRY glTextureAverageColorQD3D12(GLuint texture, GLfloat r, GLfloat g, GLfloat b, GLfloat a)
{
if (texture == 0)
return;
TextureResource& tex = QD3D12_EnsureTextureName(texture);
tex.averageColor[0] = ClampValue<float>(r, 0.0f, 1.0f);
tex.averageColor[1] = ClampValue<float>(g, 0.0f, 1.0f);
tex.averageColor[2] = ClampValue<float>(b, 0.0f, 1.0f);
tex.averageColor[3] = ClampValue<float>(a, 0.0f, 1.0f);
tex.cpuGeneration++;
}
void APIENTRY glRaytracingMaterialFlagsQD3D12(GLuint flags)
{
g_gl.currentRayMaterialFlags = QD3D12_ClampRayMaterialFlags((uint32_t)flags);
@@ -17237,6 +17264,15 @@ int QD3D12_GetFrameGenerationMultiplier(void)
return (int)g_gl.frameGenerationMultiplier;
}
int QD3D12_GetActiveFrameGenerationMultiplier(void)
{
#if defined(QD3D12_ENABLE_STREAMLINE)
if (g_qd3d12Sl.dlssGActive && g_qd3d12Sl.dlssGActiveFrameMultiplier >= 2)
return (int)g_qd3d12Sl.dlssGActiveFrameMultiplier;
#endif
return 1;
}
void QD3D12_EnableDLAA(int enabled)
{
const QD3D12UpscalerBackend oldBackend = g_gl.upscalerBackend;
@@ -18818,6 +18854,11 @@ void glUpdateBottomAccelStructure(bool opaque, uint32_t& meshHandle)
meshDesc.indices = &drawIndexes[0];
meshDesc.indexCount = (uint32_t)drawIndexes.size();
meshDesc.allowUpdate = 1;
meshDesc.averageColor[0] = meshDesc.averageColor[1] = meshDesc.averageColor[2] = meshDesc.averageColor[3] = 1.0f;
TextureResource* diffuseTexture = QD3D12_FindTextureResource(g_gl.boundTexture[0]);
if (diffuseTexture)
memcpy(meshDesc.averageColor, diffuseTexture->averageColor, sizeof(meshDesc.averageColor));
const uint32_t materialFlags = QD3D12_CurrentEffectiveRayMaterialFlags();
const bool isGlass = QD3D12_RayMaterialFlagsHaveGlass(materialFlags);
@@ -18836,6 +18877,12 @@ void glUpdateBottomAccelStructure(bool opaque, uint32_t& meshHandle)
{
g_qd3d12RaytracingMeshMaterialFlags[meshHandle] = materialFlags;
glRaytracingSetMeshMaterialFlags((glRaytracingMeshHandle_t)meshHandle, materialFlags);
glRaytracingSetMeshAverageColor(
(glRaytracingMeshHandle_t)meshHandle,
meshDesc.averageColor[0],
meshDesc.averageColor[1],
meshDesc.averageColor[2],
meshDesc.averageColor[3]);
}
}
+4
View File
@@ -1639,6 +1639,7 @@ typedef struct glRaytracingMeshDesc_s
uint32_t indexCount;
int allowUpdate;
int opaque;
float averageColor[4];
} glRaytracingMeshDesc_t;
typedef struct glRaytracingInstanceDesc_s
@@ -2227,6 +2228,7 @@ void APIENTRY glTextureSpecularMap(GLuint texture, GLboolean isSpecularMap);
void APIENTRY glBindSpecularMapTexture(GLuint texture);
void APIENTRY glSpecularMapTexture(GLuint texture);
void APIENTRY glSpecularMapStrengthf(GLfloat strength);
void APIENTRY glTextureAverageColorQD3D12(GLuint texture, GLfloat r, GLfloat g, GLfloat b, GLfloat a);
void glUpdateTopLevelAceelStructure(
glRaytracingSceneHandle_t scene,
@@ -2272,6 +2274,7 @@ extern "C" {
uint32_t glRaytracingGetMeshMaterialFlags(glRaytracingMeshHandle_t meshHandle);
void glRaytracingSetMeshMaterialFlags(glRaytracingMeshHandle_t meshHandle, uint32_t materialFlags);
void glRaytracingSetMeshGlass(glRaytracingMeshHandle_t meshHandle, int isGlass);
void glRaytracingSetMeshAverageColor(glRaytracingMeshHandle_t meshHandle, float r, float g, float b, float a);
// For callers that create raytracing instances directly instead of using the
// shim's glUpdateTopLevelAceelStructure() helper. Glass meshes must also use
@@ -2328,6 +2331,7 @@ void QD3D12_SetUpscalerSharpness(float sharpness);
void QD3D12_SetToneMapBrightness(float brightness);
void QD3D12_SetFrameGenerationMultiplier(int multiplier);
int QD3D12_GetFrameGenerationMultiplier(void);
int QD3D12_GetActiveFrameGenerationMultiplier(void);
void QD3D12_SetCurrentWindowDLSSAllowed(int allowed);
void QD3D12_EnableTAA(int enabled);
+3 -1
View File
@@ -192,6 +192,7 @@ public:
void Reload( bool checkPrecompressed, bool force );
void AddReference() { refCount++; };
const float* GetAverageColor() const { return averageColor; };
//==========================================================
@@ -250,6 +251,7 @@ public:
// data for listImages
int uploadWidth, uploadHeight, uploadDepth; // after power of two, downsample, and MAX_TEXTURE_SIZE
int internalFormat;
float averageColor[4]; // normalized average source pixel color
idImage *cacheUsagePrev, *cacheUsageNext; // for dynamic cache purging of old images
@@ -286,6 +288,7 @@ ID_INLINE idImage::idImage() {
bindCount = 0;
uploadWidth = uploadHeight = uploadDepth = 0;
internalFormat = 0;
averageColor[0] = averageColor[1] = averageColor[2] = averageColor[3] = 1.0f;
cacheUsagePrev = cacheUsageNext = NULL;
hashNext = NULL;
isMonochrome = false;
@@ -499,4 +502,3 @@ IMAGEPROGRAM
void R_LoadImageProgram( const char *name, byte **pic, int *width, int *height, ID_TIME_T *timestamp, textureDepth_t *depth = NULL );
const char *R_ParsePastImageProgram( idLexer &src );
+61
View File
@@ -43,6 +43,61 @@ static bool FormatIsDXT( int internalFormat ) {
return true;
}
static void R_SetImageAverageColor( idImage *image, const byte *pic, int width, int height ) {
if ( !image || !pic || width <= 0 || height <= 0 ) {
return;
}
uint64_t sum[4] = { 0, 0, 0, 0 };
const int pixelCount = width * height;
for ( int i = 0; i < pixelCount; i++ ) {
const byte *rgba = pic + i * 4;
sum[0] += rgba[0];
sum[1] += rgba[1];
sum[2] += rgba[2];
sum[3] += rgba[3];
}
const float scale = 1.0f / ( 255.0f * (float)pixelCount );
image->averageColor[0] = sum[0] * scale;
image->averageColor[1] = sum[1] * scale;
image->averageColor[2] = sum[2] * scale;
image->averageColor[3] = sum[3] * scale;
}
static void R_SetCubeImageAverageColor( idImage *image, const byte *pic[6], int size ) {
if ( !image || !pic || size <= 0 ) {
return;
}
uint64_t sum[4] = { 0, 0, 0, 0 };
int faceCount = 0;
const int facePixels = size * size;
for ( int face = 0; face < 6; face++ ) {
if ( !pic[face] ) {
continue;
}
faceCount++;
for ( int i = 0; i < facePixels; i++ ) {
const byte *rgba = pic[face] + i * 4;
sum[0] += rgba[0];
sum[1] += rgba[1];
sum[2] += rgba[2];
sum[3] += rgba[3];
}
}
if ( faceCount == 0 ) {
return;
}
const float scale = 1.0f / ( 255.0f * (float)( facePixels * faceCount ) );
image->averageColor[0] = sum[0] * scale;
image->averageColor[1] = sum[1] * scale;
image->averageColor[2] = sum[2] * scale;
image->averageColor[3] = sum[3] * scale;
}
int MakePowerOfTwo( int num ) {
int pot;
for (pot = 1 ; pot < num ; pot<<=1) {
@@ -463,6 +518,7 @@ void idImage::GenerateImage( const byte *pic, int width, int height,
allowDownSize = allowDownSizeParm;
repeat = repeatParm;
depth = depthParm;
R_SetImageAverageColor( this, pic, width, height );
// if we don't have a rendering context, just return after we
// have filled in the parms. We must have the values set, or
@@ -494,6 +550,7 @@ void idImage::GenerateImage( const byte *pic, int width, int height,
// generate the texture number
glGenTextures( 1, &texnum );
glTextureAverageColorQD3D12( texnum, averageColor[0], averageColor[1], averageColor[2], averageColor[3] );
// select proper internal format before we resample
internalFormat = SelectInternalFormat( &pic, 1, width, height, depth, &isMonochrome );
@@ -670,6 +727,7 @@ void idImage::Generate3DImage( const byte *pic, int width, int height, int picDe
allowDownSize = allowDownSizeParm;
repeat = repeatParm;
depth = minDepthParm;
R_SetImageAverageColor( this, pic, width, height * picDepth );
// if we don't have a rendering context, just return after we
// have filled in the parms. We must have the values set, or
@@ -691,6 +749,7 @@ void idImage::Generate3DImage( const byte *pic, int width, int height, int picDe
// generate the texture number
glGenTextures( 1, &texnum );
glTextureAverageColorQD3D12( texnum, averageColor[0], averageColor[1], averageColor[2], averageColor[3] );
// select proper internal format before we resample
// this function doesn't need to know it is 3D, so just make it very "tall"
@@ -807,6 +866,7 @@ void idImage::GenerateCubeImage( const byte *pic[6], int size,
filter = filterParm;
allowDownSize = allowDownSizeParm;
depth = depthParm;
R_SetCubeImageAverageColor( this, pic, size );
type = TT_CUBIC;
@@ -826,6 +886,7 @@ void idImage::GenerateCubeImage( const byte *pic[6], int size,
// generate the texture number
glGenTextures( 1, &texnum );
glTextureAverageColorQD3D12( texnum, averageColor[0], averageColor[1], averageColor[2], averageColor[3] );
// select proper internal format before we resample
internalFormat = SelectInternalFormat( pic, 6, width, height, depth, &isMonochrome );