particle system sprite sheets use relative parameters now

This commit is contained in:
Turanszki Janos
2020-05-07 22:48:24 +01:00
parent a1bf837a5e
commit 6f92abc1ff
13 changed files with 117 additions and 122 deletions
+32 -32
View File
@@ -225,40 +225,40 @@ EmitterWindow::EmitterWindow(EditorComponent* editor) : GUI(&editor->GetGUI())
auto emitter = GetEmitter();
if (emitter != nullptr)
{
emitter->framerate = args.fValue;
emitter->frameRate = args.fValue;
}
});
emitterWindow->AddWidget(frameRateInput);
frameWidthInput = new wiTextInputField("");
frameWidthInput->SetPos(XMFLOAT2(x + 150, y));
frameWidthInput->SetSize(XMFLOAT2(40, 18));
frameWidthInput->SetText("");
frameWidthInput->SetTooltip("Enter a value to enable sprite sheet frame width in pixels.");
frameWidthInput->SetDescription("Frame Width: ");
frameWidthInput->OnInputAccepted([this](wiEventArgs args) {
framesXInput = new wiTextInputField("");
framesXInput->SetPos(XMFLOAT2(x + 150, y));
framesXInput->SetSize(XMFLOAT2(40, 18));
framesXInput->SetText("");
framesXInput->SetTooltip("How many horizontal frames there are in the spritesheet.");
framesXInput->SetDescription("Frames X: ");
framesXInput->OnInputAccepted([this](wiEventArgs args) {
auto emitter = GetEmitter();
if (emitter != nullptr)
{
emitter->frameWidth = (uint32_t)args.iValue;
emitter->framesX = (uint32_t)args.iValue;
}
});
emitterWindow->AddWidget(frameWidthInput);
emitterWindow->AddWidget(framesXInput);
frameHeightInput = new wiTextInputField("");
frameHeightInput->SetPos(XMFLOAT2(x + 300, y));
frameHeightInput->SetSize(XMFLOAT2(40, 18));
frameHeightInput->SetText("");
frameHeightInput->SetTooltip("Enter a value to enable sprite sheet frame height in pixels.");
frameHeightInput->SetDescription("Frame Height: ");
frameHeightInput->OnInputAccepted([this](wiEventArgs args) {
framesYInput = new wiTextInputField("");
framesYInput->SetPos(XMFLOAT2(x + 300, y));
framesYInput->SetSize(XMFLOAT2(40, 18));
framesYInput->SetText("");
framesYInput->SetTooltip("How many vertical frames there are in the spritesheet.");
framesYInput->SetDescription("Frames Y: ");
framesYInput->OnInputAccepted([this](wiEventArgs args) {
auto emitter = GetEmitter();
if (emitter != nullptr)
{
emitter->frameHeight = (uint32_t)args.iValue;
emitter->framesY = (uint32_t)args.iValue;
}
});
emitterWindow->AddWidget(frameHeightInput);
emitterWindow->AddWidget(framesYInput);
frameCountInput = new wiTextInputField("");
frameCountInput->SetPos(XMFLOAT2(x, y += step));
@@ -275,20 +275,20 @@ EmitterWindow::EmitterWindow(EditorComponent* editor) : GUI(&editor->GetGUI())
});
emitterWindow->AddWidget(frameCountInput);
horizontalFrameCountInput = new wiTextInputField("");
horizontalFrameCountInput->SetPos(XMFLOAT2(x + 300, y));
horizontalFrameCountInput->SetSize(XMFLOAT2(40, 18));
horizontalFrameCountInput->SetText("");
horizontalFrameCountInput->SetTooltip("Specifies how many sprite sheet frames are in the horizontal direction. 0 = all frames are placed horizontally.");
horizontalFrameCountInput->SetDescription("Horizontal Frame Count: ");
horizontalFrameCountInput->OnInputAccepted([this](wiEventArgs args) {
frameStartInput = new wiTextInputField("");
frameStartInput->SetPos(XMFLOAT2(x + 300, y));
frameStartInput->SetSize(XMFLOAT2(40, 18));
frameStartInput->SetText("");
frameStartInput->SetTooltip("Specifies the starting frame of the animation.");
frameStartInput->SetDescription("Start Frame: ");
frameStartInput->OnInputAccepted([this](wiEventArgs args) {
auto emitter = GetEmitter();
if (emitter != nullptr)
{
emitter->horizontalFrameCount = (uint32_t)args.iValue;
emitter->frameStart = (uint32_t)args.iValue;
}
});
emitterWindow->AddWidget(horizontalFrameCountInput);
emitterWindow->AddWidget(frameStartInput);
maxParticlesSlider = new wiSlider(100.0f, 1000000.0f, 10000, 100000, "Max particle count: ");
maxParticlesSlider->SetSize(XMFLOAT2(360, itemheight));
@@ -592,11 +592,11 @@ void EmitterWindow::SetEntity(Entity entity)
frameBlendingCheckBox->SetCheck(emitter->IsFrameBlendingEnabled());
maxParticlesSlider->SetValue((float)emitter->GetMaxParticleCount());
frameRateInput->SetValue(emitter->framerate);
frameWidthInput->SetValue((int)emitter->frameWidth);
frameHeightInput->SetValue((int)emitter->frameHeight);
frameRateInput->SetValue(emitter->frameRate);
framesXInput->SetValue((int)emitter->framesX);
framesYInput->SetValue((int)emitter->framesY);
frameCountInput->SetValue((int)emitter->frameCount);
horizontalFrameCountInput->SetValue((int)emitter->horizontalFrameCount);
frameStartInput->SetValue((int)emitter->frameStart);
emitCountSlider->SetValue(emitter->count);
emitSizeSlider->SetValue(emitter->size);
+3 -3
View File
@@ -61,10 +61,10 @@ public:
wiSlider* sph_e_Slider;
wiTextInputField* frameRateInput;
wiTextInputField* frameWidthInput;
wiTextInputField* frameHeightInput;
wiTextInputField* framesXInput;
wiTextInputField* framesYInput;
wiTextInputField* frameCountInput;
wiTextInputField* horizontalFrameCountInput;
wiTextInputField* frameStartInput;
};
+30 -30
View File
@@ -152,35 +152,35 @@ HairParticleWindow::HairParticleWindow(EditorComponent* editor) : GUI(&editor->G
viewDistanceSlider->SetTooltip("Set view distance. After this, particles will be faded out.");
hairWindow->AddWidget(viewDistanceSlider);
frameWidthInput = new wiTextInputField("");
frameWidthInput->SetPos(XMFLOAT2(x, y += step));
frameWidthInput->SetSize(XMFLOAT2(40, 18));
frameWidthInput->SetText("");
frameWidthInput->SetTooltip("Enter a value to enable sprite sheet frame width in pixels.");
frameWidthInput->SetDescription("Frame Width: ");
frameWidthInput->OnInputAccepted([this](wiEventArgs args) {
framesXInput = new wiTextInputField("");
framesXInput->SetPos(XMFLOAT2(x, y += step));
framesXInput->SetSize(XMFLOAT2(40, 18));
framesXInput->SetText("");
framesXInput->SetTooltip("How many horizontal frames there are in the spritesheet.");
framesXInput->SetDescription("Frames X: ");
framesXInput->OnInputAccepted([this](wiEventArgs args) {
auto hair = GetHair();
if (hair != nullptr)
{
hair->frameWidth = (uint32_t)args.iValue;
hair->framesX = (uint32_t)args.iValue;
}
});
hairWindow->AddWidget(frameWidthInput);
hairWindow->AddWidget(framesXInput);
frameHeightInput = new wiTextInputField("");
frameHeightInput->SetPos(XMFLOAT2(x + 250, y));
frameHeightInput->SetSize(XMFLOAT2(40, 18));
frameHeightInput->SetText("");
frameHeightInput->SetTooltip("Enter a value to enable sprite sheet frame height in pixels.");
frameHeightInput->SetDescription("Frame Height: ");
frameHeightInput->OnInputAccepted([this](wiEventArgs args) {
framesYInput = new wiTextInputField("");
framesYInput->SetPos(XMFLOAT2(x + 250, y));
framesYInput->SetSize(XMFLOAT2(40, 18));
framesYInput->SetText("");
framesYInput->SetTooltip("How many vertical frames there are in the spritesheet.");
framesYInput->SetDescription("Frames Y: ");
framesYInput->OnInputAccepted([this](wiEventArgs args) {
auto hair = GetHair();
if (hair != nullptr)
{
hair->frameHeight = (uint32_t)args.iValue;
hair->framesY = (uint32_t)args.iValue;
}
});
hairWindow->AddWidget(frameHeightInput);
hairWindow->AddWidget(framesYInput);
step = 20;
@@ -199,20 +199,20 @@ HairParticleWindow::HairParticleWindow(EditorComponent* editor) : GUI(&editor->G
});
hairWindow->AddWidget(frameCountInput);
horizontalFrameCountInput = new wiTextInputField("");
horizontalFrameCountInput->SetPos(XMFLOAT2(x + 250, y));
horizontalFrameCountInput->SetSize(XMFLOAT2(40, 18));
horizontalFrameCountInput->SetText("");
horizontalFrameCountInput->SetTooltip("Specifies how many sprite sheet frames are in the horizontal direction. 0 = all frames are placed horizontally.");
horizontalFrameCountInput->SetDescription("Horizontal Frame Count: ");
horizontalFrameCountInput->OnInputAccepted([this](wiEventArgs args) {
frameStartInput = new wiTextInputField("");
frameStartInput->SetPos(XMFLOAT2(x + 250, y));
frameStartInput->SetSize(XMFLOAT2(40, 18));
frameStartInput->SetText("");
frameStartInput->SetTooltip("Specifies the first frame of the sheet that can be used.");
frameStartInput->SetDescription("First Frame: ");
frameStartInput->OnInputAccepted([this](wiEventArgs args) {
auto hair = GetHair();
if (hair != nullptr)
{
hair->horizontalFrameCount = (uint32_t)args.iValue;
hair->frameStart = (uint32_t)args.iValue;
}
});
hairWindow->AddWidget(horizontalFrameCountInput);
hairWindow->AddWidget(frameStartInput);
hairWindow->Translate(XMFLOAT3(200, 50, 0));
@@ -243,10 +243,10 @@ void HairParticleWindow::SetEntity(Entity entity)
segmentcountSlider->SetValue((float)hair->segmentCount);
randomSeedSlider->SetValue((float)hair->randomSeed);
viewDistanceSlider->SetValue(hair->viewDistance);
frameWidthInput->SetValue((int)hair->frameWidth);
frameHeightInput->SetValue((int)hair->frameHeight);
framesXInput->SetValue((int)hair->framesX);
framesYInput->SetValue((int)hair->framesY);
frameCountInput->SetValue((int)hair->frameCount);
horizontalFrameCountInput->SetValue((int)hair->horizontalFrameCount);
frameStartInput->SetValue((int)hair->frameStart);
hairWindow->SetEnabled(true);
}
+3 -3
View File
@@ -40,10 +40,10 @@ public:
wiSlider* segmentcountSlider;
wiSlider* randomSeedSlider;
wiSlider* viewDistanceSlider;
wiTextInputField* frameWidthInput;
wiTextInputField* frameHeightInput;
wiTextInputField* framesXInput;
wiTextInputField* framesYInput;
wiTextInputField* frameCountInput;
wiTextInputField* horizontalFrameCountInput;
wiTextInputField* frameStartInput;
};
+3 -5
View File
@@ -55,15 +55,13 @@ CBUFFER(EmittedParticleCB, CBSLOT_OTHER_EMITTEDPARTICLE)
float xEmitterOpacity;
uint xEmitterMaxParticleCount;
uint2 xEmitterFrameSize;
uint2 xEmitterFramesXY;
uint xEmitterFrameCount;
uint xEmitterHorizontalFrameCount;
uint xEmitterFrameStart;
float2 xEmitterTexMul;
float2 xEmitterResolution_rcp;
float3 padding_xEmitter;
float xEmitterFrameRate;
float padding_xEmitter;
float xSPH_h; // smoothing radius
float xSPH_h_rcp; // 1.0f / smoothing radius
+2 -3
View File
@@ -39,12 +39,11 @@ CBUFFER(HairParticleCB, CBSLOT_OTHER_HAIRPARTICLE)
uint xHairBaseMeshVertexPositionStride;
uint xHairNumDispatchGroups;
uint2 xHairFrameSize;
uint2 xHairFramesXY;
uint xHairFrameCount;
uint xHairHorizontalFrameCount;
uint xHairFrameStart;
float2 xHairTexMul;
float2 xHairResolution_rcp;
float xHairAspect;
float3 padding_xHair;
+7 -5
View File
@@ -39,16 +39,18 @@ VertextoPixel main(uint fakeIndex : SV_VERTEXID)
float2 uv2 = uv;
// Sprite sheet UV transform:
const float spriteframe = xEmitterFrameRate == 0 ? (lifeLerp * xEmitterFrameCount) : ((particle.life * xEmitterFrameRate) % xEmitterFrameCount);
const float spriteframe = xEmitterFrameRate == 0 ?
lerp(xEmitterFrameStart, xEmitterFrameCount, lifeLerp) :
((xEmitterFrameStart + particle.life * xEmitterFrameRate) % xEmitterFrameCount);
const uint currentFrame = floor(spriteframe);
const uint nextFrame = ceil(spriteframe);
const float frameBlend = frac(spriteframe);
uint2 offset = uint2(currentFrame % xEmitterHorizontalFrameCount, currentFrame / xEmitterHorizontalFrameCount) * xEmitterFrameSize;
uint2 offset = uint2(currentFrame % xEmitterFramesXY.x, currentFrame / xEmitterFramesXY.x);
uv.xy += offset;
uv.xy *= xEmitterTexMul;
uv.xy += offset * xEmitterResolution_rcp;
uint2 offset2 = uint2(nextFrame % xEmitterHorizontalFrameCount, nextFrame / xEmitterHorizontalFrameCount) * xEmitterFrameSize;
uint2 offset2 = uint2(nextFrame % xEmitterFramesXY.x, nextFrame / xEmitterFramesXY.x);
uv2.xy += offset2;
uv2.xy *= xEmitterTexMul;
uv2.xy += offset2 * xEmitterResolution_rcp;
// rotate the billboard:
float2x2 rot = float2x2(
+3 -3
View File
@@ -68,10 +68,10 @@ VertexToPixel main(uint fakeIndex : SV_VERTEXID)
patchPos.y += 1;
// Sprite sheet UV transform:
const uint currentFrame = rand % xHairFrameCount;
uint2 offset = uint2(currentFrame % xHairHorizontalFrameCount, currentFrame / xHairHorizontalFrameCount) * xHairFrameSize;
const uint currentFrame = (xHairFrameStart + rand) % xHairFrameCount;
uint2 offset = uint2(currentFrame % xHairFramesXY.x, currentFrame / xHairFramesXY.x);
uv.xy += offset;
uv.xy *= xHairTexMul;
uv.xy += offset * xHairResolution_rcp;
// scale the billboard by the texture aspect:
float2 frame = float2(xHairAspect, 1);
+12 -16
View File
@@ -247,8 +247,6 @@ void wiEmittedParticle::UpdateGPU(const TransformComponent& transform, const Mat
{
device->EventBegin("UpdateEmittedParticles", cmd);
const TextureDesc& desc = material.GetBaseColorMap()->GetDesc();
EmittedParticleCB cb;
cb.xEmitterWorld = transform.world;
cb.xEmitCount = (uint32_t)emit;
@@ -269,13 +267,11 @@ void wiEmittedParticle::UpdateGPU(const TransformComponent& transform, const Mat
cb.xParticleMass = mass;
cb.xEmitterMaxParticleCount = MAX_PARTICLES;
cb.xEmitterFixedTimestep = FIXED_TIMESTEP;
cb.xEmitterFrameSize = uint2(frameWidth == 0 ? desc.Width : frameWidth, frameHeight == 0 ? desc.Height : frameHeight);
cb.xEmitterFramesXY = uint2(framesX, framesY);
cb.xEmitterFrameCount = std::max(1u, frameCount);
cb.xEmitterHorizontalFrameCount = std::max(1u, horizontalFrameCount == 0 ? frameCount : horizontalFrameCount);
cb.xEmitterTexMul = float2((float)cb.xEmitterFrameSize.x / (float)desc.Width, (float)cb.xEmitterFrameSize.y / (float)desc.Height);
cb.xEmitterResolution_rcp.x = 1.0f / (float)desc.Width;
cb.xEmitterResolution_rcp.y = 1.0f / (float)desc.Height;
cb.xEmitterFrameRate = framerate;
cb.xEmitterFrameStart = frameStart;
cb.xEmitterTexMul = float2(1.0f / (float)cb.xEmitterFramesXY.x, 1.0f / (float)cb.xEmitterFramesXY.y);
cb.xEmitterFrameRate = frameRate;
cb.xEmitterOptions = 0;
if (IsSPHEnabled())
@@ -776,11 +772,11 @@ void wiEmittedParticle::Serialize(wiArchive& archive, wiECS::Entity seed)
if (archive.GetVersion() >= 45)
{
archive >> frameWidth;
archive >> frameHeight;
archive >> framesX;
archive >> framesY;
archive >> frameCount;
archive >> horizontalFrameCount;
archive >> framerate;
archive >> frameStart;
archive >> frameRate;
}
}
else
@@ -808,11 +804,11 @@ void wiEmittedParticle::Serialize(wiArchive& archive, wiECS::Entity seed)
if (archive.GetVersion() >= 45)
{
archive << frameWidth;
archive << frameHeight;
archive << framesX;
archive << framesY;
archive << frameCount;
archive << horizontalFrameCount;
archive << framerate;
archive << frameStart;
archive << frameRate;
}
}
}
+5 -5
View File
@@ -101,11 +101,11 @@ public:
float SPH_e = 0.018f; // viscosity constant
// Sprite sheet properties:
uint32_t frameWidth = 0;
uint32_t frameHeight = 0;
uint32_t frameCount = 0;
uint32_t horizontalFrameCount = 0;
float framerate = 0; // frames per second
uint32_t framesX = 1;
uint32_t framesY = 1;
uint32_t frameCount = 1;
uint32_t frameStart = 0;
float frameRate = 0; // frames per second
void SetMaxParticleCount(uint32_t value);
uint32_t GetMaxParticleCount() const { return MAX_PARTICLES; }
+12 -12
View File
@@ -171,13 +171,13 @@ void wiHairParticle::UpdateGPU(const MeshComponent& mesh, const MaterialComponen
hcb.xHairBaseMeshVertexPositionStride = sizeof(MeshComponent::Vertex_POS);
// segmentCount will be loop in the shader, not a threadgroup so we don't need it here:
hcb.xHairNumDispatchGroups = (hcb.xHairParticleCount + THREADCOUNT_SIMULATEHAIR - 1) / THREADCOUNT_SIMULATEHAIR;
hcb.xHairFrameSize = uint2(frameWidth == 0 ? desc.Width : frameWidth, frameHeight == 0 ? desc.Height : frameHeight);
hcb.xHairFramesXY = uint2(framesX, framesY);
hcb.xHairFrameCount = std::max(1u, frameCount);
hcb.xHairHorizontalFrameCount = std::max(1u, horizontalFrameCount == 0 ? frameCount : horizontalFrameCount);
hcb.xHairTexMul = float2((float)hcb.xHairFrameSize.x / (float)desc.Width, (float)hcb.xHairFrameSize.y / (float)desc.Height);
hcb.xHairResolution_rcp.x = 1.0f / (float)desc.Width;
hcb.xHairResolution_rcp.y = 1.0f / (float)desc.Height;
hcb.xHairAspect = (float)hcb.xHairFrameSize.x / (float)hcb.xHairFrameSize.y;
hcb.xHairFramesXY = uint2(framesX, framesY);
hcb.xHairFrameCount = std::max(1u, frameCount);
hcb.xHairFrameStart = frameStart;
hcb.xHairTexMul = float2(1.0f / (float)hcb.xHairFramesXY.x, 1.0f / (float)hcb.xHairFramesXY.y);
hcb.xHairAspect = (float)desc.Width / (float)desc.Height;
device->UpdateBuffer(&cb, &hcb, cmd);
device->BindConstantBuffer(CS, &cb, CB_GETBINDSLOT(HairParticleCB), cmd);
@@ -264,10 +264,10 @@ void wiHairParticle::Serialize(wiArchive& archive, wiECS::Entity seed)
}
if (archive.GetVersion() >= 42)
{
archive >> frameWidth;
archive >> frameHeight;
archive >> framesX;
archive >> framesY;
archive >> frameCount;
archive >> horizontalFrameCount;
archive >> frameStart;
}
}
else
@@ -287,10 +287,10 @@ void wiHairParticle::Serialize(wiArchive& archive, wiECS::Entity seed)
}
if (archive.GetVersion() >= 42)
{
archive << frameWidth;
archive << frameHeight;
archive << framesX;
archive << framesY;
archive << frameCount;
archive << horizontalFrameCount;
archive << frameStart;
}
}
}
+4 -4
View File
@@ -48,10 +48,10 @@ public:
std::vector<float> vertex_lengths;
// Sprite sheet properties:
uint32_t frameWidth = 0;
uint32_t frameHeight = 0;
uint32_t frameCount = 0;
uint32_t horizontalFrameCount = 0;
uint32_t framesX = 1;
uint32_t framesY = 1;
uint32_t frameCount = 1;
uint32_t frameStart = 0;
// Non-serialized attributes:
XMFLOAT4X4 world;
+1 -1
View File
@@ -9,7 +9,7 @@ namespace wiVersion
// minor features, major updates
const int minor = 41;
// minor bug fixes, alterations, refactors, updates
const int revision = 4;
const int revision = 5;
const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);