From 8a07bb23617577e3b1e7122d7587a3dff302d8e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tur=C3=A1nszki=20J=C3=A1nos?= Date: Tue, 28 Feb 2023 08:25:58 +0100 Subject: [PATCH] added decal flag: alpha only basecolor; renderer fixes; --- Editor/DecalWindow.cpp | 19 +++- Editor/DecalWindow.h | 1 + WickedEngine/shaders/ShaderInterop_Renderer.h | 2 + WickedEngine/shaders/lightCullingCS.hlsl | 11 ++- WickedEngine/shaders/objectHF.hlsli | 22 +++-- WickedEngine/shaders/surfaceHF.hlsli | 11 ++- WickedEngine/wiRenderer.cpp | 94 +++++++++++++------ WickedEngine/wiScene_Components.h | 6 ++ WickedEngine/wiVersion.cpp | 2 +- 9 files changed, 119 insertions(+), 49 deletions(-) diff --git a/Editor/DecalWindow.cpp b/Editor/DecalWindow.cpp index 2db83dfb0..703ea9389 100644 --- a/Editor/DecalWindow.cpp +++ b/Editor/DecalWindow.cpp @@ -40,8 +40,23 @@ void DecalWindow::Create(EditorComponent* _editor) y += step; + onlyalphaCheckBox.Create("Alpha only basecolor: "); + onlyalphaCheckBox.SetSize(XMFLOAT2(hei, hei)); + onlyalphaCheckBox.SetTooltip("You can enable this to only use alpha channel from basecolor map. Useful for blending normalmap-only decals."); + onlyalphaCheckBox.OnClick([=](wi::gui::EventArgs args) { + Scene& scene = editor->GetCurrentScene(); + DecalComponent* decal = scene.decals.GetComponent(entity); + if (decal != nullptr) + { + decal->SetBaseColorOnlyAlpha(args.bValue); + } + }); + AddWidget(&onlyalphaCheckBox); + + y += step; + infoLabel.Create(""); - infoLabel.SetText("Set decal properties (texture, color, etc.) in the Material window."); + infoLabel.SetText("Set decal properties in the Material component. Decals support the following material properties:\n - Base color\n - Base color texture\n - Emissive strength\n - Normalmap texture\n - Normalmap strength"); infoLabel.SetSize(XMFLOAT2(300, 100)); infoLabel.SetPos(XMFLOAT2(10, y)); infoLabel.SetColor(wi::Color::Transparent()); @@ -64,6 +79,7 @@ void DecalWindow::SetEntity(Entity entity) if (decal != nullptr) { SetEnabled(true); + onlyalphaCheckBox.SetCheck(decal->IsBaseColorOnlyAlpha()); } else { @@ -110,5 +126,6 @@ void DecalWindow::ResizeLayout() add_fullwidth(infoLabel); add_right(placementCheckBox); + add_right(onlyalphaCheckBox); } diff --git a/Editor/DecalWindow.h b/Editor/DecalWindow.h index aee5371b5..7c130eb1f 100644 --- a/Editor/DecalWindow.h +++ b/Editor/DecalWindow.h @@ -13,6 +13,7 @@ public: void SetEntity(wi::ecs::Entity entity); wi::gui::CheckBox placementCheckBox; + wi::gui::CheckBox onlyalphaCheckBox; wi::gui::Label infoLabel; void ResizeLayout() override; diff --git a/WickedEngine/shaders/ShaderInterop_Renderer.h b/WickedEngine/shaders/ShaderInterop_Renderer.h index e64c48ba6..592305234 100644 --- a/WickedEngine/shaders/ShaderInterop_Renderer.h +++ b/WickedEngine/shaders/ShaderInterop_Renderer.h @@ -839,6 +839,8 @@ enum SHADER_ENTITY_TYPE static const uint ENTITY_FLAG_LIGHT_STATIC = 1 << 0; static const uint ENTITY_FLAG_LIGHT_VOLUMETRICCLOUDS = 1 << 1; +static const uint ENTITY_FLAG_DECAL_BASECOLOR_ONLY_ALPHA = 1 << 0; + static const uint SHADER_ENTITY_COUNT = 256; static const uint SHADER_ENTITY_TILE_BUCKET_COUNT = SHADER_ENTITY_COUNT / 32; diff --git a/WickedEngine/shaders/lightCullingCS.hlsl b/WickedEngine/shaders/lightCullingCS.hlsl index e975e423b..f0ef825f3 100644 --- a/WickedEngine/shaders/lightCullingCS.hlsl +++ b/WickedEngine/shaders/lightCullingCS.hlsl @@ -230,15 +230,12 @@ void main(uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : { ShaderEntity entity = load_entity(i); - if (entity.GetFlags() & ENTITY_FLAG_LIGHT_STATIC) - { - continue; // static lights will be skipped here (they are used at lightmap baking) - } - switch (entity.GetType()) { case ENTITY_TYPE_POINTLIGHT: { + if (entity.GetFlags() & ENTITY_FLAG_LIGHT_STATIC) + break; // static lights will be skipped here (they are used at lightmap baking) float3 positionVS = mul(GetCamera().view, float4(entity.position, 1)).xyz; Sphere sphere = { positionVS.xyz, entity.GetRange() + entity.GetLength() }; if (SphereInsideFrustum(sphere, GroupFrustum, nearClipVS, maxDepthVS)) @@ -259,6 +256,8 @@ void main(uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : break; case ENTITY_TYPE_SPOTLIGHT: { + if (entity.GetFlags() & ENTITY_FLAG_LIGHT_STATIC) + break; // static lights will be skipped here (they are used at lightmap baking) float3 positionVS = mul(GetCamera().view, float4(entity.position, 1)).xyz; float3 directionVS = mul((float3x3)GetCamera().view, entity.GetDirection()); // Construct a tight fitting sphere around the spotlight cone: @@ -283,6 +282,8 @@ void main(uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : break; case ENTITY_TYPE_DIRECTIONALLIGHT: { + if (entity.GetFlags() & ENTITY_FLAG_LIGHT_STATIC) + break; // static lights will be skipped here (they are used at lightmap baking) AppendEntity_Transparent(i); AppendEntity_Opaque(i); } diff --git a/WickedEngine/shaders/objectHF.hlsli b/WickedEngine/shaders/objectHF.hlsli index 6f6ee71f9..92154aa55 100644 --- a/WickedEngine/shaders/objectHF.hlsli +++ b/WickedEngine/shaders/objectHF.hlsli @@ -533,10 +533,13 @@ inline void ForwardDecals(inout Surface surface) if (decalTexture >= 0) { decalColor *= bindless_textures[NonUniformResourceIndex(decalTexture)].SampleGrad(sampler_objectshader, uvw.xy, decalDX, decalDY); - // perform manual blending of decals: - // NOTE: they are sorted top-to-bottom, but blending is performed bottom-to-top - decalAccumulation.rgb = mad(1 - decalAccumulation.a, decalColor.a * decalColor.rgb, decalAccumulation.rgb); - decalAccumulation.a = mad(1 - decalColor.a, decalAccumulation.a, decalColor.a); + if ((decal.GetFlags() & ENTITY_FLAG_DECAL_BASECOLOR_ONLY_ALPHA) == 0) + { + // perform manual blending of decals: + // NOTE: they are sorted top-to-bottom, but blending is performed bottom-to-top + decalAccumulation.rgb = mad(1 - decalAccumulation.a, decalColor.a * decalColor.rgb, decalAccumulation.rgb); + decalAccumulation.a = mad(1 - decalColor.a, decalAccumulation.a, decalColor.a); + } } [branch] if (decalNormal >= 0) @@ -848,10 +851,13 @@ inline void TiledDecals(inout Surface surface, uint flatTileIndex) if (decalTexture >= 0) { decalColor *= bindless_textures[NonUniformResourceIndex(decalTexture)].SampleGrad(sampler_objectshader, uvw.xy, decalDX, decalDY); - // perform manual blending of decals: - // NOTE: they are sorted top-to-bottom, but blending is performed bottom-to-top - decalAccumulation.rgb = mad(1 - decalAccumulation.a, decalColor.a * decalColor.rgb, decalAccumulation.rgb); - decalAccumulation.a = mad(1 - decalColor.a, decalAccumulation.a, decalColor.a); + if ((decal.GetFlags() & ENTITY_FLAG_DECAL_BASECOLOR_ONLY_ALPHA) == 0) + { + // perform manual blending of decals: + // NOTE: they are sorted top-to-bottom, but blending is performed bottom-to-top + decalAccumulation.rgb = mad(1 - decalAccumulation.a, decalColor.a * decalColor.rgb, decalAccumulation.rgb); + decalAccumulation.a = mad(1 - decalColor.a, decalAccumulation.a, decalColor.a); + } } [branch] if (decalNormal >= 0) diff --git a/WickedEngine/shaders/surfaceHF.hlsli b/WickedEngine/shaders/surfaceHF.hlsli index 8501572ce..952a3605d 100644 --- a/WickedEngine/shaders/surfaceHF.hlsli +++ b/WickedEngine/shaders/surfaceHF.hlsli @@ -507,10 +507,13 @@ struct Surface if (decalTexture >= 0) { decalColor *= bindless_textures[NonUniformResourceIndex(decalTexture)].SampleGrad(sam, uvw.xy, decalDX, decalDY); - // perform manual blending of decals: - // NOTE: they are sorted top-to-bottom, but blending is performed bottom-to-top - decalAccumulation.rgb = mad(1 - decalAccumulation.a, decalColor.a * decalColor.rgb, decalAccumulation.rgb); - decalAccumulation.a = mad(1 - decalColor.a, decalAccumulation.a, decalColor.a); + if ((decal.GetFlags() & ENTITY_FLAG_DECAL_BASECOLOR_ONLY_ALPHA) == 0) + { + // perform manual blending of decals: + // NOTE: they are sorted top-to-bottom, but blending is performed bottom-to-top + decalAccumulation.rgb = mad(1 - decalAccumulation.a, decalColor.a * decalColor.rgb, decalAccumulation.rgb); + decalAccumulation.a = mad(1 - decalColor.a, decalAccumulation.a, decalColor.a); + } } [branch] if (decalNormal >= 0) diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index f5fd0cd3b..6e6c85f38 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -3749,6 +3749,10 @@ void UpdateRenderData( } shaderentity.SetType(ENTITY_TYPE_DECAL); + if (decal.IsBaseColorOnlyAlpha()) + { + shaderentity.SetFlags(ENTITY_FLAG_DECAL_BASECOLOR_ONLY_ALPHA); + } shaderentity.position = decal.position; shaderentity.SetRange(decal.range); float emissive_mul = 1 + decal.emissive; @@ -4105,22 +4109,39 @@ void UpdateRenderData( wi::profiler::EndRange(range); } - auto range = wi::profiler::BeginRangeGPU("Skinning", cmd); - device->EventBegin("Skinning", cmd); + device->EventBegin("Morph Targets", cmd); { + auto range = wi::profiler::BeginRangeGPU("Morph Targets", cmd); + bool morphs = false; for (size_t i = 0; i < vis.scene->meshes.GetCount(); ++i) { - Entity entity = vis.scene->meshes.GetEntity(i); const MeshComponent& mesh = vis.scene->meshes[i]; if (mesh.dirty_morph && !mesh.vertex_positions_morphed.empty()) { + morphs = true; mesh.dirty_morph = false; GraphicsDevice::GPUAllocation allocation = device->AllocateGPU(mesh.vb_pos_nor_wind.size, cmd); std::memcpy(allocation.data, mesh.vertex_positions_morphed.data(), mesh.vb_pos_nor_wind.size); device->CopyBuffer(&mesh.generalBuffer, mesh.vb_pos_nor_wind.offset, &allocation.buffer, allocation.offset, mesh.vb_pos_nor_wind.size, cmd); barrier_stack.push_back(GPUBarrier::Buffer(&mesh.generalBuffer, ResourceState::COPY_DST, ResourceState::SHADER_RESOURCE)); } + } + if (morphs) + { + barrier_stack_flush(cmd); + } + + wi::profiler::EndRange(range); // Morph Targets + } + + device->EventBegin("Skinning", cmd); + { + auto range = wi::profiler::BeginRangeGPU("Skinning", cmd); + for (size_t i = 0; i < vis.scene->meshes.GetCount(); ++i) + { + Entity entity = vis.scene->meshes.GetEntity(i); + const MeshComponent& mesh = vis.scene->meshes[i]; if (mesh.IsSkinned() && vis.scene->armatures.Contains(mesh.armatureID)) { @@ -4148,23 +4169,21 @@ void UpdateRenderData( device->Dispatch(((uint32_t)mesh.vertex_positions.size() + 63) / 64, 1, 1, cmd); barrier_stack.push_back(GPUBarrier::Buffer(&mesh.streamoutBuffer, ResourceState::UNORDERED_ACCESS, ResourceState::SHADER_RESOURCE)); - } - } - barrier_stack_flush(cmd); - + wi::profiler::EndRange(range); // skinning } device->EventEnd(cmd); - wi::profiler::EndRange(range); // skinning + + barrier_stack_flush(cmd); // wind/skinning flush // Hair particle systems GPU simulation: // (This must be non-async too, as prepass will render hairs!) static thread_local wi::vector hair_updates; if (!vis.visibleHairs.empty() && frameCB.delta_time > 0) { - range = wi::profiler::BeginRangeGPU("HairParticles - Simulate", cmd); + auto range = wi::profiler::BeginRangeGPU("HairParticles - Simulate", cmd); for (uint32_t hairIndex : vis.visibleHairs) { const wi::HairParticleSystem& hair = vis.scene->hairs[hairIndex]; @@ -4239,16 +4258,14 @@ void UpdateRenderData( device->Dispatch((uint32_t)vis.scene->instanceArraySize, 1, 1, cmd); - { - GPUBarrier barriers[] = { - GPUBarrier::Buffer(&vis.scene->meshletBuffer, ResourceState::UNORDERED_ACCESS, ResourceState::SHADER_RESOURCE), - }; - device->Barrier(barriers, arraysize(barriers), cmd); - } + barrier_stack.push_back(GPUBarrier::Buffer(&vis.scene->meshletBuffer, ResourceState::UNORDERED_ACCESS, ResourceState::SHADER_RESOURCE)); + wi::profiler::EndRange(range); device->EventEnd(cmd); } + barrier_stack_flush(cmd); + device->EventEnd(cmd); } @@ -8580,7 +8597,7 @@ void RayTraceScene( BindCommonResources(cmd); const XMFLOAT4& halton = wi::math::GetHaltonSequence(accumulation_sample); - RaytracingCB cb; + RaytracingCB cb = {}; cb.xTracePixelOffset = XMFLOAT2(halton.x, halton.y); cb.xTraceAccumulationFactor = 1.0f / ((float)accumulation_sample + 1.0f); cb.xTraceResolution.x = desc.width; @@ -8599,36 +8616,53 @@ void RayTraceScene( }; device->BindUAVs(uavs, 0, arraysize(uavs), cmd); - { - GPUBarrier barriers[] = { - GPUBarrier::Image(&output, output.desc.layout, ResourceState::UNORDERED_ACCESS), - }; - device->Barrier(barriers, arraysize(barriers), cmd); - } - + barrier_stack.push_back(GPUBarrier::Image(&output, output.desc.layout, ResourceState::UNORDERED_ACCESS)); if (output_albedo != nullptr) { + barrier_stack.push_back(GPUBarrier::Image(output_albedo, output_albedo->desc.layout, ResourceState::UNORDERED_ACCESS)); device->BindUAV(output_albedo, 1, cmd); } if (output_normal != nullptr) { + barrier_stack.push_back(GPUBarrier::Image(output_normal, output_normal->desc.layout, ResourceState::UNORDERED_ACCESS)); device->BindUAV(output_normal, 2, cmd); } + barrier_stack_flush(cmd); + + if (accumulation_sample == 0) + { + device->ClearUAV(&output, 0, cmd); + barrier_stack.push_back(GPUBarrier::Memory(&output)); + if (output_albedo != nullptr) + { + device->ClearUAV(output_albedo, 0, cmd); + barrier_stack.push_back(GPUBarrier::Memory(output_albedo)); + } + if (output_normal != nullptr) + { + device->ClearUAV(output_normal, 0, cmd); + barrier_stack.push_back(GPUBarrier::Memory(output_normal)); + } + barrier_stack_flush(cmd); + } device->Dispatch( (desc.width + RAYTRACING_LAUNCH_BLOCKSIZE - 1) / RAYTRACING_LAUNCH_BLOCKSIZE, (desc.height + RAYTRACING_LAUNCH_BLOCKSIZE - 1) / RAYTRACING_LAUNCH_BLOCKSIZE, 1, - cmd); + cmd + ); + barrier_stack.push_back(GPUBarrier::Image(&output, ResourceState::UNORDERED_ACCESS, output.desc.layout)); + if (output_albedo != nullptr) { - GPUBarrier barriers[] = { - GPUBarrier::Memory(), - GPUBarrier::Image(&output, ResourceState::UNORDERED_ACCESS, output.desc.layout), - }; - device->Barrier(barriers, arraysize(barriers), cmd); + barrier_stack.push_back(GPUBarrier::Image(output_albedo, ResourceState::UNORDERED_ACCESS, output_albedo->desc.layout)); } - + if (output_normal != nullptr) + { + barrier_stack.push_back(GPUBarrier::Image(output_normal, ResourceState::UNORDERED_ACCESS, output_normal->desc.layout)); + } + barrier_stack_flush(cmd); wi::profiler::EndRange(range); device->EventEnd(cmd); // RayTraceScene diff --git a/WickedEngine/wiScene_Components.h b/WickedEngine/wiScene_Components.h index 8a8cc4ccd..403e8f202 100644 --- a/WickedEngine/wiScene_Components.h +++ b/WickedEngine/wiScene_Components.h @@ -1050,9 +1050,15 @@ namespace wi::scene enum FLAGS { EMPTY = 0, + BASECOLOR_ONLY_ALPHA = 1 << 0, }; uint32_t _flags = EMPTY; + // Set decal to only use alpha from base color texture. Useful for blending normalmap-only decals + constexpr void SetBaseColorOnlyAlpha(bool value) { if (value) { _flags |= BASECOLOR_ONLY_ALPHA; } else { _flags ^= BASECOLOR_ONLY_ALPHA; } } + + constexpr bool IsBaseColorOnlyAlpha() const { return _flags & BASECOLOR_ONLY_ALPHA; } + // Non-serialized attributes: float emissive; XMFLOAT4 color; diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index f3795e325..419f992f3 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 = 164; + const int revision = 165; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);