From fa50179d00993a5db1150b504ea9e56eafa6172d Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Wed, 11 Mar 2026 21:51:50 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=20NanoVDB=20=E4=BD=93?= =?UTF-8?q?=E7=A7=AF=E4=BA=91=E6=B8=B2=E6=9F=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 完成步骤2:读取 NanoVDB 密度并渲染体积云 修改内容: 1. NanoVDBLoader: 添加 voxel_size 输出用于调试 2. volume.hlsl: 实现完整的 ray marching 体积渲染 - 初始化 NanoVDB 访问器 - 密度采样函数 - 光线步进和累积 3. wireframe.hlsl: 新增边界框线框着色器 4. main.cpp: - 移动相机到云的外部 - 添加独立的常量缓冲区避免冲突 - 同时渲染体积云和边界框 已知问题: - 边界框位置计算需要改进 - bunny.nvdb 渲染效果不佳 - 需要进一步优化密度和步进参数 --- NanoVDBLoader.cpp | 3 ++ Res/Shader/volume.hlsl | 50 ++++++++++++++++++++++---- Res/Shader/wireframe.hlsl | 26 ++++++++++++++ main.cpp | 75 ++++++++++++++++++++++++++++----------- 4 files changed, 128 insertions(+), 26 deletions(-) create mode 100644 Res/Shader/wireframe.hlsl diff --git a/NanoVDBLoader.cpp b/NanoVDBLoader.cpp index 8280723f..c0ca095e 100644 --- a/NanoVDBLoader.cpp +++ b/NanoVDBLoader.cpp @@ -33,6 +33,9 @@ bool LoadNanoVDB(const char* filePath, NanoVDBData& outData, ID3D12GraphicsComma outData.worldBBox[i] = bboxData[i]; } + double* voxelSizeData = (double*)((char*)bufferData + 608); + printf("[NanoVDB] Voxel size: [%.6f, %.6f, %.6f]\n", voxelSizeData[0], voxelSizeData[1], voxelSizeData[2]); + outData.cpuData = bufferData; outData.byteSize = byteSize; outData.elementCount = elementCount; diff --git a/Res/Shader/volume.hlsl b/Res/Shader/volume.hlsl index 853fe862..3f370cb0 100644 --- a/Res/Shader/volume.hlsl +++ b/Res/Shader/volume.hlsl @@ -28,6 +28,37 @@ struct PSInput float3 worldPos : TEXCOORD1; }; +struct NanoVolume +{ + pnanovdb_grid_handle_t grid; + pnanovdb_grid_type_t grid_type; + pnanovdb_readaccessor_t acc; +}; + +void initVolume(inout NanoVolume volume) +{ + pnanovdb_grid_handle_t grid; + grid.address.byte_offset = 0; + + pnanovdb_grid_type_t grid_type = pnanovdb_buf_read_uint32(buf, PNANOVDB_GRID_OFF_GRID_TYPE); + pnanovdb_tree_handle_t tree = pnanovdb_grid_get_tree(buf, grid); + pnanovdb_root_handle_t root = pnanovdb_tree_get_root(buf, tree); + pnanovdb_readaccessor_t acc; + pnanovdb_readaccessor_init(acc, root); + + volume.grid = grid; + volume.grid_type = grid_type; + volume.acc = acc; +} + +float get_value_coord(inout pnanovdb_readaccessor_t acc, float3 pos) +{ + pnanovdb_vec3_t p = pos; + pnanovdb_coord_t ijk = pnanovdb_hdda_pos_to_ijk(p); + pnanovdb_address_t address = pnanovdb_readaccessor_get_value_address(PNANOVDB_GRID_TYPE_FLOAT, buf, acc, ijk); + return pnanovdb_read_float(buf, address); +} + PSInput MainVS(VSInput input) { PSInput output; @@ -63,20 +94,27 @@ float4 MainPS(PSInput input) : SV_TARGET tmin = max(0, tmin); + NanoVolume volume; + initVolume(volume); + float3 color = float3(0, 0, 0); - float alpha = 0; + float transmittance = 1.0; for (uint i = 0; i < _MaxSteps; i++) { float t = tmin + i * _StepSize; - if (t > tmax || alpha > 0.99) break; + if (t > tmax || transmittance < 0.01) break; - float3 pos = _CameraPos + rayDir * t; + float3 worldPos = _CameraPos + rayDir * t; - float density = 0.1; + float density = get_value_coord(volume.acc, worldPos) * _DensityScale; - color += density * float3(0.5, 0.7, 1.0) * (1 - alpha); - alpha += density * (1 - alpha); + if (density > 0.001) { + float3 S = density * float3(1, 1, 1); + color += transmittance * S * _StepSize; + transmittance *= exp(-density * _StepSize); + } } + float alpha = 1.0 - transmittance; return float4(color, alpha); } \ No newline at end of file diff --git a/Res/Shader/wireframe.hlsl b/Res/Shader/wireframe.hlsl new file mode 100644 index 00000000..2b5a55f6 --- /dev/null +++ b/Res/Shader/wireframe.hlsl @@ -0,0 +1,26 @@ +cbuffer CB0 : register(b1) +{ + float4x4 _ViewProjection; +}; + +struct VSInput +{ + float3 position : POSITION; +}; + +struct PSInput +{ + float4 position : SV_POSITION; +}; + +PSInput MainVS(VSInput input) +{ + PSInput output; + output.position = mul(_ViewProjection, float4(input.position, 1.0)); + return output; +} + +float4 MainPS(PSInput input) : SV_TARGET +{ + return float4(0.0, 1.0, 0.0, 1.0); +} \ No newline at end of file diff --git a/main.cpp b/main.cpp index 0f5d47c4..102a634c 100644 --- a/main.cpp +++ b/main.cpp @@ -79,7 +79,7 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLi ID3D12CommandAllocator* commandAllocator = GetCommandAllocator(); NanoVDBData nanoVDBData = {}; - LoadNanoVDB("Res/NanoVDB/bunny.nvdb", nanoVDBData, commandList, commandAllocator); + LoadNanoVDB("Res/NanoVDB/cloud.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], @@ -138,6 +138,7 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLi ID3D12RootSignature* volumeRootSignature = InitVolumeRootSignature(); printf("Volume root signature created\n"); + D3D12_SHADER_BYTECODE volumeVS, volumePS; memset(&volumeVS, 0, sizeof(volumeVS)); memset(&volumePS, 0, sizeof(volumePS)); @@ -145,13 +146,7 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLi 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); - } - + ID3D12PipelineState* quadPSO = CreateQuadPSO(volumeRootSignature, volumeVS, volumePS); if (!quadPSO) { printf("Quad PSO creation failed!\n"); @@ -159,12 +154,31 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLi printf("Quad PSO created: %p\n", quadPSO); } + D3D12_SHADER_BYTECODE wireframeVS, wireframePS; + memset(&wireframeVS, 0, sizeof(wireframeVS)); + memset(&wireframePS, 0, sizeof(wireframePS)); + CreateShaderFromFile(L"Res/Shader/wireframe.hlsl", "MainVS", "vs_5_1", &wireframeVS); + CreateShaderFromFile(L"Res/Shader/wireframe.hlsl", "MainPS", "ps_5_1", &wireframePS); + printf("Wireframe VS: ptr=%p, size=%zu\n", wireframeVS.pShaderBytecode, wireframeVS.BytecodeLength); + printf("Wireframe PS: ptr=%p, size=%zu\n", wireframePS.pShaderBytecode, wireframePS.BytecodeLength); + + ID3D12PipelineState* volumePSO = CreateVolumePSO(volumeRootSignature, wireframeVS, wireframePS); + if (!volumePSO) { + printf("Volume PSO creation failed!\n"); + } else { + printf("Volume PSO created: %p\n", volumePSO); + } + ID3D12Resource* volumeCB = CreateConstantBufferObject(65536); + ID3D12Resource* wireframeCB = 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); - DirectX::XMMATRIX viewMatrix = DirectX::XMMatrixIdentity(); + DirectX::XMMATRIX viewMatrix = DirectX::XMMatrixLookAtLH( + DirectX::XMVectorSet(-10.0f, 73.0f, -600.0f, 1.0f), + DirectX::XMVectorSet(-10.0f, 73.0f, 0.0f, 1.0f), + DirectX::XMVectorSet(0.0f, 1.0f, 0.0f, 1.0f)); DirectX::XMMATRIX modelMatrix = DirectX::XMMatrixTranslation(0.0f,0.0f,5.0f); //modelMatrix *= DirectX::XMMatrixRotationZ(90.0f*3.141592f/180.0f); DirectX::XMFLOAT4X4 tempMatrix; @@ -278,17 +292,17 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLi float volumeCBData[32]; memcpy(volumeCBData, &invViewProjMat, sizeof(float) * 16); - volumeCBData[16] = 0.0f; - volumeCBData[17] = 0.0f; - volumeCBData[18] = -5.0f; - volumeCBData[19] = 1.0f; - volumeCBData[20] = bboxMin[0] - bboxCenter[0]; - volumeCBData[21] = bboxMin[1] - bboxCenter[1]; - volumeCBData[22] = bboxMin[2] - bboxCenter[2] + 80.0f; - volumeCBData[23] = 0.5f; - volumeCBData[24] = bboxMax[0] - bboxCenter[0]; - volumeCBData[25] = bboxMax[1] - bboxCenter[1]; - volumeCBData[26] = bboxMax[2] - bboxCenter[2] + 80.0f; + volumeCBData[16] = -10.0f; + volumeCBData[17] = 73.0f; + volumeCBData[18] = -600.0f; + volumeCBData[19] = 0.01f; // DensityScale + volumeCBData[20] = (float)nanoVDBData.worldBBox[0]; + volumeCBData[21] = (float)nanoVDBData.worldBBox[1]; + volumeCBData[22] = (float)nanoVDBData.worldBBox[2]; + volumeCBData[23] = 0.5f; // StepSize + volumeCBData[24] = (float)nanoVDBData.worldBBox[3]; + volumeCBData[25] = (float)nanoVDBData.worldBBox[4]; + volumeCBData[26] = (float)nanoVDBData.worldBBox[5]; volumeCBData[27] = 128; UpdateConstantBuffer(volumeCB, volumeCBData, sizeof(float) * 28); if (frameCount == 1) { @@ -308,6 +322,27 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLi commandList->DrawIndexedInstanced(6, 1, 0, 0, 0); } + 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 wireframeCBData[16]; + memcpy(wireframeCBData, &bboxViewProjMat, sizeof(float) * 16); + UpdateConstantBuffer(wireframeCB, wireframeCBData, sizeof(float) * 16); + + if (volumePSO) { + commandList->SetPipelineState(volumePSO); + commandList->SetGraphicsRootSignature(volumeRootSignature); + commandList->SetGraphicsRootConstantBufferView(0, wireframeCB->GetGPUVirtualAddress()); + commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_LINELIST); + commandList->IASetVertexBuffers(0, 1, &D3D12_VERTEX_BUFFER_VIEW{ cubeVBO->GetGPUVirtualAddress(), 8 * 3 * sizeof(float), sizeof(float) * 3 }); + commandList->IASetIndexBuffer(&D3D12_INDEX_BUFFER_VIEW{ cubeIBO->GetGPUVirtualAddress(), 24 * sizeof(uint32_t), DXGI_FORMAT_R32_UINT }); + commandList->DrawIndexedInstanced(24, 1, 0, 0, 0); + } + EndRenderToSwapChain(commandList); EndCommandList(); SwapD3D12Buffers();