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); }