diff --git a/Editor/Editor.cpp b/Editor/Editor.cpp
index 1ce7e23bb..fd24f65ba 100644
--- a/Editor/Editor.cpp
+++ b/Editor/Editor.cpp
@@ -335,7 +335,6 @@ void EditorComponent::ChangeRenderPath(RENDERPATH path)
lightWnd = new LightWindow(&GetGUI());
animWnd = new AnimationWindow(&GetGUI());
emitterWnd = new EmitterWindow(&GetGUI());
- emitterWnd->SetMaterialWnd(materialWnd);
forceFieldWnd = new ForceFieldWindow(&GetGUI());
oceanWnd = new OceanWindow(&GetGUI());
}
@@ -1162,27 +1161,23 @@ void EditorComponent::Update(float dt)
}
}
}
- //if (pickMask & PICK_EMITTER)
- //{
- // for (auto& object : model->objects)
- // {
- // if (object->eParticleSystems.empty())
- // {
- // continue;
- // }
-
- // XMVECTOR disV = XMVector3LinePointDistance(XMLoadFloat3(&pickRay.origin), XMLoadFloat3(&pickRay.origin) + XMLoadFloat3(&pickRay.direction), XMLoadFloat3(&object->translation));
- // float dis = XMVectorGetX(disV);
- // if (dis < wiMath::Distance(object->translation, pickRay.origin) * 0.05f && dis < hovered.distance)
- // {
- // hovered.Clear();
- // hovered.transform = object;
- // hovered.object = object;
- // hovered.distance = dis;
- // }
- // }
- //}
+ if (pickMask & PICK_EMITTER)
+ {
+ for (size_t i = 0; i < scene.emitters.GetCount(); ++i)
+ {
+ Entity entity = scene.emitters.GetEntity(i);
+ const TransformComponent& transform = *scene.transforms.GetComponent(entity);
+ XMVECTOR disV = XMVector3LinePointDistance(XMLoadFloat3(&pickRay.origin), XMLoadFloat3(&pickRay.origin) + XMLoadFloat3(&pickRay.direction), XMLoadFloat3(&transform.translation));
+ float dis = XMVectorGetX(disV);
+ if (dis < wiMath::Distance(transform.translation, pickRay.origin) * 0.05f && dis < hovered.distance)
+ {
+ hovered.Clear();
+ hovered.entity = entity;
+ hovered.distance = dis;
+ }
+ }
+ }
if (pickMask & PICK_ENVPROBE)
{
for (size_t i = 0; i < scene.probes.GetCount(); ++i)
@@ -1405,59 +1400,7 @@ void EditorComponent::Update(float dt)
envProbeWnd->SetEntity(picked->entity);
forceFieldWnd->SetEntity(picked->entity);
cameraWnd->SetEntity(picked->entity);
-
- //if (picked->object != nullptr)
- //{
- // meshWnd->SetMesh(picked->object->mesh);
- // if (picked->subsetIndex >= 0 && picked->subsetIndex < (int)picked->object->mesh->subsets.size())
- // {
- // Material* material = picked->object->mesh->subsets[picked->subsetIndex].material;
-
- // materialWnd->SetMaterial(material);
-
- // material->SetUserStencilRef(EDITORSTENCILREF_HIGHLIGHT);
- // }
- // //if (picked->object->isArmatureDeformed())
- // //{
- // // animWnd->SetArmature(picked->object->mesh->armature);
- // //}
- //}
- //else
- //{
- // meshWnd->SetMesh(nullptr);
- // materialWnd->SetMaterial(nullptr);
- // //animWnd->SetArmature(nullptr);
- //}
-
- //if (picked->light != nullptr)
- //{
- //}
- //lightWnd->SetLight(picked->light);
- //if (picked->decal != nullptr)
- //{
- //}
- //decalWnd->SetDecal(picked->decal);
- //if (picked->envProbe != nullptr)
- //{
- //}
- //envProbeWnd->SetProbe(picked->envProbe);
- //forceFieldWnd->SetForceField(picked->forceField);
- //if (picked->camera != nullptr)
- //{
- // cameraWnd->SetProxy(picked->camera);
- //}
-
- //if (picked->armature != nullptr)
- //{
- // animWnd->SetArmature(picked->armature);
- //}
- //else
- //{
- // animWnd->SetArmature(nullptr);
- //}
-
- //objectWnd->SetObject(picked->object);
- //emitterWnd->SetObject(picked->object);
+ materialWnd->SetEntity(picked->entity);
}
//// Delete
@@ -1978,41 +1921,39 @@ void EditorComponent::Compose()
}
}
- //if (rendererWnd->GetPickType() & PICK_EMITTER)
- //{
- // for (auto& y : x->objects)
- // {
- // if (y->eParticleSystems.empty())
- // {
- // continue;
- // }
+ if (rendererWnd->GetPickType() & PICK_EMITTER)
+ {
+ for (size_t i = 0; i < scene.emitters.GetCount(); ++i)
+ {
+ Entity entity = scene.emitters.GetEntity(i);
+ const TransformComponent& transform = *scene.transforms.GetComponent(entity);
- // float dist = wiMath::Distance(y->translation, camera->translation) * 0.08f;
+ float dist = wiMath::Distance(transform.translation, camera->Eye) * 0.08f;
- // wiImageEffects fx;
- // fx.pos = y->translation;
- // fx.siz = XMFLOAT2(dist, dist);
- // fx.typeFlag = ImageType::WORLD;
- // fx.pivot = XMFLOAT2(0.5f, 0.5f);
- // fx.col = XMFLOAT4(1, 1, 1, 0.5f);
+ wiImageEffects fx;
+ fx.pos = transform.translation;
+ fx.siz = XMFLOAT2(dist, dist);
+ fx.typeFlag = ImageType::WORLD;
+ fx.pivot = XMFLOAT2(0.5f, 0.5f);
+ fx.col = XMFLOAT4(1, 1, 1, 0.5f);
- // if (hovered.object == y)
- // {
- // fx.col = XMFLOAT4(1, 1, 1, 1);
- // }
- // for (auto& picked : selected)
- // {
- // if (picked->object == y)
- // {
- // fx.col = XMFLOAT4(1, 1, 0, 1);
- // break;
- // }
- // }
+ if (hovered.entity == entity)
+ {
+ fx.col = XMFLOAT4(1, 1, 1, 1);
+ }
+ for (auto& picked : selected)
+ {
+ if (picked->entity == entity)
+ {
+ fx.col = XMFLOAT4(1, 1, 0, 1);
+ break;
+ }
+ }
- // wiImage::Draw(&emitterTex, fx, GRAPHICSTHREAD_IMMEDIATE);
- // }
- //}
+ wiImage::Draw(&emitterTex, fx, GRAPHICSTHREAD_IMMEDIATE);
+ }
+ }
if (translator_active && translator->enabled)
diff --git a/Editor/EmitterWindow.cpp b/Editor/EmitterWindow.cpp
index 536cd7933..3d44f0078 100644
--- a/Editor/EmitterWindow.cpp
+++ b/Editor/EmitterWindow.cpp
@@ -12,8 +12,6 @@ EmitterWindow::EmitterWindow(wiGUI* gui) : GUI(gui)
{
assert(GUI && "Invalid GUI!");
- materialWnd = nullptr;
-
float screenW = (float)wiRenderer::GetDevice()->GetScreenWidth();
float screenH = (float)wiRenderer::GetDevice()->GetScreenHeight();
@@ -24,412 +22,398 @@ EmitterWindow::EmitterWindow(wiGUI* gui) : GUI(gui)
GUI->AddWidget(emitterWindow);
float x = 150;
- float y = 10;
+ float y = 20;
float step = 35;
- //emitterComboBox = new wiComboBox("Emitter: ");
- //emitterComboBox->SetPos(XMFLOAT2(x, y += step));
- //emitterComboBox->SetSize(XMFLOAT2(360, 25));
- //emitterComboBox->OnSelect([&](wiEventArgs args) {
- // if (object != nullptr && args.iValue >= 0)
- // {
- // SetObject(object);
- // }
- //});
- //emitterComboBox->SetEnabled(false);
- //emitterComboBox->SetTooltip("Choose an emitter associated with the selected object");
- //emitterWindow->AddWidget(emitterComboBox);
+ addButton = new wiButton("Add Emitter");
+ addButton->SetPos(XMFLOAT2(x, y += step));
+ addButton->SetSize(XMFLOAT2(150, 30));
+ addButton->OnClick([&](wiEventArgs args) {
+ Scene& scene = wiRenderer::GetScene();
+ scene.Entity_CreateEmitter("editorEmitter");
+ });
+ addButton->SetTooltip("Add new emitter particle system.");
+ emitterWindow->AddWidget(addButton);
+
+ restartButton = new wiButton("Restart Emitter");
+ restartButton->SetPos(XMFLOAT2(x + 160, y));
+ restartButton->SetSize(XMFLOAT2(150, 30));
+ restartButton->OnClick([&](wiEventArgs args) {
+ auto emitter = GetEmitter();
+ if (emitter != nullptr)
+ {
+ emitter->Restart();
+ }
+ });
+ restartButton->SetTooltip("Restart particle system emitter");
+ emitterWindow->AddWidget(restartButton);
+
+ meshComboBox = new wiComboBox("Mesh: ");
+ meshComboBox->SetSize(XMFLOAT2(300, 25));
+ meshComboBox->SetPos(XMFLOAT2(x, y += step));
+ meshComboBox->SetEnabled(false);
+ meshComboBox->OnSelect([&](wiEventArgs args) {
+ auto emitter = GetEmitter();
+ if (emitter != nullptr)
+ {
+ if (args.iValue == 0)
+ {
+ emitter->meshID = INVALID_ENTITY;
+ }
+ else
+ {
+ Scene& scene = wiRenderer::GetScene();
+ emitter->meshID = scene.meshes.GetEntity(args.iValue - 1);
+ }
+ }
+ });
+ meshComboBox->SetTooltip("Choose an animation clip...");
+ emitterWindow->AddWidget(meshComboBox);
+
+ shaderTypeComboBox = new wiComboBox("ShaderType: ");
+ shaderTypeComboBox->SetPos(XMFLOAT2(x, y += step));
+ shaderTypeComboBox->SetSize(XMFLOAT2(300, 25));
+ shaderTypeComboBox->AddItem("SOFT");
+ shaderTypeComboBox->AddItem("SOFT + DISTORTION");
+ shaderTypeComboBox->AddItem("SIMPLEST");
+ shaderTypeComboBox->OnSelect([&](wiEventArgs args) {
+ auto emitter = GetEmitter();
+ if (emitter != nullptr)
+ {
+ emitter->shaderType = (wiEmittedParticle::PARTICLESHADERTYPE)args.iValue;
+ }
+ });
+ shaderTypeComboBox->SetEnabled(false);
+ shaderTypeComboBox->SetTooltip("Choose a shader type for the particles. This is responsible of how they will be rendered.");
+ emitterWindow->AddWidget(shaderTypeComboBox);
- //shaderTypeComboBox = new wiComboBox("ShaderType: ");
- //shaderTypeComboBox->SetPos(XMFLOAT2(x, y += step));
- //shaderTypeComboBox->SetSize(XMFLOAT2(200, 25));
- //shaderTypeComboBox->AddItem("SOFT");
- //shaderTypeComboBox->AddItem("SOFT + DISTORTION");
- //shaderTypeComboBox->AddItem("SIMPLEST");
- //shaderTypeComboBox->OnSelect([&](wiEventArgs args) {
- // auto emitter = GetEmitter();
- // if (emitter != nullptr)
- // {
- // emitter->shaderType = (wiEmittedParticle::PARTICLESHADERTYPE)args.iValue;
- // }
- //});
- //shaderTypeComboBox->SetEnabled(false);
- //shaderTypeComboBox->SetTooltip("Choose a shader type for the particles. This is responsible of how they will be rendered.");
- //emitterWindow->AddWidget(shaderTypeComboBox);
+ sortCheckBox = new wiCheckBox("Sorting Enabled: ");
+ sortCheckBox->SetPos(XMFLOAT2(x, y += step));
+ sortCheckBox->OnClick([&](wiEventArgs args) {
+ auto emitter = GetEmitter();
+ if (emitter != nullptr)
+ {
+ emitter->SORTING = args.bValue;
+ }
+ });
+ sortCheckBox->SetCheck(false);
+ sortCheckBox->SetTooltip("Enable sorting of the particles. This might slow down performance.");
+ emitterWindow->AddWidget(sortCheckBox);
- //sortCheckBox = new wiCheckBox("Sorting Enabled: ");
- //sortCheckBox->SetPos(XMFLOAT2(x, y += step));
- //sortCheckBox->OnClick([&](wiEventArgs args) {
- // auto emitter = GetEmitter();
- // if (emitter != nullptr)
- // {
- // emitter->SORTING = args.bValue;
- // }
- //});
- //sortCheckBox->SetCheck(false);
- //sortCheckBox->SetTooltip("Enable sorting of the particles. This might slow down performance.");
- //emitterWindow->AddWidget(sortCheckBox);
+ depthCollisionsCheckBox = new wiCheckBox("Depth Buffer Collisions Enabled: ");
+ depthCollisionsCheckBox->SetPos(XMFLOAT2(x + 250, y));
+ depthCollisionsCheckBox->OnClick([&](wiEventArgs args) {
+ auto emitter = GetEmitter();
+ if (emitter != nullptr)
+ {
+ emitter->DEPTHCOLLISIONS = args.bValue;
+ }
+ });
+ depthCollisionsCheckBox->SetCheck(false);
+ depthCollisionsCheckBox->SetTooltip("Enable particle collisions with the depth buffer.");
+ emitterWindow->AddWidget(depthCollisionsCheckBox);
- //depthCollisionsCheckBox = new wiCheckBox("Depth Buffer Collisions Enabled: ");
- //depthCollisionsCheckBox->SetPos(XMFLOAT2(x + 250, y));
- //depthCollisionsCheckBox->OnClick([&](wiEventArgs args) {
- // auto emitter = GetEmitter();
- // if (emitter != nullptr)
- // {
- // emitter->DEPTHCOLLISIONS = args.bValue;
- // }
- //});
- //depthCollisionsCheckBox->SetCheck(false);
- //depthCollisionsCheckBox->SetTooltip("Enable particle collisions with the depth buffer.");
- //emitterWindow->AddWidget(depthCollisionsCheckBox);
+ sphCheckBox = new wiCheckBox("SPH - FluidSim: ");
+ sphCheckBox->SetPos(XMFLOAT2(x + 400, y));
+ sphCheckBox->OnClick([&](wiEventArgs args) {
+ auto emitter = GetEmitter();
+ if (emitter != nullptr)
+ {
+ emitter->SPH_FLUIDSIMULATION = args.bValue;
+ }
+ });
+ sphCheckBox->SetCheck(false);
+ sphCheckBox->SetTooltip("Enable particle collisions with each other. Simulate with Smooth Particle Hydrodynamics (SPH) solver.");
+ emitterWindow->AddWidget(sphCheckBox);
- //sphCheckBox = new wiCheckBox("SPH - FluidSim: ");
- //sphCheckBox->SetPos(XMFLOAT2(x + 400, y));
- //sphCheckBox->OnClick([&](wiEventArgs args) {
- // auto emitter = GetEmitter();
- // if (emitter != nullptr)
- // {
- // emitter->SPH_FLUIDSIMULATION = args.bValue;
- // }
- //});
- //sphCheckBox->SetCheck(false);
- //sphCheckBox->SetTooltip("Enable particle collisions with each other. Simulate with Smooth Particle Hydrodynamics (SPH) solver.");
- //emitterWindow->AddWidget(sphCheckBox);
+ pauseCheckBox = new wiCheckBox("PAUSE: ");
+ pauseCheckBox->SetPos(XMFLOAT2(x, y += step));
+ pauseCheckBox->OnClick([&](wiEventArgs args) {
+ auto emitter = GetEmitter();
+ if (emitter != nullptr)
+ {
+ emitter->PAUSED = args.bValue;
+ }
+ });
+ pauseCheckBox->SetCheck(false);
+ pauseCheckBox->SetTooltip("Stop simulation update.");
+ emitterWindow->AddWidget(pauseCheckBox);
- //pauseCheckBox = new wiCheckBox("PAUSE: ");
- //pauseCheckBox->SetPos(XMFLOAT2(x, y += step));
- //pauseCheckBox->OnClick([&](wiEventArgs args) {
- // auto emitter = GetEmitter();
- // if (emitter != nullptr)
- // {
- // emitter->PAUSED = args.bValue;
- // }
- //});
- //pauseCheckBox->SetCheck(false);
- //pauseCheckBox->SetTooltip("Stop simulation update.");
- //emitterWindow->AddWidget(pauseCheckBox);
-
-
- //debugCheckBox = new wiCheckBox("DEBUG: ");
- //debugCheckBox->SetPos(XMFLOAT2(x + 120, y));
- //debugCheckBox->OnClick([&](wiEventArgs args) {
- // auto emitter = GetEmitter();
- // if (emitter != nullptr)
- // {
- // emitter->DEBUG = args.bValue;
- // }
- //});
- //debugCheckBox->SetCheck(false);
- //debugCheckBox->SetTooltip("Enable debug info for the emitter. This involves reading back GPU data, so rendering can slow down.");
- //emitterWindow->AddWidget(debugCheckBox);
+ debugCheckBox = new wiCheckBox("DEBUG: ");
+ debugCheckBox->SetPos(XMFLOAT2(x + 120, y));
+ debugCheckBox->OnClick([&](wiEventArgs args) {
+ auto emitter = GetEmitter();
+ if (emitter != nullptr)
+ {
+ emitter->DEBUG = args.bValue;
+ }
+ });
+ debugCheckBox->SetCheck(false);
+ debugCheckBox->SetTooltip("Enable debug info for the emitter. This involves reading back GPU data, so rendering can slow down.");
+ emitterWindow->AddWidget(debugCheckBox);
- //infoLabel = new wiLabel("EmitterInfo");
- //infoLabel->SetSize(XMFLOAT2(380, 140));
- //infoLabel->SetPos(XMFLOAT2(x, y += step));
- //emitterWindow->AddWidget(infoLabel);
+ infoLabel = new wiLabel("EmitterInfo");
+ infoLabel->SetSize(XMFLOAT2(380, 140));
+ infoLabel->SetPos(XMFLOAT2(x, y += step));
+ emitterWindow->AddWidget(infoLabel);
- //maxParticlesSlider = new wiSlider(100.0f, 1000000.0f, 10000, 100000, "Max particle count: ");
- //maxParticlesSlider->SetSize(XMFLOAT2(360, 30));
- //maxParticlesSlider->SetPos(XMFLOAT2(x, y += step + 140));
- //maxParticlesSlider->OnSlide([&](wiEventArgs args) {
- // auto emitter = GetEmitter();
- // if (emitter != nullptr)
- // {
- // emitter->SetMaxParticleCount((uint32_t)args.iValue);
- // }
- //});
- //maxParticlesSlider->SetEnabled(false);
- //maxParticlesSlider->SetTooltip("Set the maximum amount of particles this system can handle. This has an effect on the memory budget.");
- //emitterWindow->AddWidget(maxParticlesSlider);
+ maxParticlesSlider = new wiSlider(100.0f, 1000000.0f, 10000, 100000, "Max particle count: ");
+ maxParticlesSlider->SetSize(XMFLOAT2(360, 30));
+ maxParticlesSlider->SetPos(XMFLOAT2(x, y += step + 140));
+ maxParticlesSlider->OnSlide([&](wiEventArgs args) {
+ auto emitter = GetEmitter();
+ if (emitter != nullptr)
+ {
+ emitter->SetMaxParticleCount((uint32_t)args.iValue);
+ }
+ });
+ maxParticlesSlider->SetEnabled(false);
+ maxParticlesSlider->SetTooltip("Set the maximum amount of particles this system can handle. This has an effect on the memory budget.");
+ emitterWindow->AddWidget(maxParticlesSlider);
- //y += 30;
+ y += 30;
- ////////////////////////////////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////////////////////////////////
- //emitCountSlider = new wiSlider(0.0f, 10000.0f, 1.0f, 100000, "Emit count per sec: ");
- //emitCountSlider->SetSize(XMFLOAT2(360, 30));
- //emitCountSlider->SetPos(XMFLOAT2(x, y += step));
- //emitCountSlider->OnSlide([&](wiEventArgs args) {
- // auto emitter = GetEmitter();
- // if (emitter != nullptr)
- // {
- // emitter->count = args.fValue;
- // }
- //});
- //emitCountSlider->SetEnabled(false);
- //emitCountSlider->SetTooltip("Set the number of particles to emit per second.");
- //emitterWindow->AddWidget(emitCountSlider);
+ emitCountSlider = new wiSlider(0.0f, 10000.0f, 1.0f, 100000, "Emit count per sec: ");
+ emitCountSlider->SetSize(XMFLOAT2(360, 30));
+ emitCountSlider->SetPos(XMFLOAT2(x, y += step));
+ emitCountSlider->OnSlide([&](wiEventArgs args) {
+ auto emitter = GetEmitter();
+ if (emitter != nullptr)
+ {
+ emitter->count = args.fValue;
+ }
+ });
+ emitCountSlider->SetEnabled(false);
+ emitCountSlider->SetTooltip("Set the number of particles to emit per second.");
+ emitterWindow->AddWidget(emitCountSlider);
- //emitSizeSlider = new wiSlider(0.01f, 10.0f, 1.0f, 100000, "Size: ");
- //emitSizeSlider->SetSize(XMFLOAT2(360, 30));
- //emitSizeSlider->SetPos(XMFLOAT2(x, y += step));
- //emitSizeSlider->OnSlide([&](wiEventArgs args) {
- // auto emitter = GetEmitter();
- // if (emitter != nullptr)
- // {
- // emitter->size = args.fValue;
- // }
- //});
- //emitSizeSlider->SetEnabled(false);
- //emitSizeSlider->SetTooltip("Set the size of the emitted particles.");
- //emitterWindow->AddWidget(emitSizeSlider);
+ emitSizeSlider = new wiSlider(0.01f, 10.0f, 1.0f, 100000, "Size: ");
+ emitSizeSlider->SetSize(XMFLOAT2(360, 30));
+ emitSizeSlider->SetPos(XMFLOAT2(x, y += step));
+ emitSizeSlider->OnSlide([&](wiEventArgs args) {
+ auto emitter = GetEmitter();
+ if (emitter != nullptr)
+ {
+ emitter->size = args.fValue;
+ }
+ });
+ emitSizeSlider->SetEnabled(false);
+ emitSizeSlider->SetTooltip("Set the size of the emitted particles.");
+ emitterWindow->AddWidget(emitSizeSlider);
- //emitRotationSlider = new wiSlider(0.0f, 1.0f, 0.0f, 100000, "Rotation: ");
- //emitRotationSlider->SetSize(XMFLOAT2(360, 30));
- //emitRotationSlider->SetPos(XMFLOAT2(x, y += step));
- //emitRotationSlider->OnSlide([&](wiEventArgs args) {
- // auto emitter = GetEmitter();
- // if (emitter != nullptr)
- // {
- // emitter->rotation = args.fValue;
- // }
- //});
- //emitRotationSlider->SetEnabled(false);
- //emitRotationSlider->SetTooltip("Set the rotation velocity of the emitted particles.");
- //emitterWindow->AddWidget(emitRotationSlider);
+ emitRotationSlider = new wiSlider(0.0f, 1.0f, 0.0f, 100000, "Rotation: ");
+ emitRotationSlider->SetSize(XMFLOAT2(360, 30));
+ emitRotationSlider->SetPos(XMFLOAT2(x, y += step));
+ emitRotationSlider->OnSlide([&](wiEventArgs args) {
+ auto emitter = GetEmitter();
+ if (emitter != nullptr)
+ {
+ emitter->rotation = args.fValue;
+ }
+ });
+ emitRotationSlider->SetEnabled(false);
+ emitRotationSlider->SetTooltip("Set the rotation velocity of the emitted particles.");
+ emitterWindow->AddWidget(emitRotationSlider);
- //emitNormalSlider = new wiSlider(0.0f, 100.0f, 1.0f, 100000, "Normal factor: ");
- //emitNormalSlider->SetSize(XMFLOAT2(360, 30));
- //emitNormalSlider->SetPos(XMFLOAT2(x, y += step));
- //emitNormalSlider->OnSlide([&](wiEventArgs args) {
- // auto emitter = GetEmitter();
- // if (emitter != nullptr)
- // {
- // emitter->normal_factor = args.fValue;
- // }
- //});
- //emitNormalSlider->SetEnabled(false);
- //emitNormalSlider->SetTooltip("Set the velocity of the emitted particles based on the normal vector of the emitter surface.");
- //emitterWindow->AddWidget(emitNormalSlider);
+ emitNormalSlider = new wiSlider(0.0f, 100.0f, 1.0f, 100000, "Normal factor: ");
+ emitNormalSlider->SetSize(XMFLOAT2(360, 30));
+ emitNormalSlider->SetPos(XMFLOAT2(x, y += step));
+ emitNormalSlider->OnSlide([&](wiEventArgs args) {
+ auto emitter = GetEmitter();
+ if (emitter != nullptr)
+ {
+ emitter->normal_factor = args.fValue;
+ }
+ });
+ emitNormalSlider->SetEnabled(false);
+ emitNormalSlider->SetTooltip("Set the velocity of the emitted particles based on the normal vector of the emitter surface.");
+ emitterWindow->AddWidget(emitNormalSlider);
- //emitScalingSlider = new wiSlider(0.0f, 100.0f, 1.0f, 100000, "Scaling: ");
- //emitScalingSlider->SetSize(XMFLOAT2(360, 30));
- //emitScalingSlider->SetPos(XMFLOAT2(x, y += step));
- //emitScalingSlider->OnSlide([&](wiEventArgs args) {
- // auto emitter = GetEmitter();
- // if (emitter != nullptr)
- // {
- // emitter->scaleX = args.fValue;
- // }
- //});
- //emitScalingSlider->SetEnabled(false);
- //emitScalingSlider->SetTooltip("Set the scaling of the particles based on their lifetime.");
- //emitterWindow->AddWidget(emitScalingSlider);
+ emitScalingSlider = new wiSlider(0.0f, 100.0f, 1.0f, 100000, "Scaling: ");
+ emitScalingSlider->SetSize(XMFLOAT2(360, 30));
+ emitScalingSlider->SetPos(XMFLOAT2(x, y += step));
+ emitScalingSlider->OnSlide([&](wiEventArgs args) {
+ auto emitter = GetEmitter();
+ if (emitter != nullptr)
+ {
+ emitter->scaleX = args.fValue;
+ }
+ });
+ emitScalingSlider->SetEnabled(false);
+ emitScalingSlider->SetTooltip("Set the scaling of the particles based on their lifetime.");
+ emitterWindow->AddWidget(emitScalingSlider);
- //emitLifeSlider = new wiSlider(0.0f, 1000.0f, 1.0f, 100000, "Life span: ");
- //emitLifeSlider->SetSize(XMFLOAT2(360, 30));
- //emitLifeSlider->SetPos(XMFLOAT2(x, y += step));
- //emitLifeSlider->OnSlide([&](wiEventArgs args) {
- // auto emitter = GetEmitter();
- // if (emitter != nullptr)
- // {
- // emitter->life = args.fValue;
- // }
- //});
- //emitLifeSlider->SetEnabled(false);
- //emitLifeSlider->SetTooltip("Set the lifespan of the emitted particles.");
- //emitterWindow->AddWidget(emitLifeSlider);
+ emitLifeSlider = new wiSlider(0.0f, 1000.0f, 1.0f, 100000, "Life span: ");
+ emitLifeSlider->SetSize(XMFLOAT2(360, 30));
+ emitLifeSlider->SetPos(XMFLOAT2(x, y += step));
+ emitLifeSlider->OnSlide([&](wiEventArgs args) {
+ auto emitter = GetEmitter();
+ if (emitter != nullptr)
+ {
+ emitter->life = args.fValue;
+ }
+ });
+ emitLifeSlider->SetEnabled(false);
+ emitLifeSlider->SetTooltip("Set the lifespan of the emitted particles.");
+ emitterWindow->AddWidget(emitLifeSlider);
- //emitRandomnessSlider = new wiSlider(0.0f, 1.0f, 1.0f, 100000, "Randomness: ");
- //emitRandomnessSlider->SetSize(XMFLOAT2(360, 30));
- //emitRandomnessSlider->SetPos(XMFLOAT2(x, y += step));
- //emitRandomnessSlider->OnSlide([&](wiEventArgs args) {
- // auto emitter = GetEmitter();
- // if (emitter != nullptr)
- // {
- // emitter->random_factor = args.fValue;
- // }
- //});
- //emitRandomnessSlider->SetEnabled(false);
- //emitRandomnessSlider->SetTooltip("Set the general randomness of the emitter.");
- //emitterWindow->AddWidget(emitRandomnessSlider);
+ emitRandomnessSlider = new wiSlider(0.0f, 1.0f, 1.0f, 100000, "Randomness: ");
+ emitRandomnessSlider->SetSize(XMFLOAT2(360, 30));
+ emitRandomnessSlider->SetPos(XMFLOAT2(x, y += step));
+ emitRandomnessSlider->OnSlide([&](wiEventArgs args) {
+ auto emitter = GetEmitter();
+ if (emitter != nullptr)
+ {
+ emitter->random_factor = args.fValue;
+ }
+ });
+ emitRandomnessSlider->SetEnabled(false);
+ emitRandomnessSlider->SetTooltip("Set the general randomness of the emitter.");
+ emitterWindow->AddWidget(emitRandomnessSlider);
- //emitLifeRandomnessSlider = new wiSlider(0.0f, 2.0f, 0.0f, 100000, "Life randomness: ");
- //emitLifeRandomnessSlider->SetSize(XMFLOAT2(360, 30));
- //emitLifeRandomnessSlider->SetPos(XMFLOAT2(x, y += step));
- //emitLifeRandomnessSlider->OnSlide([&](wiEventArgs args) {
- // auto emitter = GetEmitter();
- // if (emitter != nullptr)
- // {
- // emitter->random_life = args.fValue;
- // }
- //});
- //emitLifeRandomnessSlider->SetEnabled(false);
- //emitLifeRandomnessSlider->SetTooltip("Set the randomness of lifespans for the emitted particles.");
- //emitterWindow->AddWidget(emitLifeRandomnessSlider);
+ emitLifeRandomnessSlider = new wiSlider(0.0f, 2.0f, 0.0f, 100000, "Life randomness: ");
+ emitLifeRandomnessSlider->SetSize(XMFLOAT2(360, 30));
+ emitLifeRandomnessSlider->SetPos(XMFLOAT2(x, y += step));
+ emitLifeRandomnessSlider->OnSlide([&](wiEventArgs args) {
+ auto emitter = GetEmitter();
+ if (emitter != nullptr)
+ {
+ emitter->random_life = args.fValue;
+ }
+ });
+ emitLifeRandomnessSlider->SetEnabled(false);
+ emitLifeRandomnessSlider->SetTooltip("Set the randomness of lifespans for the emitted particles.");
+ emitterWindow->AddWidget(emitLifeRandomnessSlider);
- //emitMotionBlurSlider = new wiSlider(0.0f, 1.0f, 1.0f, 100000, "Motion blur: ");
- //emitMotionBlurSlider->SetSize(XMFLOAT2(360, 30));
- //emitMotionBlurSlider->SetPos(XMFLOAT2(x, y += step));
- //emitMotionBlurSlider->OnSlide([&](wiEventArgs args) {
- // auto emitter = GetEmitter();
- // if (emitter != nullptr)
- // {
- // emitter->motionBlurAmount = args.fValue;
- // }
- //});
- //emitMotionBlurSlider->SetEnabled(false);
- //emitMotionBlurSlider->SetTooltip("Set the motion blur amount for the particle system.");
- //emitterWindow->AddWidget(emitMotionBlurSlider);
+ emitMotionBlurSlider = new wiSlider(0.0f, 1.0f, 1.0f, 100000, "Motion blur: ");
+ emitMotionBlurSlider->SetSize(XMFLOAT2(360, 30));
+ emitMotionBlurSlider->SetPos(XMFLOAT2(x, y += step));
+ emitMotionBlurSlider->OnSlide([&](wiEventArgs args) {
+ auto emitter = GetEmitter();
+ if (emitter != nullptr)
+ {
+ emitter->motionBlurAmount = args.fValue;
+ }
+ });
+ emitMotionBlurSlider->SetEnabled(false);
+ emitMotionBlurSlider->SetTooltip("Set the motion blur amount for the particle system.");
+ emitterWindow->AddWidget(emitMotionBlurSlider);
- //emitMassSlider = new wiSlider(0.1f, 100.0f, 1.0f, 100000, "Mass: ");
- //emitMassSlider->SetSize(XMFLOAT2(360, 30));
- //emitMassSlider->SetPos(XMFLOAT2(x, y += step));
- //emitMassSlider->OnSlide([&](wiEventArgs args) {
- // auto emitter = GetEmitter();
- // if (emitter != nullptr)
- // {
- // emitter->mass = args.fValue;
- // }
- //});
- //emitMassSlider->SetEnabled(false);
- //emitMassSlider->SetTooltip("Set the mass per particle.");
- //emitterWindow->AddWidget(emitMassSlider);
+ emitMassSlider = new wiSlider(0.1f, 100.0f, 1.0f, 100000, "Mass: ");
+ emitMassSlider->SetSize(XMFLOAT2(360, 30));
+ emitMassSlider->SetPos(XMFLOAT2(x, y += step));
+ emitMassSlider->OnSlide([&](wiEventArgs args) {
+ auto emitter = GetEmitter();
+ if (emitter != nullptr)
+ {
+ emitter->mass = args.fValue;
+ }
+ });
+ emitMassSlider->SetEnabled(false);
+ emitMassSlider->SetTooltip("Set the mass per particle.");
+ emitterWindow->AddWidget(emitMassSlider);
- //timestepSlider = new wiSlider(-1, 0.016f, -1, 100000, "Timestep: ");
- //timestepSlider->SetSize(XMFLOAT2(360, 30));
- //timestepSlider->SetPos(XMFLOAT2(x, y += step*2));
- //timestepSlider->OnSlide([&](wiEventArgs args) {
- // auto emitter = GetEmitter();
- // if (emitter != nullptr)
- // {
- // emitter->FIXED_TIMESTEP = args.fValue;
- // }
- //});
- //timestepSlider->SetEnabled(false);
- //timestepSlider->SetTooltip("Adjust timestep for emitter simulation. -1 means variable timestep, positive means fixed timestep.");
- //emitterWindow->AddWidget(timestepSlider);
+ timestepSlider = new wiSlider(-1, 0.016f, -1, 100000, "Timestep: ");
+ timestepSlider->SetSize(XMFLOAT2(360, 30));
+ timestepSlider->SetPos(XMFLOAT2(x, y += step*2));
+ timestepSlider->OnSlide([&](wiEventArgs args) {
+ auto emitter = GetEmitter();
+ if (emitter != nullptr)
+ {
+ emitter->FIXED_TIMESTEP = args.fValue;
+ }
+ });
+ timestepSlider->SetEnabled(false);
+ timestepSlider->SetTooltip("Adjust timestep for emitter simulation. -1 means variable timestep, positive means fixed timestep.");
+ emitterWindow->AddWidget(timestepSlider);
- ////////////////// SPH ////////////////////////////
+ //////////////// SPH ////////////////////////////
- //y += step;
+ y += step;
- //sph_h_Slider = new wiSlider(0.1f, 100.0f, 1.0f, 100000, "SPH Smoothing Radius (h): ");
- //sph_h_Slider->SetSize(XMFLOAT2(360, 30));
- //sph_h_Slider->SetPos(XMFLOAT2(x, y += step));
- //sph_h_Slider->OnSlide([&](wiEventArgs args) {
- // auto emitter = GetEmitter();
- // if (emitter != nullptr)
- // {
- // emitter->SPH_h = args.fValue;
- // }
- //});
- //sph_h_Slider->SetEnabled(false);
- //sph_h_Slider->SetTooltip("Set the SPH parameter: smoothing radius");
- //emitterWindow->AddWidget(sph_h_Slider);
+ sph_h_Slider = new wiSlider(0.1f, 100.0f, 1.0f, 100000, "SPH Smoothing Radius (h): ");
+ sph_h_Slider->SetSize(XMFLOAT2(360, 30));
+ sph_h_Slider->SetPos(XMFLOAT2(x, y += step));
+ sph_h_Slider->OnSlide([&](wiEventArgs args) {
+ auto emitter = GetEmitter();
+ if (emitter != nullptr)
+ {
+ emitter->SPH_h = args.fValue;
+ }
+ });
+ sph_h_Slider->SetEnabled(false);
+ sph_h_Slider->SetTooltip("Set the SPH parameter: smoothing radius");
+ emitterWindow->AddWidget(sph_h_Slider);
- //sph_K_Slider = new wiSlider(0.1f, 100.0f, 1.0f, 100000, "SPH Pressure Constant (K): ");
- //sph_K_Slider->SetSize(XMFLOAT2(360, 30));
- //sph_K_Slider->SetPos(XMFLOAT2(x, y += step));
- //sph_K_Slider->OnSlide([&](wiEventArgs args) {
- // auto emitter = GetEmitter();
- // if (emitter != nullptr)
- // {
- // emitter->SPH_K = args.fValue;
- // }
- //});
- //sph_K_Slider->SetEnabled(false);
- //sph_K_Slider->SetTooltip("Set the SPH parameter: pressure constant");
- //emitterWindow->AddWidget(sph_K_Slider);
+ sph_K_Slider = new wiSlider(0.1f, 100.0f, 1.0f, 100000, "SPH Pressure Constant (K): ");
+ sph_K_Slider->SetSize(XMFLOAT2(360, 30));
+ sph_K_Slider->SetPos(XMFLOAT2(x, y += step));
+ sph_K_Slider->OnSlide([&](wiEventArgs args) {
+ auto emitter = GetEmitter();
+ if (emitter != nullptr)
+ {
+ emitter->SPH_K = args.fValue;
+ }
+ });
+ sph_K_Slider->SetEnabled(false);
+ sph_K_Slider->SetTooltip("Set the SPH parameter: pressure constant");
+ emitterWindow->AddWidget(sph_K_Slider);
- //sph_p0_Slider = new wiSlider(0.1f, 100.0f, 1.0f, 100000, "SPH Reference Density (p0): ");
- //sph_p0_Slider->SetSize(XMFLOAT2(360, 30));
- //sph_p0_Slider->SetPos(XMFLOAT2(x, y += step));
- //sph_p0_Slider->OnSlide([&](wiEventArgs args) {
- // auto emitter = GetEmitter();
- // if (emitter != nullptr)
- // {
- // emitter->SPH_p0 = args.fValue;
- // }
- //});
- //sph_p0_Slider->SetEnabled(false);
- //sph_p0_Slider->SetTooltip("Set the SPH parameter: reference density");
- //emitterWindow->AddWidget(sph_p0_Slider);
+ sph_p0_Slider = new wiSlider(0.1f, 100.0f, 1.0f, 100000, "SPH Reference Density (p0): ");
+ sph_p0_Slider->SetSize(XMFLOAT2(360, 30));
+ sph_p0_Slider->SetPos(XMFLOAT2(x, y += step));
+ sph_p0_Slider->OnSlide([&](wiEventArgs args) {
+ auto emitter = GetEmitter();
+ if (emitter != nullptr)
+ {
+ emitter->SPH_p0 = args.fValue;
+ }
+ });
+ sph_p0_Slider->SetEnabled(false);
+ sph_p0_Slider->SetTooltip("Set the SPH parameter: reference density");
+ emitterWindow->AddWidget(sph_p0_Slider);
- //sph_e_Slider = new wiSlider(0.1f, 100.0f, 1.0f, 100000, "SPH Viscosity (e): ");
- //sph_e_Slider->SetSize(XMFLOAT2(360, 30));
- //sph_e_Slider->SetPos(XMFLOAT2(x, y += step));
- //sph_e_Slider->OnSlide([&](wiEventArgs args) {
- // auto emitter = GetEmitter();
- // if (emitter != nullptr)
- // {
- // emitter->SPH_e = args.fValue;
- // }
- //});
- //sph_e_Slider->SetEnabled(false);
- //sph_e_Slider->SetTooltip("Set the SPH parameter: viscosity constant");
- //emitterWindow->AddWidget(sph_e_Slider);
+ sph_e_Slider = new wiSlider(0.1f, 100.0f, 1.0f, 100000, "SPH Viscosity (e): ");
+ sph_e_Slider->SetSize(XMFLOAT2(360, 30));
+ sph_e_Slider->SetPos(XMFLOAT2(x, y += step));
+ sph_e_Slider->OnSlide([&](wiEventArgs args) {
+ auto emitter = GetEmitter();
+ if (emitter != nullptr)
+ {
+ emitter->SPH_e = args.fValue;
+ }
+ });
+ sph_e_Slider->SetEnabled(false);
+ sph_e_Slider->SetTooltip("Set the SPH parameter: viscosity constant");
+ emitterWindow->AddWidget(sph_e_Slider);
-
-
-
- //////// UTIL /////////////////
-
- //y += step;
-
- //materialSelectButton = new wiButton("Select Material");
- //materialSelectButton->SetPos(XMFLOAT2(x, y += step));
- //materialSelectButton->SetSize(XMFLOAT2(150, 30));
- //materialSelectButton->OnClick([&](wiEventArgs args) {
- // if (materialWnd != nullptr)
- // {
- // auto emitter = GetEmitter();
- // if (emitter != nullptr)
- // {
- // materialWnd->SetMaterial(emitter->material);
- // }
- // }
- //});
- //materialSelectButton->SetTooltip("Select corresponding material in the Material Window.");
- //emitterWindow->AddWidget(materialSelectButton);
-
-
-
- //restartButton = new wiButton("Restart Emitter");
- //restartButton->SetPos(XMFLOAT2(x + 200, y));
- //restartButton->SetSize(XMFLOAT2(150, 30));
- //restartButton->OnClick([&](wiEventArgs args) {
- // if (materialWnd != nullptr)
- // {
- // auto emitter = GetEmitter();
- // if (emitter != nullptr)
- // {
- // emitter->Restart();
- // }
- // }
- //});
- //restartButton->SetTooltip("Restart particle system emitter");
- //emitterWindow->AddWidget(restartButton);
-
-
-
-
emitterWindow->Translate(XMFLOAT3(200, 50, 0));
emitterWindow->SetVisible(false);
SetEntity(entity);
}
-
EmitterWindow::~EmitterWindow()
{
emitterWindow->RemoveWidgets(true);
@@ -439,124 +423,116 @@ EmitterWindow::~EmitterWindow()
void EmitterWindow::SetEntity(Entity entity)
{
+ if (this->entity == entity)
+ return;
+
+
+ // first try to turn off any debug readbacks for emitters:
+ if (GetEmitter() != nullptr)
+ {
+ GetEmitter()->DEBUG = false;
+ }
+ debugCheckBox->SetCheck(false);
+
this->entity = entity;
- //if (this->object == obj)
- // return;
+ auto emitter = GetEmitter();
- //// first try to turn off any debug readbacks for emitters:
- //if (GetEmitter() != nullptr)
- //{
- // GetEmitter()->DEBUG = false;
- //}
- //debugCheckBox->SetCheck(false);
+ if (emitter != nullptr)
+ {
+ sortCheckBox->SetCheck(emitter->SORTING);
+ depthCollisionsCheckBox->SetCheck(emitter->DEPTHCOLLISIONS);
+ sphCheckBox->SetCheck(emitter->SPH_FLUIDSIMULATION);
+ pauseCheckBox->SetCheck(emitter->PAUSED);
+ maxParticlesSlider->SetValue((float)emitter->GetMaxParticleCount());
- //object = obj;
+ emitCountSlider->SetValue(emitter->count);
+ emitSizeSlider->SetValue(emitter->size);
+ emitRotationSlider->SetValue(emitter->rotation);
+ emitNormalSlider->SetValue(emitter->normal_factor);
+ emitScalingSlider->SetValue(emitter->scaleX);
+ emitLifeSlider->SetValue(emitter->life);
+ emitRandomnessSlider->SetValue(emitter->random_factor);
+ emitLifeRandomnessSlider->SetValue(emitter->random_life);
+ emitMotionBlurSlider->SetValue(emitter->motionBlurAmount);
+ emitMassSlider->SetValue(emitter->mass);
+ timestepSlider->SetValue(emitter->FIXED_TIMESTEP);
- //emitterComboBox->ClearItems();
+ sph_h_Slider->SetValue(emitter->SPH_h);
+ sph_K_Slider->SetValue(emitter->SPH_K);
+ sph_p0_Slider->SetValue(emitter->SPH_p0);
+ sph_e_Slider->SetValue(emitter->SPH_e);
- //if (object != nullptr)
- //{
- // for (auto& x : object->eParticleSystems)
- // {
- // emitterComboBox->AddItem(x->name);
- // emitterComboBox->SetEnabled(true);
- // }
+ //emitterWindow->SetEnabled(true);
+ }
+ else
+ {
+ infoLabel->SetText("No emitter object selected.");
- // auto emitter = GetEmitter();
- // if (emitter != nullptr)
- // {
- // sortCheckBox->SetCheck(emitter->SORTING);
- // depthCollisionsCheckBox->SetCheck(emitter->DEPTHCOLLISIONS);
- // sphCheckBox->SetCheck(emitter->SPH_FLUIDSIMULATION);
- // pauseCheckBox->SetCheck(emitter->PAUSED);
- // maxParticlesSlider->SetValue((float)emitter->GetMaxParticleCount());
+ //emitterWindow->SetEnabled(false);
+ }
- // emitCountSlider->SetValue(emitter->count);
- // emitSizeSlider->SetValue(emitter->size);
- // emitRotationSlider->SetValue(emitter->rotation);
- // emitNormalSlider->SetValue(emitter->normal_factor);
- // emitScalingSlider->SetValue(emitter->scaleX);
- // emitLifeSlider->SetValue(emitter->life);
- // emitRandomnessSlider->SetValue(emitter->random_factor);
- // emitLifeRandomnessSlider->SetValue(emitter->random_life);
- // emitMotionBlurSlider->SetValue(emitter->motionBlurAmount);
- // emitMassSlider->SetValue(emitter->mass);
- // timestepSlider->SetValue(emitter->FIXED_TIMESTEP);
-
- // sph_h_Slider->SetValue(emitter->SPH_h);
- // sph_K_Slider->SetValue(emitter->SPH_K);
- // sph_p0_Slider->SetValue(emitter->SPH_p0);
- // sph_e_Slider->SetValue(emitter->SPH_e);
- // }
-
- // emitterWindow->SetEnabled(true);
- //}
- //else
- //{
- // infoLabel->SetText("No emitter object selected.");
-
- // emitterWindow->SetEnabled(false);
- //}
-
-}
-
-void EmitterWindow::SetMaterialWnd(MaterialWindow* wnd)
-{
- materialWnd = wnd;
}
wiEmittedParticle* EmitterWindow::GetEmitter()
{
- //if (object == nullptr)
- //{
- // return nullptr;
- //}
+ if (entity == INVALID_ENTITY)
+ {
+ return nullptr;
+ }
- //int sel = emitterComboBox->GetSelected();
+ Scene& scene = wiRenderer::GetScene();
+ wiEmittedParticle* emitter = scene.emitters.GetComponent(entity);
- //if (sel < 0)
- //{
- // return nullptr;
- //}
-
- //if ((int)object->eParticleSystems.size() > sel)
- //{
- // return object->eParticleSystems[sel];
- //}
-
- return nullptr;
+ return emitter;
}
void EmitterWindow::UpdateData()
{
- //auto emitter = GetEmitter();
- //if (emitter == nullptr)
- //{
- // return;
- //}
+ auto emitter = GetEmitter();
+ if (emitter == nullptr)
+ {
+ return;
+ }
+ Scene& scene = wiRenderer::GetScene();
- //stringstream ss("");
- //ss.precision(2);
- //ss << "Emitter name: " << emitter->name << endl;
- //ss << "Emitter Object: " << (emitter->object != nullptr ? emitter->object->name : "ERROR: NO EMITTER OBJECT") << endl;
- //ss << "Emitter Material: " << (emitter->material != nullptr ? emitter->material->name : "ERROR: NO EMITTER MATERIAL") << endl;
- //ss << "Memort Budget: " << emitter->GetMemorySizeInBytes() / 1024.0f / 1024.0f << " MB" << endl;
- //ss << endl;
+ meshComboBox->ClearItems();
+ meshComboBox->AddItem("NO MESH");
+ for (size_t i = 0; i < scene.meshes.GetCount(); ++i)
+ {
+ Entity entity = scene.meshes.GetEntity(i);
+ const NameComponent& name = *scene.names.GetComponent(entity);
+ meshComboBox->AddItem(name.name);
- //if (emitter->DEBUG)
- //{
- // auto data = emitter->GetDebugData();
+ if (emitter->meshID == entity)
+ {
+ meshComboBox->SetSelected((int)i + 1);
+ }
+ }
- // ss << "Alive Particle Count = " << data.aliveCount << endl;
- // ss << "Dead Particle Count = " << data.deadCount << endl;
- // ss << "GPU Emit count = " << data.realEmitCount << endl;
- //}
- //else
- //{
- // ss << "For additional data, enable [DEBUG]" << endl;
- //}
+ NameComponent* name = scene.names.GetComponent(entity);
+ NameComponent* meshName = scene.names.GetComponent(emitter->meshID);
- //infoLabel->SetText(ss.str());
+ stringstream ss("");
+ ss.precision(2);
+ ss << "Emitter name: " << name->name << " (" << entity << ")" << endl;
+ ss << "Emitter Mesh: " << (meshName != nullptr ? meshName->name : "NO EMITTER MESH") << " (" << emitter->meshID << ")" << endl;
+ ss << "Memort Budget: " << emitter->GetMemorySizeInBytes() / 1024.0f / 1024.0f << " MB" << endl;
+ ss << endl;
+
+ if (emitter->DEBUG)
+ {
+ auto data = emitter->GetDebugData();
+
+ ss << "Alive Particle Count = " << data.aliveCount << endl;
+ ss << "Dead Particle Count = " << data.deadCount << endl;
+ ss << "GPU Emit count = " << data.realEmitCount << endl;
+ }
+ else
+ {
+ ss << "For additional data, enable [DEBUG]" << endl;
+ }
+
+ infoLabel->SetText(ss.str());
}
diff --git a/Editor/EmitterWindow.h b/Editor/EmitterWindow.h
index a1f842771..659e28c0c 100644
--- a/Editor/EmitterWindow.h
+++ b/Editor/EmitterWindow.h
@@ -1,7 +1,5 @@
#pragma once
-class wiEmittedParticle;
-
class wiGUI;
class wiWindow;
class wiLabel;
@@ -21,17 +19,17 @@ public:
wiECS::Entity entity;
void SetEntity(wiECS::Entity entity);
- void SetMaterialWnd(MaterialWindow* wnd);
void UpdateData();
- wiEmittedParticle* GetEmitter();
+ wiSceneSystem::wiEmittedParticle* GetEmitter();
wiGUI* GUI;
- MaterialWindow* materialWnd;
wiWindow* emitterWindow;
- wiComboBox* emitterComboBox;
+ wiButton* addButton;
+ wiButton* restartButton;
+ wiComboBox* meshComboBox;
wiComboBox* shaderTypeComboBox;
wiLabel* infoLabel;
wiSlider* maxParticlesSlider;
@@ -55,8 +53,6 @@ public:
wiSlider* sph_K_Slider;
wiSlider* sph_p0_Slider;
wiSlider* sph_e_Slider;
- wiButton* materialSelectButton;
- wiButton* restartButton;
};
diff --git a/WickedEngine/WickedEngine_SHADERS.vcxproj b/WickedEngine/WickedEngine_SHADERS.vcxproj
index 2344f1c92..7f9f01727 100644
--- a/WickedEngine/WickedEngine_SHADERS.vcxproj
+++ b/WickedEngine/WickedEngine_SHADERS.vcxproj
@@ -133,6 +133,10 @@
Compute
5.0
+
+ Compute
+ 5.0
+
Compute
5.0
diff --git a/WickedEngine/WickedEngine_SHADERS.vcxproj.filters b/WickedEngine/WickedEngine_SHADERS.vcxproj.filters
index 1de3bf8f2..6c2d6588f 100644
--- a/WickedEngine/WickedEngine_SHADERS.vcxproj.filters
+++ b/WickedEngine/WickedEngine_SHADERS.vcxproj.filters
@@ -786,6 +786,9 @@
CS
+
+ CS
+
diff --git a/WickedEngine/emittedparticle_emitCS.hlsl b/WickedEngine/emittedparticle_emitCS.hlsl
index 9908a450f..df351cdf0 100644
--- a/WickedEngine/emittedparticle_emitCS.hlsl
+++ b/WickedEngine/emittedparticle_emitCS.hlsl
@@ -8,8 +8,11 @@ RWSTRUCTUREDBUFFER(deadBuffer, uint, 3);
RWRAWBUFFER(counterBuffer, 4);
TEXTURE2D(randomTex, float4, TEXSLOT_ONDEMAND0);
+
+#ifdef EMIT_FROM_MESH
TYPEDBUFFER(meshIndexBuffer, uint, TEXSLOT_ONDEMAND1);
RAWBUFFER(meshVertexBuffer_POS, TEXSLOT_ONDEMAND2);
+#endif // EMIT_FROM_MESH
[numthreads(THREADCOUNT_EMIT, 1, 1)]
@@ -23,6 +26,7 @@ void main(uint3 DTid : SV_DispatchThreadID)
const float3 randoms = randomTex.SampleLevel(sampler_linear_wrap, float2((float)DTid.x / (float)THREADCOUNT_EMIT, g_xFrame_Time + xEmitterRandomness), 0).rgb;
+#ifdef EMIT_FROM_MESH
// random triangle on emitter surface:
uint tri = (uint)(((xEmitterMeshIndexCount - 1) / 3) * randoms.x);
@@ -74,6 +78,14 @@ void main(uint3 DTid : SV_DispatchThreadID)
pos = mul(xEmitterWorld, float4(pos, 1)).xyz;
nor = normalize(mul((float3x3)xEmitterWorld, nor));
+#else
+
+ // Just emit from center point:
+ float3 pos = mul(xEmitterWorld, float4(0, 0, 0, 1)).xyz;
+ float3 nor = 0;
+
+#endif // EMIT_FROM_MESH
+
float particleStartingSize = xParticleSize + xParticleSize * (randoms.y - 0.5f) * xParticleRandomFactor;
// create new particle:
diff --git a/WickedEngine/emittedparticle_emitCS_FROMMESH.hlsl b/WickedEngine/emittedparticle_emitCS_FROMMESH.hlsl
new file mode 100644
index 000000000..87c21955e
--- /dev/null
+++ b/WickedEngine/emittedparticle_emitCS_FROMMESH.hlsl
@@ -0,0 +1,2 @@
+#define EMIT_FROM_MESH
+#include "emittedparticle_emitCS.hlsl"
diff --git a/WickedEngine/wiECS.h b/WickedEngine/wiECS.h
index 1c96c7888..0f5b7c7e6 100644
--- a/WickedEngine/wiECS.h
+++ b/WickedEngine/wiECS.h
@@ -35,7 +35,6 @@ namespace wiECS
components.clear();
entities.clear();
lookup.clear();
- dead.clear();
}
// Create a new component and retrieve a reference to it:
diff --git a/WickedEngine/wiEmittedParticle.cpp b/WickedEngine/wiEmittedParticle.cpp
index 4e79556d9..d300c398b 100644
--- a/WickedEngine/wiEmittedParticle.cpp
+++ b/WickedEngine/wiEmittedParticle.cpp
@@ -13,11 +13,13 @@
using namespace std;
using namespace wiGraphicsTypes;
-using namespace wiSceneSystem;
+
+namespace wiSceneSystem
+{
VertexShader *wiEmittedParticle::vertexShader = nullptr;
PixelShader *wiEmittedParticle::pixelShader[PARTICLESHADERTYPE_COUNT] = {};
-ComputeShader *wiEmittedParticle::kickoffUpdateCS = nullptr, *wiEmittedParticle::finishUpdateCS = nullptr, *wiEmittedParticle::emitCS = nullptr, *wiEmittedParticle::sphpartitionCS = nullptr,
+ComputeShader *wiEmittedParticle::kickoffUpdateCS = nullptr, *wiEmittedParticle::finishUpdateCS = nullptr, *wiEmittedParticle::emitCS = nullptr, *wiEmittedParticle::emitCS_FROMMESH = nullptr, *wiEmittedParticle::sphpartitionCS = nullptr,
*wiEmittedParticle::sphpartitionoffsetsCS = nullptr, *wiEmittedParticle::sphpartitionoffsetsresetCS = nullptr, *wiEmittedParticle::sphdensityCS = nullptr, *wiEmittedParticle::sphforceCS = nullptr,
*wiEmittedParticle::simulateCS = nullptr, *wiEmittedParticle::simulateCS_SORTING = nullptr, *wiEmittedParticle::simulateCS_DEPTHCOLLISIONS = nullptr, *wiEmittedParticle::simulateCS_SORTING_DEPTHCOLLISIONS = nullptr;
@@ -26,87 +28,10 @@ RasterizerState wiEmittedParticle::rasterizerState, wiEmittedParticle::wireFram
DepthStencilState wiEmittedParticle::depthStencilState;
GraphicsPSO wiEmittedParticle::PSO[BLENDMODE_COUNT][PARTICLESHADERTYPE_COUNT];
GraphicsPSO wiEmittedParticle::PSO_wire;
-ComputePSO wiEmittedParticle::CPSO_kickoffUpdate, wiEmittedParticle::CPSO_finishUpdate, wiEmittedParticle::CPSO_emit, wiEmittedParticle::CPSO_sphpartition, wiEmittedParticle::CPSO_sphpartitionoffsets,
+ComputePSO wiEmittedParticle::CPSO_kickoffUpdate, wiEmittedParticle::CPSO_finishUpdate, wiEmittedParticle::CPSO_emit, wiEmittedParticle::CPSO_emit_FROMMESH, wiEmittedParticle::CPSO_sphpartition, wiEmittedParticle::CPSO_sphpartitionoffsets,
wiEmittedParticle::CPSO_sphpartitionoffsetsreset, wiEmittedParticle::CPSO_sphdensity, wiEmittedParticle::CPSO_sphforce, wiEmittedParticle::CPSO_simulate,
wiEmittedParticle::CPSO_simulate_SORTING, wiEmittedParticle::CPSO_simulate_DEPTHCOLLISIONS, wiEmittedParticle::CPSO_simulate_SORTING_DEPTHCOLLISIONS;
-wiEmittedParticle::wiEmittedParticle()
-{
- name = "";
- //object = nullptr;
- materialName = "";
- //material = nullptr;
-
- size = 1;
- random_factor = 0;
- normal_factor = 1;
-
- count = 1;
- life = 60;
- random_life = 0;
- emit = 0;
-
- scaleX = 1;
- scaleY = 1;
- rotation = 0;
-
- motionBlurAmount = 0.0f;
-
- SetMaxParticleCount(10000);
-}
-
-//wiEmittedParticle::wiEmittedParticle(const std::string& newName, const std::string& newMat, Object* newObject, float newSize, float newRandomFac, float newNormalFac
-// ,float newCount, float newLife, float newRandLife, float newScaleX, float newScaleY, float newRot)
-//{
-// name=newName;
-// object=newObject;
-// materialName = newMat;
-// for (MeshSubset& subset : object->mesh->subsets)
-// {
-// if (!newMat.compare(subset.material->name)) {
-// material = subset.material;
-// break;
-// }
-// }
-//
-// size=newSize;
-// random_factor=newRandomFac;
-// normal_factor=newNormalFac;
-//
-// count=newCount;
-// life=newLife;
-// random_life=newRandLife;
-// emit=0;
-//
-// scaleX=newScaleX;
-// scaleY=newScaleY;
-// rotation = newRot;
-//
-// motionBlurAmount = 0.0f;
-//
-// SetMaxParticleCount(10000);
-//}
-
-wiEmittedParticle::wiEmittedParticle(const wiEmittedParticle& other)
-{
- name = other.name + "0";
- //object = other.object;
- materialName = other.materialName;
- //material = other.material;
- size = other.size;
- random_factor = other.random_factor;
- normal_factor = other.normal_factor;
- count = other.count;
- life = other.life;
- random_life = other.random_life;
- emit = 0;
- scaleX = other.scaleX;
- scaleY = other.scaleY;
- rotation = other.rotation;
- motionBlurAmount = other.motionBlurAmount;
-
- SetMaxParticleCount(other.GetMaxParticleCount());
-}
void wiEmittedParticle::SetMaxParticleCount(uint32_t value)
{
@@ -122,35 +47,20 @@ void wiEmittedParticle::CreateSelfBuffers()
}
buffersUpToDate = true;
- SAFE_DELETE(particleBuffer);
- SAFE_DELETE(aliveList[0]);
- SAFE_DELETE(aliveList[1]);
- SAFE_DELETE(deadList);
- SAFE_DELETE(distanceBuffer);
- SAFE_DELETE(sphPartitionCellIndices);
- SAFE_DELETE(sphPartitionCellOffsets);
- SAFE_DELETE(densityBuffer);
- SAFE_DELETE(counterBuffer);
- SAFE_DELETE(indirectBuffers);
- SAFE_DELETE(constantBuffer);
- SAFE_DELETE(debugDataReadbackBuffer);
- SAFE_DELETE(debugDataReadbackIndexBuffer);
- SAFE_DELETE(debugDataReadbackDistanceBuffer);
-
- particleBuffer = new GPUBuffer;
- aliveList[0] = new GPUBuffer;
- aliveList[1] = new GPUBuffer;
- deadList = new GPUBuffer;
- distanceBuffer = new GPUBuffer;
- sphPartitionCellIndices = new GPUBuffer;
- sphPartitionCellOffsets = new GPUBuffer;
- densityBuffer = new GPUBuffer;
- counterBuffer = new GPUBuffer;
- indirectBuffers = new GPUBuffer;
- constantBuffer = new GPUBuffer;
- debugDataReadbackBuffer = new GPUBuffer;
- debugDataReadbackIndexBuffer = new GPUBuffer;
- debugDataReadbackDistanceBuffer = new GPUBuffer;
+ particleBuffer.reset(new GPUBuffer);
+ aliveList[0].reset(new GPUBuffer);
+ aliveList[1].reset(new GPUBuffer);
+ deadList.reset(new GPUBuffer);
+ distanceBuffer.reset(new GPUBuffer);
+ sphPartitionCellIndices.reset(new GPUBuffer);
+ sphPartitionCellOffsets.reset(new GPUBuffer);
+ densityBuffer.reset(new GPUBuffer);
+ counterBuffer.reset(new GPUBuffer);
+ indirectBuffers.reset(new GPUBuffer);
+ constantBuffer.reset(new GPUBuffer);
+ debugDataReadbackBuffer.reset(new GPUBuffer);
+ debugDataReadbackIndexBuffer.reset(new GPUBuffer);
+ debugDataReadbackDistanceBuffer.reset(new GPUBuffer);
// GPU-local buffer descriptors:
@@ -164,13 +74,13 @@ void wiEmittedParticle::CreateSelfBuffers()
// Particle buffer:
bd.StructureByteStride = sizeof(Particle);
bd.ByteWidth = bd.StructureByteStride * MAX_PARTICLES;
- wiRenderer::GetDevice()->CreateBuffer(&bd, nullptr, particleBuffer);
+ wiRenderer::GetDevice()->CreateBuffer(&bd, nullptr, particleBuffer.get());
// Alive index lists (double buffered):
bd.StructureByteStride = sizeof(uint32_t);
bd.ByteWidth = bd.StructureByteStride * MAX_PARTICLES;
- wiRenderer::GetDevice()->CreateBuffer(&bd, nullptr, aliveList[0]);
- wiRenderer::GetDevice()->CreateBuffer(&bd, nullptr, aliveList[1]);
+ wiRenderer::GetDevice()->CreateBuffer(&bd, nullptr, aliveList[0].get());
+ wiRenderer::GetDevice()->CreateBuffer(&bd, nullptr, aliveList[1].get());
// Dead index list:
uint32_t* indices = new uint32_t[MAX_PARTICLES];
@@ -179,7 +89,7 @@ void wiEmittedParticle::CreateSelfBuffers()
indices[i] = i;
}
data.pSysMem = indices;
- wiRenderer::GetDevice()->CreateBuffer(&bd, &data, deadList);
+ wiRenderer::GetDevice()->CreateBuffer(&bd, &data, deadList.get());
SAFE_DELETE_ARRAY(indices);
data.pSysMem = nullptr;
@@ -192,24 +102,24 @@ void wiEmittedParticle::CreateSelfBuffers()
distances[i] = 0;
}
data.pSysMem = distances;
- wiRenderer::GetDevice()->CreateBuffer(&bd, &data, distanceBuffer);
+ wiRenderer::GetDevice()->CreateBuffer(&bd, &data, distanceBuffer.get());
SAFE_DELETE_ARRAY(distances);
data.pSysMem = nullptr;
// SPH Partitioning grid indices per particle:
bd.StructureByteStride = sizeof(float); // really, it is uint, but sorting is performing comparisons on floats, so whateva
bd.ByteWidth = bd.StructureByteStride * MAX_PARTICLES;
- wiRenderer::GetDevice()->CreateBuffer(&bd, nullptr, sphPartitionCellIndices);
+ wiRenderer::GetDevice()->CreateBuffer(&bd, nullptr, sphPartitionCellIndices.get());
// SPH Partitioning grid cell offsets into particle index list:
bd.StructureByteStride = sizeof(uint32_t);
bd.ByteWidth = bd.StructureByteStride * SPH_PARTITION_BUCKET_COUNT;
- wiRenderer::GetDevice()->CreateBuffer(&bd, nullptr, sphPartitionCellOffsets);
+ wiRenderer::GetDevice()->CreateBuffer(&bd, nullptr, sphPartitionCellOffsets.get());
// Density buffer (for SPH simulation):
bd.StructureByteStride = sizeof(float);
bd.ByteWidth = bd.StructureByteStride * MAX_PARTICLES;
- wiRenderer::GetDevice()->CreateBuffer(&bd, nullptr, densityBuffer);
+ wiRenderer::GetDevice()->CreateBuffer(&bd, nullptr, densityBuffer.get());
// Particle System statistics:
ParticleCounters counters;
@@ -222,7 +132,7 @@ void wiEmittedParticle::CreateSelfBuffers()
bd.ByteWidth = sizeof(counters);
bd.StructureByteStride = sizeof(counters);
bd.MiscFlags = RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS;
- wiRenderer::GetDevice()->CreateBuffer(&bd, &data, counterBuffer);
+ wiRenderer::GetDevice()->CreateBuffer(&bd, &data, counterBuffer.get());
data.pSysMem = nullptr;
// Indirect Execution buffer:
@@ -232,7 +142,7 @@ void wiEmittedParticle::CreateSelfBuffers()
sizeof(wiGraphicsTypes::IndirectDispatchArgs) +
sizeof(wiGraphicsTypes::IndirectDispatchArgs) +
sizeof(wiGraphicsTypes::IndirectDrawArgsInstanced);
- wiRenderer::GetDevice()->CreateBuffer(&bd, nullptr, indirectBuffers);
+ wiRenderer::GetDevice()->CreateBuffer(&bd, nullptr, indirectBuffers.get());
// Constant buffer:
bd.Usage = USAGE_DYNAMIC;
@@ -240,7 +150,7 @@ void wiEmittedParticle::CreateSelfBuffers()
bd.BindFlags = BIND_CONSTANT_BUFFER;
bd.CPUAccessFlags = CPU_ACCESS_WRITE;
bd.MiscFlags = 0;
- wiRenderer::GetDevice()->CreateBuffer(&bd, nullptr, constantBuffer);
+ wiRenderer::GetDevice()->CreateBuffer(&bd, nullptr, constantBuffer.get());
// Debug information CPU-readback buffer:
{
@@ -249,7 +159,7 @@ void wiEmittedParticle::CreateSelfBuffers()
debugBufDesc.CPUAccessFlags = CPU_ACCESS_READ;
debugBufDesc.BindFlags = 0;
debugBufDesc.MiscFlags = 0;
- wiRenderer::GetDevice()->CreateBuffer(&debugBufDesc, nullptr, debugDataReadbackBuffer);
+ wiRenderer::GetDevice()->CreateBuffer(&debugBufDesc, nullptr, debugDataReadbackBuffer.get());
}
// Sorting debug buffers:
@@ -259,7 +169,7 @@ void wiEmittedParticle::CreateSelfBuffers()
debugBufDesc.CPUAccessFlags = CPU_ACCESS_READ;
debugBufDesc.BindFlags = 0;
debugBufDesc.MiscFlags = 0;
- wiRenderer::GetDevice()->CreateBuffer(&debugBufDesc, nullptr, debugDataReadbackIndexBuffer);
+ wiRenderer::GetDevice()->CreateBuffer(&debugBufDesc, nullptr, debugDataReadbackIndexBuffer.get());
}
{
GPUBufferDesc debugBufDesc = distanceBuffer->GetDesc();
@@ -267,7 +177,7 @@ void wiEmittedParticle::CreateSelfBuffers()
debugBufDesc.CPUAccessFlags = CPU_ACCESS_READ;
debugBufDesc.BindFlags = 0;
debugBufDesc.MiscFlags = 0;
- wiRenderer::GetDevice()->CreateBuffer(&debugBufDesc, nullptr, debugDataReadbackDistanceBuffer);
+ wiRenderer::GetDevice()->CreateBuffer(&debugBufDesc, nullptr, debugDataReadbackDistanceBuffer.get());
}
}
@@ -293,12 +203,6 @@ uint32_t wiEmittedParticle::GetMemorySizeInBytes() const
return retVal;
}
-XMFLOAT3 wiEmittedParticle::GetPosition() const
-{
- //return object == nullptr ? XMFLOAT3(0, 0, 0) : object->translation;
- return XMFLOAT3(0, 0, 0);
-}
-
void wiEmittedParticle::Update(float dt)
{
if (PAUSED)
@@ -320,389 +224,368 @@ void wiEmittedParticle::Restart()
}
//#define DEBUG_SORTING // slow but great for debug!!
-void wiEmittedParticle::UpdateRenderData(GRAPHICSTHREAD threadID)
+void wiEmittedParticle::UpdateRenderData(const TransformComponent& transform, const MaterialComponent& material, const MeshComponent* mesh, GRAPHICSTHREAD threadID)
{
-// CreateSelfBuffers();
-//
-// GraphicsDevice* device = wiRenderer::GetDevice();
-//
-//
-// if (!PAUSED)
-// {
-//
-// device->EventBegin("UpdateEmittedParticles", threadID);
-//
-// EmittedParticleCB cb;
-// cb.xEmitterWorld = object->world;
-// cb.xEmitCount = (UINT)emit;
-// cb.xEmitterMeshIndexCount = (UINT)object->mesh->indices.size();
-// cb.xEmitterMeshVertexPositionStride = sizeof(Mesh::Vertex_POS);
-// cb.xEmitterRandomness = wiRandom::getRandom(0, 1000) * 0.001f;
-// cb.xParticleLifeSpan = life / 60.0f;
-// cb.xParticleLifeSpanRandomness = random_life;
-// cb.xParticleNormalFactor = normal_factor;
-// cb.xParticleRandomFactor = random_factor;
-// cb.xParticleScaling = scaleX;
-// cb.xParticleSize = size;
-// cb.xParticleMotionBlurAmount = motionBlurAmount;
-// cb.xParticleRotation = rotation * XM_PI * 60;
-// cb.xParticleColor = wiMath::CompressColor(XMFLOAT4(material->baseColor.x, material->baseColor.y, material->baseColor.z, 1));
-// cb.xEmitterOpacity = material->alpha;
-// cb.xParticleMass = mass;
-// cb.xEmitterMaxParticleCount = MAX_PARTICLES;
-// cb.xEmitterFixedTimestep = FIXED_TIMESTEP;
-//
-// // SPH:
-// cb.xSPH_h = SPH_h;
-// cb.xSPH_h_rcp = 1.0f / SPH_h;
-// cb.xSPH_h2 = SPH_h * SPH_h;
-// cb.xSPH_h3 = cb.xSPH_h2 * SPH_h;
-// const float h6 = cb.xSPH_h2 * cb.xSPH_h2 * cb.xSPH_h2;
-// const float h9 = cb.xSPH_h3 * cb.xSPH_h3;
-// cb.xSPH_poly6_constant = (315.0f / (64.0f * XM_PI * h9));
-// cb.xSPH_spiky_constant = (-45 / (XM_PI * h6));
-// cb.xSPH_K = SPH_K;
-// cb.xSPH_p0 = SPH_p0;
-// cb.xSPH_e = SPH_e;
-// cb.xSPH_ENABLED = SPH_FLUIDSIMULATION ? 1 : 0;
-//
-// device->UpdateBuffer(constantBuffer, &cb, threadID);
-// device->BindConstantBuffer(CS, constantBuffer, CB_GETBINDSLOT(EmittedParticleCB), threadID);
-//
-// GPUResource* uavs[] = {
-// particleBuffer,
-// aliveList[0], // CURRENT alivelist
-// aliveList[1], // NEW alivelist
-// deadList,
-// counterBuffer,
-// indirectBuffers,
-// distanceBuffer,
-// };
-// device->BindUAVs(CS, uavs, 0, ARRAYSIZE(uavs), threadID);
-//
-// GPUResource* resources[] = {
-// wiTextureHelper::getInstance()->getRandom64x64(),
-// object->mesh->indexBuffer,
-// object->mesh->vertexBuffer_POS,
-// };
-// device->BindResources(CS, resources, TEXSLOT_ONDEMAND0, ARRAYSIZE(resources), threadID);
-//
-// GPUResource* indres[] = {
-// indirectBuffers
-// };
-// device->TransitionBarrier(indres, 1, RESOURCE_STATE_INDIRECT_ARGUMENT, RESOURCE_STATE_UNORDERED_ACCESS, threadID);
-//
-// // kick off updating, set up state
-// device->EventBegin("KickOff Update", threadID);
-// device->BindComputePSO(&CPSO_kickoffUpdate, threadID);
-// device->Dispatch(1, 1, 1, threadID);
-// device->UAVBarrier(uavs, ARRAYSIZE(uavs), threadID);
-// device->EventEnd(threadID);
-//
-// device->TransitionBarrier(indres, 1, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_INDIRECT_ARGUMENT, threadID);
-//
-// // emit the required amount if there are free slots in dead list
-// device->EventBegin("Emit", threadID);
-// device->BindComputePSO(&CPSO_emit, threadID);
-// device->DispatchIndirect(indirectBuffers, ARGUMENTBUFFER_OFFSET_DISPATCHEMIT, threadID);
-// device->UAVBarrier(uavs, ARRAYSIZE(uavs), threadID);
-// device->EventEnd(threadID);
-//
-// if (SPH_FLUIDSIMULATION)
-// {
-// wiProfiler::GetInstance().BeginRange("SPH - Simulation", wiProfiler::DOMAIN_GPU, threadID);
-//
-// // Smooth Particle Hydrodynamics:
-// device->EventBegin("SPH - Simulation", threadID);
-//
-//#ifdef SPH_USE_ACCELERATION_GRID
-// // 1.) Assign particles into partitioning grid:
-// device->EventBegin("Partitioning", threadID);
-// device->BindComputePSO(&CPSO_sphpartition, threadID);
-// device->UnbindUAVs(0, 8, threadID);
-// GPUResource* res_partition[] = {
-// aliveList[0], // CURRENT alivelist
-// counterBuffer,
-// particleBuffer,
-// };
-// device->BindResources(CS, res_partition, 0, ARRAYSIZE(res_partition), threadID);
-// GPUResource* uav_partition[] = {
-// sphPartitionCellIndices,
-// };
-// device->BindUAVs(CS, uav_partition, 0, ARRAYSIZE(uav_partition), threadID);
-// device->DispatchIndirect(indirectBuffers, ARGUMENTBUFFER_OFFSET_DISPATCHSIMULATION, threadID);
-// device->UAVBarrier(uav_partition, ARRAYSIZE(uav_partition), threadID);
-// device->EventEnd(threadID);
-//
-// // 2.) Sort particle index list based on partition grid cell index:
-// wiGPUSortLib::Sort(MAX_PARTICLES, sphPartitionCellIndices, counterBuffer, PARTICLECOUNTER_OFFSET_ALIVECOUNT, aliveList[0], threadID);
-//
-// // 3.) Reset grid cell offset buffer with invalid offsets (max uint):
-// device->EventBegin("PartitionOffsetsReset", threadID);
-// device->BindComputePSO(&CPSO_sphpartitionoffsetsreset, threadID);
-// device->UnbindUAVs(0, 8, threadID);
-// GPUResource* uav_partitionoffsets[] = {
-// sphPartitionCellOffsets,
-// };
-// device->BindUAVs(CS, uav_partitionoffsets, 0, ARRAYSIZE(uav_partitionoffsets), threadID);
-// device->Dispatch((UINT)ceilf((float)SPH_PARTITION_BUCKET_COUNT / (float)THREADCOUNT_SIMULATION), 1, 1, threadID);
-// device->UAVBarrier(uav_partitionoffsets, ARRAYSIZE(uav_partitionoffsets), threadID);
-// device->EventEnd(threadID);
-//
-// // 4.) Assemble grid cell offsets from the sorted particle index list <--> grid cell index list connection:
-// device->EventBegin("PartitionOffsets", threadID);
-// device->BindComputePSO(&CPSO_sphpartitionoffsets, threadID);
-// GPUResource* res_partitionoffsets[] = {
-// aliveList[0], // CURRENT alivelist
-// counterBuffer,
-// sphPartitionCellIndices,
-// };
-// device->BindResources(CS, res_partitionoffsets, 0, ARRAYSIZE(res_partitionoffsets), threadID);
-// device->DispatchIndirect(indirectBuffers, ARGUMENTBUFFER_OFFSET_DISPATCHSIMULATION, threadID);
-// device->UAVBarrier(uav_partitionoffsets, ARRAYSIZE(uav_partitionoffsets), threadID);
-// device->EventEnd(threadID);
-//
-//#endif // SPH_USE_ACCELERATION_GRID
-//
-// // 5.) Compute particle density field:
-// device->EventBegin("Density Evaluation", threadID);
-// device->BindComputePSO(&CPSO_sphdensity, threadID);
-// device->UnbindUAVs(0, 8, threadID);
-// GPUResource* res_density[] = {
-// aliveList[0], // CURRENT alivelist
-// counterBuffer,
-// particleBuffer,
-// sphPartitionCellIndices,
-// sphPartitionCellOffsets,
-// };
-// device->BindResources(CS, res_density, 0, ARRAYSIZE(res_density), threadID);
-// GPUResource* uav_density[] = {
-// densityBuffer
-// };
-// device->BindUAVs(CS, uav_density, 0, ARRAYSIZE(uav_density), threadID);
-// device->DispatchIndirect(indirectBuffers, ARGUMENTBUFFER_OFFSET_DISPATCHSIMULATION, threadID);
-// device->UAVBarrier(uav_density, ARRAYSIZE(uav_density), threadID);
-// device->EventEnd(threadID);
-//
-// // 6.) Compute particle pressure forces:
-// device->EventBegin("Force Evaluation", threadID);
-// device->BindComputePSO(&CPSO_sphforce, threadID);
-// device->UnbindUAVs(0, 8, threadID);
-// GPUResource* res_force[] = {
-// aliveList[0], // CURRENT alivelist
-// counterBuffer,
-// densityBuffer,
-// sphPartitionCellIndices,
-// sphPartitionCellOffsets,
-// };
-// device->BindResources(CS, res_force, 0, ARRAYSIZE(res_force), threadID);
-// GPUResource* uav_force[] = {
-// particleBuffer,
-// };
-// device->BindUAVs(CS, uav_force, 0, ARRAYSIZE(uav_force), threadID);
-// device->DispatchIndirect(indirectBuffers, ARGUMENTBUFFER_OFFSET_DISPATCHSIMULATION, threadID);
-// device->UAVBarrier(uav_force, ARRAYSIZE(uav_force), threadID);
-// device->EventEnd(threadID);
-//
-// device->UnbindResources(0, 3, threadID);
-// device->UnbindUAVs(0, 8, threadID);
-//
-// device->EventEnd(threadID);
-//
-// wiProfiler::GetInstance().EndRange(threadID);
-// }
-//
-// device->EventBegin("Simulate", threadID);
-// device->BindUAVs(CS, uavs, 0, ARRAYSIZE(uavs), threadID);
-// device->BindResources(CS, resources, TEXSLOT_ONDEMAND0, ARRAYSIZE(resources), threadID);
-//
-// // update CURRENT alive list, write NEW alive list
-// if (SORTING)
-// {
-// if (DEPTHCOLLISIONS)
-// {
-// device->BindComputePSO(&CPSO_simulate_SORTING_DEPTHCOLLISIONS, threadID);
-// }
-// else
-// {
-// device->BindComputePSO(&CPSO_simulate_SORTING, threadID);
-// }
-// }
-// else
-// {
-// if (DEPTHCOLLISIONS)
-// {
-// device->BindComputePSO(&CPSO_simulate_DEPTHCOLLISIONS, threadID);
-// }
-// else
-// {
-// device->BindComputePSO(&CPSO_simulate, threadID);
-// }
-// }
-// device->DispatchIndirect(indirectBuffers, ARGUMENTBUFFER_OFFSET_DISPATCHSIMULATION, threadID);
-// device->UAVBarrier(uavs, ARRAYSIZE(uavs), threadID);
-// device->EventEnd(threadID);
-//
-//
-// device->UnbindUAVs(0, ARRAYSIZE(uavs), threadID);
-// device->UnbindResources(TEXSLOT_ONDEMAND0, ARRAYSIZE(resources), threadID);
-//
-// device->EventEnd(threadID);
-//
-// }
-//
-// if (SORTING)
-// {
-//#ifdef DEBUG_SORTING
-// vector before(maxCount);
-// device->DownloadBuffer(aliveList[1], debugDataReadbackIndexBuffer, before.data(), threadID);
-//
-// device->DownloadBuffer(counterBuffer, debugDataReadbackBuffer, &debugData, threadID);
-// uint32_t particleCount = debugData.aliveCount_afterSimulation;
-//#endif // DEBUG_SORTING
-//
-//
-// wiGPUSortLib::Sort(MAX_PARTICLES, distanceBuffer, counterBuffer, PARTICLECOUNTER_OFFSET_ALIVECOUNT_AFTERSIMULATION, aliveList[1], threadID);
-//
-//
-//#ifdef DEBUG_SORTING
-// vector after(maxCount);
-// device->DownloadBuffer(aliveList[1], debugDataReadbackIndexBuffer, after.data(), threadID);
-//
-// vector distances(maxCount);
-// device->DownloadBuffer(distanceBuffer, debugDataReadbackDistanceBuffer, distances.data(), threadID);
-//
-// if (particleCount > 1)
-// {
-// // CPU sort:
-// for (uint32_t i = 0; i < particleCount - 1; ++i)
-// {
-// for (uint32_t j = i + 1; j < particleCount; ++j)
-// {
-// uint32_t particleIndexA = before[i];
-// uint32_t particleIndexB = before[j];
-//
-// float distA = distances[particleIndexA];
-// float distB = distances[particleIndexB];
-//
-// if (distA > distB)
-// {
-// before[i] = particleIndexB;
-// before[j] = particleIndexA;
-// }
-// }
-// }
-//
-// // Validate:
-// bool valid = true;
-// uint32_t i = 0;
-// for (i = 0; i < particleCount; ++i)
-// {
-// if (before[i] != after[i])
-// {
-// if (distances[before[i]] != distances[after[i]]) // if distances are equal, we just don't care...
-// {
-// valid = false;
-// break;
-// }
-// }
-// }
-//
-// assert(valid && "Invalid GPU sorting result!");
-//
-// // Also we can reupload CPU sorted particles to verify:
-// if (!valid)
-// {
-// device->UpdateBuffer(aliveList[1], before.data(), threadID);
-// }
-// }
-//#endif // DEBUG_SORTING
-// }
-//
-// if (!PAUSED)
-// {
-// // finish updating, update draw argument buffer:
-// device->EventBegin("FinishUpdate", threadID);
-// device->BindComputePSO(&CPSO_finishUpdate, threadID);
-//
-// GPUResource* res[] = {
-// counterBuffer,
-// };
-// device->BindResources(CS, res, 0, ARRAYSIZE(res), threadID);
-//
-// GPUResource* uavs[] = {
-// indirectBuffers,
-// };
-// device->BindUAVs(CS, uavs, 0, ARRAYSIZE(uavs), threadID);
-//
-// device->Dispatch(1, 1, 1, threadID);
-// device->UAVBarrier(uavs, ARRAYSIZE(uavs), threadID);
-//
-// device->UnbindUAVs(0, ARRAYSIZE(uavs), threadID);
-// device->UnbindResources(0, ARRAYSIZE(res), threadID);
-// device->EventEnd(threadID);
-//
-//
-// // Swap CURRENT alivelist with NEW alivelist
-// SwapPtr(aliveList[0], aliveList[1]);
-// emit -= (UINT)emit;
-// }
-//
-// if (DEBUG)
-// {
-// device->DownloadResource(counterBuffer, debugDataReadbackBuffer, &debugData, threadID);
-// }
+ CreateSelfBuffers();
+
+ GraphicsDevice* device = wiRenderer::GetDevice();
+
+
+ if (!PAUSED)
+ {
+
+ device->EventBegin("UpdateEmittedParticles", threadID);
+
+ EmittedParticleCB cb;
+ cb.xEmitterWorld = transform.world;
+ cb.xEmitCount = (UINT)emit;
+ cb.xEmitterMeshIndexCount = mesh == nullptr ? 0 : (UINT)mesh->indices.size();
+ cb.xEmitterMeshVertexPositionStride = sizeof(MeshComponent::Vertex_POS);
+ cb.xEmitterRandomness = wiRandom::getRandom(0, 1000) * 0.001f;
+ cb.xParticleLifeSpan = life;
+ cb.xParticleLifeSpanRandomness = random_life;
+ cb.xParticleNormalFactor = normal_factor;
+ cb.xParticleRandomFactor = random_factor;
+ cb.xParticleScaling = scaleX;
+ cb.xParticleSize = size;
+ cb.xParticleMotionBlurAmount = motionBlurAmount;
+ cb.xParticleRotation = rotation * XM_PI * 60;
+ cb.xParticleColor = wiMath::CompressColor(XMFLOAT4(material.baseColor.x, material.baseColor.y, material.baseColor.z, 1));
+ cb.xEmitterOpacity = material.GetOpacity();
+ cb.xParticleMass = mass;
+ cb.xEmitterMaxParticleCount = MAX_PARTICLES;
+ cb.xEmitterFixedTimestep = FIXED_TIMESTEP;
+
+ // SPH:
+ cb.xSPH_h = SPH_h;
+ cb.xSPH_h_rcp = 1.0f / SPH_h;
+ cb.xSPH_h2 = SPH_h * SPH_h;
+ cb.xSPH_h3 = cb.xSPH_h2 * SPH_h;
+ const float h6 = cb.xSPH_h2 * cb.xSPH_h2 * cb.xSPH_h2;
+ const float h9 = cb.xSPH_h3 * cb.xSPH_h3;
+ cb.xSPH_poly6_constant = (315.0f / (64.0f * XM_PI * h9));
+ cb.xSPH_spiky_constant = (-45 / (XM_PI * h6));
+ cb.xSPH_K = SPH_K;
+ cb.xSPH_p0 = SPH_p0;
+ cb.xSPH_e = SPH_e;
+ cb.xSPH_ENABLED = SPH_FLUIDSIMULATION ? 1 : 0;
+
+ device->UpdateBuffer(constantBuffer.get(), &cb, threadID);
+ device->BindConstantBuffer(CS, constantBuffer.get(), CB_GETBINDSLOT(EmittedParticleCB), threadID);
+
+ GPUResource* uavs[] = {
+ particleBuffer.get(),
+ aliveList[0].get(), // CURRENT alivelist
+ aliveList[1].get(), // NEW alivelist
+ deadList.get(),
+ counterBuffer.get(),
+ indirectBuffers.get(),
+ distanceBuffer.get(),
+ };
+ device->BindUAVs(CS, uavs, 0, ARRAYSIZE(uavs), threadID);
+
+ GPUResource* resources[] = {
+ wiTextureHelper::getInstance()->getRandom64x64(),
+ mesh == nullptr ? nullptr : mesh->indexBuffer.get(),
+ mesh == nullptr ? nullptr : (mesh->streamoutBuffer_POS != nullptr ? mesh->streamoutBuffer_POS.get() : mesh->vertexBuffer_POS.get()),
+ };
+ device->BindResources(CS, resources, TEXSLOT_ONDEMAND0, ARRAYSIZE(resources), threadID);
+
+ GPUResource* indres[] = {
+ indirectBuffers.get()
+ };
+ device->TransitionBarrier(indres, 1, RESOURCE_STATE_INDIRECT_ARGUMENT, RESOURCE_STATE_UNORDERED_ACCESS, threadID);
+
+ // kick off updating, set up state
+ device->EventBegin("KickOff Update", threadID);
+ device->BindComputePSO(&CPSO_kickoffUpdate, threadID);
+ device->Dispatch(1, 1, 1, threadID);
+ device->UAVBarrier(uavs, ARRAYSIZE(uavs), threadID);
+ device->EventEnd(threadID);
+
+ device->TransitionBarrier(indres, 1, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_INDIRECT_ARGUMENT, threadID);
+
+ // emit the required amount if there are free slots in dead list
+ device->EventBegin("Emit", threadID);
+ device->BindComputePSO(mesh == nullptr ? &CPSO_emit : &CPSO_emit_FROMMESH, threadID);
+ device->DispatchIndirect(indirectBuffers.get(), ARGUMENTBUFFER_OFFSET_DISPATCHEMIT, threadID);
+ device->UAVBarrier(uavs, ARRAYSIZE(uavs), threadID);
+ device->EventEnd(threadID);
+
+ if (SPH_FLUIDSIMULATION)
+ {
+ wiProfiler::GetInstance().BeginRange("SPH - Simulation", wiProfiler::DOMAIN_GPU, threadID);
+
+ // Smooth Particle Hydrodynamics:
+ device->EventBegin("SPH - Simulation", threadID);
+
+#ifdef SPH_USE_ACCELERATION_GRID
+ // 1.) Assign particles into partitioning grid:
+ device->EventBegin("Partitioning", threadID);
+ device->BindComputePSO(&CPSO_sphpartition, threadID);
+ device->UnbindUAVs(0, 8, threadID);
+ GPUResource* res_partition[] = {
+ aliveList[0].get(), // CURRENT alivelist
+ counterBuffer.get(),
+ particleBuffer.get(),
+ };
+ device->BindResources(CS, res_partition, 0, ARRAYSIZE(res_partition), threadID);
+ GPUResource* uav_partition[] = {
+ sphPartitionCellIndices.get(),
+ };
+ device->BindUAVs(CS, uav_partition, 0, ARRAYSIZE(uav_partition), threadID);
+ device->DispatchIndirect(indirectBuffers.get(), ARGUMENTBUFFER_OFFSET_DISPATCHSIMULATION, threadID);
+ device->UAVBarrier(uav_partition, ARRAYSIZE(uav_partition), threadID);
+ device->EventEnd(threadID);
+
+ // 2.) Sort particle index list based on partition grid cell index:
+ wiGPUSortLib::Sort(MAX_PARTICLES, sphPartitionCellIndices.get(), counterBuffer.get(), PARTICLECOUNTER_OFFSET_ALIVECOUNT, aliveList[0].get(), threadID);
+
+ // 3.) Reset grid cell offset buffer with invalid offsets (max uint):
+ device->EventBegin("PartitionOffsetsReset", threadID);
+ device->BindComputePSO(&CPSO_sphpartitionoffsetsreset, threadID);
+ device->UnbindUAVs(0, 8, threadID);
+ GPUResource* uav_partitionoffsets[] = {
+ sphPartitionCellOffsets.get(),
+ };
+ device->BindUAVs(CS, uav_partitionoffsets, 0, ARRAYSIZE(uav_partitionoffsets), threadID);
+ device->Dispatch((UINT)ceilf((float)SPH_PARTITION_BUCKET_COUNT / (float)THREADCOUNT_SIMULATION), 1, 1, threadID);
+ device->UAVBarrier(uav_partitionoffsets, ARRAYSIZE(uav_partitionoffsets), threadID);
+ device->EventEnd(threadID);
+
+ // 4.) Assemble grid cell offsets from the sorted particle index list <--> grid cell index list connection:
+ device->EventBegin("PartitionOffsets", threadID);
+ device->BindComputePSO(&CPSO_sphpartitionoffsets, threadID);
+ GPUResource* res_partitionoffsets[] = {
+ aliveList[0].get(), // CURRENT alivelist
+ counterBuffer.get(),
+ sphPartitionCellIndices.get(),
+ };
+ device->BindResources(CS, res_partitionoffsets, 0, ARRAYSIZE(res_partitionoffsets), threadID);
+ device->DispatchIndirect(indirectBuffers.get(), ARGUMENTBUFFER_OFFSET_DISPATCHSIMULATION, threadID);
+ device->UAVBarrier(uav_partitionoffsets, ARRAYSIZE(uav_partitionoffsets), threadID);
+ device->EventEnd(threadID);
+
+#endif // SPH_USE_ACCELERATION_GRID
+
+ // 5.) Compute particle density field:
+ device->EventBegin("Density Evaluation", threadID);
+ device->BindComputePSO(&CPSO_sphdensity, threadID);
+ device->UnbindUAVs(0, 8, threadID);
+ GPUResource* res_density[] = {
+ aliveList[0].get(), // CURRENT alivelist
+ counterBuffer.get(),
+ particleBuffer.get(),
+ sphPartitionCellIndices.get(),
+ sphPartitionCellOffsets.get(),
+ };
+ device->BindResources(CS, res_density, 0, ARRAYSIZE(res_density), threadID);
+ GPUResource* uav_density[] = {
+ densityBuffer.get()
+ };
+ device->BindUAVs(CS, uav_density, 0, ARRAYSIZE(uav_density), threadID);
+ device->DispatchIndirect(indirectBuffers.get(), ARGUMENTBUFFER_OFFSET_DISPATCHSIMULATION, threadID);
+ device->UAVBarrier(uav_density, ARRAYSIZE(uav_density), threadID);
+ device->EventEnd(threadID);
+
+ // 6.) Compute particle pressure forces:
+ device->EventBegin("Force Evaluation", threadID);
+ device->BindComputePSO(&CPSO_sphforce, threadID);
+ device->UnbindUAVs(0, 8, threadID);
+ GPUResource* res_force[] = {
+ aliveList[0].get(), // CURRENT alivelist
+ counterBuffer.get(),
+ densityBuffer.get(),
+ sphPartitionCellIndices.get(),
+ sphPartitionCellOffsets.get(),
+ };
+ device->BindResources(CS, res_force, 0, ARRAYSIZE(res_force), threadID);
+ GPUResource* uav_force[] = {
+ particleBuffer.get(),
+ };
+ device->BindUAVs(CS, uav_force, 0, ARRAYSIZE(uav_force), threadID);
+ device->DispatchIndirect(indirectBuffers.get(), ARGUMENTBUFFER_OFFSET_DISPATCHSIMULATION, threadID);
+ device->UAVBarrier(uav_force, ARRAYSIZE(uav_force), threadID);
+ device->EventEnd(threadID);
+
+ device->UnbindResources(0, 3, threadID);
+ device->UnbindUAVs(0, 8, threadID);
+
+ device->EventEnd(threadID);
+
+ wiProfiler::GetInstance().EndRange(threadID);
+ }
+
+ device->EventBegin("Simulate", threadID);
+ device->BindUAVs(CS, uavs, 0, ARRAYSIZE(uavs), threadID);
+ device->BindResources(CS, resources, TEXSLOT_ONDEMAND0, ARRAYSIZE(resources), threadID);
+
+ // update CURRENT alive list, write NEW alive list
+ if (SORTING)
+ {
+ if (DEPTHCOLLISIONS)
+ {
+ device->BindComputePSO(&CPSO_simulate_SORTING_DEPTHCOLLISIONS, threadID);
+ }
+ else
+ {
+ device->BindComputePSO(&CPSO_simulate_SORTING, threadID);
+ }
+ }
+ else
+ {
+ if (DEPTHCOLLISIONS)
+ {
+ device->BindComputePSO(&CPSO_simulate_DEPTHCOLLISIONS, threadID);
+ }
+ else
+ {
+ device->BindComputePSO(&CPSO_simulate, threadID);
+ }
+ }
+ device->DispatchIndirect(indirectBuffers.get(), ARGUMENTBUFFER_OFFSET_DISPATCHSIMULATION, threadID);
+ device->UAVBarrier(uavs, ARRAYSIZE(uavs), threadID);
+ device->EventEnd(threadID);
+
+
+ device->UnbindUAVs(0, ARRAYSIZE(uavs), threadID);
+ device->UnbindResources(TEXSLOT_ONDEMAND0, ARRAYSIZE(resources), threadID);
+
+ device->EventEnd(threadID);
+
+ }
+
+ if (SORTING)
+ {
+#ifdef DEBUG_SORTING
+ vector before(MAX_PARTICLES);
+ device->DownloadResource(aliveList[1].get(), debugDataReadbackIndexBuffer.get(), before.data(), threadID);
+
+ device->DownloadResource(counterBuffer.get(), debugDataReadbackBuffer.get(), &debugData, threadID);
+ uint32_t particleCount = debugData.aliveCount_afterSimulation;
+#endif // DEBUG_SORTING
+
+
+ wiGPUSortLib::Sort(MAX_PARTICLES, distanceBuffer.get(), counterBuffer.get(), PARTICLECOUNTER_OFFSET_ALIVECOUNT_AFTERSIMULATION, aliveList[1].get(), threadID);
+
+
+#ifdef DEBUG_SORTING
+ vector after(MAX_PARTICLES);
+ device->DownloadResource(aliveList[1].get(), debugDataReadbackIndexBuffer.get(), after.data(), threadID);
+
+ vector distances(MAX_PARTICLES);
+ device->DownloadResource(distanceBuffer.get(), debugDataReadbackDistanceBuffer.get(), distances.data(), threadID);
+
+ if (particleCount > 1)
+ {
+ // CPU sort:
+ for (uint32_t i = 0; i < particleCount - 1; ++i)
+ {
+ for (uint32_t j = i + 1; j < particleCount; ++j)
+ {
+ uint32_t particleIndexA = before[i];
+ uint32_t particleIndexB = before[j];
+
+ float distA = distances[particleIndexA];
+ float distB = distances[particleIndexB];
+
+ if (distA > distB)
+ {
+ before[i] = particleIndexB;
+ before[j] = particleIndexA;
+ }
+ }
+ }
+
+ // Validate:
+ bool valid = true;
+ uint32_t i = 0;
+ for (i = 0; i < particleCount; ++i)
+ {
+ if (before[i] != after[i])
+ {
+ if (distances[before[i]] != distances[after[i]]) // if distances are equal, we just don't care...
+ {
+ valid = false;
+ break;
+ }
+ }
+ }
+
+ assert(valid && "Invalid GPU sorting result!");
+
+ // Also we can reupload CPU sorted particles to verify:
+ if (!valid)
+ {
+ device->UpdateBuffer(aliveList[1].get(), before.data(), threadID);
+ }
+ }
+#endif // DEBUG_SORTING
+ }
+
+ if (!PAUSED)
+ {
+ // finish updating, update draw argument buffer:
+ device->EventBegin("FinishUpdate", threadID);
+ device->BindComputePSO(&CPSO_finishUpdate, threadID);
+
+ GPUResource* res[] = {
+ counterBuffer.get(),
+ };
+ device->BindResources(CS, res, 0, ARRAYSIZE(res), threadID);
+
+ GPUResource* uavs[] = {
+ indirectBuffers.get(),
+ };
+ device->BindUAVs(CS, uavs, 0, ARRAYSIZE(uavs), threadID);
+
+ device->Dispatch(1, 1, 1, threadID);
+ device->UAVBarrier(uavs, ARRAYSIZE(uavs), threadID);
+
+ device->UnbindUAVs(0, ARRAYSIZE(uavs), threadID);
+ device->UnbindResources(0, ARRAYSIZE(res), threadID);
+ device->EventEnd(threadID);
+
+
+ // Swap CURRENT alivelist with NEW alivelist
+ aliveList[0].swap(aliveList[1]);
+ emit -= (UINT)emit;
+ }
+
+ if (DEBUG)
+ {
+ device->DownloadResource(counterBuffer.get(), debugDataReadbackBuffer.get(), &debugData, threadID);
+ }
}
-void wiEmittedParticle::Draw(GRAPHICSTHREAD threadID)
+void wiEmittedParticle::Draw(const MaterialComponent& material, GRAPHICSTHREAD threadID)
{
- //GraphicsDevice* device = wiRenderer::GetDevice();
- //device->EventBegin("EmittedParticle", threadID);
+ GraphicsDevice* device = wiRenderer::GetDevice();
+ device->EventBegin("EmittedParticle", threadID);
- //if (wiRenderer::IsWireRender())
- //{
- // device->BindGraphicsPSO(&PSO_wire, threadID);
- //}
- //else
- //{
- // device->BindGraphicsPSO(&PSO[material->blendFlag][shaderType], threadID);
- //}
+ if (wiRenderer::IsWireRender())
+ {
+ device->BindGraphicsPSO(&PSO_wire, threadID);
+ }
+ else
+ {
+ device->BindGraphicsPSO(&PSO[material.blendFlag][shaderType], threadID);
+ device->BindResource(PS, material.GetBaseColorMap(), TEXSLOT_ONDEMAND0, threadID);
+ }
- //device->BindConstantBuffer(VS, constantBuffer, CB_GETBINDSLOT(EmittedParticleCB), threadID);
+ device->BindConstantBuffer(VS, constantBuffer.get(), CB_GETBINDSLOT(EmittedParticleCB), threadID);
- //GPUResource* res[] = {
- // particleBuffer,
- // aliveList[0]
- //};
- //device->TransitionBarrier(res, ARRAYSIZE(res), RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, threadID);
- //device->BindResources(VS, res, 0, ARRAYSIZE(res), threadID);
+ GPUResource* res[] = {
+ particleBuffer.get(),
+ aliveList[0].get()
+ };
+ device->TransitionBarrier(res, ARRAYSIZE(res), RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, threadID);
+ device->BindResources(VS, res, 0, ARRAYSIZE(res), threadID);
- //if (!wiRenderer::IsWireRender() && material->texture)
- //{
- // device->BindResource(PS, material->texture, TEXSLOT_ONDEMAND0, threadID);
- //}
+ device->DrawInstancedIndirect(indirectBuffers.get(), ARGUMENTBUFFER_OFFSET_DRAWPARTICLES, threadID);
- //device->DrawInstancedIndirect(indirectBuffers, ARGUMENTBUFFER_OFFSET_DRAWPARTICLES, threadID);
-
- //device->EventEnd(threadID);
-}
-
-
-void wiEmittedParticle::CleanUp()
-{
- SAFE_DELETE(particleBuffer);
- SAFE_DELETE(aliveList[0]);
- SAFE_DELETE(aliveList[1]);
- SAFE_DELETE(deadList);
- SAFE_DELETE(distanceBuffer);
- SAFE_DELETE(densityBuffer);
- SAFE_DELETE(counterBuffer);
- SAFE_DELETE(indirectBuffers);
- SAFE_DELETE(constantBuffer);
- SAFE_DELETE(debugDataReadbackBuffer);
- SAFE_DELETE(debugDataReadbackIndexBuffer);
- SAFE_DELETE(debugDataReadbackDistanceBuffer);
+ device->EventEnd(threadID);
}
@@ -721,6 +604,7 @@ void wiEmittedParticle::LoadShaders()
kickoffUpdateCS = static_cast(wiResourceManager::GetShaderManager()->add(wiRenderer::SHADERPATH + "emittedparticle_kickoffUpdateCS.cso", wiResourceManager::COMPUTESHADER));
finishUpdateCS = static_cast(wiResourceManager::GetShaderManager()->add(wiRenderer::SHADERPATH + "emittedparticle_finishUpdateCS.cso", wiResourceManager::COMPUTESHADER));
emitCS = static_cast(wiResourceManager::GetShaderManager()->add(wiRenderer::SHADERPATH + "emittedparticle_emitCS.cso", wiResourceManager::COMPUTESHADER));
+ emitCS_FROMMESH = static_cast(wiResourceManager::GetShaderManager()->add(wiRenderer::SHADERPATH + "emittedparticle_emitCS_FROMMESH.cso", wiResourceManager::COMPUTESHADER));
sphpartitionCS = static_cast(wiResourceManager::GetShaderManager()->add(wiRenderer::SHADERPATH + "emittedparticle_sphpartitionCS.cso", wiResourceManager::COMPUTESHADER));
sphpartitionoffsetsCS = static_cast(wiResourceManager::GetShaderManager()->add(wiRenderer::SHADERPATH + "emittedparticle_sphpartitionoffsetsCS.cso", wiResourceManager::COMPUTESHADER));
sphpartitionoffsetsresetCS = static_cast(wiResourceManager::GetShaderManager()->add(wiRenderer::SHADERPATH + "emittedparticle_sphpartitionoffsetsresetCS.cso", wiResourceManager::COMPUTESHADER));
@@ -777,6 +661,9 @@ void wiEmittedParticle::LoadShaders()
desc.cs = emitCS;
device->CreateComputePSO(&desc, &CPSO_emit);
+ desc.cs = emitCS_FROMMESH;
+ device->CreateComputePSO(&desc, &CPSO_emit_FROMMESH);
+
desc.cs = sphpartitionCS;
device->CreateComputePSO(&desc, &CPSO_sphpartition);
@@ -893,106 +780,11 @@ void wiEmittedParticle::CleanUpStatic()
SAFE_DELETE(pixelShader[i]);
}
SAFE_DELETE(emitCS);
+ SAFE_DELETE(emitCS_FROMMESH);
SAFE_DELETE(simulateCS);
SAFE_DELETE(simulateCS_SORTING);
SAFE_DELETE(simulateCS_DEPTHCOLLISIONS);
SAFE_DELETE(simulateCS_SORTING_DEPTHCOLLISIONS);
}
-void wiEmittedParticle::Serialize(wiArchive& archive)
-{
- if (archive.IsReadMode())
- {
- archive >> emit;
- if (archive.GetVersion() < 9)
- {
- XMFLOAT4X4 transform4;
- XMFLOAT3X3 transform3;
- archive >> transform4;
- archive >> transform3;
- }
- archive >> name;
- archive >> materialName;
- archive >> size;
- archive >> random_factor;
- archive >> normal_factor;
- archive >> count;
- archive >> life;
- archive >> random_life;
- archive >> scaleX;
- archive >> scaleY;
- archive >> rotation;
- archive >> motionBlurAmount;
- if (archive.GetVersion() < 9)
- {
- string lightName;
- archive >> lightName;
- }
- if (archive.GetVersion() >= 11)
- {
- archive >> MAX_PARTICLES;
- archive >> SORTING;
- }
- if (archive.GetVersion() >= 12)
- {
- archive >> DEPTHCOLLISIONS;
- }
- if (archive.GetVersion() >= 14)
- {
- int tmp;
- archive >> tmp;
- shaderType = (PARTICLESHADERTYPE)tmp;
- }
- if (archive.GetVersion() >= 18)
- {
- archive >> mass;
- archive >> FIXED_TIMESTEP;
- archive >> SPH_FLUIDSIMULATION;
- archive >> SPH_h;
- archive >> SPH_K;
- archive >> SPH_p0;
- archive >> SPH_e;
- }
-
- }
- else
- {
- archive << emit;
- archive << name;
- archive << materialName;
- archive << size;
- archive << random_factor;
- archive << normal_factor;
- archive << count;
- archive << life;
- archive << random_life;
- archive << scaleX;
- archive << scaleY;
- archive << rotation;
- archive << motionBlurAmount;
- if (archive.GetVersion() >= 11)
- {
- archive << MAX_PARTICLES;
- archive << SORTING;
- }
- if (archive.GetVersion() >= 12)
- {
- archive << DEPTHCOLLISIONS;
- }
- if (archive.GetVersion() >= 14)
- {
- archive << (int)shaderType;
- }
- if (archive.GetVersion() >= 18)
- {
- archive << mass;
- archive << FIXED_TIMESTEP;
- archive << SPH_FLUIDSIMULATION;
- archive << SPH_h;
- archive << SPH_K;
- archive << SPH_p0;
- archive << SPH_e;
- }
-
- }
}
diff --git a/WickedEngine/wiEmittedParticle.h b/WickedEngine/wiEmittedParticle.h
index d8b47e5c9..ab9269d46 100644
--- a/WickedEngine/wiEmittedParticle.h
+++ b/WickedEngine/wiEmittedParticle.h
@@ -4,9 +4,14 @@
#include "wiIntersectables.h"
#include "ShaderInterop_EmittedParticle.h"
#include "wiImageEffects.h"
+#include "wiSceneSystem_Decl.h"
+#include "wiECS.h"
class wiArchive;
+namespace wiSceneSystem
+{
+
class wiEmittedParticle
{
public:
@@ -20,23 +25,23 @@ public:
private:
ParticleCounters debugData = {};
- wiGraphicsTypes::GPUBuffer* debugDataReadbackBuffer = nullptr;
- wiGraphicsTypes::GPUBuffer* debugDataReadbackIndexBuffer = nullptr;
- wiGraphicsTypes::GPUBuffer* debugDataReadbackDistanceBuffer = nullptr;
+ std::unique_ptr debugDataReadbackBuffer;
+ std::unique_ptr debugDataReadbackIndexBuffer;
+ std::unique_ptr debugDataReadbackDistanceBuffer;
- wiGraphicsTypes::GPUBuffer* particleBuffer = nullptr;
- wiGraphicsTypes::GPUBuffer* aliveList[2] = { nullptr, nullptr };
- wiGraphicsTypes::GPUBuffer* deadList = nullptr;
- wiGraphicsTypes::GPUBuffer* distanceBuffer = nullptr; // for sorting
- wiGraphicsTypes::GPUBuffer* sphPartitionCellIndices = nullptr; // for SPH
- wiGraphicsTypes::GPUBuffer* sphPartitionCellOffsets = nullptr; // for SPH
- wiGraphicsTypes::GPUBuffer* densityBuffer = nullptr; // for SPH
- wiGraphicsTypes::GPUBuffer* counterBuffer = nullptr;
- wiGraphicsTypes::GPUBuffer* indirectBuffers = nullptr; // kickoffUpdate, simulation, draw
- wiGraphicsTypes::GPUBuffer* constantBuffer = nullptr;
+ std::unique_ptr particleBuffer;
+ std::unique_ptr aliveList[2];
+ std::unique_ptr deadList;
+ std::unique_ptr distanceBuffer; // for sorting
+ std::unique_ptr sphPartitionCellIndices; // for SPH
+ std::unique_ptr sphPartitionCellOffsets; // for SPH
+ std::unique_ptr densityBuffer; // for SPH
+ std::unique_ptr counterBuffer;
+ std::unique_ptr indirectBuffers; // kickoffUpdate, simulation, draw
+ std::unique_ptr constantBuffer;
void CreateSelfBuffers();
- static wiGraphicsTypes::ComputeShader *kickoffUpdateCS, *finishUpdateCS, *emitCS, *sphpartitionCS, *sphpartitionoffsetsCS, *sphpartitionoffsetsresetCS, *sphdensityCS, *sphforceCS, *simulateCS, *simulateCS_SORTING, *simulateCS_DEPTHCOLLISIONS, *simulateCS_SORTING_DEPTHCOLLISIONS;
+ static wiGraphicsTypes::ComputeShader *kickoffUpdateCS, *finishUpdateCS, *emitCS, *emitCS_FROMMESH, *sphpartitionCS, *sphpartitionoffsetsCS, *sphpartitionoffsetsresetCS, *sphdensityCS, *sphforceCS, *simulateCS, *simulateCS_SORTING, *simulateCS_DEPTHCOLLISIONS, *simulateCS_SORTING_DEPTHCOLLISIONS;
static wiGraphicsTypes::VertexShader *vertexShader;
static wiGraphicsTypes::PixelShader *pixelShader[PARTICLESHADERTYPE_COUNT];
static wiGraphicsTypes::BlendState blendStates[BLENDMODE_COUNT];
@@ -45,35 +50,31 @@ private:
static wiGraphicsTypes::GraphicsPSO PSO[BLENDMODE_COUNT][PARTICLESHADERTYPE_COUNT];
static wiGraphicsTypes::GraphicsPSO PSO_wire;
- static wiGraphicsTypes::ComputePSO CPSO_kickoffUpdate, CPSO_finishUpdate, CPSO_emit, CPSO_sphpartition, CPSO_sphpartitionoffsets, CPSO_sphpartitionoffsetsreset, CPSO_sphdensity, CPSO_sphforce, CPSO_simulate, CPSO_simulate_SORTING, CPSO_simulate_DEPTHCOLLISIONS, CPSO_simulate_SORTING_DEPTHCOLLISIONS;
+ static wiGraphicsTypes::ComputePSO CPSO_kickoffUpdate, CPSO_finishUpdate, CPSO_emit, CPSO_emit_FROMMESH, CPSO_sphpartition, CPSO_sphpartitionoffsets, CPSO_sphpartitionoffsetsreset, CPSO_sphdensity, CPSO_sphforce, CPSO_simulate, CPSO_simulate_SORTING, CPSO_simulate_DEPTHCOLLISIONS, CPSO_simulate_SORTING_DEPTHCOLLISIONS;
public:
static void LoadShaders();
+ static void SetUpStatic();
+ static void CleanUpStatic();
private:
static void LoadBuffers();
static void SetUpStates();
- float emit;
+ float emit = 0.0f;
bool buffersUpToDate = false;
- uint32_t MAX_PARTICLES;
+ uint32_t MAX_PARTICLES = 1000;
public:
- wiEmittedParticle();
- //wiEmittedParticle(const std::string& newName, const std::string& newMat, wiSceneComponents::Object* newObject, float newSize, float newRandomFac, float newNormalFac
- // ,float newCount, float newLife, float newRandLife, float newScaleX, float newScaleY, float newRot);
- wiEmittedParticle(const wiEmittedParticle& other);
- static void SetUpStatic();
- static void CleanUpStatic();
-
void Update(float dt);
void Burst(float num);
void Restart();
- void UpdateRenderData(GRAPHICSTHREAD threadID);
+ wiECS::Entity meshID = wiECS::INVALID_ENTITY;
- void Draw(GRAPHICSTHREAD threadID);
- void CleanUp();
+ // Must have a transform and material component, but mesh is optional
+ void UpdateRenderData(const TransformComponent& transform, const MaterialComponent& material, const MeshComponent* mesh, GRAPHICSTHREAD threadID);
+ void Draw(const MaterialComponent& material, GRAPHICSTHREAD threadID);
bool DEBUG = false;
ParticleCounters GetDebugData() { return debugData; }
@@ -86,15 +87,16 @@ public:
PARTICLESHADERTYPE shaderType = SOFT;
- std::string name;
- //wiSceneComponents::Object* object;
- std::string materialName;
- //wiSceneComponents::Material* material;
-
- float size,random_factor,normal_factor;
- float count,life,random_life;
- float scaleX,scaleY,rotation;
- float motionBlurAmount;
+ float size = 1.0f;
+ float random_factor = 1.0f;
+ float normal_factor = 1.0f;
+ float count = 0.0f;
+ float life = 1.0f;
+ float random_life = 1.0f;
+ float scaleX = 1.0f;
+ float scaleY = 1.0f;
+ float rotation = 0.0f;
+ float motionBlurAmount = 0.0f;
float mass = 1.0f;
float SPH_h = 1.0f; // smoothing radius
@@ -105,9 +107,7 @@ public:
void SetMaxParticleCount(uint32_t value);
uint32_t GetMaxParticleCount() const { return MAX_PARTICLES; }
uint32_t GetMemorySizeInBytes() const;
-
- XMFLOAT3 GetPosition() const;
-
- void Serialize(wiArchive& archive);
};
+}
+
diff --git a/WickedEngine/wiHairParticle.cpp b/WickedEngine/wiHairParticle.cpp
index 715032983..31906d720 100644
--- a/WickedEngine/wiHairParticle.cpp
+++ b/WickedEngine/wiHairParticle.cpp
@@ -12,7 +12,9 @@
using namespace std;
using namespace wiGraphicsTypes;
-using namespace wiSceneSystem;
+
+namespace wiSceneSystem
+{
VertexShader *wiHairParticle::vs = nullptr;
PixelShader *wiHairParticle::ps[];
@@ -24,84 +26,6 @@ GraphicsPSO wiHairParticle::PSO[SHADERTYPE_COUNT][2];
GraphicsPSO wiHairParticle::PSO_wire;
int wiHairParticle::LOD[3];
-wiHairParticle::wiHairParticle()
-{
- cb = nullptr;
- particleBuffer = nullptr;
- ib = nullptr;
- ib_transposed = nullptr;
- name = "";
- densityG = "";
- lenG = "";
- length = 0;
- count = 0;
- //material = nullptr;
- //object = nullptr;
- materialName = "";
- particleCount = 0;
-}
-//wiHairParticle::wiHairParticle(const std::string& newName, float newLen, int newCount
-// , const std::string& newMat, Object* newObject, const std::string& densityGroup, const std::string& lengthGroup)
-//{
-// cb = nullptr;
-// particleBuffer = nullptr;
-// ib = nullptr;
-// ib_transposed = nullptr;
-// drawargs = nullptr;
-// name=newName;
-// densityG=densityGroup;
-// lenG=lengthGroup;
-// length=newLen;
-// count=newCount;
-// material=nullptr;
-// object = newObject;
-// materialName = newMat;
-// particleCount = 0;
-// for (MeshSubset& subset : object->mesh->subsets)
-// {
-// if (!newMat.compare(subset.material->name)) {
-// material = subset.material;
-// break;
-// }
-// }
-//
-// if (material)
-// {
-// Generate();
-// }
-//}
-wiHairParticle::wiHairParticle(const wiHairParticle& other)
-{
- cb = nullptr;
- particleBuffer = nullptr;
- ib = nullptr;
- ib_transposed = nullptr;
- drawargs = nullptr;
- name = other.name + "0";
- densityG = other.densityG;
- lenG = other.lenG;
- length = other.length;
- count = other.count;
- //material = other.material;
- //object = other.object;
- materialName = other.materialName;
- particleCount = other.particleCount;
- //material = other.material;
-
- //if (material)
- {
- Generate();
- }
-}
-
-void wiHairParticle::CleanUp()
-{
- SAFE_DELETE(cb);
- SAFE_DELETE(particleBuffer);
- SAFE_DELETE(ib);
- SAFE_DELETE(drawargs);
-}
-
void wiHairParticle::CleanUpStatic()
{
SAFE_DELETE(vs);
@@ -572,33 +496,4 @@ void wiHairParticle::Draw(CameraComponent* camera, SHADERTYPE shaderType, bool t
//}
}
-
-void wiHairParticle::Serialize(wiArchive& archive)
-{
- if (archive.IsReadMode())
- {
- archive >> length;
- archive >> count;
- archive >> name;
- archive >> densityG;
- archive >> lenG;
- archive >> materialName;
- if (archive.GetVersion() < 15)
- {
- archive >> OriginalMatrix_Inverse;
- }
- }
- else
- {
- archive << length;
- archive << count;
- archive << name;
- archive << densityG;
- archive << lenG;
- archive << materialName;
- if (archive.GetVersion() < 15)
- {
- archive << OriginalMatrix_Inverse;
- }
- }
}
diff --git a/WickedEngine/wiHairParticle.h b/WickedEngine/wiHairParticle.h
index 291067805..628bb7b87 100644
--- a/WickedEngine/wiHairParticle.h
+++ b/WickedEngine/wiHairParticle.h
@@ -6,6 +6,9 @@
class wiArchive;
+namespace wiSceneSystem
+{
+
class wiHairParticle
{
public:
@@ -26,11 +29,11 @@ private:
float __pad1;
};
- wiGraphicsTypes::GPUBuffer *cb;
- wiGraphicsTypes::GPUBuffer *particleBuffer;
- wiGraphicsTypes::GPUBuffer *ib;
- wiGraphicsTypes::GPUBuffer *ib_transposed;
- wiGraphicsTypes::GPUBuffer *drawargs;
+ std::unique_ptr cb;
+ std::unique_ptr particleBuffer;
+ std::unique_ptr ib;
+ std::unique_ptr ib_transposed;
+ std::unique_ptr drawargs;
static wiGraphicsTypes::VertexShader *vs;
static wiGraphicsTypes::PixelShader *ps[SHADERTYPE_COUNT];
@@ -45,12 +48,6 @@ public:
static void LoadShaders();
public:
- wiHairParticle();
- //wiHairParticle(const std::string& newName, float newLen, int newCount
- // , const std::string& newMat, wiSceneComponents::Object* newObject, const std::string& densityGroup, const std::string& lengthGroup);
- wiHairParticle(const wiHairParticle& other);
-
- void CleanUp();
void Generate();
void ComputeCulling(wiSceneSystem::CameraComponent* camera, GRAPHICSTHREAD threadID);
@@ -60,14 +57,9 @@ public:
static void SetUpStatic();
static void Settings(int lod0,int lod1,int lod2);
- float length;
- int count;
- std::string name, densityG, lenG, materialName;
- //wiSceneComponents::Material* material;
+ float length = 1.0f;
XMFLOAT4X4 OriginalMatrix_Inverse;
- //wiSceneComponents::Object* object;
- size_t particleCount;
-
- void Serialize(wiArchive& archive);
+ size_t particleCount = 0;
};
+}
diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp
index f2e661900..b3ff87147 100644
--- a/WickedEngine/wiRenderer.cpp
+++ b/WickedEngine/wiRenderer.cpp
@@ -3460,12 +3460,7 @@ void wiRenderer::UpdateRenderData(GRAPHICSTHREAD threadID)
device->BindUAVs(CS, sos, 0, ARRAYSIZE(sos), threadID);
device->Dispatch((UINT)ceilf((float)mesh.vertex_positions.size() / SKINNING_COMPUTE_THREADCOUNT), 1, 1, threadID);
- device->UAVBarrier(sos, ARRAYSIZE(sos), threadID); // todo: defer
- //device->TransitionBarrier(sos, ARRAYSIZE(sos), RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER, threadID);
- }
- else if (mesh.IsDynamicVB())
- {
-
+ device->UAVBarrier(sos, ARRAYSIZE(sos), threadID); // todo: defer, to gain from async compute
}
}
@@ -3480,15 +3475,17 @@ void wiRenderer::UpdateRenderData(GRAPHICSTHREAD threadID)
device->EventEnd(threadID);
wiProfiler::GetInstance().EndRange(threadID); // skinning
- //// Particle system simulation/sorting/culling:
- //for (auto& x : emitterSystems)
- //{
- // x->UpdateRenderData(threadID);
- //}
- //for (wiHairParticle* hair : mainCameraCulling.culledHairParticleSystems)
- //{
- // hair->ComputeCulling(getCamera(), threadID);
- //}
+ // GPU Particle systems simulation/sorting/culling:
+ for (size_t i = 0; i < scene.emitters.GetCount(); ++i)
+ {
+ wiEmittedParticle& emitter = scene.emitters[i];
+ Entity entity = scene.emitters.GetEntity(i);
+ const TransformComponent& transform = *scene.transforms.GetComponent(entity);
+ const MaterialComponent& material = *scene.materials.GetComponent(entity);
+ const MeshComponent* mesh = scene.meshes.GetComponent(emitter.meshID);
+
+ emitter.UpdateRenderData(transform, material, mesh, threadID);
+ }
// Compute water simulation:
if (ocean != nullptr)
@@ -3994,36 +3991,55 @@ void wiRenderer::DrawDebugWorld(CameraComponent* camera, GRAPHICSTHREAD threadID
device->EventEnd(threadID);
}
- //if (debugEmitters || !renderableBoxes.empty())
- //{
- // device->EventBegin("DebugEmitters", threadID);
+ if (debugEmitters)
+ {
+ device->EventBegin("DebugEmitters", threadID);
- // device->BindGraphicsPSO(PSO_debug[DEBUGRENDERING_EMITTER], threadID);
+ MiscCB sb;
+ for (size_t i = 0; i < scene.emitters.GetCount(); ++i)
+ {
+ const wiEmittedParticle& emitter = scene.emitters[i];
+ Entity entity = scene.emitters.GetEntity(i);
+ const TransformComponent& transform = *scene.transforms.GetComponent(entity);
+ const MeshComponent* mesh = scene.meshes.GetComponent(emitter.meshID);
- // MiscCB sb;
- // for (auto& x : emitterSystems)
- // {
- // if (x->object != nullptr && x->object->mesh != nullptr)
- // {
- // sb.mTransform = XMMatrixTranspose(XMLoadFloat4x4(&x->object->world)*camera->GetViewProjection());
- // sb.mColor = XMFLOAT4(0, 1, 0, 1);
- // device->UpdateBuffer(constantBuffers[CBTYPE_MISC], &sb, threadID);
+ sb.mTransform = XMMatrixTranspose(XMLoadFloat4x4(&transform.world)*camera->GetViewProjection());
+ sb.mColor = XMFLOAT4(0, 1, 0, 1);
+ device->UpdateBuffer(constantBuffers[CBTYPE_MISC], &sb, threadID);
- // GPUBuffer* vbs[] = {
- // x->object->mesh->vertexBuffer_POS,
- // };
- // const UINT strides[] = {
- // sizeof(MeshComponent::Vertex_POS),
- // };
- // device->BindVertexBuffers(vbs, 0, ARRAYSIZE(vbs), strides, nullptr, threadID);
- // device->BindIndexBuffer(x->object->mesh->indexBuffer, x->object->mesh->GetIndexFormat(), 0, threadID);
+ if (mesh == nullptr)
+ {
+ // No mesh, just draw a box:
+ device->BindGraphicsPSO(PSO_debug[DEBUGRENDERING_CUBE], threadID);
+ GPUBuffer* vbs[] = {
+ &Cube::vertexBuffer,
+ };
+ const UINT strides[] = {
+ sizeof(XMFLOAT4) + sizeof(XMFLOAT4),
+ };
+ device->BindVertexBuffers(vbs, 0, ARRAYSIZE(vbs), strides, nullptr, threadID);
+ device->BindIndexBuffer(&Cube::indexBuffer, INDEXFORMAT_16BIT, 0, threadID);
+ device->DrawIndexed(24, 0, 0, threadID);
+ }
+ else
+ {
+ // Draw mesh wireframe:
+ device->BindGraphicsPSO(PSO_debug[DEBUGRENDERING_EMITTER], threadID);
+ GPUBuffer* vbs[] = {
+ mesh->streamoutBuffer_POS != nullptr ? mesh->streamoutBuffer_POS.get() : mesh->vertexBuffer_POS.get(),
+ };
+ const UINT strides[] = {
+ sizeof(MeshComponent::Vertex_POS),
+ };
+ device->BindVertexBuffers(vbs, 0, ARRAYSIZE(vbs), strides, nullptr, threadID);
+ device->BindIndexBuffer(mesh->indexBuffer.get(), mesh->GetIndexFormat(), 0, threadID);
- // device->DrawIndexed((int)x->object->mesh->indices.size(), 0, 0, threadID);
- // }
- // }
+ device->DrawIndexed((int)mesh->indices.size(), 0, 0, threadID);
+ }
+ }
- // device->EventEnd(threadID);
- //}
+ device->EventEnd(threadID);
+ }
if (debugForceFields)
@@ -4101,23 +4117,24 @@ void wiRenderer::DrawDebugWorld(CameraComponent* camera, GRAPHICSTHREAD threadID
void wiRenderer::DrawSoftParticles(CameraComponent* camera, bool distortion, GRAPHICSTHREAD threadID)
{
- //// todo: remove allocation of vector
- //vector sortedEmitters(emitterSystems.begin(), emitterSystems.end());
- //std::sort(sortedEmitters.begin(), sortedEmitters.end(), [&](const wiEmittedParticle* a, const wiEmittedParticle* b) {
- // return wiMath::DistanceSquared(camera->translation, a->GetPosition()) > wiMath::DistanceSquared(camera->translation, b->GetPosition());
- //});
+ Scene& scene = GetScene();
+
+ for (size_t i = 0; i < scene.emitters.GetCount(); ++i)
+ {
+ wiEmittedParticle& emitter = scene.emitters[i];
+ Entity entity = scene.emitters.GetEntity(i);
+ const MaterialComponent& material = *scene.materials.GetComponent(entity);
+
+ if (distortion && emitter.shaderType == wiEmittedParticle::SOFT_DISTORTION)
+ {
+ emitter.Draw(material, threadID);
+ }
+ else if (!distortion && (emitter.shaderType == wiEmittedParticle::SOFT || emitter.shaderType == wiEmittedParticle::SIMPLEST || IsWireRender()))
+ {
+ emitter.Draw(material, threadID);
+ }
+ }
- //for (wiEmittedParticle* e : sortedEmitters)
- //{
- // if (distortion && e->shaderType == wiEmittedParticle::SOFT_DISTORTION)
- // {
- // e->Draw(threadID);
- // }
- // else if (!distortion && (e->shaderType == wiEmittedParticle::SOFT || e->shaderType == wiEmittedParticle::SIMPLEST || IsWireRender()))
- // {
- // e->Draw(threadID);
- // }
- //}
}
void wiRenderer::DrawTrails(GRAPHICSTHREAD threadID, Texture2D* refracRes)
{
diff --git a/WickedEngine/wiRenderer.h b/WickedEngine/wiRenderer.h
index a66dccc66..f0189f42d 100644
--- a/WickedEngine/wiRenderer.h
+++ b/WickedEngine/wiRenderer.h
@@ -11,13 +11,7 @@
#include
#include
-class Cube;
-class Translator;
-class wiParticle;
-class wiEmittedParticle;
-class wiHairParticle;
class wiSprite;
-class TaskThread;
class PHYSICS;
class wiRenderTarget;
class wiOcean;
diff --git a/WickedEngine/wiRenderer_BindLua.cpp b/WickedEngine/wiRenderer_BindLua.cpp
index 03de98471..345830177 100644
--- a/WickedEngine/wiRenderer_BindLua.cpp
+++ b/WickedEngine/wiRenderer_BindLua.cpp
@@ -11,6 +11,7 @@
using namespace std;
using namespace wiGraphicsTypes;
+using namespace wiSceneSystem;
namespace wiRenderer_BindLua
{
diff --git a/WickedEngine/wiSceneSystem.cpp b/WickedEngine/wiSceneSystem.cpp
index 678ab2d34..670795f82 100644
--- a/WickedEngine/wiSceneSystem.cpp
+++ b/WickedEngine/wiSceneSystem.cpp
@@ -364,7 +364,7 @@ namespace wiSceneSystem
assert(SUCCEEDED(hr));
bd.Usage = USAGE_DEFAULT;
- bd.BindFlags = BIND_VERTEX_BUFFER | BIND_UNORDERED_ACCESS;
+ bd.BindFlags = BIND_VERTEX_BUFFER | BIND_UNORDERED_ACCESS | BIND_SHADER_RESOURCE;
bd.CPUAccessFlags = 0;
bd.MiscFlags = RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS;
@@ -763,9 +763,15 @@ namespace wiSceneSystem
RunLightUpdateSystem(*cameras.GetComponent(wiRenderer::getCameraID()), transforms, aabb_lights, lights, sunDirection, sunColor);
+ RunEmitterUpdateSystem(emitters, dt);
+
}
void Scene::Clear()
{
+ // Preferrably, we wouldn't write all of this, just call clear on every container
+ // But: we want to only delete the owned entities, and there might be others
+ // Think about it, probably there is a better way...
+
for (Entity entity : owned_entities)
{
names.Remove(entity);
@@ -789,6 +795,8 @@ namespace wiSceneSystem
decals.Remove(entity);
aabb_decals.Remove(entity);
animations.Remove(entity);
+ emitters.Remove(entity);
+ hairs.Remove(entity);
models.Remove(entity);
}
@@ -820,6 +828,8 @@ namespace wiSceneSystem
decals.Remove(entity);
aabb_decals.Remove(entity);
animations.Remove(entity);
+ emitters.Remove(entity);
+ hairs.Remove(entity);
models.Remove(entity);
}
Entity Scene::Entity_FindByName(const std::string& name)
@@ -916,8 +926,9 @@ namespace wiSceneSystem
layers.Create(entity);
- transforms.Create(entity).Translate(position);
- transforms.GetComponent(entity)->UpdateTransform();
+ TransformComponent& transform = transforms.Create(entity);
+ transform.Translate(position);
+ transform.UpdateTransform();
aabb_lights.Create(entity).createFromHalfWidth(position, XMFLOAT3(range, range, range));
@@ -943,8 +954,9 @@ namespace wiSceneSystem
layers.Create(entity);
- transforms.Create(entity).Translate(position);
- transforms.GetComponent(entity)->UpdateTransform();
+ TransformComponent& transform = transforms.Create(entity);
+ transform.Translate(position);
+ transform.UpdateTransform();
ForceFieldComponent& force = forces.Create(entity);
force.gravity = 0;
@@ -966,8 +978,9 @@ namespace wiSceneSystem
layers.Create(entity);
- transforms.Create(entity).Translate(position);
- transforms.GetComponent(entity)->UpdateTransform();
+ TransformComponent& transform = transforms.Create(entity);
+ transform.Translate(position);
+ transform.UpdateTransform();
aabb_probes.Create(entity);
@@ -1031,6 +1044,27 @@ namespace wiSceneSystem
return entity;
}
+ Entity Scene::Entity_CreateEmitter(
+ const std::string& name,
+ const XMFLOAT3& position
+ )
+ {
+ Entity entity = CreateEntity();
+
+ owned_entities.insert(entity);
+
+ names.Create(entity) = name;
+
+ emitters.Create(entity);
+
+ TransformComponent& transform = transforms.Create(entity);
+ transform.Translate(position);
+ transform.UpdateTransform();
+
+ materials.Create(entity);
+
+ return entity;
+ }
void Scene::Component_Attach(Entity entity, Entity parent)
{
@@ -1694,6 +1728,13 @@ namespace wiSceneSystem
}
}
-
+ void RunEmitterUpdateSystem(ComponentManager& emitters, float dt)
+ {
+ for (size_t i = 0; i < emitters.GetCount(); ++i)
+ {
+ wiEmittedParticle& emitter = emitters[i];
+ emitter.Update(dt);
+ }
+ }
}
diff --git a/WickedEngine/wiSceneSystem.h b/WickedEngine/wiSceneSystem.h
index 446a7ab0a..04ecfa083 100644
--- a/WickedEngine/wiSceneSystem.h
+++ b/WickedEngine/wiSceneSystem.h
@@ -6,6 +6,8 @@
#include "ShaderInterop.h"
#include "wiFrustum.h"
#include "wiRenderTarget.h"
+#include "wiEmittedParticle.h"
+#include "wiHairParticle.h"
#include "wiECS.h"
#include "wiSceneSystem_Decl.h"
@@ -686,6 +688,8 @@ namespace wiSceneSystem
wiECS::ComponentManager decals;
wiECS::ComponentManager aabb_decals;
wiECS::ComponentManager animations;
+ wiECS::ComponentManager emitters;
+ wiECS::ComponentManager hairs;
wiECS::ComponentManager models;
AABB bounds;
@@ -714,23 +718,19 @@ namespace wiSceneSystem
void Entity_Remove(wiECS::Entity entity);
// Finds the first entity by the name (if it exists, otherwise returns INVALID_ENTITY):
wiECS::Entity Entity_FindByName(const std::string& name);
- // Helper function to create a model entity:
+
wiECS::Entity Entity_CreateModel(
const std::string& name
);
- // Helper function to create a material entity:
wiECS::Entity Entity_CreateMaterial(
const std::string& name
);
- // Helper function to create a model entity:
wiECS::Entity Entity_CreateObject(
const std::string& name
);
- // Helper function to create a model entity:
wiECS::Entity Entity_CreateMesh(
const std::string& name
);
- // Helper function to create a light entity:
wiECS::Entity Entity_CreateLight(
const std::string& name,
const XMFLOAT3& position = XMFLOAT3(0, 0, 0),
@@ -738,27 +738,27 @@ namespace wiSceneSystem
float energy = 1,
float range = 10
);
- // Helper function to create a force entity:
wiECS::Entity Entity_CreateForce(
const std::string& name,
const XMFLOAT3& position = XMFLOAT3(0, 0, 0)
);
- // Helper function to create an environment capture probe entity:
wiECS::Entity Entity_CreateEnvironmentProbe(
const std::string& name,
const XMFLOAT3& position = XMFLOAT3(0, 0, 0)
);
- // Helper function to create a decal entity:
wiECS::Entity Entity_CreateDecal(
const std::string& name,
const std::string& textureName,
const std::string& normalMapName = ""
);
- // Helper function to create a camera entity:
wiECS::Entity Entity_CreateCamera(
const std::string& name,
float width, float height, float nearPlane = 0.01f, float farPlane = 1000.0f, float fov = XM_PIDIV4
);
+ wiECS::Entity Entity_CreateEmitter(
+ const std::string& name,
+ const XMFLOAT3& position = XMFLOAT3(0, 0, 0)
+ );
// Attaches an entity to a parent:
void Component_Attach(wiECS::Entity entity, wiECS::Entity parent);
@@ -826,6 +826,7 @@ namespace wiSceneSystem
wiECS::ComponentManager& lights,
XMFLOAT3& sunDirection, XMFLOAT3& sunColor
);
+ void RunEmitterUpdateSystem(wiECS::ComponentManager& emitters, float dt);
}