Trying to add fluid simulation
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,47 @@
|
||||
import FluidGridData;
|
||||
|
||||
struct Parameter
|
||||
{
|
||||
float iso;
|
||||
FluidGridData<float> density;
|
||||
RWStructuredBuffer<float3> vertices;
|
||||
RWStructuredBuffer<uint> indices;
|
||||
RWStructuredBuffer<uint> surfaceCount;
|
||||
RWStructuredBuffer<uint> vertexCount;
|
||||
};
|
||||
ParameterBlock<Parameter> params;
|
||||
|
||||
float getDensity(uint x, uint y, uint z)
|
||||
{
|
||||
return params.density[x + gridSize.x * y + gridSize.x * gridSize.y * z];
|
||||
}
|
||||
|
||||
[shader("compute")]
|
||||
[numthreads(32, 8, 1)]
|
||||
void main(uint3 dispatchThreadID : SV_DispatchThreadID)
|
||||
{
|
||||
uint x = dispatchThreadID.x+1;
|
||||
uint y = dispatchThreadID.y+1;
|
||||
uint z = dispatchThreadID.z+1;
|
||||
FluidGridData<float> density = params.density;
|
||||
if(x >= gridSize.x-3 || y >= gridSize.y-3 || z >= gridSize.z-3) return;
|
||||
|
||||
float phi[8] = {
|
||||
getDensity(x, y, z),
|
||||
getDensity(x + 1, y, z),
|
||||
getDensity(x, y + 1, z),
|
||||
getDensity(x + 1, y + 1, z),
|
||||
getDensity(x, y, z + 1),
|
||||
getDensity(x + 1, y, z + 1),
|
||||
getDensity(x, y + 1, z + 1),
|
||||
getDensity(x + 1, y + 1, z + 1)
|
||||
};
|
||||
|
||||
uint cubeIndex = 0;
|
||||
for (uint i = 0; i < 8; ++i) {
|
||||
if (phi[i] < params.iso) {
|
||||
cubeIndex |= (1 << i);
|
||||
}
|
||||
}
|
||||
if(cubeIndex == 0 || cubeIndex == 255) return;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
static const uint3 gridSize = uint3(256, 256, 256);
|
||||
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,205 @@
|
||||
import FluidGridData;
|
||||
import MarchingCubesData;
|
||||
|
||||
struct Params
|
||||
{
|
||||
RWStructuredBuffer<float> vertexBuffer;
|
||||
RWStructuredBuffer<float> normalBuffer;
|
||||
RWStructuredBuffer<uint> indexBuffer;
|
||||
RWStructuredBuffer<uint> indicesCount;
|
||||
FluidGridData<float> levelSet;
|
||||
};
|
||||
ParameterBlock<Params> params;
|
||||
|
||||
const static float isoLevel = 0.0f;
|
||||
const static float3 cellSize = 1.0f / gridSize;
|
||||
|
||||
float3 vertexInterp(float isoLevel, float3 p1, float3 p2, float valp1, float valp2)
|
||||
{
|
||||
if (abs(isoLevel - valp1) < 0.00001)
|
||||
return p1;
|
||||
if (abs(isoLevel - valp2) < 0.00001)
|
||||
return p2;
|
||||
if (abs(valp1 - valp2) < 0.00001)
|
||||
return p1;
|
||||
float mu = (isoLevel - valp1) / (valp2 - valp1);
|
||||
return p1 + mu * (p2 - p1);
|
||||
}
|
||||
|
||||
float3 gridPos(uint x, uint y, uint z)
|
||||
{
|
||||
return float3(x, y, z) * cellSize;
|
||||
}
|
||||
|
||||
// TODO: parameterize
|
||||
const static uint32_t LOCAL_THREADGROUP_SIZE = 16 * 8 * 1; // Must match numthreads
|
||||
const static uint32_t MAX_TRIS_PER_THREAD = 5; // Max triangles per cube configuration
|
||||
const static uint32_t MAX_VERTS_PER_GROUP = LOCAL_THREADGROUP_SIZE * MAX_TRIS_PER_THREAD * 3;
|
||||
|
||||
groupshared float3 localVertices[MAX_VERTS_PER_GROUP];
|
||||
groupshared float3 localNormals[MAX_VERTS_PER_GROUP];
|
||||
groupshared uint localTriCounts[LOCAL_THREADGROUP_SIZE]; // per-thread triangle counts
|
||||
groupshared uint localOffsets[LOCAL_THREADGROUP_SIZE]; // per-thread exclusive offsets (in vertices)
|
||||
groupshared uint localBaseOffset; // global base offset for this workgroup
|
||||
|
||||
// Hillis-Steele inclusive scan on localTriCounts, result in localOffsets
|
||||
// Then convert to exclusive scan and allocate global space
|
||||
void prefixSumAndAllocate(uint groupIndex)
|
||||
{
|
||||
localOffsets[groupIndex] = localTriCounts[groupIndex];
|
||||
GroupMemoryBarrierWithGroupSync();
|
||||
|
||||
for (uint offset = 1; offset < LOCAL_THREADGROUP_SIZE; offset *= 2)
|
||||
{
|
||||
uint temp = 0;
|
||||
if (groupIndex >= offset)
|
||||
temp = localOffsets[groupIndex - offset];
|
||||
GroupMemoryBarrierWithGroupSync();
|
||||
localOffsets[groupIndex] += temp;
|
||||
GroupMemoryBarrierWithGroupSync();
|
||||
}
|
||||
|
||||
// localOffsets is now an inclusive prefix sum
|
||||
// Last thread has the total — allocate global space
|
||||
if (groupIndex == LOCAL_THREADGROUP_SIZE - 1)
|
||||
{
|
||||
uint totalVerts = localOffsets[groupIndex] * 3;
|
||||
InterlockedAdd(params.indicesCount[0], totalVerts, localBaseOffset);
|
||||
}
|
||||
GroupMemoryBarrierWithGroupSync();
|
||||
|
||||
// Convert inclusive to exclusive: shift right, first element = 0
|
||||
uint inclusive = localOffsets[groupIndex];
|
||||
GroupMemoryBarrierWithGroupSync();
|
||||
localOffsets[groupIndex] = (groupIndex == 0) ? 0 : localOffsets[groupIndex - 1];
|
||||
GroupMemoryBarrierWithGroupSync();
|
||||
}
|
||||
|
||||
[shader("compute")]
|
||||
[numthreads(16, 8, 1)]
|
||||
void marchingCubes(uint3 dispatchThreadID : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex)
|
||||
{
|
||||
uint x = dispatchThreadID.x + 1;
|
||||
uint y = dispatchThreadID.y + 1;
|
||||
uint z = dispatchThreadID.z + 1;
|
||||
FluidGridData<float> levelSet = params.levelSet;
|
||||
|
||||
// Don't early-return — all threads must participate in barriers.
|
||||
// Use a flag to skip work for out-of-bounds threads.
|
||||
bool valid = (x < gridSize.x - 2 && y < gridSize.y - 2 && z < gridSize.z - 2);
|
||||
|
||||
float val[8];
|
||||
uint cubeIndex = 0;
|
||||
uint triCount = 0;
|
||||
|
||||
if (valid)
|
||||
{
|
||||
val[0] = levelSet[x, y, z];
|
||||
val[1] = levelSet[x + 1, y, z];
|
||||
val[2] = levelSet[x + 1, y + 1, z];
|
||||
val[3] = levelSet[x, y + 1, z];
|
||||
val[4] = levelSet[x, y, z + 1];
|
||||
val[5] = levelSet[x + 1, y, z + 1];
|
||||
val[6] = levelSet[x + 1, y + 1, z + 1];
|
||||
val[7] = levelSet[x, y + 1, z + 1];
|
||||
|
||||
if (val[0] < isoLevel) cubeIndex |= 1;
|
||||
if (val[1] < isoLevel) cubeIndex |= 2;
|
||||
if (val[2] < isoLevel) cubeIndex |= 4;
|
||||
if (val[3] < isoLevel) cubeIndex |= 8;
|
||||
if (val[4] < isoLevel) cubeIndex |= 16;
|
||||
if (val[5] < isoLevel) cubeIndex |= 32;
|
||||
if (val[6] < isoLevel) cubeIndex |= 64;
|
||||
if (val[7] < isoLevel) cubeIndex |= 128;
|
||||
|
||||
for (int i = 0; triTable[cubeIndex][i] != -1; i += 3)
|
||||
triCount++;
|
||||
}
|
||||
|
||||
// Prefix sum to compute per-thread offsets and allocate global space
|
||||
localTriCounts[groupIndex] = triCount;
|
||||
GroupMemoryBarrierWithGroupSync();
|
||||
prefixSumAndAllocate(groupIndex);
|
||||
|
||||
// localOffsets[groupIndex] = exclusive sum of triCounts before this thread
|
||||
// localBaseOffset = global vertex offset for this workgroup
|
||||
|
||||
if (valid && triCount > 0)
|
||||
{
|
||||
float3 pos[8];
|
||||
pos[0] = gridPos(x, y, z);
|
||||
pos[1] = gridPos(x + 1, y, z);
|
||||
pos[2] = gridPos(x + 1, y + 1, z);
|
||||
pos[3] = gridPos(x, y + 1, z);
|
||||
pos[4] = gridPos(x, y, z + 1);
|
||||
pos[5] = gridPos(x + 1, y, z + 1);
|
||||
pos[6] = gridPos(x + 1, y + 1, z + 1);
|
||||
pos[7] = gridPos(x, y + 1, z + 1);
|
||||
|
||||
float3 vertList[12];
|
||||
if ((edgeTable[cubeIndex] & 1) != 0)
|
||||
vertList[0] = vertexInterp(isoLevel, pos[0], pos[1], val[0], val[1]);
|
||||
if ((edgeTable[cubeIndex] & 2) != 0)
|
||||
vertList[1] = vertexInterp(isoLevel, pos[1], pos[2], val[1], val[2]);
|
||||
if ((edgeTable[cubeIndex] & 4) != 0)
|
||||
vertList[2] = vertexInterp(isoLevel, pos[2], pos[3], val[2], val[3]);
|
||||
if ((edgeTable[cubeIndex] & 8) != 0)
|
||||
vertList[3] = vertexInterp(isoLevel, pos[3], pos[0], val[3], val[0]);
|
||||
if ((edgeTable[cubeIndex] & 16) != 0)
|
||||
vertList[4] = vertexInterp(isoLevel, pos[4], pos[5], val[4], val[5]);
|
||||
if ((edgeTable[cubeIndex] & 32) != 0)
|
||||
vertList[5] = vertexInterp(isoLevel, pos[5], pos[6], val[5], val[6]);
|
||||
if ((edgeTable[cubeIndex] & 64) != 0)
|
||||
vertList[6] = vertexInterp(isoLevel, pos[6], pos[7], val[6], val[7]);
|
||||
if ((edgeTable[cubeIndex] & 128) != 0)
|
||||
vertList[7] = vertexInterp(isoLevel, pos[7], pos[4], val[7], val[4]);
|
||||
if ((edgeTable[cubeIndex] & 256) != 0)
|
||||
vertList[8] = vertexInterp(isoLevel, pos[0], pos[4], val[0], val[4]);
|
||||
if ((edgeTable[cubeIndex] & 512) != 0)
|
||||
vertList[9] = vertexInterp(isoLevel, pos[1], pos[5], val[1], val[5]);
|
||||
if ((edgeTable[cubeIndex] & 1024) != 0)
|
||||
vertList[10] = vertexInterp(isoLevel, pos[2], pos[6], val[2], val[6]);
|
||||
if ((edgeTable[cubeIndex] & 2048) != 0)
|
||||
vertList[11] = vertexInterp(isoLevel, pos[3], pos[7], val[3], val[7]);
|
||||
|
||||
// Write triangles into shared memory
|
||||
uint localOff = localOffsets[groupIndex] * 3; // in vertices
|
||||
for (int i = 0; triTable[cubeIndex][i] != -1; i += 3)
|
||||
{
|
||||
float3 v0 = vertList[triTable[cubeIndex][i]];
|
||||
float3 v1 = vertList[triTable[cubeIndex][i + 1]];
|
||||
float3 v2 = vertList[triTable[cubeIndex][i + 2]];
|
||||
float3 n = normalize(cross(v1 - v0, v2 - v0));
|
||||
|
||||
localVertices[localOff] = v0;
|
||||
localVertices[localOff + 1] = v1;
|
||||
localVertices[localOff + 2] = v2;
|
||||
localNormals[localOff] = n;
|
||||
localNormals[localOff + 1] = n;
|
||||
localNormals[localOff + 2] = n;
|
||||
localOff += 3;
|
||||
}
|
||||
}
|
||||
|
||||
GroupMemoryBarrierWithGroupSync();
|
||||
|
||||
// Copy from shared memory to global buffers
|
||||
// Each thread copies a chunk of the workgroup's output
|
||||
uint totalGroupVerts = localTriCounts[LOCAL_THREADGROUP_SIZE - 1] > 0
|
||||
? (localOffsets[LOCAL_THREADGROUP_SIZE - 1] + localTriCounts[LOCAL_THREADGROUP_SIZE - 1]) * 3
|
||||
: localOffsets[LOCAL_THREADGROUP_SIZE - 1] * 3;
|
||||
|
||||
for (uint i = groupIndex; i < totalGroupVerts; i += LOCAL_THREADGROUP_SIZE)
|
||||
{
|
||||
uint globalIdx = localBaseOffset + i;
|
||||
float3 v = localVertices[i];
|
||||
float3 n = localNormals[i];
|
||||
params.vertexBuffer[globalIdx * 3 + 0] = v.x;
|
||||
params.vertexBuffer[globalIdx * 3 + 1] = v.y;
|
||||
params.vertexBuffer[globalIdx * 3 + 2] = v.z;
|
||||
params.normalBuffer[globalIdx * 3 + 0] = n.x;
|
||||
params.normalBuffer[globalIdx * 3 + 1] = n.y;
|
||||
params.normalBuffer[globalIdx * 3 + 2] = n.z;
|
||||
params.indexBuffer[globalIdx] = globalIdx;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,299 @@
|
||||
// Marching Cubes edge table: for each cube configuration (256), a 12-bit mask
|
||||
// indicating which edges are intersected by the isosurface.
|
||||
// clang-format off
|
||||
static const uint16_t edgeTable[256] = {
|
||||
0x000, 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c,
|
||||
0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00,
|
||||
0x190, 0x099, 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c,
|
||||
0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90,
|
||||
0x230, 0x339, 0x033, 0x13a, 0x636, 0x73f, 0x435, 0x53c,
|
||||
0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30,
|
||||
0x3a0, 0x2a9, 0x1a3, 0x0aa, 0x7a6, 0x6af, 0x5a5, 0x4ac,
|
||||
0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0,
|
||||
0x460, 0x569, 0x663, 0x76a, 0x066, 0x16f, 0x265, 0x36c,
|
||||
0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60,
|
||||
0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0x0ff, 0x3f5, 0x2fc,
|
||||
0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0,
|
||||
0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x055, 0x15c,
|
||||
0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950,
|
||||
0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0x0cc,
|
||||
0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0,
|
||||
0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc,
|
||||
0x0cc, 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0,
|
||||
0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c,
|
||||
0x15c, 0x055, 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650,
|
||||
0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc,
|
||||
0x2fc, 0x3f5, 0x0ff, 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0,
|
||||
0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c,
|
||||
0x36c, 0x265, 0x16f, 0x066, 0x76a, 0x663, 0x569, 0x460,
|
||||
0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac,
|
||||
0x4ac, 0x5a5, 0x6af, 0x7a6, 0x0aa, 0x1a3, 0x2a9, 0x3a0,
|
||||
0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c,
|
||||
0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x033, 0x339, 0x230,
|
||||
0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c,
|
||||
0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x099, 0x190,
|
||||
0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c,
|
||||
0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x000,
|
||||
};
|
||||
|
||||
// Marching Cubes triangle table: for each cube configuration, up to 5
|
||||
// triangles specified as sequences of edge indices, terminated by -1.
|
||||
static const int8_t triTable[256][16] = {
|
||||
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{0,8,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{0,1,9,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{1,8,3,9,8,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{1,2,10,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{0,8,3,1,2,10,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{9,2,10,0,2,9,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{2,8,3,2,10,8,10,9,8,-1,-1,-1,-1,-1,-1,-1},
|
||||
{3,11,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{0,11,2,8,11,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{1,9,0,2,3,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{1,11,2,1,9,11,9,8,11,-1,-1,-1,-1,-1,-1,-1},
|
||||
{3,10,1,11,10,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{0,10,1,0,8,10,8,11,10,-1,-1,-1,-1,-1,-1,-1},
|
||||
{3,9,0,3,11,9,11,10,9,-1,-1,-1,-1,-1,-1,-1},
|
||||
{9,8,10,10,8,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{4,7,8,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{4,3,0,7,3,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{0,1,9,8,4,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{4,1,9,4,7,1,7,3,1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{1,2,10,8,4,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{3,4,7,3,0,4,1,2,10,-1,-1,-1,-1,-1,-1,-1},
|
||||
{9,2,10,9,0,2,8,4,7,-1,-1,-1,-1,-1,-1,-1},
|
||||
{2,10,9,2,9,7,2,7,3,7,9,4,-1,-1,-1,-1},
|
||||
{8,4,7,3,11,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{11,4,7,11,2,4,2,0,4,-1,-1,-1,-1,-1,-1,-1},
|
||||
{9,0,1,8,4,7,2,3,11,-1,-1,-1,-1,-1,-1,-1},
|
||||
{4,7,11,9,4,11,9,11,2,9,2,1,-1,-1,-1,-1},
|
||||
{3,10,1,3,11,10,7,8,4,-1,-1,-1,-1,-1,-1,-1},
|
||||
{1,11,10,1,4,11,1,0,4,7,11,4,-1,-1,-1,-1},
|
||||
{4,7,8,9,0,11,9,11,10,11,0,3,-1,-1,-1,-1},
|
||||
{4,7,11,4,11,9,9,11,10,-1,-1,-1,-1,-1,-1,-1},
|
||||
{9,5,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{9,5,4,0,8,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{0,5,4,1,5,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{8,5,4,8,3,5,3,1,5,-1,-1,-1,-1,-1,-1,-1},
|
||||
{1,2,10,9,5,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{3,0,8,1,2,10,4,9,5,-1,-1,-1,-1,-1,-1,-1},
|
||||
{5,2,10,5,4,2,4,0,2,-1,-1,-1,-1,-1,-1,-1},
|
||||
{2,10,5,3,2,5,3,5,4,3,4,8,-1,-1,-1,-1},
|
||||
{9,5,4,2,3,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{0,11,2,0,8,11,4,9,5,-1,-1,-1,-1,-1,-1,-1},
|
||||
{0,5,4,0,1,5,2,3,11,-1,-1,-1,-1,-1,-1,-1},
|
||||
{2,1,5,2,5,8,2,8,11,4,8,5,-1,-1,-1,-1},
|
||||
{10,3,11,10,1,3,9,5,4,-1,-1,-1,-1,-1,-1,-1},
|
||||
{4,9,5,0,8,1,8,10,1,8,11,10,-1,-1,-1,-1},
|
||||
{5,4,0,5,0,11,5,11,10,11,0,3,-1,-1,-1,-1},
|
||||
{5,4,8,5,8,10,10,8,11,-1,-1,-1,-1,-1,-1,-1},
|
||||
{9,7,8,5,7,9,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{9,3,0,9,5,3,5,7,3,-1,-1,-1,-1,-1,-1,-1},
|
||||
{0,7,8,0,1,7,1,5,7,-1,-1,-1,-1,-1,-1,-1},
|
||||
{1,5,3,3,5,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{9,7,8,9,5,7,10,1,2,-1,-1,-1,-1,-1,-1,-1},
|
||||
{10,1,2,9,5,0,5,3,0,5,7,3,-1,-1,-1,-1},
|
||||
{8,0,2,8,2,5,8,5,7,10,5,2,-1,-1,-1,-1},
|
||||
{2,10,5,2,5,3,3,5,7,-1,-1,-1,-1,-1,-1,-1},
|
||||
{7,9,5,7,8,9,3,11,2,-1,-1,-1,-1,-1,-1,-1},
|
||||
{9,5,7,9,7,2,9,2,0,2,7,11,-1,-1,-1,-1},
|
||||
{2,3,11,0,1,8,1,7,8,1,5,7,-1,-1,-1,-1},
|
||||
{11,2,1,11,1,7,7,1,5,-1,-1,-1,-1,-1,-1,-1},
|
||||
{9,5,8,8,5,7,10,1,3,10,3,11,-1,-1,-1,-1},
|
||||
{5,7,0,5,0,9,7,11,0,1,0,10,11,10,0,-1},
|
||||
{11,10,0,11,0,3,10,5,0,8,0,7,5,7,0,-1},
|
||||
{11,10,5,7,11,5,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{10,6,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{0,8,3,5,10,6,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{9,0,1,5,10,6,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{1,8,3,1,9,8,5,10,6,-1,-1,-1,-1,-1,-1},
|
||||
{1,6,5,2,6,1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{1,6,5,1,2,6,3,0,8,-1,-1,-1,-1,-1,-1},
|
||||
{9,6,5,9,0,6,0,2,6,-1,-1,-1,-1,-1,-1},
|
||||
{5,9,8,5,8,2,5,2,6,3,2,8,-1,-1,-1,-1},
|
||||
{2,3,11,10,6,5,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{11,0,8,11,2,0,10,6,5,-1,-1,-1,-1,-1,-1},
|
||||
{0,1,9,2,3,11,5,10,6,-1,-1,-1,-1,-1,-1},
|
||||
{5,10,6,1,9,2,9,11,2,9,8,11,-1,-1,-1,-1},
|
||||
{6,3,11,6,5,3,5,1,3,-1,-1,-1,-1,-1,-1,-1},
|
||||
{0,8,11,0,11,5,0,5,1,5,11,6,-1,-1,-1,-1},
|
||||
{3,11,6,0,3,6,0,6,5,0,5,9,-1,-1,-1,-1},
|
||||
{6,5,9,6,9,11,11,9,8,-1,-1,-1,-1,-1,-1,-1},
|
||||
{5,10,6,4,7,8,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{4,3,0,4,7,3,6,5,10,-1,-1,-1,-1,-1,-1,-1},
|
||||
{1,9,0,5,10,6,8,4,7,-1,-1,-1,-1,-1,-1,-1},
|
||||
{10,6,5,1,9,7,1,7,3,7,9,4,-1,-1,-1,-1},
|
||||
{6,1,2,6,5,1,4,7,8,-1,-1,-1,-1,-1,-1,-1},
|
||||
{1,2,5,5,2,6,3,0,4,3,4,7,-1,-1,-1,-1},
|
||||
{8,4,7,9,0,5,0,6,5,0,2,6,-1,-1,-1,-1},
|
||||
{7,3,9,7,9,4,3,2,9,5,9,6,2,6,9,-1},
|
||||
{3,11,2,7,8,4,10,6,5,-1,-1,-1,-1,-1,-1,-1},
|
||||
{5,10,6,4,7,2,4,2,0,2,7,11,-1,-1,-1,-1},
|
||||
{0,1,9,4,7,8,2,3,11,5,10,6,-1,-1,-1,-1},
|
||||
{9,2,1,9,11,2,9,4,11,7,11,4,5,10,6,-1},
|
||||
{8,4,7,3,11,5,3,5,1,5,11,6,-1,-1,-1,-1},
|
||||
{5,1,11,5,11,6,1,0,11,7,11,4,0,4,11,-1},
|
||||
{0,5,9,0,6,5,0,3,6,11,6,3,8,4,7,-1},
|
||||
{6,5,9,6,9,11,4,7,9,7,11,9,-1,-1,-1,-1},
|
||||
{10,4,9,6,4,10,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{4,10,6,4,9,10,0,8,3,-1,-1,-1,-1,-1,-1},
|
||||
{10,0,1,10,6,0,6,4,0,-1,-1,-1,-1,-1,-1},
|
||||
{8,3,1,8,1,6,8,6,4,6,1,10,-1,-1,-1,-1},
|
||||
{1,4,9,1,2,4,2,6,4,-1,-1,-1,-1,-1,-1,-1},
|
||||
{3,0,8,1,2,9,2,4,9,2,6,4,-1,-1,-1,-1},
|
||||
{0,2,4,4,2,6,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{8,3,2,8,2,4,4,2,6,-1,-1,-1,-1,-1,-1,-1},
|
||||
{10,4,9,10,6,4,11,2,3,-1,-1,-1,-1,-1,-1},
|
||||
{0,8,2,2,8,11,4,9,10,4,10,6,-1,-1,-1,-1},
|
||||
{3,11,2,0,1,6,0,6,4,6,1,10,-1,-1,-1,-1},
|
||||
{6,4,1,6,1,10,4,8,1,2,1,11,8,11,1,-1},
|
||||
{9,6,4,9,3,6,9,1,3,11,6,3,-1,-1,-1,-1},
|
||||
{8,11,1,8,1,0,11,6,1,9,1,4,6,4,1,-1},
|
||||
{3,11,6,3,6,0,0,6,4,-1,-1,-1,-1,-1,-1,-1},
|
||||
{6,4,8,11,6,8,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{7,10,6,7,8,10,8,9,10,-1,-1,-1,-1,-1,-1,-1},
|
||||
{0,7,3,0,10,7,0,9,10,6,7,10,-1,-1,-1,-1},
|
||||
{10,6,7,1,10,7,1,7,8,1,8,0,-1,-1,-1,-1},
|
||||
{10,6,7,10,7,1,1,7,3,-1,-1,-1,-1,-1,-1,-1},
|
||||
{1,2,6,1,6,8,1,8,9,8,6,7,-1,-1,-1,-1},
|
||||
{2,6,9,2,9,1,6,7,9,0,9,3,7,3,9,-1},
|
||||
{7,8,0,7,0,6,6,0,2,-1,-1,-1,-1,-1,-1,-1},
|
||||
{7,3,2,6,7,2,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{2,3,11,10,6,8,10,8,9,8,6,7,-1,-1,-1,-1},
|
||||
{2,0,7,2,7,11,0,9,7,6,7,10,9,10,7,-1},
|
||||
{1,8,0,1,7,8,1,10,7,6,7,10,2,3,11,-1},
|
||||
{11,2,1,11,1,7,10,6,1,6,7,1,-1,-1,-1,-1},
|
||||
{8,9,6,8,6,7,9,1,6,11,6,3,1,3,6,-1},
|
||||
{0,9,1,11,6,7,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{7,8,0,7,0,6,3,11,0,11,6,0,-1,-1,-1,-1},
|
||||
{7,11,6,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{7,6,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{3,0,8,11,7,6,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{0,1,9,11,7,6,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{8,1,9,8,3,1,11,7,6,-1,-1,-1,-1,-1,-1},
|
||||
{10,1,2,6,11,7,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{1,2,10,3,0,8,6,11,7,-1,-1,-1,-1,-1,-1},
|
||||
{2,9,0,2,10,9,6,11,7,-1,-1,-1,-1,-1,-1},
|
||||
{6,11,7,2,10,3,10,8,3,10,9,8,-1,-1,-1,-1},
|
||||
{7,2,3,6,2,7,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{7,0,8,7,6,0,6,2,0,-1,-1,-1,-1,-1,-1,-1},
|
||||
{2,7,6,2,3,7,0,1,9,-1,-1,-1,-1,-1,-1,-1},
|
||||
{1,6,2,1,8,6,1,9,8,8,7,6,-1,-1,-1,-1},
|
||||
{10,7,6,10,1,7,1,3,7,-1,-1,-1,-1,-1,-1,-1},
|
||||
{10,7,6,1,7,10,1,8,7,1,0,8,-1,-1,-1,-1},
|
||||
{0,3,7,0,7,10,0,10,9,6,10,7,-1,-1,-1,-1},
|
||||
{7,6,10,7,10,8,8,10,9,-1,-1,-1,-1,-1,-1,-1},
|
||||
{6,8,4,11,8,6,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{3,6,11,3,0,6,0,4,6,-1,-1,-1,-1,-1,-1,-1},
|
||||
{8,6,11,8,4,6,9,0,1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{9,4,6,9,6,3,9,3,1,11,3,6,-1,-1,-1,-1},
|
||||
{6,8,4,6,11,8,2,10,1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{1,2,10,3,0,11,0,6,11,0,4,6,-1,-1,-1,-1},
|
||||
{4,11,8,4,6,11,0,2,9,2,10,9,-1,-1,-1,-1},
|
||||
{10,9,3,10,3,2,9,4,3,11,3,6,4,6,3,-1},
|
||||
{8,2,3,8,4,2,4,6,2,-1,-1,-1,-1,-1,-1,-1},
|
||||
{0,4,2,4,6,2,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{1,9,0,2,3,4,2,4,6,4,3,8,-1,-1,-1,-1},
|
||||
{1,9,4,1,4,2,2,4,6,-1,-1,-1,-1,-1,-1,-1},
|
||||
{8,1,3,8,6,1,8,4,6,6,10,1,-1,-1,-1,-1},
|
||||
{10,1,0,10,0,6,6,0,4,-1,-1,-1,-1,-1,-1,-1},
|
||||
{4,6,3,4,3,8,6,10,3,0,3,9,10,9,3,-1},
|
||||
{10,9,4,6,10,4,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{4,9,5,7,6,11,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{0,8,3,4,9,5,11,7,6,-1,-1,-1,-1,-1,-1,-1},
|
||||
{5,0,1,5,4,0,7,6,11,-1,-1,-1,-1,-1,-1,-1},
|
||||
{11,7,6,8,3,4,3,5,4,3,1,5,-1,-1,-1,-1},
|
||||
{9,5,4,10,1,2,7,6,11,-1,-1,-1,-1,-1,-1,-1},
|
||||
{6,11,7,1,2,10,0,8,3,4,9,5,-1,-1,-1,-1},
|
||||
{7,6,11,5,4,10,4,2,10,4,0,2,-1,-1,-1,-1},
|
||||
{3,4,8,3,5,4,3,2,5,10,5,2,11,7,6,-1},
|
||||
{7,2,3,7,6,2,5,4,9,-1,-1,-1,-1,-1,-1,-1},
|
||||
{9,5,4,0,8,6,0,6,2,6,8,7,-1,-1,-1,-1},
|
||||
{3,6,2,3,7,6,1,5,0,5,4,0,-1,-1,-1,-1},
|
||||
{6,2,8,6,8,7,2,1,8,4,8,5,1,5,8,-1},
|
||||
{9,5,4,10,1,6,1,7,6,1,3,7,-1,-1,-1,-1},
|
||||
{1,6,10,1,7,6,1,0,7,8,7,0,9,5,4,-1},
|
||||
{4,0,10,4,10,5,0,3,10,6,10,7,3,7,10,-1},
|
||||
{7,6,10,7,10,8,5,4,10,4,8,10,-1,-1,-1,-1},
|
||||
{6,9,5,6,11,9,11,8,9,-1,-1,-1,-1,-1,-1,-1},
|
||||
{3,6,11,0,6,3,0,5,6,0,9,5,-1,-1,-1,-1},
|
||||
{0,11,8,0,5,11,0,1,5,5,6,11,-1,-1,-1,-1},
|
||||
{6,11,3,6,3,5,5,3,1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{1,2,10,9,5,11,9,11,8,11,5,6,-1,-1,-1,-1},
|
||||
{0,11,3,0,6,11,0,9,6,5,6,9,1,2,10,-1},
|
||||
{11,8,5,11,5,6,8,0,5,10,5,2,0,2,5,-1},
|
||||
{6,11,3,6,3,5,2,10,3,10,5,3,-1,-1,-1,-1},
|
||||
{5,8,9,5,2,8,5,6,2,3,8,2,-1,-1,-1,-1},
|
||||
{9,5,6,9,6,0,0,6,2,-1,-1,-1,-1,-1,-1,-1},
|
||||
{1,5,8,1,8,0,5,6,8,3,8,2,6,2,8,-1},
|
||||
{1,5,6,2,1,6,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{1,3,6,1,6,10,3,8,6,5,6,9,8,9,6,-1},
|
||||
{10,1,0,10,0,6,9,5,0,5,6,0,-1,-1,-1,-1},
|
||||
{0,3,8,5,6,10,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{10,5,6,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{11,5,10,7,5,11,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{11,5,10,11,7,5,8,3,0,-1,-1,-1,-1,-1,-1},
|
||||
{5,11,7,5,10,11,1,9,0,-1,-1,-1,-1,-1,-1},
|
||||
{10,7,5,10,11,7,9,8,1,8,3,1,-1,-1,-1,-1},
|
||||
{11,1,2,11,7,1,7,5,1,-1,-1,-1,-1,-1,-1},
|
||||
{0,8,3,1,2,7,1,7,5,7,2,11,-1,-1,-1,-1},
|
||||
{9,7,5,9,2,7,9,0,2,2,11,7,-1,-1,-1,-1},
|
||||
{7,5,2,7,2,11,5,9,2,3,2,8,9,8,2,-1},
|
||||
{2,5,10,2,3,5,3,7,5,-1,-1,-1,-1,-1,-1,-1},
|
||||
{8,2,0,8,5,2,8,7,5,10,2,5,-1,-1,-1,-1},
|
||||
{9,0,1,5,10,3,5,3,7,3,10,2,-1,-1,-1,-1},
|
||||
{9,8,2,9,2,1,8,7,2,10,2,5,7,5,2,-1},
|
||||
{1,3,5,3,7,5,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{0,8,7,0,7,1,1,7,5,-1,-1,-1,-1,-1,-1,-1},
|
||||
{9,0,3,9,3,5,5,3,7,-1,-1,-1,-1,-1,-1,-1},
|
||||
{9,8,7,5,9,7,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{5,8,4,5,10,8,10,11,8,-1,-1,-1,-1,-1,-1,-1},
|
||||
{5,0,4,5,11,0,5,10,11,11,3,0,-1,-1,-1,-1},
|
||||
{0,1,9,8,4,10,8,10,11,10,4,5,-1,-1,-1,-1},
|
||||
{10,11,4,10,4,5,11,3,4,9,4,1,3,1,4,-1},
|
||||
{2,5,1,2,8,5,2,11,8,4,5,8,-1,-1,-1,-1},
|
||||
{0,4,11,0,11,3,4,5,11,2,11,1,5,1,11,-1},
|
||||
{0,2,5,0,5,9,2,11,5,4,5,8,11,8,5,-1},
|
||||
{9,4,5,2,11,3,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{2,5,10,3,5,2,3,4,5,3,8,4,-1,-1,-1,-1},
|
||||
{5,10,2,5,2,4,4,2,0,-1,-1,-1,-1,-1,-1,-1},
|
||||
{3,10,2,3,5,10,3,8,5,4,5,8,0,1,9,-1},
|
||||
{5,10,2,5,2,4,1,9,2,9,4,2,-1,-1,-1,-1},
|
||||
{8,4,5,8,5,3,3,5,1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{0,4,5,1,0,5,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{8,4,5,8,5,3,9,0,5,0,3,5,-1,-1,-1,-1},
|
||||
{9,4,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{4,11,7,4,9,11,9,10,11,-1,-1,-1,-1,-1,-1},
|
||||
{0,8,3,4,9,7,9,11,7,9,10,11,-1,-1,-1,-1},
|
||||
{1,10,11,1,11,4,1,4,0,7,4,11,-1,-1,-1,-1},
|
||||
{3,1,4,3,4,8,1,10,4,7,4,11,10,11,4,-1},
|
||||
{4,11,7,9,11,4,9,2,11,9,1,2,-1,-1,-1,-1},
|
||||
{9,7,4,9,11,7,9,1,11,2,11,1,0,8,3,-1},
|
||||
{11,7,4,11,4,2,2,4,0,-1,-1,-1,-1,-1,-1,-1},
|
||||
{11,7,4,11,4,2,8,3,4,3,2,4,-1,-1,-1,-1},
|
||||
{2,9,10,2,7,9,2,3,7,7,4,9,-1,-1,-1,-1},
|
||||
{9,10,7,9,7,4,10,2,7,8,7,0,2,0,7,-1},
|
||||
{3,7,10,3,10,2,7,4,10,1,10,0,4,0,10,-1},
|
||||
{1,10,2,8,7,4,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{4,9,1,4,1,7,7,1,3,-1,-1,-1,-1,-1,-1,-1},
|
||||
{4,9,1,4,1,7,0,8,1,8,7,1,-1,-1,-1,-1},
|
||||
{4,0,3,7,4,3,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{4,8,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{9,10,8,10,11,8,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{3,0,9,3,9,11,11,9,10,-1,-1,-1,-1,-1,-1,-1},
|
||||
{0,1,10,0,10,8,8,10,11,-1,-1,-1,-1,-1,-1,-1},
|
||||
{3,1,10,11,3,10,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{1,2,11,1,11,9,9,11,8,-1,-1,-1,-1,-1,-1,-1},
|
||||
{3,0,9,3,9,11,1,2,9,2,11,9,-1,-1,-1,-1},
|
||||
{0,2,11,8,0,11,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{3,2,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{2,3,8,2,8,10,10,8,9,-1,-1,-1,-1,-1,-1,-1},
|
||||
{9,10,2,0,9,2,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{2,3,8,2,8,10,0,1,8,1,10,8,-1,-1,-1,-1},
|
||||
{1,10,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{1,3,8,9,1,8,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{0,9,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{0,3,8,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
|
||||
};
|
||||
// clang-format on
|
||||
@@ -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,59 @@
|
||||
import Common;
|
||||
import FluidGridData;
|
||||
import LightEnv;
|
||||
import MaterialParameter;
|
||||
|
||||
struct Params
|
||||
{
|
||||
StructuredBuffer<float> vertexBuffer;
|
||||
StructuredBuffer<float> normalBuffer;
|
||||
StructuredBuffer<uint> indexBuffer;
|
||||
};
|
||||
ParameterBlock<Params> params;
|
||||
|
||||
struct VertexOut
|
||||
{
|
||||
float3 position_WS : POSITION;
|
||||
float4 position_CS : SV_Position;
|
||||
float3 normal : NORMAL;
|
||||
};
|
||||
|
||||
[shader("vertex")]
|
||||
VertexOut vertexMain(uint vertexId : SV_VertexID)
|
||||
{
|
||||
VertexOut output;
|
||||
uint index = params.indexBuffer[vertexId];
|
||||
float3 vertex = float3(params.vertexBuffer[index * 3 + 0],
|
||||
params.vertexBuffer[index * 3 + 1],
|
||||
params.vertexBuffer[index * 3 + 2]) * 5;
|
||||
float3 normal = float3(params.normalBuffer[index * 3 + 0],
|
||||
params.normalBuffer[index * 3 + 1],
|
||||
params.normalBuffer[index * 3 + 2]);
|
||||
output.position_WS = vertex;
|
||||
output.position_CS = mul(pViewParams.viewProjectionMatrix, float4(vertex, 1));
|
||||
output.normal = normal;
|
||||
return output;
|
||||
}
|
||||
|
||||
[shader("pixel")]
|
||||
float4 fragmentMain(VertexOut input) : SV_Target
|
||||
{
|
||||
BlinnPhong brdf;
|
||||
brdf.baseColor = float3(0, 0, 1);
|
||||
brdf.alpha = 1;
|
||||
brdf.specularColor = float3(1, 1, 1);
|
||||
brdf.normal = input.normal;
|
||||
brdf.shininess = 32;
|
||||
brdf.ambient = float3(0.1, 0.1, 0.1);
|
||||
brdf.emissive = float3(0, 0, 0);
|
||||
float3 result = float3(0, 0, 0);
|
||||
float3 viewDir = normalize(pViewParams.cameraPosition_WS.xyz - input.position_WS);
|
||||
for(int i = 0; i < pLightEnv.numDirectionalLights; i++)
|
||||
{
|
||||
LightingParameter lightParams;
|
||||
lightParams.position_WS = input.position_WS;
|
||||
lightParams.viewDir_WS = viewDir;
|
||||
result += pLightEnv.directionalLights[i].illuminate(lightParams, brdf);
|
||||
}
|
||||
return float4(result, 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,65 @@
|
||||
import FluidGridData;
|
||||
|
||||
struct Params
|
||||
{
|
||||
float dtau;
|
||||
// read-write: phi being reinitialized
|
||||
FluidGridData<float> phi;
|
||||
// read-only: snapshot of phi before reinitialization (for sign)
|
||||
FluidGridData<float> phi0;
|
||||
};
|
||||
ParameterBlock<Params> params;
|
||||
|
||||
// Smooth sign function to avoid discontinuity at zero
|
||||
float smoothSign(float x, float dx)
|
||||
{
|
||||
return x / sqrt(x * x + dx * dx);
|
||||
}
|
||||
|
||||
[shader("compute")]
|
||||
[numthreads(32, 8, 1)]
|
||||
void reinitialize(uint3 dispatchThreadID : SV_DispatchThreadID)
|
||||
{
|
||||
uint x = dispatchThreadID.x + 1;
|
||||
uint y = dispatchThreadID.y + 1;
|
||||
uint z = dispatchThreadID.z + 1;
|
||||
FluidGridData<float> phi = params.phi;
|
||||
FluidGridData<float> phi0 = params.phi0;
|
||||
if(x >= gridSize.x - 1 || y >= gridSize.y - 1 || z >= gridSize.z - 1) return;
|
||||
|
||||
float dtau = params.dtau;
|
||||
float dx = 1.0f;
|
||||
|
||||
// Current value and original sign
|
||||
float p = phi[x, y, z];
|
||||
float s = smoothSign(phi0[x, y, z], dx);
|
||||
|
||||
// Upwind finite differences for |grad phi|
|
||||
// Forward and backward differences
|
||||
float dxp = phi[x + 1, y, z] - p;
|
||||
float dxm = p - phi[x - 1, y, z];
|
||||
float dyp = phi[x, y + 1, z] - p;
|
||||
float dym = p - phi[x, y - 1, z];
|
||||
float dzp = phi[x, y, z + 1] - p;
|
||||
float dzm = p - phi[x, y, z - 1];
|
||||
|
||||
// Godunov upwind scheme
|
||||
float gradPhi;
|
||||
if (s > 0)
|
||||
{
|
||||
float ax = max(max(dxm, 0.0f), -min(dxp, 0.0f));
|
||||
float ay = max(max(dym, 0.0f), -min(dyp, 0.0f));
|
||||
float az = max(max(dzm, 0.0f), -min(dzp, 0.0f));
|
||||
gradPhi = sqrt(ax * ax + ay * ay + az * az) / dx;
|
||||
}
|
||||
else
|
||||
{
|
||||
float ax = max(-min(dxm, 0.0f), max(dxp, 0.0f));
|
||||
float ay = max(-min(dym, 0.0f), max(dyp, 0.0f));
|
||||
float az = max(-min(dzm, 0.0f), max(dzp, 0.0f));
|
||||
gradPhi = sqrt(ax * ax + ay * ay + az * az) / dx;
|
||||
}
|
||||
|
||||
// Update: push |grad phi| toward 1
|
||||
phi[x, y, z] = p - dtau * s * (gradPhi - 1.0f);
|
||||
}
|
||||
@@ -21,7 +21,6 @@ struct ViewParameter
|
||||
uint frameIndex;
|
||||
float time;
|
||||
};
|
||||
layout(set=0)
|
||||
ParameterBlock<ViewParameter> pViewParams;
|
||||
|
||||
float4 worldToModel(float4x4 inverseTransform, float4 world)
|
||||
|
||||
@@ -71,7 +71,6 @@ struct LightEnv
|
||||
Texture2D brdfLUT;
|
||||
SamplerState lutSampler;
|
||||
};
|
||||
layout(set=3)
|
||||
ParameterBlock<LightEnv> pLightEnv;
|
||||
|
||||
interface IBRDF
|
||||
|
||||
@@ -14,7 +14,6 @@ struct MaterialResources
|
||||
SamplerState samplerArray[512];
|
||||
StructuredBuffer<float> floatArray;
|
||||
};
|
||||
layout(set=4)
|
||||
ParameterBlock<MaterialResources> pResources;
|
||||
|
||||
Texture2D getMaterialTextureParameter(uint index)
|
||||
|
||||
+15
-14
@@ -45,20 +45,6 @@ struct MeshletCullingInfo
|
||||
}
|
||||
};
|
||||
|
||||
struct DrawCallOffsets
|
||||
{
|
||||
uint instanceOffset;
|
||||
uint textureOffset;
|
||||
uint samplerOffset;
|
||||
uint floatOffset;
|
||||
};
|
||||
#ifdef RAY_TRACING
|
||||
layout(shaderRecordEXT)
|
||||
#else
|
||||
layout(push_constant)
|
||||
#endif
|
||||
ConstantBuffer<DrawCallOffsets> pOffsets;
|
||||
|
||||
struct Scene
|
||||
{
|
||||
StructuredBuffer<float> positions;
|
||||
@@ -73,6 +59,21 @@ struct Scene
|
||||
};
|
||||
ParameterBlock<Scene> pScene;
|
||||
|
||||
struct DrawCallOffsets
|
||||
{
|
||||
uint instanceOffset;
|
||||
uint textureOffset;
|
||||
uint samplerOffset;
|
||||
uint floatOffset;
|
||||
};
|
||||
#ifdef RAY_TRACING
|
||||
// Shader record buffers are accessed via a different mechanism and don't use descriptor set bindings
|
||||
layout(set = 15, shaderRecordEXT)
|
||||
#else
|
||||
layout(push_constant)
|
||||
#endif
|
||||
ConstantBuffer<DrawCallOffsets> pOffsets;
|
||||
|
||||
uint32_t encodePrimitive(uint32_t meshletId)
|
||||
{
|
||||
return meshletId;
|
||||
|
||||
@@ -34,5 +34,4 @@ struct StaticMeshVertexData
|
||||
StructuredBuffer<uint16_t> color;
|
||||
StructuredBuffer<uint16_t> texCoords[MAX_TEXCOORDS];
|
||||
};
|
||||
layout(set = 1)
|
||||
ParameterBlock<StaticMeshVertexData> pVertexData;
|
||||
@@ -1,12 +1,12 @@
|
||||
import Common;
|
||||
import MaterialParameter;
|
||||
import LightEnv;
|
||||
import Scene;
|
||||
import RayTracingData;
|
||||
import VertexData;
|
||||
import Material;
|
||||
import StaticMeshVertexData;
|
||||
import MATERIAL_FILE_NAME;
|
||||
import RayTracingData;
|
||||
import Scene;
|
||||
|
||||
// simplification: all BLAS only have 1 geometry
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ struct RayTracingParams
|
||||
TextureCube<float4> skyBox;
|
||||
SamplerState skyBoxSampler;
|
||||
};
|
||||
layout(set=5)
|
||||
ParameterBlock<RayTracingParams> pRayTracingParams;
|
||||
|
||||
struct RayPayload
|
||||
|
||||
Reference in New Issue
Block a user