6
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

DXRで遊ぶ

Last updated at Posted at 2019-01-17

概要

はじめに

Direct3D 12 Raytracing,
DirectX-Graphics-Samplesより正しく詳しい情報は得られません.
処理の概観についてまとめます.

必要環境

ハードとソフトに強く依存します.

Windows 10 Version 1809
Windows SDK October 2018 (17763)
Nvidia Driver Version 415
GPU RTXシリーズ

従来のCompute Shaderでエミュレートする環境が用意されていますが今回は無視します.

SDK

d3d12_1.h がWindows SDK (17763)にはないため, DirectX-Graphics-Samples
からコピーします.

初期化

サポートチェック

デバイスは, D3D12_FEATURE_D3D12_OPTIONS5::RaytracingTierをチェックするだけです. HLSL Shader Model 6.3が必要ですが, 包含していると考えていいのでしょう.

デバイスチェック
D3D12_FEATURE_DATA_D3D12_OPTIONS5 featureSupportData = {};
return SUCCEEDED(device_->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS5, &featureSupportData, sizeof(D3D12_FEATURE_DATA_D3D12_OPTIONS5)))
        && D3D12_RAYTRACING_TIER_NOT_SUPPORTED != featureSupportData.RaytracingTier;

DXRインターフェイス

ID3D12Device5と, ID3D12GraphicsCommandList4が追加されました.

インテーフェイス取得
ID3D12Device5* device5 = nullptr;
ID3D12Device* device->QueryInterface(IID_PPV_ARGS(&device5));
ID3D12GraphicsCommandList4* commandList4 = nullptr;
ID3D12GraphicsCommandList* commandList->QueryInterface(IID_PPV_ARGS(&commandList4));

パイプライン

シェーダ関数をコンピュートユニットに発行することで処理が進みます.
CPUからは, ID3D12GraphicsCommandList4::DispatchRays

ID3D12GraphicsCommandList4::DispatchRays(D3D12_DISPATCH_RAYS_DESC* dispatchDesc)

シェーダ内の各関数に *[shader("attribute name")]*の形式で属性を付けておきます.
raygeneration関数がシステムから呼ばれ, TraceRayでレイを生成します.
"レイが何かにヒットした"等のイベントごとに, それぞれ対応する関数が呼ばれます.

下図のようにTraceRayでレイを生成して, シーンをトラバースします. Intersection はBVHの境界ボリュームに交差したときのイベントです.
Process00.png

HLSL

シェーダモデル6.3が必要です. 従来のfxcではなく, dxcにlib_6_3を指定してコンパイルします.

サンプルから引用(Raytracing.hlsl)
struct Viewport
{
    float left;
    float top;
    float right;
    float bottom;
};

struct RayGenConstantBuffer
{
    Viewport viewport;
    Viewport stencil;
};

RaytracingAccelerationStructure Scene : register(t0, space0);
RWTexture2D<float4> RenderTarget : register(u0);
ConstantBuffer<RayGenConstantBuffer> g_rayGenCB : register(b0);

struct RayPayload
{
    float4 color;
};

[shader("raygeneration")]
void MyRaygenShader()
{
    float2 lerpValues = (float2)DispatchRaysIndex() / (float2)DispatchRaysDimensions();
    
    // +Z方向に垂直投影
    float3 rayDir = float3(0, 0, 1);
    float3 origin = float3(
        lerp(g_rayGenCB.viewport.left, g_rayGenCB.viewport.right, lerpValues.x),
        lerp(g_rayGenCB.viewport.top, g_rayGenCB.viewport.bottom, lerpValues.y),
        0.0f);

    RayDesc ray;
    ray.Origin = origin;
    ray.Direction = rayDir;
    ray.TMin = 0.001;
    ray.TMax = 10000.0;
    RayPayload payload = {float4(0, 0, 0, 0)};
    TraceRay(Scene, RAY_FLAG_CULL_BACK_FACING_TRIANGLES, ~0, 0, 1, 0, ray, payload);

    RenderTarget[DispatchRaysIndex().xy] = payload.color;
}

[shader("closesthit")]
void MyClosestHitShader(inout RayPayload payload, in BuiltInTriangleIntersectionAttributes attr)
{
    float3 barycentrics = float3(1 - attr.barycentrics.x - attr.barycentrics.y, attr.barycentrics.x, attr.barycentrics.y);
    payload.color = float4(barycentrics, 1);
}

[shader("miss")]
void MyMissShader(inout RayPayload payload)
{
    payload.color = float4(0, 0, 0, 1);
}

BVH生成

Acceleration Structureが必須です. データ構造が公開されていないため自作できません.

ID3D12GraphicsCommandList4::BuildRaytracingAccelerationStructureで作成します.
トップレベルとボトムレベルのふたつを作成する必要があります.

ID3D12GraphicsCommandList4::CopyRaytracingAccelerationStructureを使えば, 事前生成ができそうです.
ただし, D3D12_SERIALIZED_RAYTRACING_ACCELERATION_STRUCTURE_HEADER
D3D12_SERIALIZED_DATA_DRIVER_MATCHING_IDENTIFIERをチェックする必要があります.

まとめ

処理の概観についてまとめました. 詳細はサンプルコードを読むしかないのですが,
シェーダを中心に必要なものを生成していくコードを読むとわかりやすいと思います.

従来のラスタライザパイプラインとは完全に分離しているため, 結果を合成するなりしないといけません.

6
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?