Hey,
I have problem with DXR HLSL code. I am trying to create simplest possible world-space shader, using ray-tracing DirectX12/DXR. I tried to achieve (as you can see in closest hit shader) flat shading of model. However, here is the result:
![https://puu.sh/GekqF/7f4eb92767.png](https://puu.sh/GekqF/7f4eb92767.png)
Which indicates, that every pixel is hitting geometry, which shouldn't be true.
![https://puu.sh/Gekrq/ea35ae21a4.png](https://puu.sh/Gekrq/ea35ae21a4.png)
As geometry I am using simple sphere presented above.
struct Vertex
{
float3 position;
float3 normal;
float3 tangent;
float3 binormal;
float2 uv;
};
struct RayPayload
{
float4 color;
};
struct Attributes
{
float2 bary;
};
struct SceneConstantBuffer
{
matrix projectionToWorld;
float4 cameraPosition;
float4 lightPosition;
float4 lightAmbientColor;
float4 lightDiffuseColor;
};
ConstantBuffer<SceneConstantBuffer> g_sceneCB : register(b0);
ConstantBuffer<CubeConstantBuffer> g_cubeCB : register(b1);
RWTexture2D<float4> RTOutput : register(u0);
RaytracingAccelerationStructure SceneBVH : register(t0);
ByteAddressBuffer indices : register(t1);
StructuredBuffer<Vertex> vertices : register(t2);
inline void GenerateCameraRay(uint2 index, out float3 origin, out float3 direction)
{
float2 xy = index + float2(0.5f, 0.5f); // center in the middle of the pixel.
float2 screenPos = xy / DispatchRaysDimensions().xy * 2.0 - 1.0;
// Invert Y for DirectX-style coordinates.
screenPos.y = -screenPos.y;
// Unproject the pixel coordinate into a ray.
float4 world = mul(float4(screenPos, 0, 1), g_sceneCB.projectionToWorld);
world.xyz /= world.w;
origin = g_sceneCB.cameraPosition.xyz;
direction = normalize(world.xyz - origin);
}
[shader("raygeneration")]
void RayGen()
{
float3 rayDir;
float3 origin;
GenerateCameraRay(DispatchRaysIndex().xy, origin, rayDir);
RayDesc ray;
ray.Origin = origin;
ray.Direction = rayDir;
ray.TMin = 0.001;
ray.TMax = 10000.0;
RayPayload payload = { float4(0, 0, 0, 0) };
TraceRay(SceneBVH, RAY_FLAG_CULL_BACK_FACING_TRIANGLES, 0xFF, 0, 1, 0, ray, payload);
RTOutput[DispatchRaysIndex().xy] = payload.color;
}
[shader("closesthit")]
void ClosestHit(inout RayPayload payload, in Attributes attrib)
{
float4 color = float4(1, 0, 1, 1);
payload.color = color;
}
[shader("miss")]
void Miss(inout RayPayload payload)
{
payload.color = float4(0.0f, 0.2f, 0.4f, 1.0f);
}
m_sceneBufferData.cameraPosition = XMFLOAT4(m_cameraPosition.x, m_cameraPosition.y, m_cameraPosition.z, 1.0f);
XMVECTOR eye = XMVECTOR{ m_cameraPosition.x, m_cameraPosition.y, m_cameraPosition.z };
XMMATRIX view = XMMatrixLookAtLH(eye, XMVECTOR{ 0,0,0 }, XMVECTOR{ 0, 1, 0 });
constexpr float FOV = 45.0f;
XMMATRIX proj = DirectX::XMMatrixPerspectiveFovLH(XMConvertToRadians(FOV), m_aspectRatio, Z_NEAR, Z_FAR);
XMMATRIX viewProj = XMMatrixMultiply(view, proj);
m_sceneBufferData.projectionToWorld = XMMatrixInverse(nullptr, viewProj);
memcpy(m_sceneBufferDataBegin, &m_sceneBufferData, sizeof(m_sceneBufferData));
My guess is, that maybe projectionToWorld matrix is actually wrong.
My other guess might be acceleration structures, but NVidia Nsight is telling me, that it is actually correct:
![](https://uploads.gamedev.net/forums/monthly_2020_08/1b948d70a4b34a5c82a235a1e9148d21.obraz.png)
I am getting this message in Nsight. It started to appear after I preparation of DXR code. I'm not sure how to fix it and if it is related to my problem:
![](https://uploads.gamedev.net/forums/monthly_2020_08/26d71d743ad142089af803590ef4aeaa.obraz.png)
void Renderer::CreateBLAS(std::shared_ptr<ModelClass> model)
{
// Describe the geometry that goes in the bottom acceleration structure(s)
D3D12_RAYTRACING_GEOMETRY_DESC geometryDesc = {};
geometryDesc.Type = D3D12_RAYTRACING_GEOMETRY_TYPE_TRIANGLES;
geometryDesc.Triangles.VertexBuffer.StartAddress = model->GetVertexBuffer()->GetGPUVirtualAddress();
geometryDesc.Triangles.VertexBuffer.StrideInBytes = model->GetVertexBufferView().StrideInBytes;
geometryDesc.Triangles.VertexCount = static_cast<UINT>(model->GetMesh(0).vertices.size());
geometryDesc.Triangles.VertexFormat = DXGI_FORMAT_R32G32B32_FLOAT;
geometryDesc.Triangles.IndexBuffer = model->GetIndexBuffer()->GetGPUVirtualAddress();
geometryDesc.Triangles.IndexFormat = model->GetIndexBufferView().Format;
geometryDesc.Triangles.IndexCount = static_cast<UINT>(model->GetIndicesCount());
geometryDesc.Triangles.Transform3x4 = 0;
geometryDesc.Flags = D3D12_RAYTRACING_GEOMETRY_FLAG_OPAQUE;
D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAGS buildFlags = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_PREFER_FAST_TRACE;
// Get the size requirements for the BLAS buffers
D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS ASInputs = {};
ASInputs.Type = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL;
ASInputs.DescsLayout = D3D12_ELEMENTS_LAYOUT_ARRAY;
ASInputs.pGeometryDescs = &geometryDesc;
ASInputs.NumDescs = 1;
ASInputs.Flags = buildFlags;
D3D12_RAYTRACING_ACCELERATION_STRUCTURE_PREBUILD_INFO ASPreBuildInfo = {};
m_device->GetRaytracingAccelerationStructurePrebuildInfo(&ASInputs, &ASPreBuildInfo);
ASPreBuildInfo.ScratchDataSizeInBytes = ALIGN(D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BYTE_ALIGNMENT, ASPreBuildInfo.ScratchDataSizeInBytes);
ASPreBuildInfo.ResultDataMaxSizeInBytes = ALIGN(D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BYTE_ALIGNMENT, ASPreBuildInfo.ResultDataMaxSizeInBytes);
// Create the BLAS scratch buffer
auto bufferInfo = CD3DX12_RESOURCE_DESC::Buffer(ASPreBuildInfo.ScratchDataSizeInBytes, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, std::max(D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BYTE_ALIGNMENT, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT));
ThrowIfFailed(m_device->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
D3D12_HEAP_FLAG_NONE,
&bufferInfo,
D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
nullptr,
IID_PPV_ARGS(&m_blasScratch)
));
// Create the BLAS buffer
bufferInfo = CD3DX12_RESOURCE_DESC::Buffer(ASPreBuildInfo.ResultDataMaxSizeInBytes, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, std::max(D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BYTE_ALIGNMENT, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT));
ThrowIfFailed(m_device->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
D3D12_HEAP_FLAG_NONE,
&bufferInfo,
D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE,
nullptr,
IID_PPV_ARGS(&m_blasResult)
));
// Describe and build the bottom level acceleration structure
D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC buildDesc = {};
buildDesc.Inputs = ASInputs;
buildDesc.ScratchAccelerationStructureData = m_blasScratch->GetGPUVirtualAddress();
buildDesc.DestAccelerationStructureData = m_blasResult->GetGPUVirtualAddress();
m_commandList->BuildRaytracingAccelerationStructure(&buildDesc, 0, nullptr);
// Wait for the BLAS build to complete
m_commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::UAV(m_blasResult.Get()));
}
void Renderer::CreateTLAS()
{
// Describe the TLAS geometry instance(s)
D3D12_RAYTRACING_INSTANCE_DESC instanceDesc = {};
instanceDesc.InstanceID = 0;
instanceDesc.InstanceContributionToHitGroupIndex = 0;
instanceDesc.InstanceMask = 0xFF;
instanceDesc.Transform[0][0] = instanceDesc.Transform[1][1] = instanceDesc.Transform[2][2] = 1;
instanceDesc.AccelerationStructure = m_blasResult->GetGPUVirtualAddress();
instanceDesc.Flags = D3D12_RAYTRACING_INSTANCE_FLAG_TRIANGLE_FRONT_COUNTERCLOCKWISE;
// Create the TLAS instance buffer
ThrowIfFailed(m_device->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Buffer(sizeof(instanceDesc)),
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
IID_PPV_ARGS(&m_tlasInstanceDesc)
));
// Copy the instance data to the buffer
UINT8* pData;
m_tlasInstanceDesc->Map(0, nullptr, (void**)&pData);
memcpy(pData, &instanceDesc, sizeof(instanceDesc));
m_tlasInstanceDesc->Unmap(0, nullptr);
D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAGS buildFlags = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_PREFER_FAST_TRACE;
// Get the size requirements for the TLAS buffers
D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS ASInputs = {};
ASInputs.Type = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL;
ASInputs.DescsLayout = D3D12_ELEMENTS_LAYOUT_ARRAY;
ASInputs.InstanceDescs = m_tlasInstanceDesc->GetGPUVirtualAddress();
ASInputs.NumDescs = 1;
ASInputs.Flags = buildFlags;
D3D12_RAYTRACING_ACCELERATION_STRUCTURE_PREBUILD_INFO ASPreBuildInfo = {};
m_device->GetRaytracingAccelerationStructurePrebuildInfo(&ASInputs, &ASPreBuildInfo);
ASPreBuildInfo.ResultDataMaxSizeInBytes = ALIGN(D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BYTE_ALIGNMENT, ASPreBuildInfo.ResultDataMaxSizeInBytes);
ASPreBuildInfo.ScratchDataSizeInBytes = ALIGN(D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BYTE_ALIGNMENT, ASPreBuildInfo.ScratchDataSizeInBytes);
// Set TLAS size
m_tlasSize = ASPreBuildInfo.ResultDataMaxSizeInBytes;
// Create TLAS scratch buffer
auto bufferInfo = CD3DX12_RESOURCE_DESC::Buffer(ASPreBuildInfo.ScratchDataSizeInBytes, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, std::max(D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BYTE_ALIGNMENT, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT));
ThrowIfFailed(m_device->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
D3D12_HEAP_FLAG_NONE,
&bufferInfo,
D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
nullptr,
IID_PPV_ARGS(&m_tlasScratch)
));
bufferInfo = CD3DX12_RESOURCE_DESC::Buffer(ASPreBuildInfo.ResultDataMaxSizeInBytes, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, std::max(D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BYTE_ALIGNMENT, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT));
ThrowIfFailed(m_device->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
D3D12_HEAP_FLAG_NONE,
&bufferInfo,
D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE,
nullptr,
IID_PPV_ARGS(&m_tlasResult)
));
// Describe and build the TLAS
D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC buildDesc = {};
buildDesc.Inputs = ASInputs;
buildDesc.ScratchAccelerationStructureData = m_tlasScratch->GetGPUVirtualAddress();
buildDesc.DestAccelerationStructureData = m_tlasResult->GetGPUVirtualAddress();
m_commandList->BuildRaytracingAccelerationStructure(&buildDesc, 0, nullptr);
// Wait for the TLAS build to complete
m_commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::UAV(m_tlasResult.Get()));
}