From af3b61a45a4de2433b727d5bd54b403f41255eea Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Wed, 11 Mar 2026 20:32:54 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=20NanoVDB=20=E8=BE=B9?= =?UTF-8?q?=E7=95=8C=E6=A1=86=E5=8F=AF=E8=A7=86=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修改内容: 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 数据 --- BattleFireDirect.cpp | 102 ++++++++++++++++++++++++++++++++++++++++- BattleFireDirect.h | 3 ++ NanoVDBLoader.cpp | 5 ++ NanoVDBLoader.h | 1 + Res/Shader/volume.hlsl | 2 +- main.cpp | 74 ++++++++++++++++++++++++++++++ 6 files changed, 184 insertions(+), 3 deletions(-) diff --git a/BattleFireDirect.cpp b/BattleFireDirect.cpp index 17475632..ee1561c9 100644 --- a/BattleFireDirect.cpp +++ b/BattleFireDirect.cpp @@ -74,6 +74,37 @@ ID3D12RootSignature* InitRootSignature() { return d3d12RootSignature; } + +ID3D12RootSignature* InitVolumeRootSignature() { + D3D12_ROOT_PARAMETER rootParameters[2]; + + rootParameters[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV; + rootParameters[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + rootParameters[0].Descriptor.RegisterSpace = 0; + rootParameters[0].Descriptor.ShaderRegister = 1; + + rootParameters[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV; + rootParameters[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + rootParameters[1].Descriptor.RegisterSpace = 0; + rootParameters[1].Descriptor.ShaderRegister = 1; + + D3D12_ROOT_SIGNATURE_DESC rootSignatureDesc = {}; + rootSignatureDesc.NumParameters = _countof(rootParameters); + rootSignatureDesc.pParameters = rootParameters; + rootSignatureDesc.NumStaticSamplers = 0; + rootSignatureDesc.pStaticSamplers = nullptr; + rootSignatureDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT; + + ID3DBlob* signature; + HRESULT hResult = D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, nullptr); + ID3D12RootSignature* d3d12RootSignature; + gD3D12Device->CreateRootSignature( + 0, signature->GetBufferPointer(), signature->GetBufferSize(), + IID_PPV_ARGS(&d3d12RootSignature)); + + return d3d12RootSignature; +} + void CreateShaderFromFile( LPCTSTR inShaderFilePath, const char* inMainFunctionName, @@ -81,12 +112,16 @@ void CreateShaderFromFile( D3D12_SHADER_BYTECODE* inShader) { ID3DBlob* shaderBuffer = nullptr; ID3DBlob* errorBuffer = nullptr; - HRESULT hResult = D3DCompileFromFile(inShaderFilePath, nullptr, nullptr, + HRESULT hResult = D3DCompileFromFile(inShaderFilePath, nullptr, D3D_COMPILE_STANDARD_FILE_INCLUDE, inMainFunctionName, inTarget, D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION, 0, &shaderBuffer, &errorBuffer); if (FAILED(hResult)) { char szLog[1024] = {0}; - strcpy(szLog, (char*)errorBuffer->GetBufferPointer()); + if (errorBuffer) { + strcpy(szLog, (char*)errorBuffer->GetBufferPointer()); + } else { + strcpy(szLog, "Unknown error"); + } printf("CreateShaderFromFile error : [%s][%s]:[%s]\n", inMainFunctionName, inTarget, szLog); errorBuffer->Release(); return; @@ -183,6 +218,69 @@ ID3D12PipelineState* CreatePSO(ID3D12RootSignature* inID3D12RootSignature, return d3d12PSO; } +ID3D12PipelineState* CreateVolumePSO(ID3D12RootSignature* inID3D12RootSignature, + D3D12_SHADER_BYTECODE inVertexShader, D3D12_SHADER_BYTECODE inPixelShader) { + D3D12_INPUT_ELEMENT_DESC vertexDataElementDesc[] = { + {"POSITION",0,DXGI_FORMAT_R32G32B32_FLOAT,0,0,D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,0} + }; + D3D12_INPUT_LAYOUT_DESC vertexDataLayoutDesc = {}; + vertexDataLayoutDesc.NumElements = 1; + vertexDataLayoutDesc.pInputElementDescs = vertexDataElementDesc; + + D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; + psoDesc.pRootSignature = inID3D12RootSignature; + psoDesc.VS = inVertexShader; + psoDesc.PS = inPixelShader; + psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM; + psoDesc.DSVFormat = DXGI_FORMAT_D24_UNORM_S8_UINT; + psoDesc.SampleDesc.Count = 1; + psoDesc.SampleDesc.Quality = 0; + psoDesc.SampleMask = 0xffffffff; + psoDesc.InputLayout = vertexDataLayoutDesc; + psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE; + + psoDesc.RasterizerState.FillMode = D3D12_FILL_MODE_WIREFRAME; + psoDesc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE; + psoDesc.RasterizerState.FrontCounterClockwise = FALSE; + psoDesc.RasterizerState.DepthBias = D3D12_DEFAULT_DEPTH_BIAS; + psoDesc.RasterizerState.DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP; + psoDesc.RasterizerState.SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS; + psoDesc.RasterizerState.DepthClipEnable = TRUE; + psoDesc.RasterizerState.MultisampleEnable = FALSE; + psoDesc.RasterizerState.AntialiasedLineEnable = FALSE; + psoDesc.RasterizerState.ForcedSampleCount = 0; + psoDesc.RasterizerState.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; + + psoDesc.DepthStencilState.DepthEnable = TRUE; + psoDesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL; + psoDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS; + psoDesc.DepthStencilState.StencilEnable = FALSE; + + psoDesc.BlendState.AlphaToCoverageEnable = FALSE; + psoDesc.BlendState.IndependentBlendEnable = FALSE; + for (int i = 0; i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i) { + psoDesc.BlendState.RenderTarget[i].BlendEnable = FALSE; + psoDesc.BlendState.RenderTarget[i].LogicOpEnable = FALSE; + psoDesc.BlendState.RenderTarget[i].SrcBlend = D3D12_BLEND_ONE; + psoDesc.BlendState.RenderTarget[i].DestBlend = D3D12_BLEND_ZERO; + psoDesc.BlendState.RenderTarget[i].BlendOp = D3D12_BLEND_OP_ADD; + psoDesc.BlendState.RenderTarget[i].SrcBlendAlpha = D3D12_BLEND_ONE; + psoDesc.BlendState.RenderTarget[i].DestBlendAlpha = D3D12_BLEND_ZERO; + psoDesc.BlendState.RenderTarget[i].BlendOpAlpha = D3D12_BLEND_OP_ADD; + psoDesc.BlendState.RenderTarget[i].LogicOp = D3D12_LOGIC_OP_NOOP; + psoDesc.BlendState.RenderTarget[i].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; + } + psoDesc.NumRenderTargets = 1; + ID3D12PipelineState* d3d12PSO = nullptr; + + HRESULT hResult = gD3D12Device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&d3d12PSO)); + if (FAILED(hResult)) { + printf("CreateVolumePSO failed: 0x%08X\n", hResult); + return nullptr; + } + return d3d12PSO; +} + bool InitD3D12(HWND inHWND, int inWidth, int inHeight) { HRESULT hResult; UINT dxgiFactoryFlags = 0; diff --git a/BattleFireDirect.h b/BattleFireDirect.h index 53d7f9e7..84c06698 100644 --- a/BattleFireDirect.h +++ b/BattleFireDirect.h @@ -9,6 +9,7 @@ D3D12_RESOURCE_BARRIER InitResourceBarrier( ID3D12Resource* inResource, D3D12_RESOURCE_STATES inPrevState, D3D12_RESOURCE_STATES inNextState); ID3D12RootSignature* InitRootSignature(); +ID3D12RootSignature* InitVolumeRootSignature(); void CreateShaderFromFile( LPCTSTR inShaderFilePath, const char* inMainFunctionName, @@ -21,6 +22,8 @@ ID3D12Resource* CreateBufferObject(ID3D12GraphicsCommandList* inCommandList, ID3D12PipelineState* CreatePSO(ID3D12RootSignature* inID3D12RootSignature, D3D12_SHADER_BYTECODE inVertexShader, D3D12_SHADER_BYTECODE inPixelShader, D3D12_SHADER_BYTECODE inGSShader); +ID3D12PipelineState* CreateVolumePSO(ID3D12RootSignature* inID3D12RootSignature, + D3D12_SHADER_BYTECODE inVertexShader, D3D12_SHADER_BYTECODE inPixelShader); bool InitD3D12(HWND inHWND, int inWidth, int inHeight); ID3D12GraphicsCommandList* GetCommandList(); ID3D12CommandAllocator* GetCommandAllocator(); diff --git a/NanoVDBLoader.cpp b/NanoVDBLoader.cpp index dc1345be..8280723f 100644 --- a/NanoVDBLoader.cpp +++ b/NanoVDBLoader.cpp @@ -28,6 +28,11 @@ bool LoadNanoVDB(const char* filePath, NanoVDBData& outData, ID3D12GraphicsComma memcpy(bufferData, gridHandle.buffer().data(), byteSize); + double* bboxData = (double*)((char*)bufferData + 560); + for (int i = 0; i < 6; i++) { + outData.worldBBox[i] = bboxData[i]; + } + outData.cpuData = bufferData; outData.byteSize = byteSize; outData.elementCount = elementCount; diff --git a/NanoVDBLoader.h b/NanoVDBLoader.h index d20650d7..ce275911 100644 --- a/NanoVDBLoader.h +++ b/NanoVDBLoader.h @@ -8,6 +8,7 @@ struct NanoVDBData { void* cpuData; uint64_t byteSize; uint64_t elementCount; + double worldBBox[6]; }; bool LoadNanoVDB(const char* filePath, NanoVDBData& outData, ID3D12GraphicsCommandList* cmdList, ID3D12CommandAllocator* cmdAlloc = nullptr); diff --git a/Res/Shader/volume.hlsl b/Res/Shader/volume.hlsl index cfe127b8..4e5545ed 100644 --- a/Res/Shader/volume.hlsl +++ b/Res/Shader/volume.hlsl @@ -1,5 +1,5 @@ #define PNANOVDB_HLSL -#define PNANOVDB_ADDRESS_64 +#define PNANOVDB_ADDRESS_32 #include "PNanoVDB.hlsl" cbuffer CB0 : register(b1) diff --git a/main.cpp b/main.cpp index 24eaaf43..37a63314 100644 --- a/main.cpp +++ b/main.cpp @@ -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();