Initial commit

This commit is contained in:
Dynamitos
2026-04-06 09:55:59 +02:00
commit 0a4552a1a4
24 changed files with 1718 additions and 0 deletions
+55
View File
@@ -0,0 +1,55 @@
import FluidGridData;
struct Params
{
// read-write
FluidGridData<float> density;
// read-only
FluidGridData<float> density0;
// read-only
FluidGridData<float> velocityX;
// read-only
FluidGridData<float> velocityY;
// read-only
FluidGridData<float> velocityZ;
float dt;
};
ParameterBlock<Params> params;
[shader("compute")]
[numthreads(32, 8, 1)]
void advect(uint3 dispatchThreadID : SV_DispatchThreadID)
{
FluidGridData<float> density = params.density;
FluidGridData<float> density0 = params.density0;
FluidGridData<float> velocityX = params.velocityX;
FluidGridData<float> velocityY = params.velocityY;
FluidGridData<float> velocityZ = params.velocityZ;
float dt = params.dt;
int x = dispatchThreadID.x + 1;
int y = dispatchThreadID.y + 1;
int z = dispatchThreadID.z + 1;
if(x >= gridSize.x - 1 || y >= gridSize.y - 1 || z >= gridSize.z - 1) return;
float dt0x = dt * (gridSize.x - 2);
float dt0y = dt * (gridSize.y - 2);
float dt0z = dt * (gridSize.z - 2);
float3 pos = float3(x - dt0x * velocityX[x, y, z], y - dt0y * velocityY[x, y, z], z - dt0z * velocityZ[x, y, z]);
pos.x = clamp(pos.x, 0.5f, gridSize.x - 1.5f);
pos.y = clamp(pos.y, 0.5f, gridSize.y - 1.5f);
pos.z = clamp(pos.z, 0.5f, gridSize.z - 1.5f);
int3 i0 = int3(pos);
int3 i1 = i0 + int3(1, 1, 1);
float3 s1 = pos - i0;
float3 s0 = 1 - s1;
density[x, y, z] =
s0.x * (s0.y * (s0.z * density0[i0.x, i0.y, i0.z] + s1.z * density0[i0.x, i0.y, i1.z]) +
s1.y * (s0.z * density0[i0.x, i1.y, i0.z] + s1.z * density0[i0.x, i1.y, i1.z])) +
s1.x * (s0.y * (s0.z * density0[i1.x, i0.y, i0.z] + s1.z * density0[i1.x, i0.y, i1.z]) +
s1.y * (s0.z * density0[i1.x, i1.y, i0.z] + s1.z * density0[i1.x, i1.y, i1.z]));
}
+35
View File
@@ -0,0 +1,35 @@
import FluidGridData;
struct Params
{
// read-only
FluidGridData<float> velocityX;
// read-only
FluidGridData<float> velocityY;
// read-only
FluidGridData<float> velocityZ;
// read-write
FluidGridData<float> divergence;
// read-write
FluidGridData<float> pressure;
};
ParameterBlock<Params> params;
[shader("compute")]
[numthreads(32, 8, 1)]
void computeDivergence(uint3 dispatchThreadID : SV_DispatchThreadID)
{
FluidGridData<float> velocityX = params.velocityX;
FluidGridData<float> velocityY = params.velocityY;
FluidGridData<float> velocityZ = params.velocityZ;
FluidGridData<float> divergence = params.divergence;
FluidGridData<float> pressure = params.pressure;
int x = dispatchThreadID.x + 1;
int y = dispatchThreadID.y + 1;
int z = dispatchThreadID.z + 1;
if(x >= gridSize.x - 1 || y >= gridSize.y - 1 || z >= gridSize.z - 1) return;
divergence[x, y, z] = -0.5f * (velocityX[x + 1, y, z] - velocityX[x - 1, y, z] + velocityY[x, y + 1, z] - velocityY[x, y - 1, z] + velocityZ[x, y, z + 1] - velocityZ[x, y, z - 1]) / gridSize.x;
pressure[x, y, z] = 0;
}
+15
View File
@@ -0,0 +1,15 @@
static const uint3 gridSize = uint3(128, 128, 128);
struct FluidGridData<T>
{
RWStructuredBuffer<T> dataGrid;
__subscript(uint3 index) -> T
{
get { return dataGrid[index.x + index.y * gridSize.x + index.z * gridSize.x * gridSize.y]; }
set { dataGrid[index.x + index.y * gridSize.x + index.z * gridSize.x * gridSize.y] = newValue; }
}
__subscript(uint x, uint y, uint z) -> T
{
get { return dataGrid[x + y * gridSize.x + z * gridSize.x * gridSize.y]; }
set { dataGrid[x + y * gridSize.x + z * gridSize.x * gridSize.y] = newValue; }
}
};
+32
View File
@@ -0,0 +1,32 @@
import FluidGridData;
struct Params
{
// read-write
FluidGridData<float> next;
// read-only
FluidGridData<float> current;
// read-only
FluidGridData<float> grid0;
float a;
float c;
};
ParameterBlock<Params> params;
[shader("compute")]
[numthreads(32, 8, 1)]
void linearSolve(uint3 dispatchThreadID : SV_DispatchThreadID)
{
FluidGridData<float> next = params.next;
FluidGridData<float> current = params.current;
FluidGridData<float> grid0 = params.grid0;
float a = params.a;
float cRecip = 1.0f / params.c;
int x = dispatchThreadID.x + 1;
int y = dispatchThreadID.y + 1;
int z = dispatchThreadID.z + 1;
if(x >= gridSize.x - 1 || y >= gridSize.y - 1 || z >= gridSize.z - 1) return;
next[x, y, z] = (grid0[x, y, z] + a * (current[x + 1, y, z] + current[x - 1, y, z] + current[x, y + 1, z] + current[x, y - 1, z] + current[x, y, z + 1] + current[x, y, z - 1])) * cRecip;
}
+33
View File
@@ -0,0 +1,33 @@
import FluidGridData;
struct Params
{
// read-write
FluidGridData<float> velocityX;
// read-write
FluidGridData<float> velocityY;
// read-write
FluidGridData<float> velocityZ;
// read-only
FluidGridData<float> pressure;
};
ParameterBlock<Params> params;
[shader("compute")]
[numthreads(32, 8, 1)]
void project(uint3 dispatchThreadID : SV_DispatchThreadID)
{
FluidGridData<float> velocityX = params.velocityX;
FluidGridData<float> velocityY = params.velocityY;
FluidGridData<float> velocityZ = params.velocityZ;
FluidGridData<float> pressure = params.pressure;
int x = dispatchThreadID.x + 1;
int y = dispatchThreadID.y + 1;
int z = dispatchThreadID.z + 1;
if(x >= gridSize.x - 1 || y >= gridSize.y - 1 || z >= gridSize.z - 1) return;
velocityX[x, y, z] -= 0.5f * (pressure[x + 1, y, z] - pressure[x - 1, y, z]) * gridSize.x;
velocityY[x, y, z] -= 0.5f * (pressure[x, y + 1, z] - pressure[x, y - 1, z]) * gridSize.y;
velocityZ[x, y, z] -= 0.5f * (pressure[x, y, z + 1] - pressure[x, y, z - 1]) * gridSize.z;
}
+32
View File
@@ -0,0 +1,32 @@
import FluidGridData;
struct Params
{
FluidGridData<float> density;
};
ParameterBlock<Params> params;
struct VertexOut
{
float4 position : SV_Position;
float2 uv : UV;
};
[shader("vertex")]
VertexOut vertexMain(uint vertexId : SV_VertexID)
{
VertexOut output;
output.uv = float2((vertexId << 1) & 2, vertexId & 2);
output.position = float4(output.uv * 2.0f - 1.0f, 0, 1);
return output;
}
[shader("pixel")]
float4 fragmentMain(VertexOut input) : SV_Target
{
FluidGridData<float> density = params.density;
int x = int(input.uv.x * (gridSize.x - 2) + 1);
int y = int(input.uv.y * (gridSize.y - 2) + 1);
float d = density[x, y, 0];
return float4(d, d, d, 1);
}
+71
View File
@@ -0,0 +1,71 @@
import FluidGridData;
struct Params
{
int b;
// read-write
FluidGridData<float> grid;
};
ParameterBlock<Params> params;
[shader("compute")]
[numthreads(32, 8, 1)]
void setBound(uint3 dispatchThreadID : SV_DispatchThreadID)
{
int b = params.b;
FluidGridData<float> grid = params.grid;
int x = dispatchThreadID.x + 1;
int y = dispatchThreadID.y + 1;
if(x >= gridSize.x - 1 || y >= gridSize.y - 1) return;
grid[0, x, y] = b == 1 ? grid[1, x, y] : -grid[1, x, y];
grid[gridSize.x - 1, x, y] = b == 1 ? grid[gridSize.x - 2, x, y] : -grid[gridSize.x - 2, x, y];
grid[x, 0, y] = b == 2 ? grid[x, 1, y] : -grid[x, 1, y];
grid[x, gridSize.y - 1, y] = b == 2 ? grid[x, gridSize.y - 2, y] : -grid[x, gridSize.y - 2, y];
grid[x, y, 0] = b == 3 ? grid[x, y, 1] : -grid[x, y, 1];
grid[x, y, gridSize.z - 1] = b == 3 ? grid[x, y, gridSize.z - 2] : -grid[x, y, gridSize.z - 2];
}
[shader("compute")]
[numthreads(128, 1, 1)]
void setBoundEdges(uint3 dispatchThreadID : SV_DispatchThreadID)
{
FluidGridData<float> grid = params.grid;
int x = dispatchThreadID.x + 1;
if(x >= gridSize.x - 1) return;
grid[x, 0, 0] = 0.5f * (grid[x, 1, 0] + grid[x, 0, 1]);
grid[x, gridSize.y - 1, 0] = 0.5f * (grid[x, gridSize.y - 2, 0] + grid[x, gridSize.y - 1, 1]);
grid[x, 0, gridSize.z - 1] = 0.5f * (grid[x, 1, gridSize.z - 1] + grid[x, 0, gridSize.z - 2]);
grid[x, gridSize.y - 1, gridSize.z - 1] = 0.5f * (grid[x, gridSize.y - 2, gridSize.z - 1] + grid[x, gridSize.y - 1, gridSize.z - 2]);
grid[0, x, 0] = 0.5f * (grid[1, x, 0] + grid[0, x, 1]);
grid[0, x, gridSize.z - 1] = 0.5f * (grid[1, x, gridSize.z - 1] + grid[0, x, gridSize.z - 2]);
grid[gridSize.x - 1, x, 0] = 0.5f * (grid[gridSize.x - 2, x, 0] + grid[gridSize.x - 1, x, 1]);
grid[gridSize.x - 1, x, gridSize.z - 1] = 0.5f * (grid[gridSize.x - 2, x, gridSize.z - 1] + grid[gridSize.x - 1, x, gridSize.z - 2]);
grid[0, 0, x] = 0.5f * (grid[1, 0, x] + grid[0, 1, x]);
grid[0, gridSize.y - 1, x] = 0.5f * (grid[1, gridSize.y - 1, x] + grid[0, gridSize.y - 2, x]);
grid[gridSize.x - 1, 0, x] = 0.5f * (grid[gridSize.x - 2, 0, x] + grid[gridSize.x - 1, 1, x]);
grid[gridSize.x - 1, gridSize.y - 1, x] = 0.5f * (grid[gridSize.x - 2, gridSize.y - 1, x] + grid[gridSize.x - 1, gridSize.y - 2, x]);
}
[shader("compute")]
[numthreads(8, 1, 1)]
void setBoundCorners(uint3 dispatchThreadID : SV_DispatchThreadID)
{
FluidGridData<float> grid = params.grid;
uint threadIdx = dispatchThreadID.x;
uint x = ((threadIdx & 1) == 0) ? 0 : (gridSize.x - 1);
uint y = ((threadIdx & 2) == 0) ? 0 : (gridSize.y - 1);
uint z = ((threadIdx & 4) == 0) ? 0 : (gridSize.z - 1);
uint nx = (x == 0) ? 1 : (gridSize.x - 2);
uint ny = (y == 0) ? 1 : (gridSize.y - 2);
uint nz = (z == 0) ? 1 : (gridSize.z - 2);
grid[x, y, z] = 0.33f * (grid[nx, y, z] + grid[x, ny, z] + grid[x, y, nz]);
}
+108
View File
@@ -0,0 +1,108 @@
import FluidGridData;
void linearSolve(int b, FluidGridData<float> grid, const FluidGridData<float> grid0, float a, float c, int iterations)
{
float cRecip = 1.0f / c;
for(int k = 0; k < iterations; k++)
{
for(int z = 1; z < gridSize.z - 1; z++)
{
for(int y = 1; y < gridSize.y - 1; y++)
{
for(int x = 1; x < gridSize.x - 1; x++)
{
grid[x, y, z] = (grid0[x, y, z] + a * (grid[x + 1, y, z] + grid[x - 1, y, z] + grid[x, y + 1, z] + grid[x, y - 1, z] + grid[x, y, z + 1] + grid[x, y, z - 1])) * cRecip;
}
}
}
setBound(b, grid);
}
}
void diffuse(int b, FluidGridData<float> grid, const FluidGridData<float> grid0, float diff, float dt, int iterations)
{
float a = dt * diff * (gridSize.x - 2) * (gridSize.y - 2) * (gridSize.z - 2);
linearSolve(b, grid, grid0, a, 1 + 6 * a, iterations);
}
void advect(int b, FluidGridData<float> density, FluidGridData<float> density0, FluidGridData<float> velocityX, FluidGridData<float> velocityY, FluidGridData<float> velocityZ, float dt)
{
float dt0x = dt * (gridSize.x - 2);
float dt0y = dt * (gridSize.y - 2);
float dt0z = dt * (gridSize.z - 2);
for(int z = 1; z < gridSize.z - 1; z++)
{
for(int y = 1; y < gridSize.y - 1; y++)
{
for(int x = 1; x < gridSize.x - 1; x++)
{
float3 pos = float3(x - dt0x * velocityX[x, y, z], y - dt0y * velocityY[x, y, z], z - dt0z * velocityZ[x, y, z]);
pos.x = clamp(pos.x, 0.5f, gridSize.x - 1.5f);
pos.y = clamp(pos.y, 0.5f, gridSize.y - 1.5f);
pos.z = clamp(pos.z, 0.5f, gridSize.z - 1.5f);
int3 i0 = int3(pos);
int3 i1 = i0 + int3(1, 1, 1);
float3 s1 = pos - i0;
float3 s0 = 1 - s1;
density[x, y, z] =
s0.x * (s0.y * (s0.z * density0[i0.x, i0.y, i0.z] + s1.z * density0[i0.x, i0.y, i1.z]) +
s1.y * (s0.z * density0[i0.x, i1.y, i0.z] + s1.z * density0[i0.x, i1.y, i1.z])) +
s1.x * (s0.y * (s0.z * density0[i1.x, i0.y, i0.z] + s1.z * density0[i1.x, i0.y, i1.z]) +
s1.y * (s0.z * density0[i1.x, i1.y, i0.z] + s1.z * density0[i1.x, i1.y, i1.z]));
}
}
}
setBound(b, density);
}
void project(FluidGridData<float> velocityX, FluidGridData<float> velocityY, FluidGridData<float> velocityZ, FluidGridData<float> pressure, FluidGridData<float> divergence, int iter)
{
for(int z = 1; z < gridSize.z - 1; z++)
{
for(int y = 1; y < gridSize.y - 1; y++)
{
for(int x = 1; x < gridSize.x - 1; x++)
{
divergence[x, y, z] = -0.5f * (velocityX[x + 1, y, z] - velocityX[x - 1, y, z] + velocityY[x, y + 1, z] - velocityY[x, y - 1, z] + velocityZ[x, y, z + 1] - velocityZ[x, y, z - 1]) / gridSize.x;
pressure[x, y, z] = 0;
}
}
}
setBound(0, divergence);
setBound(0, pressure);
linearSolve(0, pressure, divergence, 1, 6, iter);
for(int z = 1; z < gridSize.z - 1; z++)
{
for(int y = 1; y < gridSize.y - 1; y++)
{
for(int x = 1; x < gridSize.x - 1; x++)
{
velocityX[x, y, z] -= 0.5f * (pressure[x + 1, y, z] - pressure[x - 1, y, z]) * gridSize.x;
velocityY[x, y, z] -= 0.5f * (pressure[x, y + 1, z] - pressure[x, y - 1, z]) * gridSize.y;
velocityZ[x, y, z] -= 0.5f * (pressure[x, y, z + 1] - pressure[x, y, z - 1]) * gridSize.z;
}
}
}
setBound(1, velocityX);
setBound(2, velocityY);
setBound(3, velocityZ);
}
[shader("compute")]
void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
{
diffuse(1, pComputeParams.velocityX0, pComputeParams.velocityX, pComputeParams.viscosity, pComputeParams.dt, 20);
diffuse(2, pComputeParams.velocityY0, pComputeParams.velocityY, pComputeParams.viscosity, pComputeParams.dt, 20);
diffuse(3, pComputeParams.velocityZ0, pComputeParams.velocityZ, pComputeParams.viscosity, pComputeParams.dt, 20);
project(pComputeParams.velocityX0, pComputeParams.velocityY0, pComputeParams.velocityZ0, pComputeParams.scratch, pComputeParams.density, 20);
advect(1, pComputeParams.velocityX, pComputeParams.velocityX0, pComputeParams.velocityX0, pComputeParams.velocityY0, pComputeParams.velocityZ0, pComputeParams.dt);
advect(2, pComputeParams.velocityY, pComputeParams.velocityY0, pComputeParams.velocityX0, pComputeParams.velocityY0, pComputeParams.velocityZ0, pComputeParams.dt);
advect(3, pComputeParams.velocityZ, pComputeParams.velocityZ0, pComputeParams.velocityX0, pComputeParams.velocityY0, pComputeParams.velocityZ0, pComputeParams.dt);
diffuse(0, pComputeParams.scratch, pComputeParams.density, pComputeParams.diffusion, pComputeParams.dt, 20);
advect(0, pComputeParams.density, pComputeParams.scratch, pComputeParams.velocityX0, pComputeParams.velocityY0, pComputeParams.velocityZ0, pComputeParams.dt);
}