added decal flag: alpha only basecolor; renderer fixes;
This commit is contained in:
+18
-1
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
+64
-30
@@ -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<HairParticleSystem::UpdateGPUItem> 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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user