实现 NanoVDB 边界框可视化

修改内容:
1. NanoVDBLoader 添加边界框信息读取 (worldBBox[6])
2. BattleFireDirect 添加 Volume 渲染相关函数:
   - InitVolumeRootSignature(): 体积渲染的 root signature
   - CreateVolumePSO(): 线框模式 PSO
3. main.cpp:
   - 打印 NanoVDB 边界框信息
   - 创建立方体网格表示边界框
   - 渲染绿色线框立方体
4. 修复 CreateShaderFromFile 支持 #include
5. 修复 volume.hlsl 使用 32 位地址模式

验证结果:
- 成功显示 NanoVDB 边界框线框
- 着色器能正确读取 NanoVDB 数据
This commit is contained in:
2026-03-11 20:32:54 +08:00
parent bc58abc98f
commit af3b61a45a
6 changed files with 184 additions and 3 deletions

View File

@@ -81,6 +81,36 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLi
NanoVDBData nanoVDBData = {};
LoadNanoVDB("Res/NanoVDB/bunny.nvdb", nanoVDBData, commandList, commandAllocator);
printf("NanoVDB loaded: %llu bytes\n", (unsigned long long)nanoVDBData.byteSize);
printf("NanoVDB BBox: [%.2f, %.2f, %.2f] - [%.2f, %.2f, %.2f]\n",
nanoVDBData.worldBBox[0], nanoVDBData.worldBBox[1], nanoVDBData.worldBBox[2],
nanoVDBData.worldBBox[3], nanoVDBData.worldBBox[4], nanoVDBData.worldBBox[5]);
float bboxMin[3] = { (float)nanoVDBData.worldBBox[0], (float)nanoVDBData.worldBBox[1], (float)nanoVDBData.worldBBox[2] };
float bboxMax[3] = { (float)nanoVDBData.worldBBox[3], (float)nanoVDBData.worldBBox[4], (float)nanoVDBData.worldBBox[5] };
float bboxCenter[3] = { (bboxMin[0] + bboxMax[0]) / 2, (bboxMin[1] + bboxMax[1]) / 2, (bboxMin[2] + bboxMax[2]) / 2 };
float bboxSize[3] = { bboxMax[0] - bboxMin[0], bboxMax[1] - bboxMin[1], bboxMax[2] - bboxMin[2] };
printf("BBox center: [%.2f, %.2f, %.2f], size: [%.2f, %.2f, %.2f]\n",
bboxCenter[0], bboxCenter[1], bboxCenter[2],
bboxSize[0], bboxSize[1], bboxSize[2]);
float cubeVertices[] = {
-0.5f, -0.5f, -0.5f,
0.5f, -0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
-0.5f, 0.5f, -0.5f,
-0.5f, -0.5f, 0.5f,
0.5f, -0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
};
uint32_t cubeIndices[] = {
0, 1, 1, 2, 2, 3, 3, 0,
4, 5, 5, 6, 6, 7, 7, 4,
0, 4, 1, 5, 2, 6, 3, 7
};
ID3D12Resource* cubeVBO = CreateBufferObject(commandList, cubeVertices, sizeof(cubeVertices), D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER);
ID3D12Resource* cubeIBO = CreateBufferObject(commandList, cubeIndices, sizeof(cubeIndices), D3D12_RESOURCE_STATE_INDEX_BUFFER);
printf("Cube mesh created\n");
StaticMeshComponent staticMeshComponent;
staticMeshComponent.InitFromFile(commandList, "Res/Model/Sphere.lhsm");
@@ -95,6 +125,24 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLi
ID3D12PipelineState*pso=CreatePSO(rootSignature, vs, ps, gs);
printf("PSO created\n");
ID3D12RootSignature* volumeRootSignature = InitVolumeRootSignature();
printf("Volume root signature created\n");
D3D12_SHADER_BYTECODE volumeVS, volumePS;
memset(&volumeVS, 0, sizeof(volumeVS));
memset(&volumePS, 0, sizeof(volumePS));
CreateShaderFromFile(L"Res/Shader/volume.hlsl", "MainVS", "vs_5_1", &volumeVS);
CreateShaderFromFile(L"Res/Shader/volume.hlsl", "MainPS", "ps_5_1", &volumePS);
printf("Volume VS: ptr=%p, size=%zu\n", volumeVS.pShaderBytecode, volumeVS.BytecodeLength);
printf("Volume PS: ptr=%p, size=%zu\n", volumePS.pShaderBytecode, volumePS.BytecodeLength);
ID3D12PipelineState* volumePSO = CreateVolumePSO(volumeRootSignature, volumeVS, volumePS);
if (!volumePSO) {
printf("Volume PSO creation failed!\n");
} else {
printf("Volume PSO created: %p\n", volumePSO);
}
ID3D12Resource* volumeCB = CreateConstantBufferObject(65536);
ID3D12Resource* cb = CreateConstantBufferObject(65536);//1024x64(4x4)
DirectX::XMMATRIX projectionMatrix=DirectX::XMMatrixPerspectiveFovLH(
(45.0f*3.141592f)/180.0f,1280.0f/720.0f,0.1f,1000.0f);
@@ -204,6 +252,32 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLi
staticMeshComponent.mVertexCount, staticMeshComponent.mVBO, staticMeshComponent.mSubMeshes.size());
}
staticMeshComponent.Render(commandList);
DirectX::XMMATRIX bboxScale = DirectX::XMMatrixScaling(bboxSize[0], bboxSize[1], bboxSize[2]);
DirectX::XMMATRIX bboxTranslate = DirectX::XMMatrixTranslation(bboxCenter[0], bboxCenter[1], bboxCenter[2]);
DirectX::XMMATRIX bboxModel = bboxScale * bboxTranslate;
DirectX::XMMATRIX bboxViewProj = bboxModel * viewMatrix * projectionMatrix;
DirectX::XMFLOAT4X4 bboxViewProjMat;
DirectX::XMStoreFloat4x4(&bboxViewProjMat, bboxViewProj);
float volumeCBData[20];
memcpy(volumeCBData, &bboxViewProjMat, sizeof(float) * 16);
volumeCBData[16] = 0.0f;
volumeCBData[17] = 0.0f;
volumeCBData[18] = -5.0f;
volumeCBData[19] = 1.0f;
UpdateConstantBuffer(volumeCB, volumeCBData, sizeof(float) * 20);
if (volumePSO) {
commandList->SetPipelineState(volumePSO);
commandList->SetGraphicsRootSignature(volumeRootSignature);
commandList->SetGraphicsRootConstantBufferView(0, volumeCB->GetGPUVirtualAddress());
commandList->SetGraphicsRootShaderResourceView(1, nanoVDBData.gpuBuffer->GetGPUVirtualAddress());
commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_LINELIST);
commandList->IASetVertexBuffers(0, 1, &D3D12_VERTEX_BUFFER_VIEW{ cubeVBO->GetGPUVirtualAddress(), sizeof(cubeVertices), sizeof(float) * 3 });
commandList->IASetIndexBuffer(&D3D12_INDEX_BUFFER_VIEW{ cubeIBO->GetGPUVirtualAddress(), sizeof(cubeIndices), DXGI_FORMAT_R32_UINT });
commandList->DrawIndexedInstanced(24, 1, 0, 0, 0);
}
EndRenderToSwapChain(commandList);
EndCommandList();
SwapD3D12Buffers();