From ed0b3fed07c4a3f3485cc37bf0c90d32ef77a78f Mon Sep 17 00:00:00 2001 From: turanszkij Date: Sat, 11 Apr 2020 12:35:53 +0100 Subject: [PATCH] resurrected mesh wind; added wind paint tool; --- Editor/MaterialWindow.cpp | 15 ++- Editor/MaterialWindow.h | 1 + Editor/PaintToolWindow.cpp | 125 +++++++++++++++++++--- Editor/PaintToolWindow.h | 1 + WickedEngine/RenderPath3D_PathTracing.cpp | 25 +++++ WickedEngine/ShaderInterop_Renderer.h | 2 + WickedEngine/bvh_primitivesCS.hlsl | 3 +- WickedEngine/objectInputLayoutHF.hlsli | 67 ++++++++---- WickedEngine/objectVS_debug.hlsl | 2 +- WickedEngine/renderlightmapVS.hlsl | 10 +- WickedEngine/skinningCS.hlsl | 4 +- WickedEngine/wiGPUBVH.cpp | 1 + WickedEngine/wiRenderer.cpp | 14 +-- WickedEngine/wiScene.cpp | 56 ++++++---- WickedEngine/wiScene.h | 43 ++++---- WickedEngine/wiVersion.cpp | 2 +- 16 files changed, 282 insertions(+), 89 deletions(-) diff --git a/Editor/MaterialWindow.cpp b/Editor/MaterialWindow.cpp index db15006f8..67b9395cb 100644 --- a/Editor/MaterialWindow.cpp +++ b/Editor/MaterialWindow.cpp @@ -14,11 +14,11 @@ MaterialWindow::MaterialWindow(EditorComponent* editor) : GUI(&editor->GetGUI()) assert(GUI && "Invalid GUI!"); materialWindow = new wiWindow(GUI, "Material Window"); - materialWindow->SetSize(XMFLOAT2(700, 760)); + materialWindow->SetSize(XMFLOAT2(700, 770)); GUI->AddWidget(materialWindow); float x = 540, y = 0; - float step = 25; + float step = 24; waterCheckBox = new wiCheckBox("Water: "); waterCheckBox->SetTooltip("Set material as special water material."); @@ -100,6 +100,16 @@ MaterialWindow::MaterialWindow(EditorComponent* editor) : GUI(&editor->GetGUI()) }); materialWindow->AddWidget(occlusionSecondaryCheckBox); + windCheckBox = new wiCheckBox("Wind: "); + windCheckBox->SetTooltip("If enabled, vertex wind weights will affect how much wind offset affects the subset."); + windCheckBox->SetPos(XMFLOAT2(670, y += step)); + windCheckBox->OnClick([&](wiEventArgs args) { + MaterialComponent* material = wiScene::GetScene().materials.GetComponent(entity); + if (material != nullptr) + material->SetUseWind(args.bValue); + }); + materialWindow->AddWidget(windCheckBox); + step = 30; float hei = 25; @@ -789,6 +799,7 @@ void MaterialWindow::SetEntity(Entity entity) specularGlossinessCheckBox->SetCheck(material->IsUsingSpecularGlossinessWorkflow()); occlusionPrimaryCheckBox->SetCheck(material->IsOcclusionEnabled_Primary()); occlusionSecondaryCheckBox->SetCheck(material->IsOcclusionEnabled_Secondary()); + windCheckBox->SetCheck(material->IsUsingWind()); normalMapSlider->SetValue(material->normalMapStrength); roughnessSlider->SetValue(material->roughness); reflectanceSlider->SetValue(material->reflectance); diff --git a/Editor/MaterialWindow.h b/Editor/MaterialWindow.h index 687f2eee1..2feb28b9e 100644 --- a/Editor/MaterialWindow.h +++ b/Editor/MaterialWindow.h @@ -34,6 +34,7 @@ public: wiCheckBox* specularGlossinessCheckBox; wiCheckBox* occlusionPrimaryCheckBox; wiCheckBox* occlusionSecondaryCheckBox; + wiCheckBox* windCheckBox; wiSlider* normalMapSlider; wiSlider* roughnessSlider; wiSlider* reflectanceSlider; diff --git a/Editor/PaintToolWindow.cpp b/Editor/PaintToolWindow.cpp index 543799874..1cbffae29 100644 --- a/Editor/PaintToolWindow.cpp +++ b/Editor/PaintToolWindow.cpp @@ -33,6 +33,7 @@ PaintToolWindow::PaintToolWindow(EditorComponent* editor) : editor(editor) modeComboBox->AddItem("Hairparticle - Add Triangle"); modeComboBox->AddItem("Hairparticle - Remove Triangle"); modeComboBox->AddItem("Hairparticle - Length (Alpha)"); + modeComboBox->AddItem("Wind weight (Alpha)"); modeComboBox->SetSelected(0); modeComboBox->OnSelect([&](wiEventArgs args) { textureSlotComboBox->SetEnabled(false); @@ -71,6 +72,9 @@ PaintToolWindow::PaintToolWindow(EditorComponent* editor) : editor(editor) case MODE_HAIRPARTICLE_LENGTH: infoLabel->SetText("In hair particle length mode, you can adjust length of hair particles with the colorpicker Alpha channel (A). The Alpha channel is 0-255, but the length will be normalized to 0-1 range.\nThis will NOT modify random distribution of hair!"); break; + case MODE_WIND: + infoLabel->SetText("Paint the wind affection amount onto the vertices. Use the Alpha channel to control the amount."); + break; } }); window->AddWidget(modeComboBox); @@ -354,6 +358,7 @@ void PaintToolWindow::Update(float dt) break; case MODE_VERTEXCOLOR: + case MODE_WIND: { ObjectComponent* object = scene.objects.GetComponent(entity); if (object == nullptr || object->meshID == INVALID_ENTITY) @@ -371,14 +376,30 @@ void PaintToolWindow::Update(float dt) material = scene.materials.GetComponent(x.materialID); if (material != nullptr) { - material->SetUseVertexColors(true); + switch (mode) + { + case MODE_VERTEXCOLOR: + material->SetUseVertexColors(true); + break; + case MODE_WIND: + material->SetUseWind(true); + break; + } } } material = nullptr; } else { - material->SetUseVertexColors(true); + switch (mode) + { + case MODE_VERTEXCOLOR: + material->SetUseVertexColors(true); + break; + case MODE_WIND: + material->SetUseWind(true); + break; + } } const ArmatureComponent* armature = mesh->IsSkinned() ? scene.armatures.GetComponent(mesh->armatureID) : nullptr; @@ -390,11 +411,25 @@ void PaintToolWindow::Update(float dt) const XMMATRIX W = XMLoadFloat4x4(&transform->world); bool rebuild = false; - if (mesh->vertex_colors.empty()) + + switch (mode) { - mesh->vertex_colors.resize(mesh->vertex_positions.size()); - std::fill(mesh->vertex_colors.begin(), mesh->vertex_colors.end(), 0xFFFFFFFF); // fill white - rebuild = true; + case MODE_VERTEXCOLOR: + if (mesh->vertex_colors.empty()) + { + mesh->vertex_colors.resize(mesh->vertex_positions.size()); + std::fill(mesh->vertex_colors.begin(), mesh->vertex_colors.end(), wiColor::White().rgba); // fill white + rebuild = true; + } + break; + case MODE_WIND: + if (mesh->vertex_windweights.empty()) + { + mesh->vertex_windweights.resize(mesh->vertex_positions.size()); + std::fill(mesh->vertex_windweights.begin(), mesh->vertex_windweights.end(), 0xFF); // fill max affection + rebuild = true; + } + break; } if (painting) @@ -429,11 +464,26 @@ void PaintToolWindow::Update(float dt) if (z >= 0 && z <= 1 && dist <= radius) { RecordHistory(true); - wiColor vcol = mesh->vertex_colors[j]; - const float affection = amount * std::powf(1 - (dist / radius), falloff); - vcol = wiColor::lerp(vcol, color, affection); - mesh->vertex_colors[j] = vcol.rgba; rebuild = true; + const float affection = amount * std::powf(1 - (dist / radius), falloff); + + switch (mode) + { + case MODE_VERTEXCOLOR: + { + wiColor vcol = mesh->vertex_colors[j]; + vcol = wiColor::lerp(vcol, color, affection); + mesh->vertex_colors[j] = vcol.rgba; + } + break; + case MODE_WIND: + { + wiColor vcol = wiColor(0, 0, 0, mesh->vertex_windweights[j]); + vcol = wiColor::lerp(vcol, color, affection); + mesh->vertex_windweights[j] = vcol.getA(); + } + break; + } } } } @@ -460,9 +510,18 @@ void PaintToolWindow::Update(float dt) XMStoreFloat3(&tri.positionA, P[0]); XMStoreFloat3(&tri.positionB, P[1]); XMStoreFloat3(&tri.positionC, P[2]); - tri.colorA.w = 0.8f; - tri.colorB.w = 0.8f; - tri.colorC.w = 0.8f; + if (mode == MODE_WIND) + { + tri.colorA = wiColor(mesh->vertex_windweights[triangle[0]], 0, 0, 255); + tri.colorB = wiColor(mesh->vertex_windweights[triangle[1]], 0, 0, 255); + tri.colorC = wiColor(mesh->vertex_windweights[triangle[2]], 0, 0, 255); + } + else + { + tri.colorA.w = 0.8f; + tri.colorB.w = 0.8f; + tri.colorC.w = 0.8f; + } wiRenderer::DrawTriangle(tri, true); } } @@ -952,6 +1011,19 @@ void PaintToolWindow::RecordHistory(bool start, CommandList cmd) archive << mesh->vertex_colors; } break; + case PaintToolWindow::MODE_WIND: + { + ObjectComponent* object = scene.objects.GetComponent(entity); + if (object == nullptr || object->meshID == INVALID_ENTITY) + break; + + MeshComponent* mesh = scene.meshes.GetComponent(object->meshID); + if (mesh == nullptr) + break; + + archive << mesh->vertex_windweights; + } + break; case PaintToolWindow::MODE_SCULPTING_ADD: case PaintToolWindow::MODE_SCULPTING_SUBTRACT: { @@ -1073,6 +1145,33 @@ void PaintToolWindow::ConsumeHistoryOperation(wiArchive& archive, bool undo) mesh->CreateRenderData(); } break; + case PaintToolWindow::MODE_WIND: + { + ObjectComponent* object = scene.objects.GetComponent(entity); + if (object == nullptr || object->meshID == INVALID_ENTITY) + break; + + MeshComponent* mesh = scene.meshes.GetComponent(object->meshID); + if (mesh == nullptr) + break; + + MeshComponent undo_mesh; + archive >> undo_mesh.vertex_windweights; + MeshComponent redo_mesh; + archive >> redo_mesh.vertex_windweights; + + if (undo) + { + mesh->vertex_windweights = undo_mesh.vertex_windweights; + } + else + { + mesh->vertex_windweights = redo_mesh.vertex_windweights; + } + + mesh->CreateRenderData(); + } + break; case PaintToolWindow::MODE_SCULPTING_ADD: case PaintToolWindow::MODE_SCULPTING_SUBTRACT: { diff --git a/Editor/PaintToolWindow.h b/Editor/PaintToolWindow.h index 960fe5936..386f88269 100644 --- a/Editor/PaintToolWindow.h +++ b/Editor/PaintToolWindow.h @@ -60,6 +60,7 @@ public: MODE_HAIRPARTICLE_ADD_TRIANGLE, MODE_HAIRPARTICLE_REMOVE_TRIANGLE, MODE_HAIRPARTICLE_LENGTH, + MODE_WIND, }; MODE GetMode() const; void SetEntity(wiECS::Entity value, int subsetindex = -1); diff --git a/WickedEngine/RenderPath3D_PathTracing.cpp b/WickedEngine/RenderPath3D_PathTracing.cpp index 74d07326b..c00f8b25a 100644 --- a/WickedEngine/RenderPath3D_PathTracing.cpp +++ b/WickedEngine/RenderPath3D_PathTracing.cpp @@ -37,6 +37,20 @@ void RenderPath3D_PathTracing::ResizeBuffers() desc.Height = wiRenderer::GetInternalResolution().y; device->CreateTexture(&desc, nullptr, &rtPostprocess_LDR[0]); device->SetName(&rtPostprocess_LDR[0], "rtPostprocess_LDR[0]"); + + + desc.Width /= 4; + desc.Height /= 4; + desc.BindFlags = BIND_UNORDERED_ACCESS | BIND_SHADER_RESOURCE; + device->CreateTexture(&desc, nullptr, &rtGUIBlurredBackground[0]); + device->SetName(&rtGUIBlurredBackground[0], "rtGUIBlurredBackground[0]"); + + desc.Width /= 4; + desc.Height /= 4; + device->CreateTexture(&desc, nullptr, &rtGUIBlurredBackground[1]); + device->SetName(&rtGUIBlurredBackground[1], "rtGUIBlurredBackground[1]"); + device->CreateTexture(&desc, nullptr, &rtGUIBlurredBackground[2]); + device->SetName(&rtGUIBlurredBackground[2], "rtGUIBlurredBackground[2]"); } { @@ -153,6 +167,17 @@ void RenderPath3D_PathTracing::Render() const false, nullptr ); + + // GUI Background blurring: + { + auto range = wiProfiler::BeginRangeGPU("GUI Background Blur", cmd); + device->EventBegin("GUI Background Blur", cmd); + wiRenderer::Postprocess_Downsample4x(rtPostprocess_LDR[0], rtGUIBlurredBackground[0], cmd); + wiRenderer::Postprocess_Downsample4x(rtGUIBlurredBackground[0], rtGUIBlurredBackground[2], cmd); + wiRenderer::Postprocess_Blur_Gaussian(rtGUIBlurredBackground[2], rtGUIBlurredBackground[1], rtGUIBlurredBackground[2], cmd); + device->EventEnd(cmd); + wiProfiler::EndRange(range); + } }); RenderPath2D::Render(); diff --git a/WickedEngine/ShaderInterop_Renderer.h b/WickedEngine/ShaderInterop_Renderer.h index 156b2aeeb..b236a19e3 100644 --- a/WickedEngine/ShaderInterop_Renderer.h +++ b/WickedEngine/ShaderInterop_Renderer.h @@ -7,6 +7,7 @@ static const uint SHADERMATERIAL_OPTION_BIT_USE_VERTEXCOLORS = 1 << 0; static const uint SHADERMATERIAL_OPTION_BIT_SPECULARGLOSSINESS_WORKFLOW = 1 << 1; static const uint SHADERMATERIAL_OPTION_BIT_OCCLUSION_PRIMARY = 1 << 2; static const uint SHADERMATERIAL_OPTION_BIT_OCCLUSION_SECONDARY = 1 << 3; +static const uint SHADERMATERIAL_OPTION_BIT_USE_WIND = 1 << 4; struct ShaderMaterial { @@ -43,6 +44,7 @@ struct ShaderMaterial inline bool IsUsingSpecularGlossinessWorkflow() { return options & SHADERMATERIAL_OPTION_BIT_SPECULARGLOSSINESS_WORKFLOW; } inline bool IsOcclusionEnabled_Primary() { return options & SHADERMATERIAL_OPTION_BIT_OCCLUSION_PRIMARY; } inline bool IsOcclusionEnabled_Secondary() { return options & SHADERMATERIAL_OPTION_BIT_OCCLUSION_SECONDARY; } + inline bool IsUsingWind() { return options & SHADERMATERIAL_OPTION_BIT_USE_WIND; } }; struct ShaderEntity diff --git a/WickedEngine/bvh_primitivesCS.hlsl b/WickedEngine/bvh_primitivesCS.hlsl index 349170985..eb6ab3a36 100644 --- a/WickedEngine/bvh_primitivesCS.hlsl +++ b/WickedEngine/bvh_primitivesCS.hlsl @@ -12,6 +12,7 @@ RAWBUFFER(meshVertexBuffer_POS, TEXSLOT_ONDEMAND2); TYPEDBUFFER(meshVertexBuffer_UV0, float2, TEXSLOT_ONDEMAND3); TYPEDBUFFER(meshVertexBuffer_UV1, float2, TEXSLOT_ONDEMAND4); TYPEDBUFFER(meshVertexBuffer_COL, float4, TEXSLOT_ONDEMAND5); +TYPEDBUFFER(meshVertexBuffer_SUB, uint, TEXSLOT_ONDEMAND6); RWSTRUCTUREDBUFFER(primitiveIDBuffer, uint, 0); RWSTRUCTUREDBUFFER(primitiveBuffer, BVHPrimitive, 1); @@ -40,7 +41,7 @@ void main(uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex) uint nor_u = asuint(pos_nor0.w); float3 nor0 = unpack_unitvector(nor_u); - uint subsetIndex = (nor_u >> 24) & 0x000000FF; + uint subsetIndex = meshVertexBuffer_SUB[i0]; nor_u = asuint(pos_nor1.w); float3 nor1 = unpack_unitvector(nor_u); diff --git a/WickedEngine/objectInputLayoutHF.hlsli b/WickedEngine/objectInputLayoutHF.hlsli index 62ea90709..c35fbb164 100644 --- a/WickedEngine/objectInputLayoutHF.hlsli +++ b/WickedEngine/objectInputLayoutHF.hlsli @@ -23,19 +23,19 @@ struct Input_InstanceAtlas struct Input_Object_POS { - float4 pos : POSITION_NORMAL_SUBSETINDEX; + float4 pos : POSITION_NORMAL_WIND; Input_Instance inst; }; struct Input_Object_POS_TEX { - float4 pos : POSITION_NORMAL_SUBSETINDEX; + float4 pos : POSITION_NORMAL_WIND; float2 uv0 : UVSET0; float2 uv1 : UVSET1; Input_Instance inst; }; struct Input_Object_ALL { - float4 pos : POSITION_NORMAL_SUBSETINDEX; + float4 pos : POSITION_NORMAL_WIND; float2 uv0 : UVSET0; float2 uv1 : UVSET1; float2 atl : ATLAS; @@ -72,7 +72,6 @@ struct VertexSurface float2 atlas; float4 color; float3 normal; - uint subsetIndex; float4 prevPos; }; inline VertexSurface MakeVertexSurfaceFromInput(Input_Object_POS input) @@ -83,11 +82,21 @@ inline VertexSurface MakeVertexSurfaceFromInput(Input_Object_POS input) surface.color = g_xMaterial.baseColor * unpack_rgba(input.inst.userdata.x); - uint normal_subsetIndex = asuint(input.pos.w); - surface.normal.x = (float)((normal_subsetIndex >> 0) & 0x000000FF) / 255.0f * 2.0f - 1.0f; - surface.normal.y = (float)((normal_subsetIndex >> 8) & 0x000000FF) / 255.0f * 2.0f - 1.0f; - surface.normal.z = (float)((normal_subsetIndex >> 16) & 0x000000FF) / 255.0f * 2.0f - 1.0f; - surface.subsetIndex = (normal_subsetIndex >> 24) & 0x000000FF; + uint normal_wind = asuint(input.pos.w); + surface.normal.x = (float)((normal_wind >> 0) & 0x000000FF) / 255.0f * 2.0f - 1.0f; + surface.normal.y = (float)((normal_wind >> 8) & 0x000000FF) / 255.0f * 2.0f - 1.0f; + surface.normal.z = (float)((normal_wind >> 16) & 0x000000FF) / 255.0f * 2.0f - 1.0f; + + if (g_xMaterial.IsUsingWind()) + { + const float windweight = ((normal_wind >> 24) & 0x000000FF) / 255.0f; + const float waveoffset = dot(surface.position.xyz, g_xFrame_WindDirection) * g_xFrame_WindWaveSize + (surface.position.x + surface.position.y + surface.position.z) * g_xFrame_WindRandomness; + const float3 wavedir = g_xFrame_WindDirection * windweight; + const float3 wind = sin(g_xFrame_Time * g_xFrame_WindSpeed + waveoffset) * wavedir; + const float3 windPrev = sin(g_xFrame_TimePrev * g_xFrame_WindSpeed + waveoffset) * wavedir; + surface.position.xyz += wind; + surface.prevPos.xyz += windPrev; + } return surface; } @@ -99,11 +108,21 @@ inline VertexSurface MakeVertexSurfaceFromInput(Input_Object_POS_TEX input) surface.color = g_xMaterial.baseColor * unpack_rgba(input.inst.userdata.x); - uint normal_subsetIndex = asuint(input.pos.w); - surface.normal.x = (float)((normal_subsetIndex >> 0) & 0x000000FF) / 255.0f * 2.0f - 1.0f; - surface.normal.y = (float)((normal_subsetIndex >> 8) & 0x000000FF) / 255.0f * 2.0f - 1.0f; - surface.normal.z = (float)((normal_subsetIndex >> 16) & 0x000000FF) / 255.0f * 2.0f - 1.0f; - surface.subsetIndex = (normal_subsetIndex >> 24) & 0x000000FF; + uint normal_wind = asuint(input.pos.w); + surface.normal.x = (float)((normal_wind >> 0) & 0x000000FF) / 255.0f * 2.0f - 1.0f; + surface.normal.y = (float)((normal_wind >> 8) & 0x000000FF) / 255.0f * 2.0f - 1.0f; + surface.normal.z = (float)((normal_wind >> 16) & 0x000000FF) / 255.0f * 2.0f - 1.0f; + + if (g_xMaterial.IsUsingWind()) + { + const float windweight = ((normal_wind >> 24) & 0x000000FF) / 255.0f; + const float waveoffset = dot(surface.position.xyz, g_xFrame_WindDirection) * g_xFrame_WindWaveSize + (surface.position.x + surface.position.y + surface.position.z) * g_xFrame_WindRandomness; + const float3 wavedir = g_xFrame_WindDirection * windweight; + const float3 wind = sin(g_xFrame_Time * g_xFrame_WindSpeed + waveoffset) * wavedir; + const float3 windPrev = sin(g_xFrame_TimePrev * g_xFrame_WindSpeed + waveoffset) * wavedir; + surface.position.xyz += wind; + surface.prevPos.xyz += windPrev; + } surface.uvsets = float4(input.uv0 * g_xMaterial.texMulAdd.xy + g_xMaterial.texMulAdd.zw, input.uv1); @@ -122,11 +141,21 @@ inline VertexSurface MakeVertexSurfaceFromInput(Input_Object_ALL input) surface.color *= input.col; } - uint normal_subsetIndex = asuint(input.pos.w); - surface.normal.x = (float)((normal_subsetIndex >> 0) & 0x000000FF) / 255.0f * 2.0f - 1.0f; - surface.normal.y = (float)((normal_subsetIndex >> 8) & 0x000000FF) / 255.0f * 2.0f - 1.0f; - surface.normal.z = (float)((normal_subsetIndex >> 16) & 0x000000FF) / 255.0f * 2.0f - 1.0f; - surface.subsetIndex = (normal_subsetIndex >> 24) & 0x000000FF; + uint normal_wind = asuint(input.pos.w); + surface.normal.x = (float)((normal_wind >> 0) & 0x000000FF) / 255.0f * 2.0f - 1.0f; + surface.normal.y = (float)((normal_wind >> 8) & 0x000000FF) / 255.0f * 2.0f - 1.0f; + surface.normal.z = (float)((normal_wind >> 16) & 0x000000FF) / 255.0f * 2.0f - 1.0f; + + if (g_xMaterial.IsUsingWind()) + { + const float windweight = ((normal_wind >> 24) & 0x000000FF) / 255.0f; + const float waveoffset = dot(surface.position.xyz, g_xFrame_WindDirection) * g_xFrame_WindWaveSize + (surface.position.x + surface.position.y + surface.position.z) * g_xFrame_WindRandomness; + const float3 wavedir = g_xFrame_WindDirection * windweight; + const float3 wind = sin(g_xFrame_Time * g_xFrame_WindSpeed + waveoffset) * wavedir; + const float3 windPrev = sin(g_xFrame_TimePrev * g_xFrame_WindSpeed + waveoffset) * wavedir; + surface.position.xyz += wind; + surface.prevPos.xyz += windPrev; + } surface.uvsets = float4(input.uv0 * g_xMaterial.texMulAdd.xy + g_xMaterial.texMulAdd.zw, input.uv1); diff --git a/WickedEngine/objectVS_debug.hlsl b/WickedEngine/objectVS_debug.hlsl index dd1639cc2..ec41aee91 100644 --- a/WickedEngine/objectVS_debug.hlsl +++ b/WickedEngine/objectVS_debug.hlsl @@ -1,6 +1,6 @@ #include "globals.hlsli" -float4 main(float4 inPos : POSITION_NORMAL_SUBSETINDEX) : SV_POSITION +float4 main(float4 inPos : POSITION_NORMAL_WIND) : SV_POSITION { float4 pos = mul(g_xTransform, float4(inPos.xyz, 1)); diff --git a/WickedEngine/renderlightmapVS.hlsl b/WickedEngine/renderlightmapVS.hlsl index 891a03a65..6caf13ecc 100644 --- a/WickedEngine/renderlightmapVS.hlsl +++ b/WickedEngine/renderlightmapVS.hlsl @@ -4,7 +4,7 @@ struct Input { - float4 pos : POSITION_NORMAL_SUBSETINDEX; + float4 pos : POSITION_NORMAL_WIND; float2 atl : ATLAS; Input_InstancePrev instance; }; @@ -32,10 +32,10 @@ Output main(Input input) output.pos3D = mul(WORLD, float4(input.pos.xyz, 1)).xyz; - uint normal_wind_matID = asuint(input.pos.w); - output.normal.x = (float)((normal_wind_matID >> 0) & 0x000000FF) / 255.0f * 2.0f - 1.0f; - output.normal.y = (float)((normal_wind_matID >> 8) & 0x000000FF) / 255.0f * 2.0f - 1.0f; - output.normal.z = (float)((normal_wind_matID >> 16) & 0x000000FF) / 255.0f * 2.0f - 1.0f; + uint normal_wind = asuint(input.pos.w); + output.normal.x = (float)((normal_wind >> 0) & 0x000000FF) / 255.0f * 2.0f - 1.0f; + output.normal.y = (float)((normal_wind >> 8) & 0x000000FF) / 255.0f * 2.0f - 1.0f; + output.normal.z = (float)((normal_wind >> 16) & 0x000000FF) / 255.0f * 2.0f - 1.0f; return output; } \ No newline at end of file diff --git a/WickedEngine/skinningCS.hlsl b/WickedEngine/skinningCS.hlsl index dd5094ca4..d1f09bd4b 100644 --- a/WickedEngine/skinningCS.hlsl +++ b/WickedEngine/skinningCS.hlsl @@ -85,7 +85,7 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID) nor.x = (float)((pos_nor_u.w >> 0) & 0x000000FF) / 255.0f * 2.0f - 1.0f; nor.y = (float)((pos_nor_u.w >> 8) & 0x000000FF) / 255.0f * 2.0f - 1.0f; nor.z = (float)((pos_nor_u.w >> 16) & 0x000000FF) / 255.0f * 2.0f - 1.0f; - nor.w = (float)((pos_nor_u.w >> 24) & 0x000000FF) / 255.0f; // subsetindex + nor.w = (float)((pos_nor_u.w >> 24) & 0x000000FF) / 255.0f; // wind } @@ -125,7 +125,7 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID) pos_nor_u.w |= (uint)((nor.x * 0.5f + 0.5f) * 255.0f) << 0; pos_nor_u.w |= (uint)((nor.y * 0.5f + 0.5f) * 255.0f) << 8; pos_nor_u.w |= (uint)((nor.z * 0.5f + 0.5f) * 255.0f) << 16; - pos_nor_u.w |= (uint)(nor.w * 255.0f) << 24; // subsetindex + pos_nor_u.w |= (uint)(nor.w * 255.0f) << 24; // wind } // Store data: diff --git a/WickedEngine/wiGPUBVH.cpp b/WickedEngine/wiGPUBVH.cpp index ac743204b..3ee44d16b 100644 --- a/WickedEngine/wiGPUBVH.cpp +++ b/WickedEngine/wiGPUBVH.cpp @@ -411,6 +411,7 @@ void wiGPUBVH::Build(const Scene& scene, CommandList cmd) &mesh.vertexBuffer_UV0, &mesh.vertexBuffer_UV1, &mesh.vertexBuffer_COL, + &mesh.vertexBuffer_SUB, }; device->BindResources(CS, res, TEXSLOT_ONDEMAND0, arraysize(res), cmd); diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index e45cedbfe..2b4c4426c 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -1043,7 +1043,7 @@ void LoadShaders() wiJobSystem::Execute(ctx, [device] { InputLayoutDesc layout[] = { - { "POSITION_NORMAL_SUBSETINDEX", 0, MeshComponent::Vertex_POS::FORMAT, 0, InputLayoutDesc::APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, + { "POSITION_NORMAL_WIND", 0, MeshComponent::Vertex_POS::FORMAT, 0, InputLayoutDesc::APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, }; LoadShader(VS, vertexShaders[VSTYPE_OBJECT_DEBUG], "objectVS_debug.cso"); device->CreateInputLayout(layout, arraysize(layout), &vertexShaders[VSTYPE_OBJECT_DEBUG], &inputLayouts[ILTYPE_OBJECT_DEBUG]); @@ -1052,7 +1052,7 @@ void LoadShaders() wiJobSystem::Execute(ctx, [device] { InputLayoutDesc layout[] = { - { "POSITION_NORMAL_SUBSETINDEX", 0, MeshComponent::Vertex_POS::FORMAT, 0, InputLayoutDesc::APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, + { "POSITION_NORMAL_WIND", 0, MeshComponent::Vertex_POS::FORMAT, 0, InputLayoutDesc::APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, { "UVSET", 0, MeshComponent::Vertex_TEX::FORMAT, 1, InputLayoutDesc::APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, { "UVSET", 1, MeshComponent::Vertex_TEX::FORMAT, 2, InputLayoutDesc::APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, { "ATLAS", 0, MeshComponent::Vertex_TEX::FORMAT, 3, InputLayoutDesc::APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, @@ -1075,7 +1075,7 @@ void LoadShaders() wiJobSystem::Execute(ctx, [device] { InputLayoutDesc layout[] = { - { "POSITION_NORMAL_SUBSETINDEX", 0, MeshComponent::Vertex_POS::FORMAT, 0, InputLayoutDesc::APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, + { "POSITION_NORMAL_WIND", 0, MeshComponent::Vertex_POS::FORMAT, 0, InputLayoutDesc::APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, { "INSTANCEMATRIX", 0, FORMAT_R32G32B32A32_FLOAT, 1, InputLayoutDesc::APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, { "INSTANCEMATRIX", 1, FORMAT_R32G32B32A32_FLOAT, 1, InputLayoutDesc::APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, @@ -1090,7 +1090,7 @@ void LoadShaders() wiJobSystem::Execute(ctx, [device] { InputLayoutDesc layout[] = { - { "POSITION_NORMAL_SUBSETINDEX", 0, MeshComponent::Vertex_POS::FORMAT, 0, InputLayoutDesc::APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, + { "POSITION_NORMAL_WIND", 0, MeshComponent::Vertex_POS::FORMAT, 0, InputLayoutDesc::APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, { "UVSET", 0, MeshComponent::Vertex_TEX::FORMAT, 1, InputLayoutDesc::APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, { "UVSET", 1, MeshComponent::Vertex_TEX::FORMAT, 2, InputLayoutDesc::APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, @@ -1107,7 +1107,7 @@ void LoadShaders() wiJobSystem::Execute(ctx, [device] { InputLayoutDesc layout[] = { - { "POSITION_NORMAL_SUBSETINDEX", 0, MeshComponent::Vertex_POS::FORMAT, 0, InputLayoutDesc::APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, + { "POSITION_NORMAL_WIND", 0, MeshComponent::Vertex_POS::FORMAT, 0, InputLayoutDesc::APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, { "INSTANCEMATRIX", 0, FORMAT_R32G32B32A32_FLOAT, 1, InputLayoutDesc::APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, { "INSTANCEMATRIX", 1, FORMAT_R32G32B32A32_FLOAT, 1, InputLayoutDesc::APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, @@ -1122,7 +1122,7 @@ void LoadShaders() wiJobSystem::Execute(ctx, [device] { InputLayoutDesc layout[] = { - { "POSITION_NORMAL_SUBSETINDEX", 0, MeshComponent::Vertex_POS::FORMAT, 0, InputLayoutDesc::APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, + { "POSITION_NORMAL_WIND", 0, MeshComponent::Vertex_POS::FORMAT, 0, InputLayoutDesc::APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, { "UVSET", 0, MeshComponent::Vertex_TEX::FORMAT, 1, InputLayoutDesc::APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, { "UVSET", 1, MeshComponent::Vertex_TEX::FORMAT, 2, InputLayoutDesc::APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, @@ -1162,7 +1162,7 @@ void LoadShaders() wiJobSystem::Execute(ctx, [device] { InputLayoutDesc layout[] = { - { "POSITION_NORMAL_SUBSETINDEX", 0, MeshComponent::Vertex_POS::FORMAT, 0, InputLayoutDesc::APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, + { "POSITION_NORMAL_WIND", 0, MeshComponent::Vertex_POS::FORMAT, 0, InputLayoutDesc::APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, { "ATLAS", 0, MeshComponent::Vertex_TEX::FORMAT, 1, InputLayoutDesc::APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, { "INSTANCEMATRIXPREV", 0, FORMAT_R32G32B32A32_FLOAT, 2, InputLayoutDesc::APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, diff --git a/WickedEngine/wiScene.cpp b/WickedEngine/wiScene.cpp index 51c0ef83d..eee3986cc 100644 --- a/WickedEngine/wiScene.cpp +++ b/WickedEngine/wiScene.cpp @@ -300,6 +300,10 @@ namespace wiScene { retVal.options |= SHADERMATERIAL_OPTION_BIT_OCCLUSION_SECONDARY; } + if (IsUsingWind()) + { + retVal.options |= SHADERMATERIAL_OPTION_BIT_USE_WIND; + } return retVal; } @@ -356,29 +360,16 @@ namespace wiScene XMFLOAT3 _min = XMFLOAT3(FLT_MAX, FLT_MAX, FLT_MAX); XMFLOAT3 _max = XMFLOAT3(-FLT_MAX, -FLT_MAX, -FLT_MAX); - // vertexBuffer - POSITION + NORMAL + SUBSETINDEX: + // vertexBuffer - POSITION + NORMAL + WIND: { - vertex_subsets.resize(vertex_positions.size()); - - uint32_t subsetCounter = 0; - for (auto& subset : subsets) - { - for (uint32_t i = 0; i < subset.indexCount; ++i) - { - uint32_t index = indices[subset.indexOffset + i]; - vertex_subsets[index] = subsetCounter; - } - subsetCounter++; - } - std::vector vertices(vertex_positions.size()); for (size_t i = 0; i < vertices.size(); ++i) { const XMFLOAT3& pos = vertex_positions[i]; XMFLOAT3& nor = vertex_normals.empty() ? XMFLOAT3(1, 1, 1) : vertex_normals[i]; XMStoreFloat3(&nor, XMVector3Normalize(XMLoadFloat3(&nor))); - uint32_t subsetIndex = vertex_subsets[i]; - vertices[i].FromFULL(pos, nor, subsetIndex); + const uint8_t wind = vertex_windweights.empty() ? 0xFF : vertex_windweights[i]; + vertices[i].FromFULL(pos, nor, wind); _min = wiMath::Min(_min, pos); _max = wiMath::Max(_max, pos); @@ -523,6 +514,35 @@ namespace wiScene device->CreateBuffer(&bd, &InitData, &vertexBuffer_ATL); } + // vertexBuffer - SUBSETS + { + vertex_subsets.resize(vertex_positions.size()); + + uint32_t subsetCounter = 0; + for (auto& subset : subsets) + { + for (uint32_t i = 0; i < subset.indexCount; ++i) + { + uint32_t index = indices[subset.indexOffset + i]; + vertex_subsets[index] = subsetCounter; + } + subsetCounter++; + } + + GPUBufferDesc bd; + bd.Usage = USAGE_IMMUTABLE; + bd.CPUAccessFlags = 0; + bd.BindFlags = BIND_VERTEX_BUFFER | BIND_SHADER_RESOURCE; + bd.MiscFlags = 0; + bd.StructureByteStride = sizeof(uint8_t); + bd.ByteWidth = (uint32_t)(bd.StructureByteStride * vertex_subsets.size()); + bd.Format = FORMAT_R8_UINT; + + SubresourceData InitData; + InitData.pSysMem = vertex_subsets.data(); + device->CreateBuffer(&bd, &InitData, &vertexBuffer_SUB); + } + // vertexBuffer_PRE will be created on demand later! vertexBuffer_PRE = GPUBuffer(); @@ -966,8 +986,8 @@ namespace wiScene XMStoreFloat3(&pos, XMVector3Transform(XMLoadFloat3(&pos), W)); XMFLOAT3 nor = mesh.vertex_normals.empty() ? XMFLOAT3(1, 1, 1) : mesh.vertex_normals[i]; XMStoreFloat3(&nor, XMVector3Normalize(XMVector3TransformNormal(XMLoadFloat3(&nor), W))); - uint32_t subsetIndex = mesh.vertex_subsets[i]; - vertex_positions_simulation[i].FromFULL(pos, nor, subsetIndex); + const uint8_t wind = mesh.vertex_windweights.empty() ? 0xFF : mesh.vertex_windweights[i]; + vertex_positions_simulation[i].FromFULL(pos, nor, wind); _min = wiMath::Min(_min, pos); _max = wiMath::Max(_max, pos); } diff --git a/WickedEngine/wiScene.h b/WickedEngine/wiScene.h index e0621e5c9..c99d77fa2 100644 --- a/WickedEngine/wiScene.h +++ b/WickedEngine/wiScene.h @@ -116,6 +116,7 @@ namespace wiScene SPECULAR_GLOSSINESS_WORKFLOW = 1 << 6, OCCLUSION_PRIMARY = 1 << 7, OCCLUSION_SECONDARY = 1 << 8, + USE_WIND = 1 << 9, }; uint32_t _flags = DIRTY | CAST_SHADOW; @@ -205,6 +206,7 @@ namespace wiScene inline bool IsAlphaTestEnabled() const { return alphaRef <= 1.0f - 1.0f / 256.0f; } inline bool IsFlipNormalMap() const { return _flags & FLIP_NORMALMAP; } inline bool IsUsingVertexColors() const { return _flags & USE_VERTEXCOLORS; } + inline bool IsUsingWind() const { return _flags & USE_WIND; } inline bool IsUsingSpecularGlossinessWorkflow() const { return _flags & SPECULAR_GLOSSINESS_WORKFLOW; } inline bool IsOcclusionEnabled_Primary() const { return _flags & OCCLUSION_PRIMARY; } inline bool IsOcclusionEnabled_Secondary() const { return _flags & OCCLUSION_SECONDARY; } @@ -225,6 +227,7 @@ namespace wiScene inline void SetAlphaRef(float value) { SetDirty(); alphaRef = value; } inline void SetFlipNormalMap(bool value) { SetDirty(); if (value) { _flags |= FLIP_NORMALMAP; } else { _flags &= ~FLIP_NORMALMAP; } } inline void SetUseVertexColors(bool value) { SetDirty(); if (value) { _flags |= USE_VERTEXCOLORS; } else { _flags &= ~USE_VERTEXCOLORS; } } + inline void SetUseWind(bool value) { SetDirty(); if (value) { _flags |= USE_WIND; } else { _flags &= ~USE_WIND; } } inline void SetUseSpecularGlossinessWorkflow(bool value) { SetDirty(); if (value) { _flags |= SPECULAR_GLOSSINESS_WORKFLOW; } else { _flags &= ~SPECULAR_GLOSSINESS_WORKFLOW; } } inline void SetCustomShaderID(int id) { customShaderID = id; } inline void DisableCustomShader() { customShaderID = -1; } @@ -260,6 +263,7 @@ namespace wiScene std::vector vertex_boneweights; std::vector vertex_atlas; std::vector vertex_colors; + std::vector vertex_windweights; std::vector indices; struct MeshSubset @@ -293,6 +297,7 @@ namespace wiScene wiGraphics::GPUBuffer vertexBuffer_ATL; wiGraphics::GPUBuffer vertexBuffer_PRE; wiGraphics::GPUBuffer streamoutBuffer_POS; + wiGraphics::GPUBuffer vertexBuffer_SUB; std::vector vertex_subsets; @@ -330,14 +335,14 @@ namespace wiScene struct Vertex_POS { XMFLOAT3 pos = XMFLOAT3(0.0f, 0.0f, 0.0f); - uint32_t normal_subsetIndex = 0; + uint32_t normal_wind = 0; - void FromFULL(const XMFLOAT3& _pos, const XMFLOAT3& _nor, uint32_t subsetIndex) + void FromFULL(const XMFLOAT3& _pos, const XMFLOAT3& _nor, uint8_t wind) { pos.x = _pos.x; pos.y = _pos.y; pos.z = _pos.z; - MakeFromParams(_nor, subsetIndex); + MakeFromParams(_nor, wind); } inline XMVECTOR LoadPOS() const { @@ -349,36 +354,34 @@ namespace wiScene } inline void MakeFromParams(const XMFLOAT3& normal) { - normal_subsetIndex = normal_subsetIndex & 0xFF000000; // reset only the normals + normal_wind = normal_wind & 0xFF000000; // reset only the normals - normal_subsetIndex |= (uint32_t)((normal.x * 0.5f + 0.5f) * 255.0f) << 0; - normal_subsetIndex |= (uint32_t)((normal.y * 0.5f + 0.5f) * 255.0f) << 8; - normal_subsetIndex |= (uint32_t)((normal.z * 0.5f + 0.5f) * 255.0f) << 16; + normal_wind |= (uint32_t)((normal.x * 0.5f + 0.5f) * 255.0f) << 0; + normal_wind |= (uint32_t)((normal.y * 0.5f + 0.5f) * 255.0f) << 8; + normal_wind |= (uint32_t)((normal.z * 0.5f + 0.5f) * 255.0f) << 16; } - inline void MakeFromParams(const XMFLOAT3& normal, uint32_t subsetIndex) + inline void MakeFromParams(const XMFLOAT3& normal, uint8_t wind) { - assert(subsetIndex < 256); // subsetIndex is packed onto 8 bits + normal_wind = 0; - normal_subsetIndex = 0; - - normal_subsetIndex |= (uint32_t)((normal.x * 0.5f + 0.5f) * 255.0f) << 0; - normal_subsetIndex |= (uint32_t)((normal.y * 0.5f + 0.5f) * 255.0f) << 8; - normal_subsetIndex |= (uint32_t)((normal.z * 0.5f + 0.5f) * 255.0f) << 16; - normal_subsetIndex |= (subsetIndex & 0x000000FF) << 24; + normal_wind |= (uint32_t)((normal.x * 0.5f + 0.5f) * 255.0f) << 0; + normal_wind |= (uint32_t)((normal.y * 0.5f + 0.5f) * 255.0f) << 8; + normal_wind |= (uint32_t)((normal.z * 0.5f + 0.5f) * 255.0f) << 16; + normal_wind |= (uint32_t)wind << 24; } inline XMFLOAT3 GetNor_FULL() const { XMFLOAT3 nor_FULL(0, 0, 0); - nor_FULL.x = (float)((normal_subsetIndex >> 0) & 0x000000FF) / 255.0f * 2.0f - 1.0f; - nor_FULL.y = (float)((normal_subsetIndex >> 8) & 0x000000FF) / 255.0f * 2.0f - 1.0f; - nor_FULL.z = (float)((normal_subsetIndex >> 16) & 0x000000FF) / 255.0f * 2.0f - 1.0f; + nor_FULL.x = (float)((normal_wind >> 0) & 0x000000FF) / 255.0f * 2.0f - 1.0f; + nor_FULL.y = (float)((normal_wind >> 8) & 0x000000FF) / 255.0f * 2.0f - 1.0f; + nor_FULL.z = (float)((normal_wind >> 16) & 0x000000FF) / 255.0f * 2.0f - 1.0f; return nor_FULL; } - inline uint32_t GetMaterialIndex() const + inline uint8_t GetWind() const { - return (normal_subsetIndex >> 24) & 0x000000FF; + return (normal_wind >> 24) & 0x000000FF; } static const wiGraphics::FORMAT FORMAT = wiGraphics::FORMAT::FORMAT_R32G32B32A32_FLOAT; diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 46608b059..30307daac 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wiVersion // minor features, major updates const int minor = 39; // minor bug fixes, alterations, refactors, updates - const int revision = 49; + const int revision = 50; long GetVersion()