
Im Jahr 2018 kĂŒndigte Microsoft die Raytracing-API (DXR) als Teil von DirectX 12 an. Der Raytracing-Ansatz erzwingt ein völliges Ăberdenken der Darstellung von 3D-Szenen und rĂŒckt den klassischen Rasterisierungsansatz in den Hintergrund. APIs werden modernisiert, effizientere GPUs werden entwickelt und Entwickler von Visualisierungspaketen versuchen neue Möglichkeiten. Selbst bei den leistungsstĂ€rksten Grafikkarten reicht die Leistung jedoch aus, um nur wenige Strahlen pro Pixel zu erzeugen und eine stabile Bildrate zu gewĂ€hrleisten. DarĂŒber hinaus hĂ€ngt die Leistung stark von der KomplexitĂ€t der Materialien und der Szene ab. Aber schon heute ermöglichen fortschrittliche Algorithmen zur RauschunterdrĂŒckung und Akkumulation des Beleuchtungsergebnisses ein hohes MaĂ an Realismus. All dies motiviert zum Experimentieren auf diesem Gebiet.
GPU Ray Tracing ist relativ neu. Im Jahr 2009 brachte DirectX 11 Compute-Shader auf den Markt - dies gab Impulse fĂŒr die Entwicklung von Nicht-Grafik-Computing. Das Design der Beschleunigungsstrukturen fiel jedoch vollstĂ€ndig auf die Schultern des Programmierers, was die Entwicklung verlangsamte. Spezialisierte Kreuzungsbibliotheken wie AMDs Radeon Rays sind weit verbreitet. In DXR werden beschleunigende Strukturen nach dem Black-Box-Prinzip dargestellt, und der Schnittpunkt erfolgt mithilfe spezieller Hardwareblöcke. Ray Tracing wurde auch zu Vulkan als Erweiterung von VK_NV_ray_tracing fĂŒr Nvidia-Karten hinzugefĂŒgt. Im MĂ€rz 2020 wurden mit geringfĂŒgigen Ănderungen die Erweiterungen VK_KHR_ray_tracing veröffentlicht. Sie sind nicht mehr herstellerspezifisch und können in die Vulkan 1.3-Spezifikation aufgenommen werden.FĂŒr AMD ist eine vollstĂ€ndige Strahlverfolgung bis Ende 2020 geplant. Die allgegenwĂ€rtige UnterstĂŒtzung macht die Technologie vielversprechender.
DXR . â . , . , , , . , (, ). , (hit, miss, procedural hit, closest hit), , , , . pipeline .
DXR- GPU Nvidia RTX 2060 . Windows SDK 19041 ( , Miscrosoft ), IDE Visual Studio 2019, C++.
DXR , raygen-. ID3D12GraphicsCommandList4::DispatchRays() c , TraceRay(). top level acceleration structure. , . , , , (closest hit). , .

