So many changes again

This commit is contained in:
2026-04-15 16:56:19 +02:00
parent 495e683522
commit 424dea0012
30 changed files with 566 additions and 235 deletions
+6 -3
View File
@@ -4,10 +4,13 @@
namespace Seele {
namespace Component {
struct FluidGrid {
float cellSize = 1.0f;
float viscosity = 0.1f;
float diffusion = 0.01f;
bool paused = true;
float dt = 0.1f;
float viscosity = 0.001f;
float diffusion = 0.0001f;
UVector gridSize = {128, 128, 128};
Vector gravity = {0.0f, -9.81f, 0.0f};
bool enableGravity = true;
};
} // namespace Component
} // namespace Seele
@@ -1,19 +1,26 @@
#include "FluidRenderPass.h"
#include "Component/Transform.h"
#include "Graphics/Command.h"
#include "Graphics/Descriptor.h"
#include "Graphics/Enums.h"
#include "Graphics/Graphics.h"
#include "Graphics/Initializer.h"
#include "Graphics/RenderTarget.h"
#include "Graphics/Shader.h"
#include "Math/Matrix.h"
#include "Scene/LightEnvironment.h"
#include "Scene/Scene.h"
#include "Scene/FluidScene.h"
using namespace Seele;
FluidRenderPass::FluidRenderPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics), scene(scene) {
pipelineLayout = graphics->createPipelineLayout("FluidPipelineLayout");
descriptorLayout = graphics->createDescriptorLayout("params");
descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "transform",
.uniformLength = sizeof(Matrix4),
});
descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "vertexBuffer",
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
@@ -54,6 +61,8 @@ void FluidRenderPass::render() {
descriptorLayout->reset();
for (const auto& [id, data] : scene->getFluidScene()->getFluidDataMap()) {
descriptorSet = descriptorLayout->allocateDescriptorSet();
Matrix4 transformMatrix = data.transform.toMatrix();
descriptorSet->updateConstants("transform", 0, &transformMatrix);
descriptorSet->updateBuffer("vertexBuffer", 0, data.vertexBuffer);
descriptorSet->updateBuffer("normalBuffer", 0, data.normalBuffer);
descriptorSet->updateBuffer("indexBuffer", 0, data.indexBuffer);
@@ -75,6 +84,7 @@ void FluidRenderPass::endFrame() {}
void FluidRenderPass::publishOutputs() {
}
void FluidRenderPass::createRenderPass() {
colorAttachment = resources->requestRenderTarget("BASEPASS_COLOR");
colorAttachment.setLoadOp(Gfx::SE_ATTACHMENT_LOAD_OP_LOAD);
@@ -112,6 +122,7 @@ void FluidRenderPass::createRenderPass() {
Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
},
};
renderPass = graphics->createRenderPass(layout, dependency, viewport->getRenderArea(), "FluidRenderPass");
pipeline = graphics->createGraphicsPipeline(Gfx::LegacyPipelineCreateInfo{
.vertexShader = vertexShader,
@@ -124,7 +135,7 @@ void FluidRenderPass::createRenderPass() {
},
.rasterizationState =
{
.cullMode = Gfx::SE_CULL_MODE_FRONT_BIT,
.cullMode = Gfx::SE_CULL_MODE_NONE,
},
.colorBlend =
{
@@ -8,6 +8,7 @@
#include "Math/Vector.h"
#include "RenderGraph.h"
#include "Scene/Scene.h"
#include "Scene/LightEnvironment.h"
using namespace Seele;
@@ -6,6 +6,7 @@
#include "Graphics/StaticMeshVertexData.h"
#include "Material/Material.h"
#include "Material/MaterialInstance.h"
#include "Scene/LightEnvironment.h"
#include "RenderPass.h"
#include <iostream>
@@ -4,6 +4,7 @@
#include "Graphics/Initializer.h"
#include "Graphics/Shader.h"
#include "Math/Matrix.h"
#include "Scene/LightEnvironment.h"
#include <glm/ext/matrix_transform.hpp>
#include <glm/matrix.hpp>
@@ -7,13 +7,18 @@
#include "Graphics/Initializer.h"
#include "Graphics/Shader.h"
#include "Math/Vector.h"
#include <iostream>
#include "Scene/FluidScene.h"
#include <algorithm>
using namespace Seele;
constexpr static int reinitInterval = 5;
constexpr static int reinitIterations = 5;
constexpr static float reinitDtau = 0.5f;
// Reinitialization is in pseudo-time; keep it gentle to avoid eroding the interface each frame.
constexpr static int reinitInterval = 20;
constexpr static int reinitIterations = 1;
constexpr static float reinitDtau = 0.05f;
constexpr static int velocityDiffuseIterations = 8;
constexpr static int pressureSolveIterations = 24;
constexpr static int densityDiffuseIterations = 8;
#define SWAP(a, b) \
{ \
@@ -23,6 +28,12 @@ constexpr static float reinitDtau = 0.5f;
}
SimulationComputePass::SimulationComputePass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics), scene(scene) {
gridSizeLayout = graphics->createDescriptorLayout("gridParams");
gridSizeLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "gridSize",
.uniformLength = sizeof(UVector),
});
gridSizeLayout->create();
{
setBounds.pipelineLayout = graphics->createPipelineLayout("SetBoundsPipelineLayout");
setBounds.descriptorLayout = graphics->createDescriptorLayout("params");
@@ -36,6 +47,7 @@ SimulationComputePass::SimulationComputePass(Gfx::PGraphics graphics, PScene sce
});
setBounds.descriptorLayout->create();
setBounds.pipelineLayout->addDescriptorLayout(setBounds.descriptorLayout);
setBounds.pipelineLayout->addDescriptorLayout(gridSizeLayout);
graphics->beginShaderCompilation(ShaderCompilationInfo{
.name = "SetBound",
.modules = {"SetBound"},
@@ -84,6 +96,7 @@ SimulationComputePass::SimulationComputePass(Gfx::PGraphics graphics, PScene sce
});
linearSolve.descriptorLayout->create();
linearSolve.pipelineLayout->addDescriptorLayout(linearSolve.descriptorLayout);
linearSolve.pipelineLayout->addDescriptorLayout(gridSizeLayout);
graphics->beginShaderCompilation(ShaderCompilationInfo{
.name = "LinearSolve",
.modules = {"LinearSolve"},
@@ -122,6 +135,7 @@ SimulationComputePass::SimulationComputePass(Gfx::PGraphics graphics, PScene sce
});
computeDivergence.descriptorLayout->create();
computeDivergence.pipelineLayout->addDescriptorLayout(computeDivergence.descriptorLayout);
computeDivergence.pipelineLayout->addDescriptorLayout(gridSizeLayout);
graphics->beginShaderCompilation(ShaderCompilationInfo{
.name = "Divergence",
.modules = {"Divergence"},
@@ -157,6 +171,7 @@ SimulationComputePass::SimulationComputePass(Gfx::PGraphics graphics, PScene sce
});
project.descriptorLayout->create();
project.pipelineLayout->addDescriptorLayout(project.descriptorLayout);
project.pipelineLayout->addDescriptorLayout(gridSizeLayout);
graphics->beginShaderCompilation(ShaderCompilationInfo{
.name = "Project",
.modules = {"Project"},
@@ -199,6 +214,7 @@ SimulationComputePass::SimulationComputePass(Gfx::PGraphics graphics, PScene sce
});
advect.descriptorLayout->create();
advect.pipelineLayout->addDescriptorLayout(advect.descriptorLayout);
advect.pipelineLayout->addDescriptorLayout(gridSizeLayout);
graphics->beginShaderCompilation(ShaderCompilationInfo{
.name = "Advect",
.modules = {"Advect"},
@@ -230,7 +246,7 @@ SimulationComputePass::SimulationComputePass(Gfx::PGraphics graphics, PScene sce
});
reinitialize.descriptorLayout->create();
reinitialize.pipelineLayout->addDescriptorLayout(reinitialize.descriptorLayout);
reinitialize.pipelineLayout->addDescriptorLayout(gridSizeLayout);
graphics->beginShaderCompilation(ShaderCompilationInfo{
.name = "SignedDistance",
.modules = {"SignedDistance"},
@@ -244,6 +260,45 @@ SimulationComputePass::SimulationComputePass(Gfx::PGraphics graphics, PScene sce
.pipelineLayout = reinitialize.pipelineLayout,
});
}
{
applyForces.pipelineLayout = graphics->createPipelineLayout("ApplyForcesPipelineLayout");
applyForces.descriptorLayout = graphics->createDescriptorLayout("params");
applyForces.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "velocityX",
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
});
applyForces.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "velocityY",
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
});
applyForces.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "velocityZ",
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
});
applyForces.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "force",
.uniformLength = sizeof(Vector),
});
applyForces.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "dt",
.uniformLength = sizeof(float),
});
applyForces.descriptorLayout->create();
applyForces.pipelineLayout->addDescriptorLayout(applyForces.descriptorLayout);
applyForces.pipelineLayout->addDescriptorLayout(gridSizeLayout);
graphics->beginShaderCompilation(ShaderCompilationInfo{
.name = "ApplyForces",
.modules = {"ApplyForces"},
.entryPoints = {{"applyForces", "ApplyForces"}},
.rootSignature = applyForces.pipelineLayout,
});
applyForces.pipelineLayout->create();
applyForces.shader = graphics->createComputeShader({0});
applyForces.pipeline = graphics->createComputePipeline(Gfx::ComputePipelineCreateInfo{
.computeShader = applyForces.shader,
.pipelineLayout = applyForces.pipelineLayout,
});
}
}
SimulationComputePass::~SimulationComputePass() {}
@@ -255,13 +310,21 @@ void SimulationComputePass::beginFrame(const Seele::Component::Camera&, const Se
project.descriptorLayout->reset();
advect.descriptorLayout->reset();
reinitialize.descriptorLayout->reset();
applyForces.descriptorLayout->reset();
gridSizeLayout->reset();
}
void SimulationComputePass::render() {
for (auto& [entityID, data] : scene->getFluidScene()->getFluidDataMap()) {
if (data.paused) {
continue;
}
gridSizeSet = gridSizeLayout->allocateDescriptorSet();
gridSizeSet->updateConstants("gridSize", 0, &data.gridSize);
gridSizeSet->writeChanges();
graphics->beginDebugRegion("Diffuse");
for (uint iteration = 0; iteration < 4; ++iteration) {
float a = dt * data.viscosity * (data.gridSize.x - 2) * (data.gridSize.y - 2) * (data.gridSize.z - 2);
for (int iteration = 0; iteration < velocityDiffuseIterations; ++iteration) {
float a = data.dt * data.viscosity * (data.gridSize.x - 2) * (data.gridSize.x - 2);
float c = 1 + 6 * a;
linearSolvePass(data.velocityXNextBuffer, data.velocityXBuffer, data.velocityX0Buffer, a, c, data.gridSize);
linearSolvePass(data.velocityYNextBuffer, data.velocityYBuffer, data.velocityY0Buffer, a, c, data.gridSize);
@@ -287,7 +350,7 @@ void SimulationComputePass::render() {
Gfx::PShaderBuffer pressureNext = data.velocityZBuffer;
divergencePass(divergence, pressureCurrent, data.velocityX0Buffer, data.velocityY0Buffer, data.velocityZ0Buffer, data.gridSize);
for (int iteration = 0; iteration < 4; ++iteration) {
for (int iteration = 0; iteration < pressureSolveIterations; ++iteration) {
linearSolvePass(pressureNext, pressureCurrent, divergence, 1, 6, data.gridSize);
setBoundsPass(pressureNext, 0, data.gridSize);
@@ -304,15 +367,38 @@ void SimulationComputePass::render() {
graphics->endDebugRegion();
graphics->beginDebugRegion("Advect");
advectPass(data.velocityXBuffer, data.velocityX0Buffer, data.velocityX0Buffer, data.velocityY0Buffer, data.velocityZ0Buffer, dt, data.gridSize);
advectPass(data.velocityYBuffer, data.velocityY0Buffer, data.velocityX0Buffer, data.velocityY0Buffer, data.velocityZ0Buffer, dt, data.gridSize);
advectPass(data.velocityZBuffer, data.velocityZ0Buffer, data.velocityX0Buffer, data.velocityY0Buffer, data.velocityZ0Buffer, dt, data.gridSize);
advectPass(data.velocityXBuffer, data.velocityX0Buffer, data.velocityX0Buffer, data.velocityY0Buffer, data.velocityZ0Buffer, data.dt,
data.gridSize);
advectPass(data.velocityYBuffer, data.velocityY0Buffer, data.velocityX0Buffer, data.velocityY0Buffer, data.velocityZ0Buffer, data.dt,
data.gridSize);
advectPass(data.velocityZBuffer, data.velocityZ0Buffer, data.velocityX0Buffer, data.velocityY0Buffer, data.velocityZ0Buffer, data.dt,
data.gridSize);
if (data.enableGravity) {
applyForcesPass(data.velocityXBuffer, data.velocityYBuffer, data.velocityZBuffer, data.gravity, data.dt, data.gridSize);
}
// Set boundary conditions after advection/forces so the divergence sees correct wall values
setBoundsPass(data.velocityXBuffer, 1, data.gridSize);
setBoundsPass(data.velocityYBuffer, 2, data.gridSize);
setBoundsPass(data.velocityZBuffer, 3, data.gridSize);
// Re-project after advection/forces to keep the final velocity field divergence-free.
Gfx::PShaderBuffer advectedDivergence = data.velocityXNextBuffer;
Gfx::PShaderBuffer advectedPressureCurrent = data.velocityYNextBuffer;
Gfx::PShaderBuffer advectedPressureNext = data.velocityZNextBuffer;
divergencePass(advectedDivergence, advectedPressureCurrent, data.velocityXBuffer, data.velocityYBuffer, data.velocityZBuffer, data.gridSize);
for (int iteration = 0; iteration < pressureSolveIterations; ++iteration) {
linearSolvePass(advectedPressureNext, advectedPressureCurrent, advectedDivergence, 1, 6, data.gridSize);
setBoundsPass(advectedPressureNext, 0, data.gridSize);
SWAP(advectedPressureCurrent, advectedPressureNext);
}
projectPass(data.velocityXBuffer, data.velocityYBuffer, data.velocityZBuffer, advectedPressureCurrent, data.gridSize);
setBoundsPass(data.velocityXBuffer, 1, data.gridSize);
setBoundsPass(data.velocityYBuffer, 2, data.gridSize);
setBoundsPass(data.velocityZBuffer, 3, data.gridSize);
graphics->endDebugRegion();
// swap velocity buffers
SWAP(data.velocityX0Buffer, data.velocityXBuffer);
SWAP(data.velocityY0Buffer, data.velocityYBuffer);
@@ -326,8 +412,8 @@ void SimulationComputePass::render() {
graphics->copyBuffer(density0, densityCurrent);
densityCurrent->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
for (int iteration = 0; iteration < 4; ++iteration) {
float a = dt * data.diffusion * (data.gridSize.x - 2) * (data.gridSize.y - 2) * (data.gridSize.z - 2);
for (int iteration = 0; iteration < densityDiffuseIterations; ++iteration) {
float a = data.dt * data.diffusion * (data.gridSize.x - 2) * (data.gridSize.x - 2);
float c = 1 + 6 * a;
linearSolvePass(densityNext, densityCurrent, density0, a, c, data.gridSize);
setBoundsPass(densityNext, 0, data.gridSize);
@@ -335,12 +421,13 @@ void SimulationComputePass::render() {
}
graphics->endDebugRegion();
graphics->beginDebugRegion("AdvectDensity");
advectPass(data.density0Buffer, densityCurrent, data.velocityX0Buffer, data.velocityY0Buffer, data.velocityZ0Buffer, dt, data.gridSize);
advectPass(data.density0Buffer, densityCurrent, data.velocityX0Buffer, data.velocityY0Buffer, data.velocityZ0Buffer, data.dt,
data.gridSize);
setBoundsPass(data.density0Buffer, 0, data.gridSize);
graphics->endDebugRegion();
graphics->beginDebugRegion("AdvectLevelSet");
advectPass(data.phiBuffer, data.phi0Buffer, data.velocityX0Buffer, data.velocityY0Buffer, data.velocityZ0Buffer, dt, data.gridSize);
advectPass(data.phiBuffer, data.phi0Buffer, data.velocityX0Buffer, data.velocityY0Buffer, data.velocityZ0Buffer, data.dt, data.gridSize);
setBoundsPass(data.phiBuffer, 0, data.gridSize);
// Reinitialize level set every N frames to restore |grad phi| = 1
@@ -380,7 +467,11 @@ void SimulationComputePass::setBoundsPass(Gfx::PShaderBuffer grid, int b, UVecto
Gfx::OComputeCommand boundsCommand = graphics->createComputeCommand();
boundsCommand->bindPipeline(setBounds.pipeline);
boundsCommand->bindDescriptor(bounds);
boundsCommand->dispatch(getDispatchSize(gridSize, setBounds.threadGroupSize));
boundsCommand->bindDescriptor(gridSizeSet);
// Dispatch covers max(gridSize.x, gridSize.y) x max(gridSize.y, gridSize.z) to handle all faces on non-cubic grids
UVector faceDispatchGrid = {std::max(gridSize.x, gridSize.y), std::max(gridSize.y, gridSize.z), 1};
auto dispatchSize = getDispatchSize(faceDispatchGrid, setBounds.threadGroupSize);
boundsCommand->dispatch(dispatchSize.x, dispatchSize.y, 1);
graphics->executeCommands(std::move(boundsCommand));
grid->pipelineBarrier(Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, Gfx::SE_ACCESS_SHADER_WRITE_BIT,
@@ -389,7 +480,10 @@ void SimulationComputePass::setBoundsPass(Gfx::PShaderBuffer grid, int b, UVecto
Gfx::OComputeCommand edgesCommand = graphics->createComputeCommand();
edgesCommand->bindPipeline(setBounds.pipelineEdges);
edgesCommand->bindDescriptor(bounds);
edgesCommand->dispatch(getDispatchSize(gridSize, setBounds.threadGroupSize).x, 1, 1);
edgesCommand->bindDescriptor(gridSizeSet);
// Dispatch covers max dimension to handle all 12 edges on non-cubic grids; edge shader uses numthreads(128,1,1)
uint32_t maxDim = std::max({gridSize.x, gridSize.y, gridSize.z});
edgesCommand->dispatch((maxDim + 127) / 128, 1, 1);
graphics->executeCommands(std::move(edgesCommand));
grid->pipelineBarrier(Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, Gfx::SE_ACCESS_SHADER_WRITE_BIT,
@@ -398,6 +492,7 @@ void SimulationComputePass::setBoundsPass(Gfx::PShaderBuffer grid, int b, UVecto
Gfx::OComputeCommand cornersCommand = graphics->createComputeCommand();
cornersCommand->bindPipeline(setBounds.pipelineCorners);
cornersCommand->bindDescriptor(bounds);
cornersCommand->bindDescriptor(gridSizeSet);
cornersCommand->dispatch(1, 1, 1);
graphics->executeCommands(std::move(cornersCommand));
@@ -405,7 +500,8 @@ void SimulationComputePass::setBoundsPass(Gfx::PShaderBuffer grid, int b, UVecto
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
}
void SimulationComputePass::linearSolvePass(Gfx::PShaderBuffer next, Gfx::PShaderBuffer current, Gfx::PShaderBuffer grid0, float a, float c, UVector gridSize) {
void SimulationComputePass::linearSolvePass(Gfx::PShaderBuffer next, Gfx::PShaderBuffer current, Gfx::PShaderBuffer grid0, float a, float c,
UVector gridSize) {
Gfx::ODescriptorSet solve = linearSolve.descriptorLayout->allocateDescriptorSet();
solve->updateBuffer("next", 0, next);
solve->updateBuffer("current", 0, current);
@@ -416,6 +512,7 @@ void SimulationComputePass::linearSolvePass(Gfx::PShaderBuffer next, Gfx::PShade
Gfx::OComputeCommand solveCommand = graphics->createComputeCommand();
solveCommand->bindPipeline(linearSolve.pipeline);
solveCommand->bindDescriptor(solve);
solveCommand->bindDescriptor(gridSizeSet);
solveCommand->dispatch(getDispatchSize(gridSize, linearSolve.threadGroupSize));
graphics->executeCommands(std::move(solveCommand));
@@ -435,6 +532,7 @@ void SimulationComputePass::divergencePass(Seele::Gfx::PShaderBuffer divergence,
Gfx::OComputeCommand divergenceCommand = graphics->createComputeCommand();
divergenceCommand->bindPipeline(computeDivergence.pipeline);
divergenceCommand->bindDescriptor(divergenceSet);
divergenceCommand->bindDescriptor(gridSizeSet);
divergenceCommand->dispatch(getDispatchSize(gridSize, computeDivergence.threadGroupSize));
graphics->executeCommands(std::move(divergenceCommand));
// divergence is now in velocityXBuffer, pressure is in velocityYBuffer
@@ -455,6 +553,7 @@ void SimulationComputePass::projectPass(Seele::Gfx::PShaderBuffer velocityX, See
Gfx::OComputeCommand projectCommand = graphics->createComputeCommand();
projectCommand->bindPipeline(project.pipeline);
projectCommand->bindDescriptor(projectSet);
projectCommand->bindDescriptor(gridSizeSet);
projectCommand->dispatch(getDispatchSize(gridSize, project.threadGroupSize));
graphics->executeCommands(std::move(projectCommand));
@@ -479,6 +578,7 @@ void SimulationComputePass::advectPass(Gfx::PShaderBuffer quantity, Gfx::PShader
Gfx::OComputeCommand advectCommand = graphics->createComputeCommand();
advectCommand->bindPipeline(advect.pipeline);
advectCommand->bindDescriptor(advectSet);
advectCommand->bindDescriptor(gridSizeSet);
advectCommand->dispatch(getDispatchSize(gridSize, advect.threadGroupSize));
graphics->executeCommands(std::move(advectCommand));
@@ -486,6 +586,29 @@ void SimulationComputePass::advectPass(Gfx::PShaderBuffer quantity, Gfx::PShader
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
}
void SimulationComputePass::applyForcesPass(Gfx::PShaderBuffer velocityX, Gfx::PShaderBuffer velocityY, Gfx::PShaderBuffer velocityZ, Vector gravity, float dt, UVector gridSize) {
Gfx::ODescriptorSet forcesSet = applyForces.descriptorLayout->allocateDescriptorSet();
forcesSet->updateBuffer("velocityX", 0, velocityX);
forcesSet->updateBuffer("velocityY", 0, velocityY);
forcesSet->updateBuffer("velocityZ", 0, velocityZ);
forcesSet->updateConstants("force", 0, &gravity);
forcesSet->updateConstants("dt", 0, &dt);
forcesSet->writeChanges();
Gfx::OComputeCommand forcesCommand = graphics->createComputeCommand();
forcesCommand->bindPipeline(applyForces.pipeline);
forcesCommand->bindDescriptor(forcesSet);
forcesCommand->bindDescriptor(gridSizeSet);
forcesCommand->dispatch(getDispatchSize(gridSize, applyForces.threadGroupSize));
graphics->executeCommands(std::move(forcesCommand));
velocityX->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT,
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
velocityY->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT,
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
velocityZ->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT,
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
}
void SimulationComputePass::reinitializeLevelSetPass(Seele::Gfx::PShaderBuffer phi, Seele::Gfx::PShaderBuffer phi0, UVector gridSize) {
graphics->beginDebugRegion("ReinitializeLevelSet");
// Snapshot current phi into phi0 for the sign function
@@ -507,6 +630,7 @@ void SimulationComputePass::reinitializeLevelSetPass(Seele::Gfx::PShaderBuffer p
Gfx::OComputeCommand reinitCommand = graphics->createComputeCommand();
reinitCommand->bindPipeline(reinitialize.pipeline);
reinitCommand->bindDescriptor(reinitSet);
reinitCommand->bindDescriptor(gridSizeSet);
reinitCommand->dispatch(getDispatchSize(gridSize, reinitialize.threadGroupSize));
graphics->executeCommands(std::move(reinitCommand));
@@ -75,8 +75,17 @@ class SimulationComputePass : public RenderPass {
Gfx::PComputePipeline pipeline;
constexpr static UVector threadGroupSize = {32, 8, 1};
} reinitialize;
struct ApplyForces {
Gfx::OPipelineLayout pipelineLayout;
Gfx::ODescriptorLayout descriptorLayout;
Gfx::OComputeShader shader;
Gfx::PComputePipeline pipeline;
constexpr static UVector threadGroupSize = {32, 8, 1};
} applyForces;
void applyForcesPass(Gfx::PShaderBuffer velocityX, Gfx::PShaderBuffer velocityY, Gfx::PShaderBuffer velocityZ, Vector gravity, float dt, UVector gridSize);
Gfx::ODescriptorLayout gridSizeLayout;
Gfx::ODescriptorSet gridSizeSet;
PScene scene;
constexpr static float dt = 0.1f;
};
DEFINE_REF(SimulationComputePass)
} // namespace Seele
@@ -5,21 +5,18 @@
#include "Graphics/Graphics.h"
#include "Graphics/Initializer.h"
#include "Graphics/Shader.h"
#include "Math/Vector.h"
#include "Scene/FluidScene.h"
using namespace Seele;
// Linearly interpolate the position where the isosurface crosses the edge
// between two grid points.
static Vector vertexInterp(float isolevel, const Vector& p1, const Vector& p2, float v1, float v2) {
if (std::abs(v1 - v2) < 1e-10f)
return p1;
float t = (isolevel - v1) / (v2 - v1);
return Vector(p1.x + t * (p2.x - p1.x), p1.y + t * (p2.y - p1.y), p1.z + t * (p2.z - p1.z));
}
SurfaceExtractPass::SurfaceExtractPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics), scene(scene) {
pipelineLayout = graphics->createPipelineLayout("SurfaceExtractPipelineLayout");
gridSizeLayout = graphics->createDescriptorLayout("gridParams");
gridSizeLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "gridSize",
.uniformLength = sizeof(UVector),
});
gridSizeLayout->create();
descriptorLayout = graphics->createDescriptorLayout("params");
descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "vertexBuffer",
@@ -43,6 +40,7 @@ SurfaceExtractPass::SurfaceExtractPass(Gfx::PGraphics graphics, PScene scene) :
});
descriptorLayout->create();
pipelineLayout->addDescriptorLayout(descriptorLayout);
pipelineLayout->addDescriptorLayout(gridSizeLayout);
graphics->beginShaderCompilation(ShaderCompilationInfo{
.name = "MarchingCubes",
.modules = {"MarchingCubes"},
@@ -62,8 +60,12 @@ SurfaceExtractPass::~SurfaceExtractPass() {}
void SurfaceExtractPass::beginFrame(const Seele::Component::Camera&, const Seele::Component::Transform&) {}
void SurfaceExtractPass::render() {
for (auto& [entityID, data] : scene->getFluidScene()->getFluidDataMap()) {
Gfx::ODescriptorSet gridSizeSet = gridSizeLayout->allocateDescriptorSet();
gridSizeSet->updateConstants("gridSize", 0, &data.gridSize);
gridSizeSet->writeChanges();
data.vertexBuffer->rotateBuffer(data.getVertexBufferSize() * sizeof(float));
data.normalBuffer->rotateBuffer(data.getVertexBufferSize() * sizeof(float));
data.indexBuffer->rotateBuffer(data.getIndexBufferSize() * sizeof(uint32));
@@ -83,6 +85,7 @@ void SurfaceExtractPass::render() {
Gfx::OComputeCommand cmd = graphics->createComputeCommand();
cmd->bindPipeline(pipeline);
cmd->bindDescriptor(descriptorSet);
cmd->bindDescriptor(gridSizeSet);
cmd->dispatch((data.gridSize + threadGroupSize - 1u) / threadGroupSize);
graphics->executeCommands(std::move(cmd));
@@ -20,6 +20,7 @@ private:
Gfx::OPipelineLayout pipelineLayout;
Gfx::ODescriptorLayout descriptorLayout;
Gfx::ODescriptorLayout gridSizeLayout;
Gfx::ODescriptorSet descriptorSet;
Gfx::OComputeShader computeShader;
Gfx::PComputePipeline pipeline;
+1
View File
@@ -848,6 +848,7 @@ void Graphics::pickPhysicalDevice() {
vkGetPhysicalDeviceProperties2(physicalDevice, &props.get());
features.get<VkPhysicalDeviceFeatures2>().features = {
// .robustBufferAccess = true,
.geometryShader = true,
.sampleRateShading = true,
.fillModeNonSolid = true,
+54 -95
View File
@@ -1,6 +1,8 @@
#include "slang-compile.h"
#include "Containers/Array.h"
#include "Graphics/Descriptor.h"
#include <array>
#include <cstdlib>
#include <filesystem>
#include <fmt/core.h>
#include <iostream>
@@ -29,113 +31,54 @@ thread_local Slang::ComPtr<slang::ISession> session;
thread_local Array<std::string> entryPoints;
namespace {
std::filesystem::path getExecutableDirectory() {
std::error_code error;
auto exePath = std::filesystem::read_symlink("/proc/self/exe", error);
if (!error) {
return exePath.parent_path();
void appendEnvPath(const char* varName, const std::filesystem::path& path) {
if (!std::filesystem::exists(path) || !std::filesystem::is_directory(path)) {
return;
}
return std::filesystem::current_path();
const std::string newEntry = path.lexically_normal().string();
const char* currentRaw = std::getenv(varName);
std::string current = currentRaw ? currentRaw : "";
if (current.find(newEntry) != std::string::npos) {
return;
}
std::string updated = current.empty() ? newEntry : (newEntry + ":" + current);
setenv(varName, updated.c_str(), 1);
}
std::filesystem::path findExistingDirectory(std::initializer_list<std::filesystem::path> candidates) {
void configureSlangRuntimeEnv() {
std::filesystem::path exePath;
try {
exePath = std::filesystem::canonical("/proc/self/exe");
} catch (...) {
return;
}
const std::filesystem::path exeDir = exePath.parent_path();
const std::array<std::filesystem::path, 7> candidates = {
exeDir / "vcpkg_installed/x64-linux/lib",
exeDir / "vcpkg_installed/x64-linux/debug/lib",
exeDir / "vcpkg_installed/x64-linux/tools/shader-slang",
exeDir.parent_path() / "vcpkg_installed/x64-linux/lib",
exeDir.parent_path() / "vcpkg_installed/x64-linux/debug/lib",
exeDir.parent_path() / "vcpkg_installed/x64-linux/tools/shader-slang",
std::filesystem::current_path() / "build/vcpkg_installed/x64-linux/tools/shader-slang",
};
for (const auto& candidate : candidates) {
std::error_code error;
if (std::filesystem::exists(candidate, error) && std::filesystem::is_directory(candidate, error)) {
return candidate;
}
appendEnvPath("LD_LIBRARY_PATH", candidate);
appendEnvPath("PATH", candidate);
}
return {};
}
bool containsDownstreamCompilerArtifacts(const std::filesystem::path& directory) {
std::error_code error;
if (!std::filesystem::exists(directory, error) || !std::filesystem::is_directory(directory, error)) {
return false;
}
for (const auto& entry : std::filesystem::directory_iterator(directory, error)) {
if (error || !entry.is_regular_file(error)) {
continue;
}
const auto fileName = entry.path().filename().string();
if (fileName.rfind("slang-glslang", 0) == 0 || fileName.rfind("spirv-opt", 0) == 0 || fileName.rfind("spirv-dis", 0) == 0) {
return true;
}
}
return false;
}
bool hasArtifactWithPrefix(const std::filesystem::path& directory, const char* prefix) {
std::error_code error;
if (!std::filesystem::exists(directory, error) || !std::filesystem::is_directory(directory, error)) {
return false;
}
for (const auto& entry : std::filesystem::directory_iterator(directory, error)) {
if (error || !entry.is_regular_file(error)) {
continue;
}
if (entry.path().filename().string().rfind(prefix, 0) == 0) {
return true;
}
}
return false;
}
std::filesystem::path findDownstreamCompilerDirectory(std::initializer_list<std::filesystem::path> candidates) {
for (const auto& candidate : candidates) {
if (containsDownstreamCompilerArtifacts(candidate)) {
return candidate;
}
}
return findExistingDirectory(candidates);
}
void configureDownstreamCompilers(slang::IGlobalSession* session) {
const auto executableDirectory = getExecutableDirectory();
const auto currentDirectory = std::filesystem::current_path();
const auto glslangDirectory = findDownstreamCompilerDirectory({
executableDirectory,
executableDirectory / "Seele",
executableDirectory / "vcpkg_installed" / "x64-linux" / "lib",
currentDirectory / "build",
currentDirectory / "build" / "Seele",
currentDirectory / "Seele",
currentDirectory / "vcpkg_installed" / "x64-linux" / "lib",
});
if (!glslangDirectory.empty()) {
const std::string path = glslangDirectory.string();
if (hasArtifactWithPrefix(glslangDirectory, "slang-glslang") || hasArtifactWithPrefix(glslangDirectory, "libslang-glslang")) {
session->setDownstreamCompilerPath(SLANG_PASS_THROUGH_GLSLANG, path.c_str());
}
if (hasArtifactWithPrefix(glslangDirectory, "spirv-opt")) {
session->setDownstreamCompilerPath(SLANG_PASS_THROUGH_SPIRV_OPT, path.c_str());
}
if (hasArtifactWithPrefix(glslangDirectory, "spirv-dis")) {
session->setDownstreamCompilerPath(SLANG_PASS_THROUGH_SPIRV_DIS, path.c_str());
}
}
// Avoid optional SPIR-V downstream tools that are often unavailable in RenderDoc launch environments.
session->setDefaultDownstreamCompiler(SLANG_SOURCE_LANGUAGE_SPIRV, SLANG_PASS_THROUGH_NONE);
session->setDownstreamCompilerForTransition(SLANG_SPIRV, SLANG_SPIRV, SLANG_PASS_THROUGH_NONE);
session->setDownstreamCompilerForTransition(SLANG_SPIRV, SLANG_SPIRV_ASM, SLANG_PASS_THROUGH_NONE);
}
}
} // namespace
void Seele::beginCompilation(const ShaderCompilationInfo& info, SlangCompileTarget target, Gfx::PPipelineLayout layout) {
if (!globalSession) {
configureSlangRuntimeEnv();
SlangGlobalSessionDesc sessionDesc = {};
sessionDesc.enableGLSL = true;
slang::createGlobalSession(&sessionDesc, globalSession.writeRef());
configureDownstreamCompilers(globalSession);
}
slang::SessionDesc sessionDesc;
sessionDesc.flags = 0;
@@ -156,6 +99,22 @@ void Seele::beginCompilation(const ShaderCompilationInfo& info, SlangCompileTarg
.intValue0 = SLANG_OPTIMIZATION_LEVEL_NONE,
},
},
{
.name = slang::CompilerOptionName::EmitSpirvMethod,
.value =
{
.kind = slang::CompilerOptionValueKind::Int,
.intValue0 = SLANG_EMIT_SPIRV_DIRECTLY,
},
},
{
.name = slang::CompilerOptionName::PassThrough,
.value =
{
.kind = slang::CompilerOptionValueKind::Int,
.intValue0 = SLANG_PASS_THROUGH_NONE,
},
},
{
.name = slang::CompilerOptionName::SkipSPIRVValidation,
.value =
+112 -40
View File
@@ -1,9 +1,45 @@
#include "FluidScene.h"
#include "Graphics/Command.h"
#include "Graphics/Descriptor.h"
#include "Graphics/Enums.h"
#include "Graphics/Initializer.h"
using namespace Seele;
FluidScene::FluidScene(Gfx::PGraphics graphics) : graphics(graphics) {}
FluidScene::FluidScene(Gfx::PGraphics graphics) : graphics(graphics) {
pipelineLayout = graphics->createPipelineLayout("FluidScenePipelineLayout");
gridParamsLayout = graphics->createDescriptorLayout("gridParams");
gridParamsLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "gridSize",
.uniformLength = sizeof(UVector),
});
gridParamsLayout->create();
descriptorLayout = graphics->createDescriptorLayout("params");
descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "phi",
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
});
descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "density",
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
});
descriptorLayout->create();
pipelineLayout->addDescriptorLayout(descriptorLayout);
pipelineLayout->addDescriptorLayout(gridParamsLayout);
graphics->beginShaderCompilation(ShaderCompilationInfo{
.name = "AddSource",
.modules = {"AddSource"},
.entryPoints = {{"addSource", "AddSource"}},
.rootSignature = pipelineLayout,
});
pipelineLayout->create();
shader = graphics->createComputeShader({0});
pipeline = graphics->createComputePipeline(Gfx::ComputePipelineCreateInfo{
.computeShader = shader,
.pipelineLayout = pipelineLayout,
});
}
FluidScene::~FluidScene() {}
@@ -12,37 +48,37 @@ void FluidScene::updateFluidData(uint32 entityID, const Component::Transform& tr
auto& data = fluidDataMap[entityID];
uint64 totalCells = (uint64)grid.gridSize.x * grid.gridSize.y * grid.gridSize.z;
uint64 bufferSize = totalCells * sizeof(float);
Array<float> initialDensity(bufferSize / sizeof(float));
Array<float> initialVelocityX(bufferSize / sizeof(float));
Array<float> initialVelocityY(bufferSize / sizeof(float));
Array<float> initialVelocityZ(bufferSize / sizeof(float));
Array<float> initialPhi(bufferSize / sizeof(float));
// Array<float> initialDensity(bufferSize / sizeof(float));
// Array<float> initialVelocityX(bufferSize / sizeof(float));
// Array<float> initialVelocityY(bufferSize / sizeof(float));
// Array<float> initialVelocityZ(bufferSize / sizeof(float));
// Array<float> initialPhi(bufferSize / sizeof(float));
// Initialize level set to positive (outside) everywhere
float halfGridX = static_cast<float>(grid.gridSize.x) * 0.5f;
float halfGridY = static_cast<float>(grid.gridSize.y) * 0.5f;
float radius = static_cast<float>(grid.gridSize.x) * 0.2f;
// Place sphere center in the lower portion of the grid
float cx = halfGridX;
float cy = halfGridY;
float cz = static_cast<float>(grid.gridSize.z) * 0.3f;
for (uint32 z = 1; z < grid.gridSize.z - 1; ++z) {
for (uint32 y = 1; y < grid.gridSize.y - 1; ++y) {
for (uint32 x = 1; x < grid.gridSize.x - 1; ++x) {
uint32 idx = x + grid.gridSize.x * y + grid.gridSize.x * grid.gridSize.y * z;
float dx = static_cast<float>(x) - cx;
float dy = static_cast<float>(y) - cy;
float dz = static_cast<float>(z) - cz;
float dist = std::sqrt(dx * dx + dy * dy + dz * dz);
initialPhi[idx] = dist - radius;
if (dist < radius) {
initialDensity[idx] = 1.0f;
// Give an initial upward velocity to kick the simulation
initialVelocityZ[idx] = 5.0f;
}
}
}
}
// // Initialize level set to positive (outside) everywhere
// float halfGridX = static_cast<float>(grid.gridSize.x) * 0.5f;
// float halfGridY = static_cast<float>(grid.gridSize.y) * 0.5f;
// float radius = static_cast<float>(grid.gridSize.x) * 0.2f;
// // Place sphere center in the lower portion of the grid
// float cx = halfGridX;
// float cy = halfGridY;
// float cz = static_cast<float>(grid.gridSize.z) * 0.3f;
// for (uint32 z = 1; z < grid.gridSize.z - 1; ++z) {
// for (uint32 y = 1; y < grid.gridSize.y - 1; ++y) {
// for (uint32 x = 1; x < grid.gridSize.x - 1; ++x) {
// uint32 idx = x + grid.gridSize.x * y + grid.gridSize.x * grid.gridSize.y * z;
// float dx = static_cast<float>(x) - cx;
// float dy = static_cast<float>(y) - cy;
// float dz = static_cast<float>(z) - cz;
// float dist = std::sqrt(dx * dx + dy * dy + dz * dz);
// initialPhi[idx] = dist - radius;
// if (dist < radius) {
// initialDensity[idx] = 1.0f;
// // Give an initial upward velocity to kick the simulation
// initialVelocityZ[idx] = 5.0f;
// }
// }
// }
// }
data.phiBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
@@ -55,7 +91,7 @@ void FluidScene::updateFluidData(uint32 entityID, const Component::Transform& tr
.sourceData =
{
.size = bufferSize,
.data = (uint8*)initialPhi.data(),
// .data = (uint8*)initialPhi.data(),
},
.name = "Phi0Buffer",
});
@@ -70,7 +106,7 @@ void FluidScene::updateFluidData(uint32 entityID, const Component::Transform& tr
.sourceData =
{
.size = bufferSize,
.data = (uint8*)initialDensity.data(),
// .data = (uint8*)initialDensity.data(),
},
.name = "Density0Buffer",
});
@@ -127,7 +163,7 @@ void FluidScene::updateFluidData(uint32 entityID, const Component::Transform& tr
.sourceData =
{
.size = bufferSize,
.data = (uint8*)initialVelocityX.data(),
// .data = (uint8*)initialVelocityX.data(),
},
.name = "VelocityX0Buffer",
});
@@ -135,7 +171,7 @@ void FluidScene::updateFluidData(uint32 entityID, const Component::Transform& tr
.sourceData =
{
.size = bufferSize,
.data = (uint8*)initialVelocityY.data(),
// .data = (uint8*)initialVelocityY.data(),
},
.name = "VelocityY0Buffer",
});
@@ -143,7 +179,7 @@ void FluidScene::updateFluidData(uint32 entityID, const Component::Transform& tr
.sourceData =
{
.size = bufferSize,
.data = (uint8*)initialVelocityZ.data(),
// .data = (uint8*)initialVelocityZ.data(),
},
.name = "VelocityZ0Buffer",
});
@@ -157,17 +193,53 @@ void FluidScene::updateFluidData(uint32 entityID, const Component::Transform& tr
.name = "IndexBuffer",
});
data.surfaceCountBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData = {
.size = 4 * sizeof(uint32),
},
.sourceData =
{
.size = 4 * sizeof(uint32),
},
.usage = Gfx::SE_BUFFER_USAGE_INDIRECT_BUFFER_BIT,
.name = "SurfaceCountBuffer",
});
}
auto& data = fluidDataMap[entityID];
data.paused = grid.paused;
data.transform = transform.transform;
data.cellSize = grid.cellSize;
data.dt = grid.dt;
data.viscosity = grid.viscosity;
data.diffusion = grid.diffusion;
data.gridSize = grid.gridSize;
data.gravity = grid.gravity;
data.enableGravity = grid.enableGravity;
}
void FluidScene::addSource() {
for (auto& [entityID, data] : fluidDataMap) {
Gfx::ODescriptorSet gridParams = gridParamsLayout->allocateDescriptorSet();
gridParams->updateConstants("gridSize", 0, &data.gridSize);
gridParams->writeChanges();
Gfx::ODescriptorSet descriptorSet = descriptorLayout->allocateDescriptorSet();
descriptorSet->updateBuffer("phi", 0, data.phi0Buffer);
descriptorSet->updateBuffer("density", 0, data.density0Buffer);
descriptorSet->writeChanges();
Gfx::OComputeCommand command = graphics->createComputeCommand();
command->bindPipeline(pipeline);
command->bindDescriptor(descriptorSet);
command->bindDescriptor(gridParams);
command->dispatch((data.gridSize + threadGroupSize - UVector{1, 1, 1}) / threadGroupSize);
graphics->executeCommands(std::move(command));
data.phi0Buffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_TRANSFER_READ_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT);
data.density0Buffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
// Keep render/extraction level set in sync with injected source immediately.
graphics->copyBuffer(data.phi0Buffer, data.phiBuffer);
data.phiBuffer->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
data.phi0Buffer->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_READ_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
// Reinitialize soon after source injection to restore signed-distance quality.
data.frameCounter = 0;
}
}
+13 -1
View File
@@ -5,6 +5,7 @@
#include "Containers/Map.h"
#include "Graphics/Buffer.h"
#include "Graphics/Graphics.h"
#include "Graphics/Resources.h"
#include "Graphics/Shader.h"
#include "Math/Transform.h"
#include "Math/Vector.h"
@@ -17,10 +18,13 @@ class FluidScene {
virtual ~FluidScene();
struct FluidData {
Math::Transform transform;
float cellSize;
bool paused;
float viscosity;
float diffusion;
float dt = 0.01f;
UVector gridSize;
Vector gravity;
bool enableGravity;
Gfx::OShaderBuffer phiBuffer;
Gfx::OShaderBuffer phi0Buffer;
Gfx::OShaderBuffer densityBuffer;
@@ -49,7 +53,15 @@ class FluidScene {
void updateFluidData(uint32 entityID, const Component::Transform& transform, const Component::FluidGrid& grid);
const Map<uint32, FluidData>& getFluidDataMap() const { return fluidDataMap; }
void addSource();
private:
Gfx::OPipelineLayout pipelineLayout;
Gfx::ODescriptorLayout descriptorLayout;
Gfx::ODescriptorLayout gridParamsLayout;
Gfx::OComputeShader shader;
Gfx::PComputePipeline pipeline;
constexpr static UVector threadGroupSize = {32, 8, 1};
Gfx::PGraphics graphics;
Map<uint32, FluidData> fluidDataMap;
};
+2
View File
@@ -1,5 +1,7 @@
#include "Scene.h"
#include "Graphics/Graphics.h"
#include "LightEnvironment.h"
#include "FluidScene.h"
using namespace Seele;
+2 -2
View File
@@ -1,14 +1,14 @@
#pragma once
#include "MinimalEngine.h"
#include "Graphics/Graphics.h"
#include "LightEnvironment.h"
#include "Physics/PhysicsSystem.h"
#include "FluidScene.h"
#include <entt/entt.hpp>
namespace Seele {
DECLARE_REF(Material)
DECLARE_REF(Entity)
DECLARE_REF(FluidScene)
DECLARE_REF(LightEnvironment)
class Scene {
public:
Scene(Gfx::PGraphics graphics);
+35
View File
@@ -1,4 +1,6 @@
#include "FluidUpdater.h"
#include "Graphics/DebugVertex.h"
#include "Scene/FluidScene.h"
using namespace Seele;
using namespace Seele::System;
@@ -10,4 +12,37 @@ FluidUpdater::~FluidUpdater() {}
void FluidUpdater::update(entt::entity id, Component::FluidGrid &grid, Component::Transform &transform) {
auto fluidScene = scene->getFluidScene();
fluidScene->updateFluidData((uint32)id, transform, grid);
Vector corners[8];
corners[0] = transform.getPosition();
corners[1] = transform.getPosition() + Vector(transform.getScale().x, 0, 0);
corners[2] = transform.getPosition() + Vector(0, transform.getScale().y, 0);
corners[3] = transform.getPosition() + Vector(0, 0, transform.getScale().z);
corners[4] = transform.getPosition() + Vector(transform.getScale().x, transform.getScale().y, 0);
corners[5] = transform.getPosition() + Vector(transform.getScale().x, 0, transform.getScale().z);
corners[6] = transform.getPosition() + Vector(0, transform.getScale().y, transform.getScale().z);
corners[7] = transform.getPosition() + transform.getScale();
const Vector debugColor(1, 0, 0);
auto addEdge = [&](int a, int b) {
addDebugVertex(DebugVertex{.position = corners[a], .color = debugColor});
addDebugVertex(DebugVertex{.position = corners[b], .color = debugColor});
};
// Bottom face
addEdge(0, 1);
addEdge(1, 4);
addEdge(4, 2);
addEdge(2, 0);
// Top face
addEdge(3, 5);
addEdge(5, 7);
addEdge(7, 6);
addEdge(6, 3);
// Vertical edges
addEdge(0, 3);
addEdge(1, 5);
addEdge(2, 6);
addEdge(4, 7);
}
+1
View File
@@ -1,4 +1,5 @@
#include "LightGather.h"
#include "Scene/LightEnvironment.h"
using namespace Seele;
using namespace Seele::System;
+1
View File
@@ -17,6 +17,7 @@
#include "System/LightGather.h"
#include "System/MeshUpdater.h"
#include "Window/Window.h"
#include "Scene/LightEnvironment.h"
using namespace Seele;