Initial commit
This commit is contained in:
@@ -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]));
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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]);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user