miss hit-. payload â . DirectX, global root signature. per-shader , local root signature Shader binding table. , .
:
- bottom-level, top-level acceleration structures
- raytracing pipeline
- shading binding table (SBT) â per-shader
.
Bottom-level acceleration structure (BLAS)
, â . BLAS . BLAS . . BLAS GPU, command list . , BLAS (scratch-). DirectX 12, API, ID3D12Device5::GetRaytracingAccelerationStructurePrebuildInfo. D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE â .
D3D12_RAYTRACING_GEOMETRY_DESC â BLAS. ( index-buffer ):
D3D12_RAYTRACING_GEOMETRY_DESC geometryDesc = {};
geometryDesc.Type = D3D12_RAYTRACING_GEOMETRY_TYPE_TRIANGLES;
geometryDesc.Triangles.IndexBuffer = 0;// GPU-address index- ( )
geometryDesc.Triangles.IndexCount = 0;
geometryDesc.Triangles.IndexFormat = 0;// DXGI_FORMAT_R16_UINT;
geometryDesc.Triangles.VertexFormat = DXGI_FORMAT_R32G32B32_FLOAT;
geometryDesc.Triangles.VertexCount = < >;
geometryDesc.Triangles.VertexBuffer.StartAddress = <GPU-address >;
geometryDesc.Triangles.VertexBuffer.StrideInBytes = sizeof(Vertex);
BLAS:
D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS bottomLevelInputs;
bottomLevelInputs.DescsLayout = D3D12_ELEMENTS_LAYOUT_ARRAY;
bottomLevelInputs.Flags = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_PREFER_FAST_TRACE;
bottomLevelInputs.Type = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL;
bottomLevelInputs.pGeometryDescs = &geometryDesc;
bottomLevelInputs.NumDescs = 1;
D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC bottomLevelBuildDesc = {};
bottomLevelBuildDesc.Inputs = bottomLevelInputs;
bottomLevelBuildDesc.ScratchAccelerationStructureData = scratchResource->GetGPUVirtualAddress();
bottomLevelBuildDesc.DestAccelerationStructureData = bottomLevelAccelerationStructure->GetGPUVirtualAddress(); // ID3D12Resource* bottomLevelAccelerationStructure -
BLAS:
dxrCommandList->BuildRaytracingAccelerationStructure(&bottomLevelBuildDesc, 0, nullptr);
Top-level acceleration structure (TLAS)
TLAS BLAS . BLAS , . TLAS BLAS â scratch-. , scratch-, TLAS BLAS. TLAS :
D3D12_RAYTRACING_INSTANCE_DESC instanceDesc[2] = {};
for (int i = 0; i < 2; ++i)
{
instanceDesc[i].Transform = YourEngineTransformToDXR(transforms[i]);
instanceDesc[i].InstanceMask = 1;
instanceDesc[i].InstanceID = 0; //
instanceDesc[i].InstanceContributionToHitGroupIndex = i; // hit SBT
instanceDesc[i].AccelerationStructure = bottomLevelAccelerationStructure->GetGPUVirtualAddress();
}
TLAS (D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC) BLAS.
Raytracing pipeline
graphic compute raytracing pipeline state object â . RT pipeline -, . CD3DX12_STATE_OBJECT_DESC CreateSubobject(< >).
- . BytecodeLength pShaderBytecode D3D12_SHADER_BYTECODE, SetDXILLibrary() DefineExport(). 3- : raygen, hit, miss.
- Hit group (CD3DX12_HIT_GROUP_SUBOBJECT). hit group-, . SetHitGroupExport, SetHitGroupType(D3D12_HIT_GROUP_TYPE_TRIANGLES). hit-group, .
- (CD3DX12_RAYTRACING_SHADER_CONFIG_SUBOBJECT). payload â , TraceRay , closest hit â 2 float.
- (CD3DX12_RAYTRACING_PIPELINE_CONFIG_SUBOBJECT). 1.
- root signature (CD3DX12_LOCAL_ROOT_SIGNATURE_SUBOBJECT). , hit-. SBT ( ).
- local root signatore c hit group (CD3DX12_SUBOBJECT_TO_EXPORTS_ASSOCIATION_SUBOBJECT). root signature SetSubobjectToAssociate() AddExport().
- root signature (CD3DX12_GLOBAL_ROOT_SIGNATURE_SUBOBJECT). , . SetComputeRootDescriptorTable, SetComputeRootShaderResourceView SetComputeRoot32BitConstants.
Shader binding table (SBT)
SBT â . , , . , GPU-, . .
shader record. TLAS , â . . TLAS BLAS, TraceRay(), .
3 : ray generation, hit miss, , , . , . GPU- , DispatchRays(). shader record-.
shader record-a . raygen miss , shader record-a . , , , root signature, SBT. shader record D3D12_RAYTRACING_SHADER_RECORD_BYTE_ALIGNMENT ( 32 ).
void*, GetShaderIdentifier() ID3D12StateObjectProperties, COM- raytracing pipeline. raygen- (miss ) :
ComPtr<ID3D12StateObjectProperties> stateObjectProperties;
dxrStateObject.As(&stateObjectProperties);
void* rayGenShaderIdentifier = stateObjectProperties->GetShaderIdentifier(L"RayGen");
. SBT raygen miss .
hit float4 . SBT root signature: virtual GPU-address/GPU-handle. constant buffer, hit SBT shader record-. 32- 4x4- , 48, - 64 . :

