diff --git a/WickedEngine/shaders/ShaderInterop_EmittedParticle.h b/WickedEngine/shaders/ShaderInterop_EmittedParticle.h index b0d53bee0..b000784a0 100644 --- a/WickedEngine/shaders/ShaderInterop_EmittedParticle.h +++ b/WickedEngine/shaders/ShaderInterop_EmittedParticle.h @@ -62,7 +62,7 @@ CBUFFER(EmittedParticleCB, CBSLOT_OTHER_EMITTEDPARTICLE) float2 xEmitterTexMul; float xEmitterFrameRate; - float padding_xEmitter; + uint xEmitterLayerMask; float xSPH_h; // smoothing radius float xSPH_h_rcp; // 1.0f / smoothing radius diff --git a/WickedEngine/shaders/ShaderInterop_HairParticle.h b/WickedEngine/shaders/ShaderInterop_HairParticle.h index 6aae37a64..1f644e566 100644 --- a/WickedEngine/shaders/ShaderInterop_HairParticle.h +++ b/WickedEngine/shaders/ShaderInterop_HairParticle.h @@ -44,9 +44,8 @@ CBUFFER(HairParticleCB, CBSLOT_OTHER_HAIRPARTICLE) uint xHairFrameStart; float2 xHairTexMul; - float xHairAspect; - float3 padding_xHair; + uint xHairLayerMask; }; #endif // WI_SHADERINTEROP_HAIRPARTICLE_H diff --git a/WickedEngine/shaders/emittedparticle_simulateCS.hlsl b/WickedEngine/shaders/emittedparticle_simulateCS.hlsl index 241c4a0e0..e3a45bd33 100644 --- a/WickedEngine/shaders/emittedparticle_simulateCS.hlsl +++ b/WickedEngine/shaders/emittedparticle_simulateCS.hlsl @@ -8,17 +8,6 @@ RWSTRUCTUREDBUFFER(deadBuffer, uint, 3); RWRAWBUFFER(counterBuffer, 4); RWSTRUCTUREDBUFFER(distanceBuffer, float, 6); -#define NUM_LDS_FORCEFIELDS 32 -struct LDS_ForceField -{ - uint type; - float3 position; - float gravity; - float range_rcp; - float3 normal; -}; -groupshared LDS_ForceField forceFields[NUM_LDS_FORCEFIELDS]; - #define SPH_FLOOR_COLLISION #define SPH_BOX_COLLISION @@ -29,22 +18,6 @@ void main(uint3 DTid : SV_DispatchThreadID, uint Gid : SV_GroupIndex) //uint aliveCount = counterBuffer[0].aliveCount; uint aliveCount = counterBuffer.Load(PARTICLECOUNTER_OFFSET_ALIVECOUNT); - // Load the forcefields into LDS: - uint numForceFields = min(g_xFrame_ForceFieldArrayCount, NUM_LDS_FORCEFIELDS); - if (Gid < numForceFields) - { - uint forceFieldID = g_xFrame_ForceFieldArrayOffset + Gid; - ShaderEntity forceField = EntityArray[forceFieldID]; - - forceFields[Gid].type = (uint)forceField.GetType(); - forceFields[Gid].position = forceField.position; - forceFields[Gid].gravity = forceField.GetEnergy(); - forceFields[Gid].range_rcp = forceField.GetRange(); // it is actually uploaded from CPU as 1.0f / range - forceFields[Gid].normal = forceField.GetDirection(); - } - - GroupMemoryBarrierWithGroupSync(); - if (DTid.x < aliveCount) { // simulation can be either fixed or variable timestep: @@ -56,24 +29,27 @@ void main(uint3 DTid : SV_DispatchThreadID, uint Gid : SV_GroupIndex) if (particle.life > 0) { // simulate: - - for (uint i = 0; i < numForceFields; ++i) + for (uint i = 0; i < g_xFrame_ForceFieldArrayCount; ++i) { - LDS_ForceField forceField = forceFields[i]; + ShaderEntity forceField = EntityArray[g_xFrame_ForceFieldArrayOffset + i]; - float3 dir = forceField.position - particle.position; - float dist; - if (forceField.type == ENTITY_TYPE_FORCEFIELD_POINT) // point-based force field + [branch] + if (forceField.layerMask & xEmitterLayerMask) { - dist = length(dir); - } - else // planar force field - { - dist = dot(forceField.normal, dir); - dir = forceField.normal; - } + float3 dir = forceField.position - particle.position; + float dist; + if (forceField.GetType() == ENTITY_TYPE_FORCEFIELD_POINT) // point-based force field + { + dist = length(dir); + } + else // planar force field + { + dist = dot(forceField.GetDirection(), dir); + dir = forceField.GetDirection(); + } - particle.force += dir * forceField.gravity * (1 - saturate(dist * forceField.range_rcp)); + particle.force += dir * forceField.GetEnergy() * (1 - saturate(dist * forceField.GetRange())); // GetRange() is actually uploaded as 1.0 / range + } } diff --git a/WickedEngine/shaders/hairparticle_simulateCS.hlsl b/WickedEngine/shaders/hairparticle_simulateCS.hlsl index b7273a03b..2bda44fc5 100644 --- a/WickedEngine/shaders/hairparticle_simulateCS.hlsl +++ b/WickedEngine/shaders/hairparticle_simulateCS.hlsl @@ -10,35 +10,9 @@ TYPEDBUFFER(meshIndexBuffer, uint, TEXSLOT_ONDEMAND0); RAWBUFFER(meshVertexBuffer_POS, TEXSLOT_ONDEMAND1); TYPEDBUFFER(meshVertexBuffer_length, float, TEXSLOT_ONDEMAND2); -#define NUM_LDS_FORCEFIELDS 32 -struct LDS_ForceField -{ - uint type; - float3 position; - float gravity; - float range_rcp; - float3 normal; -}; -groupshared LDS_ForceField forceFields[NUM_LDS_FORCEFIELDS]; - [numthreads(THREADCOUNT_SIMULATEHAIR, 1, 1)] void main(uint3 DTid : SV_DispatchThreadID, uint3 Gid : SV_GroupID, uint groupIndex : SV_GroupIndex) { - // Load the forcefields into LDS: - uint numForceFields = min(g_xFrame_ForceFieldArrayCount, NUM_LDS_FORCEFIELDS); - if (groupIndex < numForceFields) - { - uint forceFieldID = g_xFrame_ForceFieldArrayOffset + groupIndex; - ShaderEntity forceField = EntityArray[forceFieldID]; - - forceFields[groupIndex].type = (uint)forceField.GetType(); - forceFields[groupIndex].position = forceField.position; - forceFields[groupIndex].gravity = forceField.GetEnergy(); - forceFields[groupIndex].range_rcp = forceField.GetRange(); // it is actually uploaded from CPU as 1.0f / range - forceFields[groupIndex].normal = forceField.GetDirection(); - } - GroupMemoryBarrierWithGroupSync(); - if (DTid.x >= xHairParticleCount) return; @@ -130,25 +104,29 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 Gid : SV_GroupID, uint groupIn // Accumulate forces: float3 force = 0; - for (uint i = 0; i < numForceFields; ++i) + for (uint i = 0; i < g_xFrame_ForceFieldArrayCount; ++i) { - LDS_ForceField forceField = forceFields[i]; + ShaderEntity forceField = EntityArray[g_xFrame_ForceFieldArrayOffset + i]; - //float3 dir = forceField.position - PointOnLineSegmentNearestPoint(base, tip, forceField.position); - float3 dir = forceField.position - tip; - float dist; - if (forceField.type == ENTITY_TYPE_FORCEFIELD_POINT) // point-based force field - { - //dist = length(dir); - dist = length(forceField.position - ClosestPointOnSegment(base, tip, forceField.position)); - } - else // planar force field - { - dist = dot(forceField.normal, dir); - dir = forceField.normal; - } + [branch] + if (forceField.layerMask & xHairLayerMask) + { + //float3 dir = forceField.position - PointOnLineSegmentNearestPoint(base, tip, forceField.position); + float3 dir = forceField.position - tip; + float dist; + if (forceField.GetType() == ENTITY_TYPE_FORCEFIELD_POINT) // point-based force field + { + //dist = length(dir); + dist = length(forceField.position - ClosestPointOnSegment(base, tip, forceField.position)); + } + else // planar force field + { + dist = dot(forceField.GetDirection(), dir); + dir = forceField.GetDirection(); + } - force += dir * forceField.gravity * (1 - saturate(dist * forceField.range_rcp)); + force += dir * forceField.GetEnergy() * (1 - saturate(dist * forceField.GetRange())); // GetRange() is actually uploaded as 1.0 / range + } } // Pull back to rest position: diff --git a/WickedEngine/wiEmittedParticle.cpp b/WickedEngine/wiEmittedParticle.cpp index e0487e219..86854fec7 100644 --- a/WickedEngine/wiEmittedParticle.cpp +++ b/WickedEngine/wiEmittedParticle.cpp @@ -276,6 +276,7 @@ void wiEmittedParticle::UpdateGPU(const TransformComponent& transform, const Mat cb.xParticleDrag = drag; XMStoreFloat3(&cb.xParticleVelocity, XMVector3TransformNormal(XMLoadFloat3(&velocity), XMLoadFloat4x4(&transform.world))); cb.xParticleRandomColorFactor = random_color; + cb.xEmitterLayerMask = layerMask; cb.xEmitterOptions = 0; if (IsSPHEnabled()) diff --git a/WickedEngine/wiEmittedParticle.h b/WickedEngine/wiEmittedParticle.h index ee3762e37..8b59c331c 100644 --- a/WickedEngine/wiEmittedParticle.h +++ b/WickedEngine/wiEmittedParticle.h @@ -117,6 +117,7 @@ public: // Non-serialized attributes: XMFLOAT3 center; uint32_t statisticsReadBackIndex = 0; + uint32_t layerMask = ~0u; inline bool IsDebug() const { return _flags & FLAG_DEBUG; } inline bool IsPaused() const { return _flags & FLAG_PAUSED; } diff --git a/WickedEngine/wiHairParticle.cpp b/WickedEngine/wiHairParticle.cpp index 3bdfe5345..3592aba59 100644 --- a/WickedEngine/wiHairParticle.cpp +++ b/WickedEngine/wiHairParticle.cpp @@ -189,6 +189,7 @@ void wiHairParticle::UpdateGPU(const MeshComponent& mesh, const MaterialComponen hcb.xHairFrameStart = frameStart; hcb.xHairTexMul = float2(1.0f / (float)hcb.xHairFramesXY.x, 1.0f / (float)hcb.xHairFramesXY.y); hcb.xHairAspect = (float)std::max(1u, desc.Width) / (float)std::max(1u, desc.Height); + hcb.xHairLayerMask = layerMask; device->UpdateBuffer(&cb, &hcb, cmd); // Simulate: diff --git a/WickedEngine/wiHairParticle.h b/WickedEngine/wiHairParticle.h index c764362e8..a77db4e33 100644 --- a/WickedEngine/wiHairParticle.h +++ b/WickedEngine/wiHairParticle.h @@ -60,6 +60,7 @@ public: XMFLOAT4X4 worldPrev; AABB aabb; std::vector indices; // it is dependent on vertex_lengths and contains triangles with non-zero lengths + uint32_t layerMask = ~0u; void Serialize(wiArchive& archive, wiECS::EntitySerializer& seri); diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index b9f99af20..7a6544db0 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -3559,9 +3559,8 @@ void UpdateVisibility(Visibility& vis) // Cull emitters: for (size_t i = 0; i < vis.scene->emitters.GetCount(); ++i) { - Entity entity = vis.scene->emitters.GetEntity(i); - const LayerComponent* layer = vis.scene->layers.GetComponent(entity); - if (layer != nullptr && !(layer->GetLayerMask() & vis.layerMask)) + const wiEmittedParticle& emitter = vis.scene->emitters[i]; + if (!(emitter.layerMask & vis.layerMask)) { continue; } @@ -3576,14 +3575,11 @@ void UpdateVisibility(Visibility& vis) // Cull hairs: for (size_t i = 0; i < vis.scene->hairs.GetCount(); ++i) { - Entity entity = vis.scene->hairs.GetEntity(i); - const LayerComponent* layer = vis.scene->layers.GetComponent(entity); - if (layer != nullptr && !(layer->GetLayerMask() & vis.layerMask)) + const wiHairParticle& hair = vis.scene->hairs[i]; + if (!(hair.layerMask & vis.layerMask)) { continue; } - - const wiHairParticle& hair = vis.scene->hairs[i]; if (hair.meshID == INVALID_ENTITY || !vis.frustum.CheckBoxFast(hair.aabb)) { continue; diff --git a/WickedEngine/wiScene.cpp b/WickedEngine/wiScene.cpp index a7559f94d..29d55921d 100644 --- a/WickedEngine/wiScene.cpp +++ b/WickedEngine/wiScene.cpp @@ -3152,6 +3152,13 @@ namespace wiScene wiEmittedParticle& emitter = emitters[args.jobIndex]; Entity entity = emitters.GetEntity(args.jobIndex); + + const LayerComponent* layer = layers.GetComponent(entity); + if (layer != nullptr) + { + emitter.layerMask = layer->GetLayerMask(); + } + const TransformComponent& transform = *transforms.GetComponent(entity); emitter.UpdateCPU(transform, dt); }); @@ -3159,10 +3166,16 @@ namespace wiScene wiJobSystem::Dispatch(ctx, (uint32_t)hairs.GetCount(), small_subtask_groupsize, [&](wiJobArgs args) { wiHairParticle& hair = hairs[args.jobIndex]; + Entity entity = hairs.GetEntity(args.jobIndex); + + const LayerComponent* layer = layers.GetComponent(entity); + if (layer != nullptr) + { + hair.layerMask = layer->GetLayerMask(); + } if (hair.meshID != INVALID_ENTITY) { - Entity entity = hairs.GetEntity(args.jobIndex); const MeshComponent* mesh = meshes.GetComponent(hair.meshID); if (mesh != nullptr) diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index d744bef5e..c5455cf67 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wiVersion // minor features, major updates, breaking compatibility changes const int minor = 55; // minor bug fixes, alterations, refactors, updates - const int revision = 3; + const int revision = 4; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);