From 657666a3005884dfaa43b06e5ccdb79652d6899e Mon Sep 17 00:00:00 2001 From: turanszkij Date: Thu, 28 Feb 2019 18:33:20 +0000 Subject: [PATCH] bvh visualizer added --- Editor/RendererWindow.cpp | 9 +++ Editor/RendererWindow.h | 1 + WickedEngine/RenderPath3D_PathTracing.cpp | 31 +++++---- WickedEngine/ShaderInterop_TracedRendering.h | 4 +- WickedEngine/WickedEngine_SHADERS.vcxproj | 8 +++ .../WickedEngine_SHADERS.vcxproj.filters | 6 ++ WickedEngine/raySceneIntersectHF.hlsli | 68 +++++++++++++++++++ WickedEngine/raytrace_debugbvhPS.hlsl | 39 +++++++++++ WickedEngine/raytrace_screenVS.hlsl | 18 +++++ WickedEngine/tracedRenderingHF.hlsli | 11 +-- WickedEngine/wiEnums.h | 2 + WickedEngine/wiRenderer.cpp | 44 ++++++++++-- WickedEngine/wiRenderer.h | 4 ++ WickedEngine/wiVersion.cpp | 2 +- 14 files changed, 223 insertions(+), 24 deletions(-) create mode 100644 WickedEngine/raytrace_debugbvhPS.hlsl create mode 100644 WickedEngine/raytrace_screenVS.hlsl diff --git a/Editor/RendererWindow.cpp b/Editor/RendererWindow.cpp index 252087fae..9f0d5d1c1 100644 --- a/Editor/RendererWindow.cpp +++ b/Editor/RendererWindow.cpp @@ -453,6 +453,15 @@ RendererWindow::RendererWindow(wiGUI* gui, RenderPath3D* path) : GUI(gui) debugForceFieldsCheckBox->SetCheck(wiRenderer::GetToDrawDebugForceFields()); rendererWindow->AddWidget(debugForceFieldsCheckBox); + debugRaytraceBVHCheckBox = new wiCheckBox("Raytrace BVH visualizer: "); + debugRaytraceBVHCheckBox->SetTooltip("Visualize scene BVH if raytracing is enabled"); + debugRaytraceBVHCheckBox->SetPos(XMFLOAT2(x, y += step)); + debugRaytraceBVHCheckBox->OnClick([](wiEventArgs args) { + wiRenderer::SetRaytraceDebugBVHVisualizerEnabled(args.bValue); + }); + debugRaytraceBVHCheckBox->SetCheck(wiRenderer::GetRaytraceDebugBVHVisualizerEnabled()); + rendererWindow->AddWidget(debugRaytraceBVHCheckBox); + envProbesCheckBox = new wiCheckBox("Env probe visualizer: "); envProbesCheckBox->SetTooltip("Toggle visualization of environment probes as reflective spheres"); envProbesCheckBox->SetPos(XMFLOAT2(x, y += step)); diff --git a/Editor/RendererWindow.h b/Editor/RendererWindow.h index 72ebf3acc..4262bef63 100644 --- a/Editor/RendererWindow.h +++ b/Editor/RendererWindow.h @@ -46,6 +46,7 @@ public: wiCheckBox* boneLinesCheckBox; wiCheckBox* debugEmittersCheckBox; wiCheckBox* debugForceFieldsCheckBox; + wiCheckBox* debugRaytraceBVHCheckBox; wiCheckBox* wireFrameCheckBox; wiCheckBox* advancedLightCullingCheckBox; wiCheckBox* debugLightCullingCheckBox; diff --git a/WickedEngine/RenderPath3D_PathTracing.cpp b/WickedEngine/RenderPath3D_PathTracing.cpp index 4ee522f2e..4fa3051f6 100644 --- a/WickedEngine/RenderPath3D_PathTracing.cpp +++ b/WickedEngine/RenderPath3D_PathTracing.cpp @@ -135,28 +135,35 @@ void RenderPath3D_PathTracing::RenderFrameSetUp(GRAPHICSTHREAD threadID) void RenderPath3D_PathTracing::RenderScene(GRAPHICSTHREAD threadID) { - wiProfiler::BeginRange("Traced Scene", wiProfiler::DOMAIN_GPU, threadID); + if (wiRenderer::GetRaytraceDebugBVHVisualizerEnabled()) + { + rtAccumulation.SetAndClear(threadID, 0, 0, 0, 1); + wiRenderer::DrawTracedSceneBVH(threadID); + } + else + { + wiProfiler::BeginRange("Traced Scene", wiProfiler::DOMAIN_GPU, threadID); - wiRenderer::UpdateCameraCB(wiRenderer::GetCamera(), threadID); + wiRenderer::UpdateCameraCB(wiRenderer::GetCamera(), threadID); - wiRenderer::DrawTracedScene(wiRenderer::GetCamera(), traceResult.get(), threadID); + wiRenderer::DrawTracedScene(wiRenderer::GetCamera(), traceResult.get(), threadID); - wiImageParams fx((float)wiRenderer::GetDevice()->GetScreenWidth(), (float)wiRenderer::GetDevice()->GetScreenHeight()); - fx.enableHDR(); + wiImageParams fx((float)wiRenderer::GetDevice()->GetScreenWidth(), (float)wiRenderer::GetDevice()->GetScreenHeight()); + fx.enableHDR(); - // Accumulate with moving averaged blending: - fx.opacity = 1.0f / (sam + 1.0f); - fx.blendFlag = BLENDMODE_ALPHA; + // Accumulate with moving averaged blending: + fx.opacity = 1.0f / (sam + 1.0f); + fx.blendFlag = BLENDMODE_ALPHA; - rtAccumulation.Set(threadID); - wiImage::Draw(traceResult.get(), fx, threadID); + rtAccumulation.Set(threadID); + wiImage::Draw(traceResult.get(), fx, threadID); - - wiProfiler::EndRange(threadID); // Traced Scene + wiProfiler::EndRange(threadID); // Traced Scene + } } void RenderPath3D_PathTracing::Compose() diff --git a/WickedEngine/ShaderInterop_TracedRendering.h b/WickedEngine/ShaderInterop_TracedRendering.h index 6bc381067..f569820f7 100644 --- a/WickedEngine/ShaderInterop_TracedRendering.h +++ b/WickedEngine/ShaderInterop_TracedRendering.h @@ -18,11 +18,11 @@ CBUFFER(TracedRenderingCB, CBSLOT_RENDERER_TRACED) struct TracedRenderingStoredRay { - uint pixelID; float3 origin; + uint pixelID; uint3 direction_energy; uint primitiveID; - float2 bary; + uint bary; }; struct TracedRenderingMaterial diff --git a/WickedEngine/WickedEngine_SHADERS.vcxproj b/WickedEngine/WickedEngine_SHADERS.vcxproj index 48ff97cdb..3aac676b4 100644 --- a/WickedEngine/WickedEngine_SHADERS.vcxproj +++ b/WickedEngine/WickedEngine_SHADERS.vcxproj @@ -677,6 +677,10 @@ Compute 5.0 + + Pixel + 5.0 + Compute 5.0 @@ -685,6 +689,10 @@ Compute 5.0 + + Vertex + 5.0 + Pixel diff --git a/WickedEngine/WickedEngine_SHADERS.vcxproj.filters b/WickedEngine/WickedEngine_SHADERS.vcxproj.filters index 9ab451eae..f16c8bc8c 100644 --- a/WickedEngine/WickedEngine_SHADERS.vcxproj.filters +++ b/WickedEngine/WickedEngine_SHADERS.vcxproj.filters @@ -861,6 +861,12 @@ PS + + PS + + + VS + diff --git a/WickedEngine/raySceneIntersectHF.hlsli b/WickedEngine/raySceneIntersectHF.hlsli index 42a883abc..b2a0b88fe 100644 --- a/WickedEngine/raySceneIntersectHF.hlsli +++ b/WickedEngine/raySceneIntersectHF.hlsli @@ -207,6 +207,74 @@ inline bool TraceSceneANY(Ray ray, float maxDistance) return shadow; } +// Returns number of BVH nodes that were hit: +// returns 0xFFFFFFFF when there was a stack overflow +// returns (0xFFFFFFFF - 1) when the exit condition was reached +inline uint TraceBVH(Ray ray) +{ + uint hit_counter = 0; + + // Emulated stack for tree traversal: + uint stack[RAYTRACE_STACKSIZE]; + uint stackpos = 0; + + const uint clusterCount = clusterCounterBuffer.Load(0); + const uint leafNodeOffset = clusterCount - 1; + + // push root node + stack[stackpos] = 0; + stackpos++; + + uint exit_condition = 0; + do { +#ifdef RAYTRACE_EXIT + if (exit_condition > RAYTRACE_EXIT) + return (0xFFFFFFFF - 1); + exit_condition++; +#endif // RAYTRACE_EXIT + + // pop untraversed node + stackpos--; + const uint nodeIndex = stack[stackpos]; + + BVHNode node = bvhNodeBuffer[nodeIndex]; + BVHAABB box = bvhAABBBuffer[nodeIndex]; + + if (IntersectBox(ray, box)) + { + hit_counter++; + + if (nodeIndex >= clusterCount - 1) + { + // Leaf node + } + else + { + // Internal node + if (stackpos < RAYTRACE_STACKSIZE - 1) + { + // push left child + stack[stackpos] = node.LeftChildIndex; + stackpos++; + // push right child + stack[stackpos] = node.RightChildIndex; + stackpos++; + } + else + { + // stack overflow, terminate + return 0xFFFFFFFF; + } + } + + } + + } while (stackpos > 0); + + + return hit_counter; +} + // This will modify ray to continue the trace // Also fill the final params of rayHit, such as normal, uv, materialIndex // seed should be > 0 diff --git a/WickedEngine/raytrace_debugbvhPS.hlsl b/WickedEngine/raytrace_debugbvhPS.hlsl new file mode 100644 index 000000000..16bae0d6c --- /dev/null +++ b/WickedEngine/raytrace_debugbvhPS.hlsl @@ -0,0 +1,39 @@ +#define RAYTRACE_EXIT 256 +#include "globals.hlsli" +#include "ShaderInterop_TracedRendering.h" +#include "ShaderInterop_BVH.h" +#include "tracedRenderingHF.hlsli" +#include "raySceneIntersectHF.hlsli" + +float4 main(float4 pos : SV_POSITION, float2 clipspace : TEXCOORD) : SV_Target +{ + Ray ray = CreateCameraRay(clipspace); + + uint hitCount = TraceBVH(ray); + + if (hitCount == 0xFFFFFFFF) + { + return float4(1, 0, 1, 1); // error: stack overflow (purple) + } + if (hitCount == (0xFFFFFFFF - 1)) + { + return float4(1, 1, 1, 1); // error: exit condition reached (white) + } + + const float3 mapTex[] = { + float3(0,0,0), + float3(0,0,1), + float3(0,1,1), + float3(0,1,0), + float3(1,1,0), + float3(1,0,0), + }; + const uint mapTexLen = 5; + const uint maxHeat = 100; + float l = saturate((float)hitCount / maxHeat) * mapTexLen; + float3 a = mapTex[floor(l)]; + float3 b = mapTex[ceil(l)]; + float4 heatmap = float4(lerp(a, b, l - floor(l)), 0.8f); + + return heatmap; +} \ No newline at end of file diff --git a/WickedEngine/raytrace_screenVS.hlsl b/WickedEngine/raytrace_screenVS.hlsl new file mode 100644 index 000000000..88e430d84 --- /dev/null +++ b/WickedEngine/raytrace_screenVS.hlsl @@ -0,0 +1,18 @@ +#include "fullScreenTriangleHF.hlsli" + +struct VSOut +{ + float4 pos : SV_POSITION; + float2 clipspace : TEXCOORD; +}; + +VSOut main(uint vI : SV_VERTEXID) +{ + VSOut Out; + + FullScreenTriangle(vI, Out.pos); + + Out.clipspace = Out.pos.xy; + + return Out; +} diff --git a/WickedEngine/tracedRenderingHF.hlsli b/WickedEngine/tracedRenderingHF.hlsli index f3975fab4..ee73e31ac 100644 --- a/WickedEngine/tracedRenderingHF.hlsli +++ b/WickedEngine/tracedRenderingHF.hlsli @@ -48,11 +48,11 @@ inline TracedRenderingStoredRay CreateStoredRay(in Ray ray, in uint pixelID) { TracedRenderingStoredRay storedray; - storedray.pixelID = pixelID; storedray.origin = ray.origin; + storedray.pixelID = pixelID; storedray.direction_energy = f32tof16(ray.direction) | (f32tof16(ray.energy) << 16); storedray.primitiveID = ray.primitiveID; - storedray.bary = ray.bary; + storedray.bary = f32tof16(ray.bary.x) | (f32tof16(ray.bary.y) << 16); return storedray; } @@ -64,7 +64,8 @@ inline void LoadRay(in TracedRenderingStoredRay storedray, out Ray ray, out uint ray.direction = asfloat(f16tof32(storedray.direction_energy)); ray.energy = asfloat(f16tof32(storedray.direction_energy >> 16)); ray.primitiveID = storedray.primitiveID; - ray.bary = storedray.bary; + ray.bary.x = f16tof32(storedray.bary); + ray.bary.y = f16tof32(storedray.bary >> 16); ray.Update(); } @@ -80,9 +81,9 @@ inline Ray CreateRay(float3 origin, float3 direction) return ray; } -inline Ray CreateCameraRay(float2 uv) +inline Ray CreateCameraRay(float2 clipspace) { - float4 unprojected = mul(float4(uv, 0.0f, 1.0f), g_xFrame_MainCamera_InvVP); + float4 unprojected = mul(float4(clipspace, 0.0f, 1.0f), g_xFrame_MainCamera_InvVP); unprojected.xyz /= unprojected.w; const float3 origin = g_xFrame_MainCamera_CamPos; diff --git a/WickedEngine/wiEnums.h b/WickedEngine/wiEnums.h index 2cdf93e49..723a4a24c 100644 --- a/WickedEngine/wiEnums.h +++ b/WickedEngine/wiEnums.h @@ -142,6 +142,7 @@ enum VSTYPES VSTYPE_FORCEFIELDVISUALIZER_POINT, VSTYPE_FORCEFIELDVISUALIZER_PLANE, VSTYPE_RENDERLIGHTMAP, + VSTYPE_RAYTRACE_SCREEN, VSTYPE_LAST }; // pixel shaders @@ -232,6 +233,7 @@ enum PSTYPES PSTYPE_FORCEFIELDVISUALIZER, PSTYPE_RENDERLIGHTMAP_INDIRECT, PSTYPE_RENDERLIGHTMAP_DIRECT, + PSTYPE_RAYTRACE_DEBUGBVH, PSTYPE_LAST }; // geometry shaders diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index 7b0d321c0..b53cd4beb 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -115,6 +115,7 @@ bool occlusionCulling = false; bool temporalAA = false; bool temporalAADEBUG = false; uint32_t lightmapBakeBounceCount = 4; +bool raytraceDebugVisualizer = false; struct VoxelizedSceneData { @@ -1136,6 +1137,7 @@ enum DEBUGRENDERING DEBUGRENDERING_VOXEL, DEBUGRENDERING_FORCEFIELD_POINT, DEBUGRENDERING_FORCEFIELD_PLANE, + DEBUGRENDERING_RAYTRACE_BVH, DEBUGRENDERING_COUNT }; GraphicsPSO* PSO_debug[DEBUGRENDERING_COUNT] = {}; @@ -1967,6 +1969,7 @@ void LoadShaders() vertexShaders[VSTYPE_VOXEL] = static_cast(wiResourceManager::GetShaderManager().add(SHADERPATH + "voxelVS.cso", wiResourceManager::VERTEXSHADER)); vertexShaders[VSTYPE_FORCEFIELDVISUALIZER_POINT] = static_cast(wiResourceManager::GetShaderManager().add(SHADERPATH + "forceFieldPointVisualizerVS.cso", wiResourceManager::VERTEXSHADER)); vertexShaders[VSTYPE_FORCEFIELDVISUALIZER_PLANE] = static_cast(wiResourceManager::GetShaderManager().add(SHADERPATH + "forceFieldPlaneVisualizerVS.cso", wiResourceManager::VERTEXSHADER)); + vertexShaders[VSTYPE_RAYTRACE_SCREEN] = static_cast(wiResourceManager::GetShaderManager().add(SHADERPATH + "raytrace_screenVS.cso", wiResourceManager::VERTEXSHADER)); pixelShaders[PSTYPE_OBJECT_DEFERRED] = static_cast(wiResourceManager::GetShaderManager().add(SHADERPATH + "objectPS_deferred.cso", wiResourceManager::PIXELSHADER)); @@ -2052,6 +2055,7 @@ void LoadShaders() pixelShaders[PSTYPE_FORCEFIELDVISUALIZER] = static_cast(wiResourceManager::GetShaderManager().add(SHADERPATH + "forceFieldVisualizerPS.cso", wiResourceManager::PIXELSHADER)); pixelShaders[PSTYPE_RENDERLIGHTMAP_INDIRECT] = static_cast(wiResourceManager::GetShaderManager().add(SHADERPATH + "renderlightmapPS_indirect.cso", wiResourceManager::PIXELSHADER)); pixelShaders[PSTYPE_RENDERLIGHTMAP_DIRECT] = static_cast(wiResourceManager::GetShaderManager().add(SHADERPATH + "renderlightmapPS_direct.cso", wiResourceManager::PIXELSHADER)); + pixelShaders[PSTYPE_RAYTRACE_DEBUGBVH] = static_cast(wiResourceManager::GetShaderManager().add(SHADERPATH + "raytrace_debugbvhPS.cso", wiResourceManager::PIXELSHADER)); geometryShaders[GSTYPE_ENVMAP] = static_cast(wiResourceManager::GetShaderManager().add(SHADERPATH + "envMapGS.cso", wiResourceManager::GEOMETRYSHADER)); geometryShaders[GSTYPE_ENVMAP_SKY] = static_cast(wiResourceManager::GetShaderManager().add(SHADERPATH + "envMap_skyGS.cso", wiResourceManager::GEOMETRYSHADER)); @@ -2743,6 +2747,10 @@ void LoadShaders() { GraphicsPSODesc desc; + desc.numRTs = 1; + desc.RTFormats[0] = RTFormat_hdr; + desc.DSFormat = DSFormat_full; + switch (debug) { case DEBUGRENDERING_ENVPROBE: @@ -2814,12 +2822,17 @@ void LoadShaders() desc.bs = blendStates[BSTYPE_TRANSPARENT]; desc.pt = TRIANGLESTRIP; break; + case DEBUGRENDERING_RAYTRACE_BVH: + desc.vs = vertexShaders[VSTYPE_RAYTRACE_SCREEN]; + desc.ps = pixelShaders[PSTYPE_RAYTRACE_DEBUGBVH]; + desc.dss = depthStencils[DSSTYPE_XRAY]; + desc.rs = rasterizers[RSTYPE_DOUBLESIDED]; + desc.bs = blendStates[BSTYPE_TRANSPARENT]; + desc.pt = TRIANGLELIST; + desc.DSFormat = FORMAT_UNKNOWN; + break; } - desc.numRTs = 1; - desc.RTFormats[0] = RTFormat_hdr; - desc.DSFormat = DSFormat_full; - RECREATE(PSO_debug[debug]); HRESULT hr = device->CreateGraphicsPSO(&desc, PSO_debug[debug]); assert(SUCCEEDED(hr)); @@ -5785,6 +5798,11 @@ void DrawDebugWorld(const CameraComponent& camera, GRAPHICSTHREAD threadID) device->EventEnd(threadID); } + if (GetRaytraceDebugBVHVisualizerEnabled()) + { + DrawTracedSceneBVH(threadID); + } + device->EventEnd(threadID); } @@ -7501,6 +7519,16 @@ void DrawTracedScene(const CameraComponent& camera, Texture2D* result, GRAPHICST device->EventEnd(threadID); // DrawTracedScene } +void DrawTracedSceneBVH(GRAPHICSTHREAD threadID) +{ + GraphicsDevice* device = GetDevice(); + + device->EventBegin("DebugRaytraceBVH", threadID); + device->BindGraphicsPSO(PSO_debug[DEBUGRENDERING_RAYTRACE_BVH], threadID); + sceneBVH.Bind(PS, threadID); + device->Draw(3, 0, threadID); + device->EventEnd(threadID); +} void GenerateClouds(Texture2D* dst, UINT refinementCount, float randomness, GRAPHICSTHREAD threadID) { @@ -8618,5 +8646,13 @@ uint32_t GetLightmapBakeBounceCount() { return lightmapBakeBounceCount; } +void SetRaytraceDebugBVHVisualizerEnabled(bool value) +{ + raytraceDebugVisualizer = value; +} +bool GetRaytraceDebugBVHVisualizerEnabled() +{ + return raytraceDebugVisualizer; +} } diff --git a/WickedEngine/wiRenderer.h b/WickedEngine/wiRenderer.h index 6fc542fc2..c14e931d2 100644 --- a/WickedEngine/wiRenderer.h +++ b/WickedEngine/wiRenderer.h @@ -136,6 +136,8 @@ namespace wiRenderer void BuildSceneBVH(GRAPHICSTHREAD threadID); // Render the scene with ray tracing only void DrawTracedScene(const wiSceneSystem::CameraComponent& camera, wiGraphicsTypes::Texture2D* result, GRAPHICSTHREAD threadID); + // Render the scene BVH with ray tracing + void DrawTracedSceneBVH(GRAPHICSTHREAD threadID); // Render occluders against a depth buffer void OcclusionCulling_Render(GRAPHICSTHREAD threadID); @@ -267,6 +269,8 @@ namespace wiRenderer void InvalidateBVH(); // invalidates scene bvh so if something wants to use it, it will recompute and validate it void SetLightmapBakeBounceCount(uint32_t bounces); uint32_t GetLightmapBakeBounceCount(); + void SetRaytraceDebugBVHVisualizerEnabled(bool value); + bool GetRaytraceDebugBVHVisualizerEnabled(); wiGraphicsTypes::Texture2D* GetGlobalLightmap(); diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 0fa1fabc8..286770480 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wiVersion // minor features, major updates const int minor = 24; // minor bug fixes, alterations, refactors, updates - const int revision = 41; + const int revision = 42; long GetVersion()