diff --git a/Editor/ObjectWindow.cpp b/Editor/ObjectWindow.cpp index 2fc228cdc..21bdc381b 100644 --- a/Editor/ObjectWindow.cpp +++ b/Editor/ObjectWindow.cpp @@ -257,7 +257,7 @@ void ObjectWindow::Create(EditorComponent* _editor) editor = _editor; wi::gui::Window::Create(ICON_OBJECT " Object", wi::gui::Window::WindowControls::COLLAPSE | wi::gui::Window::WindowControls::CLOSE); - SetSize(XMFLOAT2(670, 700)); + SetSize(XMFLOAT2(670, 730)); closeButton.SetTooltip("Delete ObjectComponent"); OnClose([=](wi::gui::EventArgs args) { @@ -364,6 +364,24 @@ void ObjectWindow::Create(EditorComponent* _editor) }); AddWidget(&navmeshCheckBox); + foregroundCheckBox.Create("Foreground: "); + foregroundCheckBox.SetTooltip("Set object to be rendered in the foreground. This is useful for first person hands or weapons."); + foregroundCheckBox.SetSize(XMFLOAT2(hei, hei)); + foregroundCheckBox.SetPos(XMFLOAT2(x, y += step)); + foregroundCheckBox.SetCheck(true); + foregroundCheckBox.OnClick([&](wi::gui::EventArgs args) { + wi::scene::Scene& scene = editor->GetCurrentScene(); + for (auto& x : editor->translator.selected) + { + ObjectComponent* object = scene.objects.GetComponent(x.entity); + if (object != nullptr) + { + object->SetForeground(args.bValue); + } + } + }); + AddWidget(&foregroundCheckBox); + ditherSlider.Create(0, 1, 0, 1000, "Transparency: "); ditherSlider.SetTooltip("Adjust transparency of the object. Opaque materials will use dithered transparency in this case!"); ditherSlider.SetSize(XMFLOAT2(wid, hei)); @@ -672,6 +690,7 @@ void ObjectWindow::SetEntity(Entity entity) renderableCheckBox.SetCheck(object->IsRenderable()); shadowCheckBox.SetCheck(object->IsCastingShadow()); + foregroundCheckBox.SetCheck(object->IsForeground()); navmeshCheckBox.SetCheck(object->filterMask & wi::enums::FILTER_NAVIGATION_MESH); cascadeMaskSlider.SetValue((float)object->cascadeMask); ditherSlider.SetValue(object->GetTransparency()); @@ -747,6 +766,7 @@ void ObjectWindow::ResizeLayout() add_right(renderableCheckBox); add_right(shadowCheckBox); + add_right(foregroundCheckBox); add_right(navmeshCheckBox); add(ditherSlider); add(cascadeMaskSlider); diff --git a/Editor/ObjectWindow.h b/Editor/ObjectWindow.h index cffc673e2..8a50b81f6 100644 --- a/Editor/ObjectWindow.h +++ b/Editor/ObjectWindow.h @@ -14,6 +14,7 @@ public: wi::gui::CheckBox renderableCheckBox; wi::gui::CheckBox shadowCheckBox; wi::gui::CheckBox navmeshCheckBox; + wi::gui::CheckBox foregroundCheckBox; wi::gui::Slider ditherSlider; wi::gui::Slider cascadeMaskSlider; wi::gui::Slider lodSlider; diff --git a/WickedEngine/shaders/objectHF.hlsli b/WickedEngine/shaders/objectHF.hlsli index d10c0a9b0..2f072eb55 100644 --- a/WickedEngine/shaders/objectHF.hlsli +++ b/WickedEngine/shaders/objectHF.hlsli @@ -5,21 +5,21 @@ #define TRANSPARENT_SHADOWMAP_SECONDARY_DEPTH_CHECK #else #define SHADOW_MASK_ENABLED -#endif +#endif // TRANSPARENT #if !defined(TRANSPARENT) && !defined(PREPASS) #define DISABLE_ALPHATEST -#endif +#endif // !defined(TRANSPARENT) && !defined(PREPASS) #ifdef PLANARREFLECTION #define DISABLE_ENVMAPS #define DISABLE_VOXELGI -#endif +#endif // PLANARREFLECTION #ifdef WATER #define DISABLE_ENVMAPS #define DISABLE_VOXELGI -#endif +#endif // WATER #define LIGHTMAP_QUALITY_BICUBIC diff --git a/WickedEngine/shaders/visibility_shadeCS.hlsl b/WickedEngine/shaders/visibility_shadeCS.hlsl index 353b23434..97e296992 100644 --- a/WickedEngine/shaders/visibility_shadeCS.hlsl +++ b/WickedEngine/shaders/visibility_shadeCS.hlsl @@ -5,6 +5,12 @@ //#define DISABLE_ENVMAPS //#define DISABLE_SOFT_SHADOWMAP //#define DISABLE_TRANSPARENT_SHADOWMAP + +#ifdef PLANARREFLECTION +#define DISABLE_ENVMAPS +#define DISABLE_VOXELGI +#endif // PLANARREFLECTION + #include "globals.hlsli" #include "ShaderInterop_Renderer.h" #include "raytracingHF.hlsli" diff --git a/WickedEngine/wiRenderPath3D.cpp b/WickedEngine/wiRenderPath3D.cpp index 9e47f8cf7..7ce47612a 100644 --- a/WickedEngine/wiRenderPath3D.cpp +++ b/WickedEngine/wiRenderPath3D.cpp @@ -10,6 +10,7 @@ using namespace wi::enums; namespace wi { + static constexpr float foreground_depth_range = 0.01f; void RenderPath3D::DeleteGPUResources() { @@ -832,15 +833,35 @@ namespace wi device->EventBegin("Opaque Z-prepass", cmd); auto range = wi::profiler::BeginRangeGPU("Z-Prepass", cmd); - Viewport vp; - vp.width = (float)depthBuffer_Main.GetDesc().width; - vp.height = (float)depthBuffer_Main.GetDesc().height; - device->BindViewports(1, &vp, cmd); - Rect scissor = GetScissorInternalResolution(); device->BindScissorRects(1, &scissor, cmd); - wi::renderer::DrawScene(visibility_main, RENDERPASS_PREPASS, cmd, drawscene_flags); + Viewport vp; + vp.width = (float)depthBuffer_Main.GetDesc().width; + vp.height = (float)depthBuffer_Main.GetDesc().height; + + // Foreground: + vp.min_depth = 1 - foreground_depth_range; + vp.max_depth = 1; + device->BindViewports(1, &vp, cmd); + wi::renderer::DrawScene( + visibility_main, + RENDERPASS_PREPASS, + cmd, + wi::renderer::DRAWSCENE_OPAQUE | + wi::renderer::DRAWSCENE_FOREGROUND_ONLY + ); + + // Regular: + vp.min_depth = 0; + vp.max_depth = 1; + device->BindViewports(1, &vp, cmd); + wi::renderer::DrawScene( + visibility_main, + RENDERPASS_PREPASS, + cmd, + drawscene_flags + ); wi::profiler::EndRange(range); device->EventEnd(cmd); @@ -1041,11 +1062,6 @@ namespace wi device->EventBegin("Planar reflections Z-Prepass", cmd); auto range = wi::profiler::BeginRangeGPU("Planar Reflections Z-Prepass", cmd); - Viewport vp; - vp.width = (float)depthBuffer_Reflection.GetDesc().width; - vp.height = (float)depthBuffer_Reflection.GetDesc().height; - device->BindViewports(1, &vp, cmd); - RenderPassImage rp[] = { RenderPassImage::DepthStencil( &depthBuffer_Reflection, @@ -1058,7 +1074,34 @@ namespace wi }; device->RenderPassBegin(rp, arraysize(rp), cmd); - wi::renderer::DrawScene(visibility_reflection, RENDERPASS_PREPASS, cmd, wi::renderer::DRAWSCENE_OPAQUE | wi::renderer::DRAWSCENE_IMPOSTOR | wi::renderer::DRAWSCENE_SKIP_PLANAR_REFLECTION_OBJECTS); + Viewport vp; + vp.width = (float)depthBuffer_Reflection.GetDesc().width; + vp.height = (float)depthBuffer_Reflection.GetDesc().height; + + // Foreground: + vp.min_depth = 1 - foreground_depth_range; + vp.max_depth = 1; + device->BindViewports(1, &vp, cmd); + wi::renderer::DrawScene( + visibility_reflection, + RENDERPASS_PREPASS, + cmd, + wi::renderer::DRAWSCENE_OPAQUE | + wi::renderer::DRAWSCENE_FOREGROUND_ONLY + ); + + // Regular: + vp.min_depth = 0; + vp.max_depth = 1; + device->BindViewports(1, &vp, cmd); + wi::renderer::DrawScene( + visibility_reflection, + RENDERPASS_PREPASS, + cmd, + wi::renderer::DRAWSCENE_OPAQUE | + wi::renderer::DRAWSCENE_IMPOSTOR | + wi::renderer::DRAWSCENE_SKIP_PLANAR_REFLECTION_OBJECTS + ); device->RenderPassEnd(cmd); @@ -1111,11 +1154,6 @@ namespace wi device->EventBegin("Planar reflections", cmd); auto range = wi::profiler::BeginRangeGPU("Planar Reflections", cmd); - Viewport vp; - vp.width = (float)depthBuffer_Reflection.GetDesc().width; - vp.height = (float)depthBuffer_Reflection.GetDesc().height; - device->BindViewports(1, &vp, cmd); - RenderPassImage rp[] = { RenderPassImage::RenderTarget( &rtReflection, @@ -1133,8 +1171,41 @@ namespace wi }; device->RenderPassBegin(rp, arraysize(rp), cmd); - wi::renderer::DrawScene(visibility_reflection, RENDERPASS_MAIN, cmd, wi::renderer::DRAWSCENE_OPAQUE | wi::renderer::DRAWSCENE_IMPOSTOR | wi::renderer::DRAWSCENE_SKIP_PLANAR_REFLECTION_OBJECTS); - wi::renderer::DrawScene(visibility_reflection, RENDERPASS_MAIN, cmd, wi::renderer::DRAWSCENE_TRANSPARENT | wi::renderer::DRAWSCENE_SKIP_PLANAR_REFLECTION_OBJECTS); // separate renderscene, to be drawn after opaque and transparent sort order + Viewport vp; + vp.width = (float)depthBuffer_Reflection.GetDesc().width; + vp.height = (float)depthBuffer_Reflection.GetDesc().height; + + // Foreground: + vp.min_depth = 1 - foreground_depth_range; + vp.max_depth = 1; + device->BindViewports(1, &vp, cmd); + wi::renderer::DrawScene( + visibility_reflection, + RENDERPASS_MAIN, + cmd, + wi::renderer::DRAWSCENE_OPAQUE | + wi::renderer::DRAWSCENE_FOREGROUND_ONLY + ); + + // Regular: + vp.min_depth = 0; + vp.max_depth = 1; + device->BindViewports(1, &vp, cmd); + wi::renderer::DrawScene( + visibility_reflection, + RENDERPASS_MAIN, + cmd, + wi::renderer::DRAWSCENE_OPAQUE | + wi::renderer::DRAWSCENE_IMPOSTOR | + wi::renderer::DRAWSCENE_SKIP_PLANAR_REFLECTION_OBJECTS + ); + wi::renderer::DrawScene( + visibility_reflection, + RENDERPASS_MAIN, + cmd, + wi::renderer::DRAWSCENE_TRANSPARENT | + wi::renderer::DRAWSCENE_SKIP_PLANAR_REFLECTION_OBJECTS + ); // separate renderscene, to be drawn after opaque and transparent sort order wi::renderer::DrawSky(*scene, cmd); if (scene->weather.IsRealisticSky() && scene->weather.IsRealisticSkyAerialPerspective()) @@ -1328,12 +1399,39 @@ namespace wi if (visibility_shading_in_compute) { // In visibility compute shading, the impostors must still be drawn using rasterization: - wi::renderer::DrawScene(visibility_main, RENDERPASS_MAIN, cmd, wi::renderer::DRAWSCENE_IMPOSTOR); + wi::renderer::DrawScene( + visibility_main, + RENDERPASS_MAIN, + cmd, + wi::renderer::DRAWSCENE_IMPOSTOR + ); } else { auto range = wi::profiler::BeginRangeGPU("Opaque Scene", cmd); - wi::renderer::DrawScene(visibility_main, RENDERPASS_MAIN, cmd, drawscene_flags); + + // Foreground: + vp.min_depth = 1 - foreground_depth_range; + vp.max_depth = 1; + device->BindViewports(1, &vp, cmd); + wi::renderer::DrawScene( + visibility_main, + RENDERPASS_MAIN, + cmd, + wi::renderer::DRAWSCENE_OPAQUE | + wi::renderer::DRAWSCENE_FOREGROUND_ONLY + ); + + // Regular: + vp.min_depth = 0; + vp.max_depth = 1; + device->BindViewports(1, &vp, cmd); + wi::renderer::DrawScene( + visibility_main, + RENDERPASS_MAIN, + cmd, + drawscene_flags + ); wi::renderer::DrawSky(*scene, cmd); wi::profiler::EndRange(range); // Opaque Scene } @@ -1750,11 +1848,6 @@ namespace wi }; device->RenderPassBegin(rp, getMSAASampleCount() > 1 ? 3 : 2, cmd); - Viewport vp; - vp.width = (float)depthBuffer_Main.GetDesc().width; - vp.height = (float)depthBuffer_Main.GetDesc().height; - device->BindViewports(1, &vp, cmd); - Rect scissor = GetScissorInternalResolution(); device->BindScissorRects(1, &scissor, cmd); @@ -1763,13 +1856,36 @@ namespace wi auto range = wi::profiler::BeginRangeGPU("Transparent Scene", cmd); device->EventBegin("Transparent Scene", cmd); - uint32_t drawscene_flags = 0; - drawscene_flags |= wi::renderer::DRAWSCENE_TRANSPARENT; - drawscene_flags |= wi::renderer::DRAWSCENE_OCCLUSIONCULLING; - drawscene_flags |= wi::renderer::DRAWSCENE_HAIRPARTICLE; - drawscene_flags |= wi::renderer::DRAWSCENE_TESSELLATION; - drawscene_flags |= wi::renderer::DRAWSCENE_OCEAN; - wi::renderer::DrawScene(visibility_main, RENDERPASS_MAIN, cmd, drawscene_flags); + Viewport vp; + vp.width = (float)depthBuffer_Main.GetDesc().width; + vp.height = (float)depthBuffer_Main.GetDesc().height; + + // Foreground: + vp.min_depth = 1 - foreground_depth_range; + vp.max_depth = 1; + device->BindViewports(1, &vp, cmd); + wi::renderer::DrawScene( + visibility_main, + RENDERPASS_MAIN, + cmd, + wi::renderer::DRAWSCENE_TRANSPARENT | + wi::renderer::DRAWSCENE_FOREGROUND_ONLY + ); + + // Regular: + vp.min_depth = 0; + vp.max_depth = 1; + device->BindViewports(1, &vp, cmd); + wi::renderer::DrawScene( + visibility_main, + RENDERPASS_MAIN, + cmd, + wi::renderer::DRAWSCENE_TRANSPARENT | + wi::renderer::DRAWSCENE_OCCLUSIONCULLING | + wi::renderer::DRAWSCENE_HAIRPARTICLE | + wi::renderer::DRAWSCENE_TESSELLATION | + wi::renderer::DRAWSCENE_OCEAN + ); device->EventEnd(cmd); wi::profiler::EndRange(range); // Transparent Scene diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index 74d06d95b..4cbb0bfb9 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -5651,6 +5651,7 @@ void DrawScene( const bool occlusion = (flags & DRAWSCENE_OCCLUSIONCULLING) && GetOcclusionCullingEnabled(); const bool ocean = flags & DRAWSCENE_OCEAN; const bool skip_planar_reflection_objects = flags & DRAWSCENE_SKIP_PLANAR_REFLECTION_OBJECTS; + const bool foreground_only = flags & DRAWSCENE_FOREGROUND_ONLY; device->EventBegin("DrawScene", cmd); device->BindShadingRate(ShadingRate::RATE_1X1, cmd); @@ -5689,7 +5690,7 @@ void DrawScene( continue; const ObjectComponent& object = vis.scene->objects[instanceIndex]; - if (object.IsRenderable() && (object.GetFilterMask() & filterMask)) + if (object.IsRenderable() && object.IsForeground() == foreground_only && (object.GetFilterMask() & filterMask)) { const float distance = wi::math::Distance(vis.camera->Eye, object.center); if (distance > object.fadeDistance + object.radius) diff --git a/WickedEngine/wiRenderer.h b/WickedEngine/wiRenderer.h index 900fd092e..a7c8f38b8 100644 --- a/WickedEngine/wiRenderer.h +++ b/WickedEngine/wiRenderer.h @@ -199,14 +199,15 @@ namespace wi::renderer enum DRAWSCENE_FLAGS { - DRAWSCENE_OPAQUE = 1 << 0, - DRAWSCENE_TRANSPARENT = 1 << 1, - DRAWSCENE_OCCLUSIONCULLING = 1 << 2, - DRAWSCENE_TESSELLATION = 1 << 3, - DRAWSCENE_HAIRPARTICLE = 1 << 4, - DRAWSCENE_IMPOSTOR = 1 << 5, - DRAWSCENE_OCEAN = 1 << 6, - DRAWSCENE_SKIP_PLANAR_REFLECTION_OBJECTS = 1 << 7, + DRAWSCENE_OPAQUE = 1 << 0, // include opaque objects + DRAWSCENE_TRANSPARENT = 1 << 1, // include transparent objects + DRAWSCENE_OCCLUSIONCULLING = 1 << 2, // enable skipping objects based on occlusion culling results + DRAWSCENE_TESSELLATION = 1 << 3, // enable tessellation + DRAWSCENE_HAIRPARTICLE = 1 << 4, // include hair particles + DRAWSCENE_IMPOSTOR = 1 << 5, // include impostors + DRAWSCENE_OCEAN = 1 << 6, // include ocean + 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 }; // Draw the world from a camera. You must call BindCameraCB() at least once in this frame prior to this diff --git a/WickedEngine/wiScene_Components.h b/WickedEngine/wiScene_Components.h index 38196245a..75b8efb0a 100644 --- a/WickedEngine/wiScene_Components.h +++ b/WickedEngine/wiScene_Components.h @@ -665,6 +665,7 @@ namespace wi::scene REQUEST_PLANAR_REFLECTION = 1 << 4, LIGHTMAP_RENDER_REQUEST = 1 << 5, LIGHTMAP_DISABLE_BLOCK_COMPRESSION = 1 << 6, + FOREGROUND = 1 << 7, }; uint32_t _flags = RENDERABLE | CAST_SHADOW; @@ -703,6 +704,7 @@ namespace wi::scene inline void SetRequestPlanarReflection(bool value) { if (value) { _flags |= REQUEST_PLANAR_REFLECTION; } else { _flags &= ~REQUEST_PLANAR_REFLECTION; } } inline void SetLightmapRenderRequest(bool value) { if (value) { _flags |= LIGHTMAP_RENDER_REQUEST; } else { _flags &= ~LIGHTMAP_RENDER_REQUEST; } } inline void SetLightmapDisableBlockCompression(bool value) { if (value) { _flags |= LIGHTMAP_DISABLE_BLOCK_COMPRESSION; } else { _flags &= ~LIGHTMAP_DISABLE_BLOCK_COMPRESSION; } } + inline void SetForeground(bool value) { if (value) { _flags |= FOREGROUND; } else { _flags &= ~FOREGROUND; } } inline bool IsRenderable() const { return _flags & RENDERABLE; } inline bool IsCastingShadow() const { return _flags & CAST_SHADOW; } @@ -710,6 +712,7 @@ namespace wi::scene inline bool IsRequestPlanarReflection() const { return _flags & REQUEST_PLANAR_REFLECTION; } inline bool IsLightmapRenderRequested() const { return _flags & LIGHTMAP_RENDER_REQUEST; } inline bool IsLightmapDisableBlockCompression() const { return _flags & LIGHTMAP_DISABLE_BLOCK_COMPRESSION; } + inline bool IsForeground() const { return _flags & FOREGROUND; } inline float GetTransparency() const { return 1 - color.w; } inline uint32_t GetFilterMask() const { return filterMask | filterMaskDynamic; } diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 927c13956..72bc97170 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wi::version // minor features, major updates, breaking compatibility changes const int minor = 71; // minor bug fixes, alterations, refactors, updates - const int revision = 287; + const int revision = 288; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);