实现 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:
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#define PNANOVDB_HLSL
|
||||
#define PNANOVDB_ADDRESS_64
|
||||
#define PNANOVDB_ADDRESS_32
|
||||
#include "PNanoVDB.hlsl"
|
||||
|
||||
cbuffer CB0 : register(b1)
|
||||
|
||||
74
main.cpp
74
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();
|
||||
|
||||
Reference in New Issue
Block a user