diff --git a/Editor/EmitterWindow.cpp b/Editor/EmitterWindow.cpp index 9279709eb..c2562555d 100644 --- a/Editor/EmitterWindow.cpp +++ b/Editor/EmitterWindow.cpp @@ -11,7 +11,7 @@ using namespace wiScene; void EmitterWindow::Create(EditorComponent* editor) { wiWindow::Create("Emitter Window"); - SetSize(XMFLOAT2(680, 660)); + SetSize(XMFLOAT2(680, 700)); float x = 200; float y = 5; @@ -290,6 +290,97 @@ void EmitterWindow::Create(EditorComponent* editor) }); AddWidget(&frameStartInput); + + + + VelocityXInput.Create(""); + VelocityXInput.SetValue(0); + VelocityXInput.SetDescription("Starting Velocity: "); + VelocityXInput.SetTooltip("Vector X component"); + VelocityXInput.SetPos(XMFLOAT2(x, y += step)); + VelocityXInput.SetSize(XMFLOAT2(38, itemheight)); + VelocityXInput.OnInputAccepted([&](wiEventArgs args) { + auto emitter = GetEmitter(); + if (emitter != nullptr) + { + emitter->velocity.x = args.fValue; + } + }); + AddWidget(&VelocityXInput); + + VelocityYInput.Create(""); + VelocityYInput.SetValue(0); + VelocityYInput.SetTooltip("Vector Y component"); + VelocityYInput.SetPos(XMFLOAT2(x + 40, y)); + VelocityYInput.SetSize(XMFLOAT2(38, itemheight)); + VelocityYInput.OnInputAccepted([&](wiEventArgs args) { + auto emitter = GetEmitter(); + if (emitter != nullptr) + { + emitter->velocity.y = args.fValue; + } + }); + AddWidget(&VelocityYInput); + + VelocityZInput.Create(""); + VelocityZInput.SetValue(0); + VelocityZInput.SetTooltip("Vector Z component"); + VelocityZInput.SetPos(XMFLOAT2(x + 80, y)); + VelocityZInput.SetSize(XMFLOAT2(38, itemheight)); + VelocityZInput.OnInputAccepted([&](wiEventArgs args) { + auto emitter = GetEmitter(); + if (emitter != nullptr) + { + emitter->velocity.z = args.fValue; + } + }); + AddWidget(&VelocityZInput); + + + + GravityXInput.Create(""); + GravityXInput.SetValue(0); + GravityXInput.SetDescription("Gravity: "); + GravityXInput.SetTooltip("Vector X component"); + GravityXInput.SetPos(XMFLOAT2(x + 200, y)); + GravityXInput.SetSize(XMFLOAT2(38, itemheight)); + GravityXInput.OnInputAccepted([&](wiEventArgs args) { + auto emitter = GetEmitter(); + if (emitter != nullptr) + { + emitter->gravity.x = args.fValue; + } + }); + AddWidget(&GravityXInput); + + GravityYInput.Create(""); + GravityYInput.SetValue(0); + GravityYInput.SetTooltip("Vector Y component"); + GravityYInput.SetPos(XMFLOAT2(x + 240, y)); + GravityYInput.SetSize(XMFLOAT2(38, itemheight)); + GravityYInput.OnInputAccepted([&](wiEventArgs args) { + auto emitter = GetEmitter(); + if (emitter != nullptr) + { + emitter->gravity.y = args.fValue; + } + }); + AddWidget(&GravityYInput); + + GravityZInput.Create(""); + GravityZInput.SetValue(0); + GravityZInput.SetTooltip("Vector Z component"); + GravityZInput.SetPos(XMFLOAT2(x + 280, y)); + GravityZInput.SetSize(XMFLOAT2(38, itemheight)); + GravityZInput.OnInputAccepted([&](wiEventArgs args) { + auto emitter = GetEmitter(); + if (emitter != nullptr) + { + emitter->gravity.z = args.fValue; + } + }); + AddWidget(&GravityZInput); + maxParticlesSlider.Create(100.0f, 1000000.0f, 10000, 100000, "Max particle count: "); maxParticlesSlider.SetSize(XMFLOAT2(360, itemheight)); maxParticlesSlider.SetPos(XMFLOAT2(x, y += step)); @@ -416,6 +507,20 @@ void EmitterWindow::Create(EditorComponent* editor) emitLifeRandomnessSlider.SetTooltip("Set the randomness of lifespans for the emitted particles."); AddWidget(&emitLifeRandomnessSlider); + emitColorRandomnessSlider.Create(0.0f, 2.0f, 0.0f, 100000, "Color randomness: "); + emitColorRandomnessSlider.SetSize(XMFLOAT2(360, itemheight)); + emitColorRandomnessSlider.SetPos(XMFLOAT2(x, y += step)); + emitColorRandomnessSlider.OnSlide([&](wiEventArgs args) { + auto emitter = GetEmitter(); + if (emitter != nullptr) + { + emitter->random_color = args.fValue; + } + }); + emitColorRandomnessSlider.SetEnabled(false); + emitColorRandomnessSlider.SetTooltip("Set the randomness of color for the emitted particles."); + AddWidget(&emitColorRandomnessSlider); + emitMotionBlurSlider.Create(0.0f, 1.0f, 1.0f, 100000, "Motion blur: "); emitMotionBlurSlider.SetSize(XMFLOAT2(360, itemheight)); emitMotionBlurSlider.SetPos(XMFLOAT2(x, y += step)); @@ -462,6 +567,20 @@ void EmitterWindow::Create(EditorComponent* editor) + dragSlider.Create(-1, 0.016f, -1, 100000, "Drag: "); + dragSlider.SetSize(XMFLOAT2(360, itemheight)); + dragSlider.SetPos(XMFLOAT2(x, y += step)); + dragSlider.OnSlide([&](wiEventArgs args) { + auto emitter = GetEmitter(); + if (emitter != nullptr) + { + emitter->drag = args.fValue; + } + }); + dragSlider.SetEnabled(false); + dragSlider.SetTooltip("The velocity will be multiplied with this value, so lower than 1 will slow decelerate the particles."); + AddWidget(&dragSlider); + //////////////// SPH //////////////////////////// @@ -541,33 +660,7 @@ void EmitterWindow::SetEntity(Entity entity) if (emitter != nullptr) { - emitterNameField.SetEnabled(true); - restartButton.SetEnabled(true); - shaderTypeComboBox.SetEnabled(true); - meshComboBox.SetEnabled(true); - debugCheckBox.SetEnabled(true); - volumeCheckBox.SetEnabled(true); - frameBlendingCheckBox.SetEnabled(true); - sortCheckBox.SetEnabled(true); - depthCollisionsCheckBox.SetEnabled(true); - sphCheckBox.SetEnabled(true); - pauseCheckBox.SetEnabled(true); - maxParticlesSlider.SetEnabled(true); - emitCountSlider.SetEnabled(true); - emitSizeSlider.SetEnabled(true); - emitRotationSlider.SetEnabled(true); - emitNormalSlider.SetEnabled(true); - emitScalingSlider.SetEnabled(true); - emitLifeSlider.SetEnabled(true); - emitRandomnessSlider.SetEnabled(true); - emitLifeRandomnessSlider.SetEnabled(true); - emitMotionBlurSlider.SetEnabled(true); - emitMassSlider.SetEnabled(true); - timestepSlider.SetEnabled(true); - sph_h_Slider.SetEnabled(true); - sph_K_Slider.SetEnabled(true); - sph_p0_Slider.SetEnabled(true); - sph_e_Slider.SetEnabled(true); + SetEnabled(true); shaderTypeComboBox.SetSelected((int)emitter->shaderType); @@ -593,9 +686,17 @@ void EmitterWindow::SetEntity(Entity entity) emitLifeSlider.SetValue(emitter->life); emitRandomnessSlider.SetValue(emitter->random_factor); emitLifeRandomnessSlider.SetValue(emitter->random_life); + emitColorRandomnessSlider.SetValue(emitter->random_color); emitMotionBlurSlider.SetValue(emitter->motionBlurAmount); emitMassSlider.SetValue(emitter->mass); timestepSlider.SetValue(emitter->FIXED_TIMESTEP); + dragSlider.SetValue(emitter->drag); + VelocityXInput.SetValue(emitter->velocity.x); + VelocityYInput.SetValue(emitter->velocity.y); + VelocityZInput.SetValue(emitter->velocity.z); + GravityXInput.SetValue(emitter->gravity.x); + GravityYInput.SetValue(emitter->gravity.y); + GravityZInput.SetValue(emitter->gravity.z); sph_h_Slider.SetValue(emitter->SPH_h); sph_K_Slider.SetValue(emitter->SPH_K); @@ -608,33 +709,9 @@ void EmitterWindow::SetEntity(Entity entity) { infoLabel.SetText("No emitter object selected."); - emitterNameField.SetEnabled(false); - restartButton.SetEnabled(false); - shaderTypeComboBox.SetEnabled(false); - meshComboBox.SetEnabled(false); - debugCheckBox.SetEnabled(false); - volumeCheckBox.SetEnabled(false); - frameBlendingCheckBox.SetEnabled(false); - sortCheckBox.SetEnabled(false); - depthCollisionsCheckBox.SetEnabled(false); - sphCheckBox.SetEnabled(false); - pauseCheckBox.SetEnabled(false); - maxParticlesSlider.SetEnabled(false); - emitCountSlider.SetEnabled(false); - emitSizeSlider.SetEnabled(false); - emitRotationSlider.SetEnabled(false); - emitNormalSlider.SetEnabled(false); - emitScalingSlider.SetEnabled(false); - emitLifeSlider.SetEnabled(false); - emitRandomnessSlider.SetEnabled(false); - emitLifeRandomnessSlider.SetEnabled(false); - emitMotionBlurSlider.SetEnabled(false); - emitMassSlider.SetEnabled(false); - timestepSlider.SetEnabled(false); - sph_h_Slider.SetEnabled(false); - sph_K_Slider.SetEnabled(false); - sph_p0_Slider.SetEnabled(false); - sph_e_Slider.SetEnabled(false); + SetEnabled(false); + + addButton.SetEnabled(true); } } diff --git a/Editor/EmitterWindow.h b/Editor/EmitterWindow.h index fc0ac69d7..580eb8202 100644 --- a/Editor/EmitterWindow.h +++ b/Editor/EmitterWindow.h @@ -39,9 +39,18 @@ public: wiSlider emitLifeSlider; wiSlider emitRandomnessSlider; wiSlider emitLifeRandomnessSlider; + wiSlider emitColorRandomnessSlider; wiSlider emitMotionBlurSlider; wiSlider emitMassSlider; wiSlider timestepSlider; + wiSlider dragSlider; + wiTextInputField VelocityXInput; + wiTextInputField VelocityYInput; + wiTextInputField VelocityZInput; + wiTextInputField GravityXInput; + wiTextInputField GravityYInput; + wiTextInputField GravityZInput; + wiSlider sph_h_Slider; wiSlider sph_K_Slider; wiSlider sph_p0_Slider; diff --git a/WickedEngine/ArchiveVersionHistory.txt b/WickedEngine/ArchiveVersionHistory.txt index 43a1f5724..d8251e01b 100644 --- a/WickedEngine/ArchiveVersionHistory.txt +++ b/WickedEngine/ArchiveVersionHistory.txt @@ -1,5 +1,6 @@ This file contains changelog of wiArchive versions +64: serialized per-emitter gravity, velocity, drag and random_color 63: serialized wiResourceManager embedded resources 62: serialized WeatherComponent::colorGradingMapName property 61: serialized sheen and clearcoat material properties diff --git a/WickedEngine/ShaderInterop_EmittedParticle.h b/WickedEngine/ShaderInterop_EmittedParticle.h index a5d0f5087..b0d53bee0 100644 --- a/WickedEngine/ShaderInterop_EmittedParticle.h +++ b/WickedEngine/ShaderInterop_EmittedParticle.h @@ -79,6 +79,12 @@ CBUFFER(EmittedParticleCB, CBSLOT_OTHER_EMITTEDPARTICLE) float xEmitterFixedTimestep; // we can force a fixed timestep (>0) onto the simulation to avoid blowing up float xParticleEmissive; + float3 xParticleGravity; + float xParticleDrag; + + float3 xParticleVelocity; + float xParticleRandomColorFactor; + }; static const uint THREADCOUNT_EMIT = 256; diff --git a/WickedEngine/emittedparticle_emitCS.hlsl b/WickedEngine/emittedparticle_emitCS.hlsl index da9a91568..adb7b8bf2 100644 --- a/WickedEngine/emittedparticle_emitCS.hlsl +++ b/WickedEngine/emittedparticle_emitCS.hlsl @@ -99,7 +99,7 @@ void main(uint3 DTid : SV_DispatchThreadID) particle.position = pos; particle.force = 0; particle.mass = xParticleMass; - particle.velocity = (nor + (float3(rand(seed, uv), rand(seed, uv), rand(seed, uv)) - 0.5f) * xParticleRandomFactor) * xParticleNormalFactor; + particle.velocity = xParticleVelocity + (nor + (float3(rand(seed, uv), rand(seed, uv), rand(seed, uv)) - 0.5f) * xParticleRandomFactor) * xParticleNormalFactor; particle.rotationalVelocity = xParticleRotation + (rand(seed, uv) - 0.5f) * xParticleRandomFactor; particle.maxLife = xParticleLifeSpan + xParticleLifeSpan * (rand(seed, uv) - 0.5f) * xParticleLifeSpanRandomness; particle.life = particle.maxLife; @@ -109,10 +109,9 @@ void main(uint3 DTid : SV_DispatchThreadID) particle.color_mirror |= ((rand(seed, uv) < 0.5f) << 30) & 0x20000000; uint color_modifier = 0; - //color_modifier |= (uint)(255.0f * lerp(1, rand(seed, uv), xParticleRandomFactor)) << 0; - //color_modifier |= (uint)(255.0f * lerp(1, rand(seed, uv), xParticleRandomFactor)) << 8; - //color_modifier |= (uint)(255.0f * lerp(1, rand(seed, uv), xParticleRandomFactor)) << 16; - color_modifier = 0x00FFFFFF; + color_modifier |= (uint)(255.0 * lerp(1, rand(seed, uv), xParticleRandomColorFactor)) << 0; + color_modifier |= (uint)(255.0 * lerp(1, rand(seed, uv), xParticleRandomColorFactor)) << 8; + color_modifier |= (uint)(255.0 * lerp(1, rand(seed, uv), xParticleRandomColorFactor)) << 16; particle.color_mirror |= xParticleColor & color_modifier; diff --git a/WickedEngine/emittedparticle_simulateCS.hlsl b/WickedEngine/emittedparticle_simulateCS.hlsl index a5dedfbba..241c4a0e0 100644 --- a/WickedEngine/emittedparticle_simulateCS.hlsl +++ b/WickedEngine/emittedparticle_simulateCS.hlsl @@ -120,18 +120,19 @@ void main(uint3 DTid : SV_DispatchThreadID, uint Gid : SV_GroupIndex) #endif // DEPTHCOLLISIONS // integrate: + particle.force += xParticleGravity; particle.velocity += particle.force * dt; particle.position += particle.velocity * dt; // reset force for next frame: particle.force = 0; + // drag: + particle.velocity *= xParticleDrag; + [branch] if (xEmitterOptions & EMITTER_OPTION_BIT_SPH_ENABLED) { - // drag: - particle.velocity *= 0.98f; - // debug collisions: float elastic = 0.6; diff --git a/WickedEngine/emittedparticle_sphforceCS.hlsl b/WickedEngine/emittedparticle_sphforceCS.hlsl index bb77b2c6e..3b2f7dde5 100644 --- a/WickedEngine/emittedparticle_sphforceCS.hlsl +++ b/WickedEngine/emittedparticle_sphforceCS.hlsl @@ -204,11 +204,8 @@ void main( uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex, ui f_a *= -1; f_av *= e; - // gravity: - const float3 G = float3(0, -9.8f * 2, 0); - // apply all forces: - particleA.force += (f_a + f_av) / densityA + G; + particleA.force += (f_a + f_av) / densityA; particleBuffer[particleIndexA].force = particleA.force; diff --git a/WickedEngine/wiArchive.cpp b/WickedEngine/wiArchive.cpp index 24d4304cf..9190067ef 100644 --- a/WickedEngine/wiArchive.cpp +++ b/WickedEngine/wiArchive.cpp @@ -6,7 +6,7 @@ using namespace std; // this should always be only INCREMENTED and only if a new serialization is implemeted somewhere! -uint64_t __archiveVersion = 63; +uint64_t __archiveVersion = 64; // this is the version number of which below the archive is not compatible with the current version uint64_t __archiveVersionBarrier = 22; diff --git a/WickedEngine/wiEmittedParticle.cpp b/WickedEngine/wiEmittedParticle.cpp index 58877faec..99a7ae2c8 100644 --- a/WickedEngine/wiEmittedParticle.cpp +++ b/WickedEngine/wiEmittedParticle.cpp @@ -272,6 +272,10 @@ void wiEmittedParticle::UpdateGPU(const TransformComponent& transform, const Mat cb.xEmitterFrameStart = frameStart; cb.xEmitterTexMul = float2(1.0f / (float)cb.xEmitterFramesXY.x, 1.0f / (float)cb.xEmitterFramesXY.y); cb.xEmitterFrameRate = frameRate; + cb.xParticleGravity = gravity; + cb.xParticleDrag = drag; + cb.xParticleVelocity = velocity; + cb.xParticleRandomColorFactor = random_color; cb.xEmitterOptions = 0; if (IsSPHEnabled()) @@ -813,6 +817,22 @@ void wiEmittedParticle::Serialize(wiArchive& archive, wiECS::EntitySerializer& s uint8_t shadingRate; archive >> shadingRate; // no longer needed } + + if (archive.GetVersion() >= 64) + { + archive >> velocity; + archive >> gravity; + archive >> drag; + archive >> random_color; + } + else + { + if (IsSPHEnabled()) + { + gravity = XMFLOAT3(0, -9.8f * 2, 0); + drag = 0.98f; + } + } } else { @@ -845,6 +865,14 @@ void wiEmittedParticle::Serialize(wiArchive& archive, wiECS::EntitySerializer& s archive << frameStart; archive << frameRate; } + + if (archive.GetVersion() >= 64) + { + archive << velocity; + archive << gravity; + archive << drag; + archive << random_color; + } } } diff --git a/WickedEngine/wiEmittedParticle.h b/WickedEngine/wiEmittedParticle.h index c65f9b02a..055173a8a 100644 --- a/WickedEngine/wiEmittedParticle.h +++ b/WickedEngine/wiEmittedParticle.h @@ -92,6 +92,11 @@ public: float rotation = 0.0f; float motionBlurAmount = 0.0f; float mass = 1.0f; + float random_color = 0; + + XMFLOAT3 velocity = {}; // starting velocity of all new particles + XMFLOAT3 gravity = {}; // constant gravity force + float drag = 1.0f; // constant drag (per frame velocity multiplier, reducing it will make particles slow down over time) float SPH_h = 1.0f; // smoothing radius float SPH_K = 250.0f; // pressure constant diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index e01472fe2..dfadf865f 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 = 54; // minor bug fixes, alterations, refactors, updates - const int revision = 1; + const int revision = 2; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);