シェーダーとRaytracingShaderについて

レイトレーシングについての学びなど

closesthit
シェーダーはサーフェースシェーダー側に書く

closesthit
内で法線を求める
Vertex FetchVertex(uint vertexIndex)
{
Vertex v;
v.normal = UnityRayTracingFetchVertexAttribute3(vertexIndex, kVertexAttributeNormal);
return v;
}
Vertex InterpolateVertices(Vertex v0, Vertex v1, Vertex v2, float3 barycentrics)
{
Vertex v;
#define INTERPOLATE_ATTRIBUTE(attr) v.attr = v0.attr * barycentrics.x + v1.attr * barycentrics.y + v2.attr * barycentrics.z
INTERPOLATE_ATTRIBUTE(normal);
return v;
}
uint3 triangleIndices = UnityRayTracingFetchTriangleIndices(PrimitiveIndex());
Vertex v0, v1, v2;
v0 = FetchVertex(triangleIndices.x);
v1 = FetchVertex(triangleIndices.y);
v2 = FetchVertex(triangleIndices.z);
float3 barycentricCoords = float3(1.0 - attribs.barycentrics.x - attribs.barycentrics.y, attribs.barycentrics.x, attribs.barycentrics.y);
Vertex v = InterpolateVertices(v0, v1, v2, barycentricCoords);
float3 intersectionPosition = WorldRayOrigin() + RayTCurrent() * WorldRayDirection();
float3 worldNormal = normalize(mul(v.normal, (float3x3)WorldToObject()));

DXR(DirectX Raytracing)のシステム関数一覧

レイを法線にしたがって法線を反射させる
float3 reflection = reflect(WorldRayDirection(), worldNormal);

TraceRay
は最終的に呼び出し元まで帰ってくる。
なので、最終的な出力はraygeneration
シェーダー内で求めることが出来る

分かりやすいサンプルリポジトリ

頂点補間のサンプル

参考ディスカッション
通常のシェーダーに 1 つ以上のレイトレーシング パスを追加するだけです。通常のレンダリング中はレイトレーシング パスは無視されます。
RayTracingShader.SetShaderPass("pass name")
でパスを追加することで、サーフェースシェーダー側のclosesthit
シェーダーを認識できる

レイトレーシングに関するシェーダーを読んでると出てくるShadowRay
という概念は、どうやら「光がジオメトリによって遮られているかどうか」をチェックするためのレイのことのよう

困ったらDXRの機能仕様読んどけ

これはレイトレーシングシェーダーとは直接関係ないが、累積型のシェーディング処理について。
フレームごとに求められた照度を平均化する処理。
まずは入力にフレーム情報を持たせる
int _FrameIndex;
出力には累積用のバッファを持たせる
RWStructuredBuffer<float3> _AccumulatedBuffer;
現フレームでの値を求める
float3 frameAverage = frameValue / _SampleCountPerFrame;
塁積和を求める(累積 = 旧累積 + 新たな平均分)
float3 newAccumulated = _AccumulatedBuffer[0] + frameAverage;
_AccumulatedBuffer[0] = newAccumulated;
全フレームでの平均を求める(累積和 / フレーム数)
float3 finalAverage = newAccumulated / (float)(_FrameIndex + 1);

プリミティブに交差したときに使用できる関数一覧
hit
系シェーダー(closesthit
, anyhit
)か、intersection
シェーダーでのみ使用可能

レイのヒット点を求める基本的な公式
Origin + (Direction * RayTCurrent)
RayTCurrent
はレイの長さ。OriginとDirectionはワールド空間またはオブジェクト空間のどちらかを扱うことができ、ワールド空間またはオブジェクト空間のレイのヒット点を求めることが出来る。

インクルードガードとかいうテクニックでincludeの再定義を防止できる
#ifndef XXX_INCLUDED
#define XXX_INCLUDED
#endif

hlsl自体はコンパイルされず、shaderやraytraceにライブラリとして含めたものがコンパイルされるのね