From 3a700be6914dfc3fc9d1496ca430b678ce888b7c Mon Sep 17 00:00:00 2001 From: Stanislav Denisov Date: Tue, 4 Nov 2025 14:31:53 +0100 Subject: [PATCH] Implement wireframe overlay (#1282) --- Editor/Editor.cpp | 19 ++++- Editor/GeneralWindow.cpp | 21 +++-- Editor/GeneralWindow.h | 2 +- WickedEngine/shaders/ShaderInterop_Renderer.h | 1 + WickedEngine/shaders/lightingHF.hlsli | 2 +- WickedEngine/wiRenderPath3D.cpp | 19 ++--- WickedEngine/wiRenderer.cpp | 82 ++++++++++++++----- WickedEngine/wiRenderer.h | 15 ++++ 8 files changed, 116 insertions(+), 45 deletions(-) diff --git a/Editor/Editor.cpp b/Editor/Editor.cpp index eeba2a278..0484e5b9a 100644 --- a/Editor/Editor.cpp +++ b/Editor/Editor.cpp @@ -2453,8 +2453,23 @@ void EditorComponent::Update(float dt) // Toggle wireframe mode if (CheckInput(EditorActions::WIREFRAME_MODE)) { - wi::renderer::SetWireRender(!wi::renderer::IsWireRender()); - generalWnd.wireFrameCheckBox.SetCheck(wi::renderer::IsWireRender()); + wi::renderer::WIREFRAME_MODE currentMode = wi::renderer::GetWireframeMode(); + wi::renderer::WIREFRAME_MODE mode; + switch (currentMode) + { + case wi::renderer::WIREFRAME_DISABLED: + mode = wi::renderer::WIREFRAME_ONLY; + break; + case wi::renderer::WIREFRAME_ONLY: + mode = wi::renderer::WIREFRAME_OVERLAY; + break; + case wi::renderer::WIREFRAME_OVERLAY: + default: + mode = wi::renderer::WIREFRAME_DISABLED; + break; + } + wi::renderer::SetWireframeMode(mode); + generalWnd.wireFrameComboBox.SetSelected((int)mode); } // Enable transform tool diff --git a/Editor/GeneralWindow.cpp b/Editor/GeneralWindow.cpp index 871ee898b..944fd7747 100644 --- a/Editor/GeneralWindow.cpp +++ b/Editor/GeneralWindow.cpp @@ -63,14 +63,6 @@ void GeneralWindow::Create(EditorComponent* _editor) nameDebugCheckBox.SetTooltip("Visualize the entity names in the scene"); AddWidget(&nameDebugCheckBox); - wireFrameCheckBox.Create("Render Wireframe: "); - wireFrameCheckBox.SetTooltip("Visualize the scene as a wireframe"); - wireFrameCheckBox.OnClick([](wi::gui::EventArgs args) { - wi::renderer::SetWireRender(args.bValue); - }); - wireFrameCheckBox.SetCheck(wi::renderer::IsWireRender()); - AddWidget(&wireFrameCheckBox); - aabbDebugCheckBox.Create("AABB visualizer: "); aabbDebugCheckBox.SetTooltip("Visualize the scene bounding boxes"); aabbDebugCheckBox.SetScriptTip("SetDebugPartitionTreeEnabled(bool enabled)"); @@ -389,6 +381,17 @@ void GeneralWindow::Create(EditorComponent* _editor) }); AddWidget(&localizationButton); + wireFrameComboBox.Create("Render wireframe: "); + wireFrameComboBox.SetTooltip("Choose wireframe rendering mode:\nDisabled: Normal rendering\nWireframe Only: Replace geometry with wireframe\nWireframe Overlay: Show wireframe on top of geometry"); + wireFrameComboBox.AddItem("Disabled", wi::renderer::WIREFRAME_DISABLED); + wireFrameComboBox.AddItem("Wireframe Only", wi::renderer::WIREFRAME_ONLY); + wireFrameComboBox.AddItem("Wireframe Overlay", wi::renderer::WIREFRAME_OVERLAY); + wireFrameComboBox.OnSelect([](wi::gui::EventArgs args) { + wi::renderer::SetWireframeMode((wi::renderer::WIREFRAME_MODE)args.iValue); + }); + wireFrameComboBox.SetSelected((int)wi::renderer::GetWireframeMode()); + AddWidget(&wireFrameComboBox); + languageCombo.Create("Language: "); languageCombo.SetLocalizationEnabled(wi::gui::LocalizationEnabled::Text | wi::gui::LocalizationEnabled::Tooltip); languageCombo.SetTooltip("Select a language. \nYou can also create a new language option by adding an XML file to the languages folder.\nThere is a button below that you can use to create a language template."); @@ -1494,9 +1497,9 @@ void GeneralWindow::ResizeLayout() layout.add_fullwidth(localizationButton); + layout.add(wireFrameComboBox); layout.add_right(physicsDebugCheckBox); layout.add_right(nameDebugCheckBox); - layout.add_right(wireFrameCheckBox); layout.add_right(gridHelperCheckBox); layout.add_right(aabbDebugCheckBox); layout.add_right(boneLinesCheckBox); diff --git a/Editor/GeneralWindow.h b/Editor/GeneralWindow.h index 16e847eb2..0a9ffa916 100644 --- a/Editor/GeneralWindow.h +++ b/Editor/GeneralWindow.h @@ -26,7 +26,7 @@ public: wi::gui::CheckBox debugEmittersCheckBox; wi::gui::CheckBox debugForceFieldsCheckBox; wi::gui::CheckBox debugRaytraceBVHCheckBox; - wi::gui::CheckBox wireFrameCheckBox; + wi::gui::ComboBox wireFrameComboBox; wi::gui::CheckBox envProbesCheckBox; wi::gui::CheckBox cameraVisCheckBox; wi::gui::CheckBox colliderVisCheckBox; diff --git a/WickedEngine/shaders/ShaderInterop_Renderer.h b/WickedEngine/shaders/ShaderInterop_Renderer.h index 00232c35a..1306114b2 100644 --- a/WickedEngine/shaders/ShaderInterop_Renderer.h +++ b/WickedEngine/shaders/ShaderInterop_Renderer.h @@ -1239,6 +1239,7 @@ enum FRAME_OPTIONS OPTION_BIT_REALISTIC_SKY_RECEIVE_SHADOW = 1 << 18, OPTION_BIT_VOLUMETRICCLOUDS_RECEIVE_SHADOW = 1 << 19, OPTION_BIT_CAPSULE_SHADOW_ENABLED = 1 << 20, + OPTION_BIT_DISABLE_SHADOWMAPS = 1 << 21, }; // ---------- Common Constant buffers: ----------------- diff --git a/WickedEngine/shaders/lightingHF.hlsli b/WickedEngine/shaders/lightingHF.hlsli index 40add2968..e52a0dd39 100644 --- a/WickedEngine/shaders/lightingHF.hlsli +++ b/WickedEngine/shaders/lightingHF.hlsli @@ -65,7 +65,7 @@ inline void light_directional(in ShaderEntity light, in Surface surface, inout L half3 light_color = light.GetColor().rgb * shadow_mask; [branch] - if (light.IsCastingShadow() && surface.IsReceiveShadow()) + if (light.IsCastingShadow() && surface.IsReceiveShadow() && (GetFrame().options & OPTION_BIT_DISABLE_SHADOWMAPS) == 0) { if (GetFrame().options & OPTION_BIT_VOLUMETRICCLOUDS_CAST_SHADOW) { diff --git a/WickedEngine/wiRenderPath3D.cpp b/WickedEngine/wiRenderPath3D.cpp index 6434a31a2..5eb37da4f 100644 --- a/WickedEngine/wiRenderPath3D.cpp +++ b/WickedEngine/wiRenderPath3D.cpp @@ -413,7 +413,7 @@ namespace wi { camera->jitter = fsr2Resources.GetJitter(); } - else if (wi::renderer::GetTemporalAAEnabled()) + else if (wi::renderer::GetTemporalAAEnabled() && wi::renderer::GetWireframeMode() == wi::renderer::WIREFRAME_DISABLED) { const XMFLOAT4& halton = wi::math::GetHaltonSequence(wi::graphics::GetDevice()->GetFrameCount() % 256); camera->jitter.x = (halton.x * 2 - 1) / (float)internalResolution.x; @@ -1144,7 +1144,7 @@ namespace wi ); } - if (wi::renderer::GetRaytracedShadowsEnabled()) + if (wi::renderer::GetRaytracedShadowsEnabled() && wi::renderer::GetWireframeMode() == wi::renderer::WIREFRAME_DISABLED) { wi::renderer::Postprocess_RTShadow( rtshadowResources, @@ -1155,7 +1155,6 @@ namespace wi cmd ); } - if (scene->weather.IsVolumetricClouds() && !scene->weather.IsVolumetricCloudsReceiveShadow()) { // When volumetric cloud DOESN'T receive shadow it can be done async to shadow maps! @@ -1165,12 +1164,11 @@ namespace wi *camera, camera_previous, camera_reflection, - wi::renderer::GetTemporalAAEnabled() || getFSR2Enabled(), + (wi::renderer::GetTemporalAAEnabled() && wi::renderer::GetWireframeMode() == wi::renderer::WIREFRAME_DISABLED) || getFSR2Enabled(), scene->weather.volumetricCloudsWeatherMapFirst.IsValid() ? &scene->weather.volumetricCloudsWeatherMapFirst.GetTexture() : nullptr, scene->weather.volumetricCloudsWeatherMapSecond.IsValid() ? &scene->weather.volumetricCloudsWeatherMapSecond.GetTexture() : nullptr ); } - if (getMeshBlendEnabled() && visibility_main.IsMeshBlendVisible()) { wi::renderer::PostProcess_MeshBlend_EdgeProcess(meshblendResources, cmd); @@ -1369,12 +1367,11 @@ namespace wi camera_reflection, camera_reflection_previous, camera_reflection, - wi::renderer::GetTemporalAAEnabled() || getFSR2Enabled(), + (wi::renderer::GetTemporalAAEnabled() && wi::renderer::GetWireframeMode() == wi::renderer::WIREFRAME_DISABLED) || getFSR2Enabled(), scene->weather.volumetricCloudsWeatherMapFirst.IsValid() ? &scene->weather.volumetricCloudsWeatherMapFirst.GetTexture() : nullptr, scene->weather.volumetricCloudsWeatherMapSecond.IsValid() ? &scene->weather.volumetricCloudsWeatherMapSecond.GetTexture() : nullptr ); } - device->EventBegin("Planar reflections", cmd); auto range = wi::profiler::BeginRangeGPU("Planar Reflections", cmd); @@ -1487,12 +1484,11 @@ namespace wi *camera, camera_previous, camera_reflection, - wi::renderer::GetTemporalAAEnabled() || getFSR2Enabled(), + (wi::renderer::GetTemporalAAEnabled() && wi::renderer::GetWireframeMode() == wi::renderer::WIREFRAME_DISABLED) || getFSR2Enabled(), scene->weather.volumetricCloudsWeatherMapFirst.IsValid() ? &scene->weather.volumetricCloudsWeatherMapFirst.GetTexture() : nullptr, scene->weather.volumetricCloudsWeatherMapSecond.IsValid() ? &scene->weather.volumetricCloudsWeatherMapSecond.GetTexture() : nullptr ); } - if (getRaytracedReflectionEnabled()) { wi::renderer::Postprocess_RTReflection( @@ -2245,6 +2241,8 @@ namespace wi wi::renderer::DrawDebugWorld(*scene, *camera, *this, cmd); + wi::renderer::DrawWireframeOverlay(visibility_main, wi::enums::RENDERPASS_MAIN, cmd); + wi::renderer::DrawLightVisualizers(visibility_main, cmd); wi::renderer::DrawSoftParticles(visibility_main, false, cmd); @@ -2364,7 +2362,7 @@ namespace wi rt_read = &rtFSR[0]; rt_write = &rtFSR[1]; } - else if (wi::renderer::GetTemporalAAEnabled() && !wi::renderer::GetTemporalAADebugEnabled() && temporalAAResources.IsValid()) + else if (wi::renderer::GetTemporalAAEnabled() && !wi::renderer::GetTemporalAADebugEnabled() && temporalAAResources.IsValid() && wi::renderer::GetWireframeMode() == wi::renderer::WIREFRAME_DISABLED) { wi::renderer::Postprocess_TemporalAA( temporalAAResources, @@ -2373,7 +2371,6 @@ namespace wi ); rt_first = temporalAAResources.GetCurrent(); } - if (scene->weather.IsOceanEnabled()) { wi::renderer::Postprocess_Underwater( diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index f9372eb87..e8b3d08a4 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -104,6 +104,7 @@ void PushBarrier(const GPUBarrier& barrier) barrier_stack.push_back(barrier); } +WIREFRAME_MODE wireframeMode = WIREFRAME_DISABLED; bool wireRender = false; bool debugBoneLines = false; bool debugPartitionTree = false; @@ -944,7 +945,7 @@ void LoadShaders() wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { LoadShader(ShaderStage::PS, shaders[PSTYPE_VOXELIZER], "objectPS_voxelizer.cso"); }); wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { LoadShader(ShaderStage::PS, shaders[PSTYPE_VOXEL], "voxelPS.cso"); }); wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { LoadShader(ShaderStage::PS, shaders[PSTYPE_FORCEFIELDVISUALIZER], "forceFieldVisualizerPS.cso"); }); - + wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { LoadShader(ShaderStage::PS, shaders[PSTYPE_RAYTRACE_DEBUGBVH], "raytrace_debugbvhPS.cso"); }); wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { LoadShader(ShaderStage::PS, shaders[PSTYPE_DOWNSAMPLEDEPTHBUFFER], "downsampleDepthBuffer4xPS.cso"); }); wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { LoadShader(ShaderStage::PS, shaders[PSTYPE_POSTPROCESS_UPSAMPLE_BILATERAL], "upsample_bilateralPS.cso"); }); @@ -996,7 +997,7 @@ void LoadShaders() wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { LoadShader(ShaderStage::CS, shaders[CSTYPE_COPYTEXTURE2D_FLOAT4], "copytexture2D_float4CS.cso"); }); wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { LoadShader(ShaderStage::CS, shaders[CSTYPE_COPYTEXTURE2D_FLOAT4_BORDEREXPAND], "copytexture2D_float4_borderexpandCS.cso"); }); wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { LoadShader(ShaderStage::CS, shaders[CSTYPE_SKINNING], "skinningCS.cso"); }); - + wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { LoadShader(ShaderStage::CS, shaders[CSTYPE_PAINT_TEXTURE], "paint_textureCS.cso"); }); wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { LoadShader(ShaderStage::CS, shaders[CSTYPE_POSTPROCESS_BLUR_GAUSSIAN_FLOAT1], "blur_gaussian_float1CS.cso"); }); @@ -2868,7 +2869,7 @@ struct SHCAM const XMMATRIX P = XMMatrixPerspectiveFovLH(fov, aspect, farPlane, nearPlane); view_projection = XMMatrixMultiply(V, P); frustum.Create(view_projection); - + BoundingFrustum::CreateFromMatrix(boundingfrustum, P); std::swap(boundingfrustum.Near, boundingfrustum.Far); boundingfrustum.Transform(boundingfrustum, XMMatrixInverse(nullptr, V)); @@ -3134,7 +3135,8 @@ void RenderMeshes( device->CheckCapability(GraphicsDeviceCapability::TESSELLATION) ; const bool skip_planareflection_objects = flags & DRAWSCENE_SKIP_PLANAR_REFLECTION_OBJECTS; - + const bool wireframe_overlay = flags & DRAWSCENE_WIREFRAME_OVERLAY; + // Do we need to compute a light mask for this pass on the CPU? const bool forwardLightmaskRequest = renderPass == RENDERPASS_ENVMAPCAPTURE || @@ -3184,7 +3186,7 @@ void RenderMeshes( const float tessF = mesh.GetTessellationFactor(); const bool tessellatorRequested = tessF > 0 && tessellation; const bool meshShaderRequested = !tessellatorRequested && mesh_shader && mesh.vb_clu.IsValid(); - const bool wireframe = IsWireRender(); + const bool wireframe = wireframe_overlay || (IsWireRender() && GetWireframeMode() != WIREFRAME_OVERLAY); // Notes on provoking index buffer: // Normally it's used for primitiveID generation, so it would be only used in PREPASS @@ -3264,6 +3266,7 @@ void RenderMeshes( { pso = tessellatorRequested ? &PSO_object_wire_tessellation : &PSO_object_wire; } + break; default: break; } @@ -3327,7 +3330,7 @@ void RenderMeshes( renderPass != RENDERPASS_PREPASS && renderPass != RENDERPASS_PREPASS_DEPTHONLY && renderPass != RENDERPASS_VOXELIZE - ) + ) { // depth only alpha test will be full res device->BindShadingRate(material.shadingRate, cmd); @@ -3460,7 +3463,7 @@ void RenderMeshes( void RenderImpostors( const Visibility& vis, - RENDERPASS renderPass, + RENDERPASS renderPass, CommandList cmd ) { @@ -3597,7 +3600,7 @@ void UpdateVisibility(Visibility& vis) assert(vis.scene != nullptr); // User must provide a scene! assert(vis.camera != nullptr); // User must provide a camera! - // The parallel frustum culling is first performed in shared memory, + // The parallel frustum culling is first performed in shared memory, // then each group writes out it's local list to global memory // The shared memory approach reduces atomics and helps the list to remain // more coherent (less randomly organized compared to original order) @@ -4277,12 +4280,12 @@ void UpdatePerFrameData( { frameCB.options |= OPTION_BIT_HEIGHT_FOG; } - if (device->CheckCapability(GraphicsDeviceCapability::RAYTRACING) && GetRaytracedShadowsEnabled()) + if (device->CheckCapability(GraphicsDeviceCapability::RAYTRACING) && GetRaytracedShadowsEnabled() && !IsWireRender()) { frameCB.options |= OPTION_BIT_RAYTRACED_SHADOWS; frameCB.options |= OPTION_BIT_SHADOW_MASK; } - if (GetScreenSpaceShadowsEnabled()) + if (GetScreenSpaceShadowsEnabled() && !IsWireRender()) { frameCB.options |= OPTION_BIT_SHADOW_MASK; } @@ -4294,6 +4297,10 @@ void UpdatePerFrameData( { frameCB.options |= OPTION_BIT_DISABLE_ALBEDO_MAPS; } + if (IsWireRender()) + { + frameCB.options |= OPTION_BIT_DISABLE_SHADOWMAPS; + } if (IsForceDiffuseLighting()) { frameCB.options |= OPTION_BIT_FORCE_DIFFUSE_LIGHTING; @@ -5935,7 +5942,7 @@ void DrawWaterRipples(const Visibility& vis, CommandList cmd) void DrawSoftParticles( const Visibility& vis, - bool distortion, + bool distortion, CommandList cmd ) { @@ -8561,6 +8568,33 @@ void DrawDebugWorld( } +void DrawWireframeOverlay( + const Visibility& vis, + RENDERPASS renderPass, + CommandList cmd +) +{ + if (GetWireframeMode() != WIREFRAME_OVERLAY || renderPass == RENDERPASS_ENVMAPCAPTURE) + return; + + if (renderPass != RENDERPASS_MAIN) + return; // Only render wireframe overlay for main pass + + if (vis.visibleObjects.empty()) + return; + + // Draw the scene again with wireframe PSOs to create an overlay effect + DrawScene( + vis, + renderPass, + cmd, + DRAWSCENE_OPAQUE | + DRAWSCENE_WIREFRAME_OVERLAY | + DRAWSCENE_TESSELLATION + ); +} + + void ComputeVolumetricCloudShadows( CommandList cmd, const Texture* weatherMapFirst, @@ -8825,7 +8859,7 @@ void ComputeSkyAtmosphereCameraVolumeLut(CommandList cmd) device->EventBegin("ComputeSkyAtmosphereCameraVolumeLut", cmd); BindCommonResources(cmd); - + // Camera Volume Lut pass: { device->EventBegin("CameraVolumeLut", cmd); @@ -8873,7 +8907,7 @@ void ComputeSkyAtmosphereCameraVolumeLut(CommandList cmd) void DrawSky(const Scene& scene, CommandList cmd) { device->EventBegin("DrawSky", cmd); - + if (scene.weather.skyMap.IsValid()) { device->BindPipelineState(&PSO_sky[SKYRENDERING_STATIC], cmd); @@ -9360,7 +9394,7 @@ void RefreshEnvProbes(const Visibility& vis, CommandList cmd) } device->PushConstants(&push, sizeof(push), cmd); - + { GPUBarrier barriers[] = { GPUBarrier::Image(&envrenderingColorBuffer, ResourceState::SHADER_RESOURCE, ResourceState::UNORDERED_ACCESS), @@ -10641,7 +10675,7 @@ void CopyTexture2D(const Texture& dst, int DstMIP, int DstX, int DstY, const Tex void RayTraceScene( const Scene& scene, const Texture& output, - int accumulation_sample, + int accumulation_sample, CommandList cmd, const Texture* output_albedo, const Texture* output_normal, @@ -12366,7 +12400,7 @@ void Postprocess_Blur_Gaussian( device->ClearUAV(&temp, 0, cmd); device->Barrier(GPUBarrier::Memory(&temp), cmd); } - + // Horizontal: { const TextureDesc& desc = temp.GetDesc(); @@ -13001,7 +13035,7 @@ void Postprocess_MSAO( const float Accentuation = 0.1f; // The msao_compute will be called repeatedly, so create a local lambda for it: - auto msao_compute = [&](const Texture& write_result, const Texture& read_depth) + auto msao_compute = [&](const Texture& write_result, const Texture& read_depth) { const TextureDesc& desc = read_depth.GetDesc(); @@ -13202,7 +13236,7 @@ void Postprocess_MSAO( msao_upsample.NoiseFilterStrength = 1.0f / (powf(10.0f, g_NoiseFilterTolerance) + msao_upsample.kUpsampleTolerance); msao_upsample.StepSize = (float)lineardepth.GetDesc().width / (float)LoWidth; device->PushConstants(&msao_upsample, sizeof(msao_upsample), cmd); - + device->BindUAV(&Destination, 0, cmd); device->BindResource(&LoResDepth, 0, cmd); device->BindResource(&HiResDepth, 1, cmd); @@ -16542,7 +16576,7 @@ void Postprocess_VolumetricClouds( PostProcess postprocess; - // Render quarter-res: + // Render quarter-res: postprocess.resolution.x = res.final_resolution.x / 4; postprocess.resolution.y = res.final_resolution.y / 4; postprocess.resolution_rcp.x = 1.0f / postprocess.resolution.x; @@ -16612,7 +16646,7 @@ void Postprocess_VolumetricClouds( postprocess.resolution.y = res.final_resolution.y / 2; postprocess.resolution_rcp.x = 1.0f / postprocess.resolution.x; postprocess.resolution_rcp.y = 1.0f / postprocess.resolution.y; - + int temporal_output = res.GetTemporalOutputIndex(); int temporal_history = res.GetTemporalInputIndex(); @@ -16780,6 +16814,8 @@ void Postprocess_TemporalAA( CommandList cmd ) { + if (IsWireRender()) + return; device->EventBegin("Postprocess_TemporalAA", cmd); auto range = wi::profiler::BeginRangeGPU("Temporal AA Resolve", cmd); const bool first_frame = res.frame == 0; @@ -18950,8 +18986,12 @@ void AddDeferredBlockCompression(const wi::graphics::Texture& texture_src, const -void SetWireRender(bool value) { wireRender = value; } +void SetWireframeMode(WIREFRAME_MODE mode) { + wireframeMode = mode; + wireRender = (mode != WIREFRAME_DISABLED); +} bool IsWireRender() { return wireRender; } +WIREFRAME_MODE GetWireframeMode() { return wireframeMode; } void SetToDrawDebugBoneLines(bool param) { debugBoneLines = param; } bool GetToDrawDebugBoneLines() { return debugBoneLines; } void SetToDrawDebugPartitionTree(bool param) { debugPartitionTree = param; } diff --git a/WickedEngine/wiRenderer.h b/WickedEngine/wiRenderer.h index 623cb0a77..117944925 100644 --- a/WickedEngine/wiRenderer.h +++ b/WickedEngine/wiRenderer.h @@ -271,6 +271,7 @@ namespace wi::renderer DRAWSCENE_SKIP_PLANAR_REFLECTION_OBJECTS = 1 << 7, // don't draw subsets which have planar reflection material DRAWSCENE_FOREGROUND_ONLY = 1 << 8, // only include objects that are tagged as foreground DRAWSCENE_MAINCAMERA = 1 << 9, // If this is active, then ObjectComponent with SetNotVisibleInMainCamera(true) won't be drawn + DRAWSCENE_WIREFRAME_OVERLAY = 1 << 10, // draw wireframe overlay }; // Draw the world from a camera. You must call BindCameraCB() at least once in this command list prior to this @@ -314,6 +315,12 @@ namespace wi::renderer const wi::Canvas& canvas, wi::graphics::CommandList cmd ); + // Draw wireframe overlay on top of scene geometry when wireframe mode is enabled + void DrawWireframeOverlay( + const Visibility& vis, + wi::enums::RENDERPASS renderPass, + wi::graphics::CommandList cmd + ); // Draw Soft offscreen particles. void DrawSoftParticles( const Visibility& vis, @@ -1121,9 +1128,17 @@ namespace wi::renderer void SetShadowProps2D(int max_resolution); void SetShadowPropsCube(int max_resolution); + enum WIREFRAME_MODE + { + WIREFRAME_DISABLED = 0, + WIREFRAME_ONLY = 1, + WIREFRAME_OVERLAY = 2, + }; void SetWireRender(bool value); bool IsWireRender(); + void SetWireframeMode(WIREFRAME_MODE mode); + WIREFRAME_MODE GetWireframeMode(); void SetToDrawDebugBoneLines(bool param); bool GetToDrawDebugBoneLines(); void SetToDrawDebugPartitionTree(bool param);