mirror of
https://github.com/jmarshall23/DoomRTX.git
synced 2026-08-12 08:11:10 +02:00
Fixed MD5 models.
GI now bounces off textures properly.
This commit is contained in:
@@ -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 }
|
||||
};
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 );
|
||||
|
||||
|
||||
@@ -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 );
|
||||
|
||||
Reference in New Issue
Block a user