vertex-fragment shader 3: raygen, hit, miss.
raygen:
#include "Common.hlsl"
#include "Global.hlsl"
struct CameraData
{
float4 forward;
float4 right;
float4 up;
float4 origin;
};
ConstantBuffer<CameraData> gCamera : register(b0);
[shader("raygeneration")]
void RayGen()
{
HitInfo payload;
payload.colorAndDistance = float4(0, 0, 0, 0);
uint2 launchIndex = DispatchRaysIndex().xy;
float2 dims = float2(DispatchRaysDimensions().xy);
float2 ndc = float2(
float(launchIndex.x + 0.5f) / dims.x * 2 - 1,
float(dims.y - launchIndex.y - 1 + 0.5) / dims.y * 2 - 1);
RayDesc ray;
ray.Origin = gCamera.origin.xyz;
ray.Direction = GetWorldRay(ndc, gCamera.forward.xyz, gCamera.right.xyz, gCamera.up.xyz);
ray.TMin = 0;
ray.TMax = 100000;
TraceRay(
SceneBVH,
RAY_FLAG_NONE,
0xFF,
0, // RayContributionToHitGroupIndex
0, // MultiplierForGeometryContributionToHitGroupIndex
0, // MissShaderIndex
ray,
payload);
gOutput[launchIndex] = float4(payload.colorAndDistance.rgb, 1.f);
}
. TLAS, , SBT. TraceRay() payload . [shader("raygeneration")] , , , "RayGen" , .
closesthit
#include "Common.hlsl"
#include "Global.hlsl"
struct InstanceData
{
float4 color;
};
ConstantBuffer<InstanceData> instanceData : register(b1);
[shader("closesthit")]
void ClosestHit(inout HitInfo payload, Attributes attrib)
{
float3 barycentrics = float3(1.f - attrib.bary.x - attrib.bary.y, attrib.bary.x, attrib.bary.y);
float3 vertexNormals[3] = {
Vertices[PrimitiveIndex() * 3].normal,
Vertices[PrimitiveIndex() * 3 + 1].normal,
Vertices[PrimitiveIndex() * 3 + 2].normal
};
float3 N = vertexNormals[0] * barycentrics.x +
vertexNormals[1] * barycentrics.y +
vertexNormals[2] * barycentrics.z;
const float3 L = normalize(float3(0, -0.4, 1));
payload.colorAndDistance = float4(instanceData.color.rgb * max(0, dot(N, L)), RayTCurrent());
}
. - payload. . . , .
miss.
#include "Common.hlsl"
[shader("miss")]
void Miss(inout HitInfo payload : SV_RayPayload)
{
payload.colorAndDistance = float4(0.0f, 0.2f, 0.7f, -1.0f);
}
â .
Main loop
main loop :
//...
// root signature
dxrCommandList->SetComputeRootSignature(raytracingGlobalRootSignature.Get());
// descriptor heap
dxrCommandList->SetDescriptorHeaps(1, descriptorHeap.GetAddressOf());
//
dxrCommandList->SetComputeRootDescriptorTable(0, raytracingOutputResourceUAVGpuDescriptor);
dxrCommandList->SetComputeRootDescriptorTable(1, buffersGpuDescriptor);
dxrCommandList->SetComputeRootShaderResourceView(2, topLevelAccelerationStructure->GetGPUVirtualAddress());
//
//...
D3D12_DISPATCH_RAYS_DESC dispatchDesc = {};
dispatchDesc.HitGroupTable.StartAddress = hitGroupShaderTable->GetGPUVirtualAddress();
dispatchDesc.HitGroupTable.SizeInBytes = hitGroupShaderTable->GetDesc().Width;
dispatchDesc.HitGroupTable.StrideInBytes = 64; // hit shader record
dispatchDesc.MissShaderTable.StartAddress = missShaderTable->GetGPUVirtualAddress();
dispatchDesc.MissShaderTable.SizeInBytes = missShaderTable->GetDesc().Width;
dispatchDesc.MissShaderTable.StrideInBytes = dispatchDesc.MissShaderTable.SizeInBytes;
dispatchDesc.RayGenerationShaderRecord.StartAddress = rayGenShaderTable->GetGPUVirtualAddress();
dispatchDesc.RayGenerationShaderRecord.SizeInBytes = rayGenShaderTable->GetDesc().Width;
dispatchDesc.Width = width;
dispatchDesc.Height = height;
dispatchDesc.Depth = 1;
dxrCommandList->SetPipelineState1(dxrStateObject.Get());
dxrCommandList->DispatchRays(&dispatchDesc);
//...

In diesem Artikel haben wir die grundlegenden Objekte untersucht, die fĂŒr den Einstieg in DXR erforderlich sind, und dieses Wissen auch in der Praxis angewendet. Die Fragen zur DirectX-Initialisierung, zum Laden von Modellen, zum Kompilieren von Shadern usw., die nicht relevant sind, wurden bewusst weggelassen. In den nĂ€chsten Artikeln ist geplant, den Schwerpunkt auf Grafiken zu legen, anstatt mit der API zu arbeiten.
Links:
https://github.com/k-payl/X12Lib/blob/master/src/examples/raytracing.cpp
https://microsoft.github.io/DirectX-Specs/d3d/Raytracing.html
https: // Entwickler. nvidia.com/rtx/raytracing/dxr/DX12-Raytracing-tutorial-Part-1