Integrating into Seele
This commit is contained in:
@@ -88,10 +88,8 @@ AlwaysBreakBeforeMultilineStrings: false
|
||||
AttributeMacros:
|
||||
- __capability
|
||||
BinPackArguments: true
|
||||
BinPackLongBracedList: true
|
||||
BinPackParameters: BinPack
|
||||
BitFieldColonSpacing: Both
|
||||
BracedInitializerIndentWidth: -1
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
@@ -120,7 +118,6 @@ BreakBeforeBinaryOperators: None
|
||||
BreakBeforeConceptDeclarations: Always
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeInlineASMColon: OnlyMultiline
|
||||
BreakBeforeTemplateCloser: false
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakBinaryOperations: Never
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
@@ -138,7 +135,6 @@ DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
EmptyLineAfterAccessModifier: Never
|
||||
EmptyLineBeforeAccessModifier: LogicalBlock
|
||||
EnumTrailingComma: Leave
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: true
|
||||
ForEachMacros:
|
||||
@@ -202,7 +198,6 @@ ObjCBlockIndentWidth: 2
|
||||
ObjCBreakBeforeNestedBlockParam: true
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
OneLineFormatOffRegex: ''
|
||||
PackConstructorInitializers: BinPack
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
@@ -230,14 +225,10 @@ RequiresExpressionIndentation: OuterScope
|
||||
SeparateDefinitionBlocks: Leave
|
||||
ShortNamespaceLines: 1
|
||||
SkipMacroDefinitionBody: false
|
||||
SortIncludes:
|
||||
Enabled: true
|
||||
IgnoreCase: false
|
||||
SortJavaStaticImport: Before
|
||||
SortUsingDeclarations: LexicographicNumeric
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterOperatorKeyword: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceAroundPointerQualifiers: Default
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
@@ -253,7 +244,6 @@ SpaceBeforeParensOptions:
|
||||
AfterFunctionDefinitionName: false
|
||||
AfterFunctionDeclarationName: false
|
||||
AfterIfMacros: true
|
||||
AfterNot: false
|
||||
AfterOverloadedOperator: false
|
||||
AfterPlacementOperator: true
|
||||
AfterRequiresInClause: false
|
||||
|
||||
+2
-1
@@ -1,2 +1,3 @@
|
||||
build/
|
||||
.cache/
|
||||
.cache/
|
||||
Assets/
|
||||
Vendored
-30
@@ -1,30 +0,0 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Launch",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}/build/FluidSimulation",
|
||||
"args": [],
|
||||
"cwd": "${workspaceRoot}/build",
|
||||
"MIMode": "gdb",
|
||||
"setupCommands": [
|
||||
{
|
||||
"text": "-enable-pretty-printing",
|
||||
"description": "enable pretty printing",
|
||||
"ignoreFailures": false
|
||||
},
|
||||
{
|
||||
"text": "source ${workspaceRoot}/Seele/gdb/Seele.py",
|
||||
"description": "load Seele python script",
|
||||
"ignoreFailures": false
|
||||
}
|
||||
],
|
||||
|
||||
}
|
||||
]
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
../Seele/.vscode/launch.json
|
||||
+2
-5
@@ -14,17 +14,14 @@ set(CMAKE_TOOLCHAIN_FILE
|
||||
project(FluidSimulation)
|
||||
|
||||
set(CMAKE_DEBUG_POSTFIX "")
|
||||
set(CMAKE_SHARED_LIBRARY_PREFIX "")
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
add_subdirectory(Seele/)
|
||||
|
||||
add_executable(FluidSimulation "")
|
||||
add_library(FluidSimulation SHARED "")
|
||||
target_link_libraries(FluidSimulation PRIVATE Engine)
|
||||
target_include_directories(FluidSimulation PRIVATE src/)
|
||||
add_subdirectory(src/)
|
||||
|
||||
add_custom_command(TARGET FluidSimulation POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
${CMAKE_SOURCE_DIR}/res $<TARGET_FILE_DIR:FluidSimulation>)
|
||||
|
||||
+18
-14
@@ -36,10 +36,28 @@
|
||||
"description": "Debug build without sanitizers",
|
||||
"binaryDir": "${sourceDir}/build",
|
||||
"cacheVariables": {
|
||||
"CMAKE_C_COMPILER": "clang",
|
||||
"CMAKE_CXX_COMPILER": "clang++",
|
||||
"CMAKE_BUILD_TYPE": "Debug",
|
||||
"CMAKE_INSTALL_PREFIX": "C:/Program Files/Seele"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "debug-asan",
|
||||
"displayName": "Debug (ASan)",
|
||||
"description": "Debug build with Address Sanitizer",
|
||||
"binaryDir": "${sourceDir}/build",
|
||||
"cacheVariables": {
|
||||
"CMAKE_C_COMPILER": "clang",
|
||||
"CMAKE_CXX_COMPILER": "clang++",
|
||||
"CMAKE_BUILD_TYPE": "Debug",
|
||||
"CMAKE_CXX_FLAGS": "-fsanitize=address -fno-omit-frame-pointer",
|
||||
"CMAKE_C_FLAGS": "-fsanitize=address -fno-omit-frame-pointer",
|
||||
"CMAKE_EXE_LINKER_FLAGS": "-fsanitize=address",
|
||||
"CMAKE_SHARED_LINKER_FLAGS": "-fsanitize=address",
|
||||
"CMAKE_INSTALL_PREFIX": "C:/Program Files/Seele"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "debug-mac",
|
||||
"displayName": "Debug Mac (no ASan)",
|
||||
@@ -65,20 +83,6 @@
|
||||
"CMAKE_SHARED_LINKER_FLAGS": "-fsanitize=address",
|
||||
"CMAKE_INSTALL_PREFIX": "C:/Program Files/Seele"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "debug-asan",
|
||||
"displayName": "Debug (ASan)",
|
||||
"description": "Debug build with Address Sanitizer",
|
||||
"binaryDir": "${sourceDir}/build",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Debug",
|
||||
"CMAKE_CXX_FLAGS": "-fsanitize=address -fno-omit-frame-pointer",
|
||||
"CMAKE_C_FLAGS": "-fsanitize=address -fno-omit-frame-pointer",
|
||||
"CMAKE_EXE_LINKER_FLAGS": "-fsanitize=address",
|
||||
"CMAKE_SHARED_LINKER_FLAGS": "-fsanitize=address",
|
||||
"CMAKE_INSTALL_PREFIX": "C:/Program Files/Seele"
|
||||
}
|
||||
}
|
||||
],
|
||||
"buildPresets": [
|
||||
|
||||
+1
-1
Submodule Seele updated: 056589a6f9...ac317a3829
File diff suppressed because one or more lines are too long
Binary file not shown.
+1535
File diff suppressed because it is too large
Load Diff
@@ -1,55 +0,0 @@
|
||||
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]));
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
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;
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
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;
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
static const uint3 gridSize = uint3(32, 32, 32);
|
||||
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; }
|
||||
}
|
||||
};
|
||||
@@ -1,32 +0,0 @@
|
||||
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;
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
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;
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
import Common;
|
||||
import FluidGridData;
|
||||
|
||||
struct Params
|
||||
{
|
||||
StructuredBuffer<float> vertexBuffer;
|
||||
StructuredBuffer<uint> indexBuffer;
|
||||
};
|
||||
ParameterBlock<Params> params;
|
||||
|
||||
struct VertexOut
|
||||
{
|
||||
float4 position : SV_Position;
|
||||
};
|
||||
|
||||
[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;
|
||||
output.position = mul(pViewParams.viewProjectionMatrix, float4(vertex, 1));
|
||||
return output;
|
||||
}
|
||||
|
||||
[shader("pixel")]
|
||||
float4 fragmentMain(VertexOut input) : SV_Target
|
||||
{
|
||||
return float4(0, 0, 1, 1);
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
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]);
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
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);
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
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);
|
||||
}
|
||||
+3
-9
@@ -1,11 +1,5 @@
|
||||
target_sources(FluidSimulation
|
||||
PRIVATE
|
||||
FluidRenderPass.h
|
||||
FluidRenderPass.cpp
|
||||
FluidSimulationView.h
|
||||
FluidSimulationView.cpp
|
||||
main.cpp
|
||||
SimulationComputePass.h
|
||||
SimulationComputePass.cpp
|
||||
SurfaceExtractPass.h
|
||||
SurfaceExtractPass.cpp)
|
||||
FluidSimulationGame.cpp
|
||||
FluidSimulationGame.h
|
||||
)
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
#pragma once
|
||||
#include "MinimalEngine.h"
|
||||
|
||||
constexpr static uint32 gridSize = 32;
|
||||
constexpr static float viscosity = 0.001f;
|
||||
constexpr static float diffusion = 0.001f;
|
||||
constexpr static float dt = 0.1f;
|
||||
@@ -1,151 +0,0 @@
|
||||
#include "FluidRenderPass.h"
|
||||
#include "Graphics/Command.h"
|
||||
#include "Graphics/Enums.h"
|
||||
#include "Graphics/Graphics.h"
|
||||
#include "Graphics/Initializer.h"
|
||||
#include "Graphics/RenderTarget.h"
|
||||
#include "Graphics/Shader.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
FluidRenderPass::FluidRenderPass(Seele::Gfx::PGraphics graphics)
|
||||
: RenderPass(graphics) {
|
||||
pipelineLayout = graphics->createPipelineLayout("FluidPipelineLayout");
|
||||
descriptorLayout = graphics->createDescriptorLayout("params");
|
||||
descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.name = "vertexBuffer",
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
});
|
||||
descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.name = "indexBuffer",
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
});
|
||||
descriptorLayout->create();
|
||||
pipelineLayout->addDescriptorLayout(viewParamsLayout);
|
||||
pipelineLayout->addDescriptorLayout(descriptorLayout);
|
||||
|
||||
graphics->beginShaderCompilation(ShaderCompilationInfo{
|
||||
.name = "Fluid",
|
||||
.modules = {"Render"},
|
||||
.entryPoints = {{"vertexMain", "Render"}, {"fragmentMain", "Render"}},
|
||||
.rootSignature = pipelineLayout,
|
||||
.dumpIntermediate = true,
|
||||
});
|
||||
pipelineLayout->create();
|
||||
vertexShader = graphics->createVertexShader({0});
|
||||
fragmentShader = graphics->createFragmentShader({1});
|
||||
}
|
||||
|
||||
FluidRenderPass::~FluidRenderPass() {}
|
||||
|
||||
void FluidRenderPass::beginFrame(const Seele::Component::Camera &camera,
|
||||
const Seele::Component::Transform &transform) {
|
||||
updateViewParameters(camera, transform);
|
||||
}
|
||||
|
||||
void FluidRenderPass::render() {
|
||||
viewParamsSet = createViewParamsSet();
|
||||
descriptorSet = descriptorLayout->allocateDescriptorSet();
|
||||
descriptorSet->updateBuffer("vertexBuffer", 0, vertexBuffer);
|
||||
descriptorSet->updateBuffer("indexBuffer", 0, indexBuffer);
|
||||
descriptorSet->writeChanges();
|
||||
graphics->beginRenderPass(renderPass);
|
||||
Gfx::ORenderCommand renderCommand = graphics->createRenderCommand();
|
||||
renderCommand->setViewport(viewport);
|
||||
renderCommand->bindPipeline(pipeline);
|
||||
renderCommand->bindDescriptor({viewParamsSet, descriptorSet});
|
||||
renderCommand->drawIndirect(surfaceCounts, 0, 1, 0);
|
||||
graphics->executeCommands(std::move(renderCommand));
|
||||
graphics->endRenderPass();
|
||||
}
|
||||
|
||||
void FluidRenderPass::endFrame() {}
|
||||
|
||||
void FluidRenderPass::publishOutputs() {
|
||||
depthTexture = graphics->createTexture2D(TextureCreateInfo{
|
||||
.format = Gfx::SE_FORMAT_D32_SFLOAT,
|
||||
.width = viewport->getWidth(),
|
||||
.height = viewport->getHeight(),
|
||||
.usage = Gfx::SE_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
|
||||
.name = "FluidDepth",
|
||||
});
|
||||
}
|
||||
|
||||
void FluidRenderPass::createRenderPass() {
|
||||
vertexBuffer = resources->requestBuffer("SURFACE_VERTICES");
|
||||
indexBuffer = resources->requestBuffer("SURFACE_INDICES");
|
||||
surfaceCounts = resources->requestBuffer("SURFACE_COUNTS");
|
||||
colorAttachment = Gfx::RenderTargetAttachment(
|
||||
viewport, Gfx::SE_IMAGE_LAYOUT_UNDEFINED,
|
||||
Gfx::SE_IMAGE_LAYOUT_PRESENT_SRC_KHR, Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR,
|
||||
Gfx::SE_ATTACHMENT_STORE_OP_STORE);
|
||||
depthAttachment = Gfx::RenderTargetAttachment(
|
||||
depthTexture->getDefaultView(), Gfx::SE_IMAGE_LAYOUT_UNDEFINED,
|
||||
Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
|
||||
Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR, Gfx::SE_ATTACHMENT_STORE_OP_DONT_CARE);
|
||||
depthAttachment.clear.depthStencil.depth = 0.0f;
|
||||
Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{
|
||||
.colorAttachments = {colorAttachment},
|
||||
.depthAttachment = depthAttachment,
|
||||
};
|
||||
Array<Gfx::SubPassDependency> dependency = {
|
||||
{
|
||||
.srcSubpass = ~0U,
|
||||
.dstSubpass = 0,
|
||||
.srcStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
|
||||
Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
|
||||
Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
|
||||
.dstStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
|
||||
Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
|
||||
Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
|
||||
.srcAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
|
||||
Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
|
||||
Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
|
||||
.dstAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
|
||||
Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
|
||||
Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
|
||||
},
|
||||
{
|
||||
.srcSubpass = 0,
|
||||
.dstSubpass = ~0U,
|
||||
.srcStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
|
||||
Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
|
||||
Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
|
||||
.dstStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
|
||||
Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
|
||||
Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
|
||||
.srcAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
|
||||
Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
|
||||
Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
|
||||
.dstAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
|
||||
Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
|
||||
Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
|
||||
},
|
||||
};
|
||||
renderPass = graphics->createRenderPass(
|
||||
layout, dependency, viewport->getRenderArea(), "FluidRenderPass");
|
||||
pipeline = graphics->createGraphicsPipeline(Gfx::LegacyPipelineCreateInfo{
|
||||
.vertexShader = vertexShader,
|
||||
.fragmentShader = fragmentShader,
|
||||
.renderPass = renderPass,
|
||||
.pipelineLayout = pipelineLayout,
|
||||
.multisampleState =
|
||||
{
|
||||
.samples = Gfx::SE_SAMPLE_COUNT_1_BIT,
|
||||
},
|
||||
.rasterizationState =
|
||||
{
|
||||
.cullMode = Gfx::SE_CULL_MODE_FRONT_BIT,
|
||||
},
|
||||
.colorBlend =
|
||||
{
|
||||
.attachmentCount = 1,
|
||||
.blendAttachments =
|
||||
{
|
||||
Gfx::ColorBlendState::BlendAttachment{
|
||||
.blendEnable = true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
#pragma once
|
||||
#include "Component/Transform.h"
|
||||
#include "Graphics/Descriptor.h"
|
||||
#include "Graphics/Initializer.h"
|
||||
#include "Graphics/RenderPass/RenderPass.h"
|
||||
#include "MinimalEngine.h"
|
||||
|
||||
class FluidRenderPass : public Seele::RenderPass {
|
||||
public:
|
||||
FluidRenderPass(Seele::Gfx::PGraphics graphics);
|
||||
virtual ~FluidRenderPass() override;
|
||||
|
||||
virtual void beginFrame(const Seele::Component::Camera &camera, const Seele::Component::Transform &transform) override;
|
||||
virtual void render() override;
|
||||
virtual void endFrame() override;
|
||||
|
||||
virtual void publishOutputs() override;
|
||||
virtual void createRenderPass() override;
|
||||
|
||||
private:
|
||||
Seele::Gfx::RenderTargetAttachment colorAttachment;
|
||||
Seele::Gfx::RenderTargetAttachment depthAttachment;
|
||||
Seele::Gfx::OTexture2D depthTexture;
|
||||
|
||||
Seele::Gfx::ODescriptorSet viewParamsSet;
|
||||
|
||||
Seele::Gfx::OPipelineLayout pipelineLayout;
|
||||
Seele::Gfx::ODescriptorLayout descriptorLayout;
|
||||
Seele::Gfx::ODescriptorSet descriptorSet;
|
||||
Seele::Gfx::OVertexShader vertexShader;
|
||||
Seele::Gfx::OFragmentShader fragmentShader;
|
||||
Seele::Gfx::PGraphicsPipeline pipeline;
|
||||
|
||||
Seele::Gfx::PShaderBuffer vertexBuffer;
|
||||
Seele::Gfx::PShaderBuffer indexBuffer;
|
||||
Seele::Gfx::PShaderBuffer surfaceCounts;
|
||||
};
|
||||
DEFINE_REF(FluidRenderPass)
|
||||
@@ -0,0 +1,34 @@
|
||||
#include "FluidSimulationGame.h"
|
||||
#include "Actor/DirectionalLightActor.h"
|
||||
#include "Actor/PointLightActor.h"
|
||||
#include "Actor/StaticMeshActor.h"
|
||||
#include "Asset/AssetRegistry.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
FluidSimulationGame::FluidSimulationGame() {}
|
||||
|
||||
FluidSimulationGame::~FluidSimulationGame() {}
|
||||
|
||||
void FluidSimulationGame::setupScene(Seele::PScene scene, Seele::PSystemGraph graph) {
|
||||
mesh = new StaticMeshActor(scene, AssetRegistry::findMesh("rttest", "rttest"));
|
||||
sun = new DirectionalLightActor(scene, Vector(1, -1, 1), 1, Vector(1, 1, 1));
|
||||
pointLight = new PointLightActor(scene, Vector(0, 1, 0), 1, Vector(1, 1, 1), 10);
|
||||
|
||||
Seele::Component::Transform transform;
|
||||
Seele::Component::FluidGrid grid;
|
||||
grid.cellSize = 0.1f;
|
||||
grid.viscosity = 0.001f;
|
||||
grid.diffusion = 0.0001f;
|
||||
grid.gridSize = {64, 64, 64};
|
||||
transform.transform.setPosition({0.0f, 0.0f, 0.0f});
|
||||
scene->getFluidScene()->updateFluidData(0, transform, grid);
|
||||
}
|
||||
|
||||
extern "C" FluidSimulationGame* createInstance() {
|
||||
return new FluidSimulationGame();
|
||||
}
|
||||
|
||||
extern "C" void destroyInstance(FluidSimulationGame* game) {
|
||||
delete game;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include "Actor/DirectionalLightActor.h"
|
||||
#include "Actor/PointLightActor.h"
|
||||
#include "Actor/StaticMeshActor.h"
|
||||
#include "Game.h"
|
||||
|
||||
class FluidSimulationGame : public Seele::Game {
|
||||
public:
|
||||
FluidSimulationGame();
|
||||
virtual ~FluidSimulationGame() override;
|
||||
virtual void setupScene(Seele::PScene scene, Seele::PSystemGraph graph) override;
|
||||
private:
|
||||
Seele::OStaticMeshActor mesh;
|
||||
Seele::ODirectionalLightActor sun;
|
||||
Seele::OPointLightActor pointLight;
|
||||
};
|
||||
|
||||
extern "C" FluidSimulationGame* createInstance();
|
||||
extern "C" void destroyInstance(FluidSimulationGame* game);
|
||||
@@ -1,99 +0,0 @@
|
||||
#include "FluidSimulationView.h"
|
||||
#include "FluidRenderPass.h"
|
||||
#include "Graphics/Enums.h"
|
||||
#include "SimulationComputePass.h"
|
||||
#include "SurfaceExtractPass.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
FluidSimulationView::FluidSimulationView(
|
||||
Gfx::PGraphics graphics, Seele::PWindow window,
|
||||
const Seele::ViewportCreateInfo &createInfo)
|
||||
: View(graphics, window, createInfo, "Fluid Simulation View") {
|
||||
camera = Component::Camera{};
|
||||
transform = Component::Transform{
|
||||
.transform = Math::Transform({0.0f, 0.0f, -5.0f}),
|
||||
};
|
||||
renderGraph.addPass(new SimulationComputePass(graphics));
|
||||
renderGraph.addPass(new SurfaceExtractPass(graphics));
|
||||
renderGraph.addPass(new FluidRenderPass(graphics));
|
||||
renderGraph.setViewport(viewport);
|
||||
renderGraph.createRenderPass();
|
||||
}
|
||||
|
||||
FluidSimulationView::~FluidSimulationView() {}
|
||||
|
||||
void FluidSimulationView::beginUpdate() {}
|
||||
|
||||
void FluidSimulationView::update() {}
|
||||
|
||||
void FluidSimulationView::commitUpdate() {}
|
||||
|
||||
void FluidSimulationView::prepareRender() {}
|
||||
|
||||
void FluidSimulationView::render() { renderGraph.render(camera, transform); }
|
||||
|
||||
void FluidSimulationView::applyArea(Seele::URect area) {}
|
||||
|
||||
void FluidSimulationView::keyCallback(Seele::KeyCode code,
|
||||
Seele::InputAction action,
|
||||
Seele::KeyModifierFlags modifier) {
|
||||
float cameraMove = static_cast<float>(Gfx::getCurrentFrameDelta()) * 4;
|
||||
if ((modifier & (uint32)KeyModifier::MOD_SHIFT)) {
|
||||
cameraMove *= 10;
|
||||
}
|
||||
Vector forward = transform.getForward();
|
||||
Vector side = transform.getRight();
|
||||
Vector moveVector = Vector();
|
||||
|
||||
if (code == KeyCode::KEY_J && action != InputAction::RELEASE) {
|
||||
std::cout << transform.getPosition() << std::endl;
|
||||
}
|
||||
|
||||
if (code == KeyCode::KEY_W && action != InputAction::RELEASE) {
|
||||
moveVector += forward * cameraMove;
|
||||
}
|
||||
if (code == KeyCode::KEY_S && action != InputAction::RELEASE) {
|
||||
moveVector += forward * -cameraMove;
|
||||
}
|
||||
if (code == KeyCode::KEY_A && action != InputAction::RELEASE) {
|
||||
moveVector += side * cameraMove;
|
||||
}
|
||||
if (code == KeyCode::KEY_D && action != InputAction::RELEASE) {
|
||||
moveVector += side * -cameraMove;
|
||||
}
|
||||
if (code == KeyCode::KEY_E && action != InputAction::RELEASE) {
|
||||
moveVector += Vector(0, cameraMove, 0);
|
||||
}
|
||||
if (code == KeyCode::KEY_Q && action != InputAction::RELEASE) {
|
||||
moveVector += Vector(0, -cameraMove, 0);
|
||||
}
|
||||
transform.translate(moveVector);
|
||||
}
|
||||
|
||||
void FluidSimulationView::mouseMoveCallback(double xPos, double yPos) {
|
||||
deltaX = xPos - mouseX;
|
||||
deltaY = yPos - mouseY;
|
||||
mouseX = xPos;
|
||||
mouseY = yPos;
|
||||
|
||||
if (buttonDown) {
|
||||
transform.setRotation(
|
||||
glm::rotate(transform.getRotation(), deltaX / 500, Vector(0, 1, 0)));
|
||||
transform.setRotation(glm::rotate(transform.getRotation(), -deltaY / 500,
|
||||
transform.getRight()));
|
||||
}
|
||||
}
|
||||
|
||||
void FluidSimulationView::mouseButtonCallback(
|
||||
Seele::MouseButton button, Seele::InputAction action,
|
||||
Seele::KeyModifierFlags modifier) {
|
||||
if(button == MouseButton::MOUSE_BUTTON_1) {
|
||||
buttonDown = action != InputAction::RELEASE;
|
||||
}
|
||||
}
|
||||
|
||||
void FluidSimulationView::scrollCallback(double xOffset, double yOffset) {}
|
||||
|
||||
void FluidSimulationView::fileCallback(int count, const char **paths) {}
|
||||
@@ -1,36 +0,0 @@
|
||||
#pragma once
|
||||
#include "Graphics/Enums.h"
|
||||
#include "Graphics/Initializer.h"
|
||||
#include "Graphics/RenderPass/RenderGraph.h"
|
||||
#include "Window/View.h"
|
||||
|
||||
class FluidSimulationView : public Seele::View {
|
||||
public:
|
||||
FluidSimulationView(Seele::Gfx::PGraphics graphics, Seele::PWindow window, const Seele::ViewportCreateInfo &createInfo);
|
||||
~FluidSimulationView() override;
|
||||
|
||||
virtual void beginUpdate() override;
|
||||
virtual void update() override;
|
||||
virtual void commitUpdate() override;
|
||||
|
||||
virtual void prepareRender() override;
|
||||
virtual void render() override;
|
||||
|
||||
protected:
|
||||
virtual void applyArea(Seele::URect area) override;
|
||||
virtual void keyCallback(Seele::KeyCode code, Seele::InputAction action, Seele::KeyModifierFlags modifier) override;
|
||||
virtual void mouseMoveCallback(double xPos, double yPos) override;
|
||||
virtual void mouseButtonCallback(Seele::MouseButton button, Seele::InputAction action, Seele::KeyModifierFlags modifier) override;
|
||||
virtual void scrollCallback(double xOffset, double yOffset) override;
|
||||
virtual void fileCallback(int count, const char **paths) override;
|
||||
|
||||
private:
|
||||
Seele::Component::Camera camera;
|
||||
Seele::Component::Transform transform;
|
||||
Seele::RenderGraph renderGraph;
|
||||
float deltaX;
|
||||
float deltaY;
|
||||
float mouseX;
|
||||
float mouseY;
|
||||
bool buttonDown = false;
|
||||
};
|
||||
@@ -1,748 +0,0 @@
|
||||
#include "SimulationComputePass.h"
|
||||
#include "Common.h"
|
||||
#include "Graphics/Buffer.h"
|
||||
#include "Graphics/Command.h"
|
||||
#include "Graphics/Descriptor.h"
|
||||
#include "Graphics/Enums.h"
|
||||
#include "Graphics/Graphics.h"
|
||||
#include "Graphics/Initializer.h"
|
||||
#include "Graphics/Shader.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
|
||||
constexpr static int reinitInterval = 5;
|
||||
constexpr static int reinitIterations = 5;
|
||||
constexpr static float reinitDtau = 0.5f;
|
||||
|
||||
#define SWAP(a, b) \
|
||||
{ \
|
||||
auto temp = std::move(a); \
|
||||
a = std::move(b); \
|
||||
b = std::move(temp); \
|
||||
}
|
||||
|
||||
SimulationComputePass::SimulationComputePass(Seele::Gfx::PGraphics graphics)
|
||||
: RenderPass(graphics) {
|
||||
{
|
||||
setBounds.pipelineLayout =
|
||||
graphics->createPipelineLayout("SetBoundsPipelineLayout");
|
||||
setBounds.descriptorLayout = graphics->createDescriptorLayout("params");
|
||||
setBounds.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.name = "b",
|
||||
.uniformLength = sizeof(int),
|
||||
});
|
||||
setBounds.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.name = "grid",
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
});
|
||||
setBounds.descriptorLayout->create();
|
||||
setBounds.pipelineLayout->addDescriptorLayout(setBounds.descriptorLayout);
|
||||
graphics->beginShaderCompilation(ShaderCompilationInfo{
|
||||
.name = "SetBound",
|
||||
.modules = {"SetBound"},
|
||||
.entryPoints = {{"setBound", "SetBound"},
|
||||
{"setBoundEdges", "SetBound"},
|
||||
{"setBoundCorners", "SetBound"}},
|
||||
.rootSignature = setBounds.pipelineLayout,
|
||||
});
|
||||
setBounds.pipelineLayout->create();
|
||||
setBounds.shader = graphics->createComputeShader({0});
|
||||
setBounds.shaderEdges = graphics->createComputeShader({1});
|
||||
setBounds.shaderCorners = graphics->createComputeShader({2});
|
||||
setBounds.pipeline =
|
||||
graphics->createComputePipeline(Gfx::ComputePipelineCreateInfo{
|
||||
.computeShader = setBounds.shader,
|
||||
.pipelineLayout = setBounds.pipelineLayout,
|
||||
});
|
||||
setBounds.pipelineEdges =
|
||||
graphics->createComputePipeline(Gfx::ComputePipelineCreateInfo{
|
||||
.computeShader = setBounds.shaderEdges,
|
||||
.pipelineLayout = setBounds.pipelineLayout,
|
||||
});
|
||||
setBounds.pipelineCorners =
|
||||
graphics->createComputePipeline(Gfx::ComputePipelineCreateInfo{
|
||||
.computeShader = setBounds.shaderCorners,
|
||||
.pipelineLayout = setBounds.pipelineLayout,
|
||||
});
|
||||
}
|
||||
{
|
||||
linearSolve.pipelineLayout =
|
||||
graphics->createPipelineLayout("LinearSolvePipelineLayout");
|
||||
linearSolve.descriptorLayout = graphics->createDescriptorLayout("params");
|
||||
linearSolve.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.name = "a",
|
||||
.uniformLength = sizeof(float),
|
||||
});
|
||||
linearSolve.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.name = "c",
|
||||
.uniformLength = sizeof(float),
|
||||
});
|
||||
linearSolve.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.name = "next",
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
});
|
||||
linearSolve.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.name = "current",
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
});
|
||||
linearSolve.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.name = "grid0",
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
});
|
||||
linearSolve.descriptorLayout->create();
|
||||
linearSolve.pipelineLayout->addDescriptorLayout(
|
||||
linearSolve.descriptorLayout);
|
||||
graphics->beginShaderCompilation(ShaderCompilationInfo{
|
||||
.name = "LinearSolve",
|
||||
.modules = {"LinearSolve"},
|
||||
.entryPoints = {{"linearSolve", "LinearSolve"}},
|
||||
.rootSignature = linearSolve.pipelineLayout,
|
||||
});
|
||||
linearSolve.pipelineLayout->create();
|
||||
linearSolve.shader = graphics->createComputeShader({0});
|
||||
linearSolve.pipeline =
|
||||
graphics->createComputePipeline(Gfx::ComputePipelineCreateInfo{
|
||||
.computeShader = linearSolve.shader,
|
||||
.pipelineLayout = linearSolve.pipelineLayout,
|
||||
});
|
||||
}
|
||||
{
|
||||
computeDivergence.pipelineLayout =
|
||||
graphics->createPipelineLayout("ComputeDivergencePipelineLayout");
|
||||
computeDivergence.descriptorLayout =
|
||||
graphics->createDescriptorLayout("params");
|
||||
computeDivergence.descriptorLayout->addDescriptorBinding(
|
||||
Gfx::DescriptorBinding{
|
||||
.name = "velocityX",
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
});
|
||||
computeDivergence.descriptorLayout->addDescriptorBinding(
|
||||
Gfx::DescriptorBinding{
|
||||
.name = "velocityY",
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
});
|
||||
computeDivergence.descriptorLayout->addDescriptorBinding(
|
||||
Gfx::DescriptorBinding{
|
||||
.name = "velocityZ",
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
});
|
||||
computeDivergence.descriptorLayout->addDescriptorBinding(
|
||||
Gfx::DescriptorBinding{
|
||||
.name = "divergence",
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
});
|
||||
computeDivergence.descriptorLayout->addDescriptorBinding(
|
||||
Gfx::DescriptorBinding{
|
||||
.name = "pressure",
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
});
|
||||
computeDivergence.descriptorLayout->create();
|
||||
computeDivergence.pipelineLayout->addDescriptorLayout(
|
||||
computeDivergence.descriptorLayout);
|
||||
graphics->beginShaderCompilation(ShaderCompilationInfo{
|
||||
.name = "Divergence",
|
||||
.modules = {"Divergence"},
|
||||
.entryPoints = {{"computeDivergence", "Divergence"}},
|
||||
.rootSignature = computeDivergence.pipelineLayout,
|
||||
});
|
||||
computeDivergence.pipelineLayout->create();
|
||||
|
||||
computeDivergence.shader = graphics->createComputeShader({0});
|
||||
computeDivergence.pipeline =
|
||||
graphics->createComputePipeline(Gfx::ComputePipelineCreateInfo{
|
||||
.computeShader = computeDivergence.shader,
|
||||
.pipelineLayout = computeDivergence.pipelineLayout,
|
||||
});
|
||||
}
|
||||
{
|
||||
project.pipelineLayout =
|
||||
graphics->createPipelineLayout("ProjectPipelineLayout");
|
||||
project.descriptorLayout = graphics->createDescriptorLayout("params");
|
||||
project.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.name = "velocityX",
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
});
|
||||
project.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.name = "velocityY",
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
});
|
||||
project.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.name = "velocityZ",
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
});
|
||||
project.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.name = "pressure",
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
});
|
||||
project.descriptorLayout->create();
|
||||
project.pipelineLayout->addDescriptorLayout(project.descriptorLayout);
|
||||
graphics->beginShaderCompilation(ShaderCompilationInfo{
|
||||
.name = "Project",
|
||||
.modules = {"Project"},
|
||||
.entryPoints = {{"project", "Project"}},
|
||||
.rootSignature = project.pipelineLayout,
|
||||
});
|
||||
project.pipelineLayout->create();
|
||||
project.shader = graphics->createComputeShader({0});
|
||||
project.pipeline =
|
||||
graphics->createComputePipeline(Gfx::ComputePipelineCreateInfo{
|
||||
.computeShader = project.shader,
|
||||
.pipelineLayout = project.pipelineLayout,
|
||||
});
|
||||
}
|
||||
{
|
||||
advect.pipelineLayout =
|
||||
graphics->createPipelineLayout("AdvectPipelineLayout");
|
||||
advect.descriptorLayout = graphics->createDescriptorLayout("params");
|
||||
advect.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.name = "density",
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
});
|
||||
advect.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.name = "density0",
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
});
|
||||
advect.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.name = "velocityX",
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
});
|
||||
advect.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.name = "velocityY",
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
});
|
||||
advect.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.name = "velocityZ",
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
});
|
||||
advect.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.name = "dt",
|
||||
.uniformLength = sizeof(float),
|
||||
});
|
||||
advect.descriptorLayout->create();
|
||||
advect.pipelineLayout->addDescriptorLayout(advect.descriptorLayout);
|
||||
graphics->beginShaderCompilation(ShaderCompilationInfo{
|
||||
.name = "Advect",
|
||||
.modules = {"Advect"},
|
||||
.entryPoints = {{"advect", "Advect"}},
|
||||
.rootSignature = advect.pipelineLayout,
|
||||
});
|
||||
advect.pipelineLayout->create();
|
||||
|
||||
advect.shader = graphics->createComputeShader({0});
|
||||
advect.pipeline =
|
||||
graphics->createComputePipeline(Gfx::ComputePipelineCreateInfo{
|
||||
.computeShader = advect.shader,
|
||||
.pipelineLayout = advect.pipelineLayout,
|
||||
});
|
||||
}
|
||||
{
|
||||
reinitialize.pipelineLayout =
|
||||
graphics->createPipelineLayout("ReinitializePipelineLayout");
|
||||
reinitialize.descriptorLayout =
|
||||
graphics->createDescriptorLayout("params");
|
||||
reinitialize.descriptorLayout->addDescriptorBinding(
|
||||
Gfx::DescriptorBinding{
|
||||
.name = "dtau",
|
||||
.uniformLength = sizeof(float),
|
||||
});
|
||||
reinitialize.descriptorLayout->addDescriptorBinding(
|
||||
Gfx::DescriptorBinding{
|
||||
.name = "phi",
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
});
|
||||
reinitialize.descriptorLayout->addDescriptorBinding(
|
||||
Gfx::DescriptorBinding{
|
||||
.name = "phi0",
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
});
|
||||
reinitialize.descriptorLayout->create();
|
||||
reinitialize.pipelineLayout->addDescriptorLayout(
|
||||
reinitialize.descriptorLayout);
|
||||
|
||||
graphics->beginShaderCompilation(ShaderCompilationInfo{
|
||||
.name = "SignedDistance",
|
||||
.modules = {"SignedDistance"},
|
||||
.entryPoints = {{"reinitialize", "SignedDistance"}},
|
||||
.rootSignature = reinitialize.pipelineLayout,
|
||||
});
|
||||
reinitialize.pipelineLayout->create();
|
||||
reinitialize.shader = graphics->createComputeShader({0});
|
||||
reinitialize.pipeline =
|
||||
graphics->createComputePipeline(Gfx::ComputePipelineCreateInfo{
|
||||
.computeShader = reinitialize.shader,
|
||||
.pipelineLayout = reinitialize.pipelineLayout,
|
||||
});
|
||||
}
|
||||
|
||||
uint64_t bufferSize = gridSize * gridSize * gridSize * 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 halfGrid = static_cast<float>(gridSize) * 0.5f;
|
||||
float radius = static_cast<float>(gridSize) * 0.2f;
|
||||
// Place sphere center in the lower portion of the grid
|
||||
float cx = halfGrid;
|
||||
float cy = halfGrid;
|
||||
float cz = static_cast<float>(gridSize) * 0.3f;
|
||||
for (uint32 z = 1; z < gridSize - 1; ++z) {
|
||||
for (uint32 y = 1; y < gridSize - 1; ++y) {
|
||||
for (uint32 x = 1; x < gridSize - 1; ++x) {
|
||||
uint32 idx = x + gridSize * y + gridSize * gridSize * 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
phiBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||
.sourceData =
|
||||
{
|
||||
.size = bufferSize,
|
||||
},
|
||||
.name = "PhiBuffer",
|
||||
});
|
||||
phi0Buffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||
.sourceData =
|
||||
{
|
||||
.size = bufferSize,
|
||||
.data = (uint8 *)initialPhi.data(),
|
||||
},
|
||||
.name = "Phi0Buffer",
|
||||
});
|
||||
densityBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||
.sourceData =
|
||||
{
|
||||
.size = bufferSize,
|
||||
},
|
||||
.name = "DensityBuffer",
|
||||
});
|
||||
scratchBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||
.sourceData =
|
||||
{
|
||||
.size = bufferSize,
|
||||
},
|
||||
.name = "ScratchBuffer",
|
||||
});
|
||||
density0Buffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||
.sourceData =
|
||||
{
|
||||
.size = bufferSize,
|
||||
.data = (uint8 *)initialDensity.data(),
|
||||
},
|
||||
.name = "Density0Buffer",
|
||||
});
|
||||
velocityXNextBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||
.sourceData =
|
||||
{
|
||||
.size = bufferSize,
|
||||
},
|
||||
.name = "VelocityXNextBuffer",
|
||||
});
|
||||
velocityYNextBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||
.sourceData =
|
||||
{
|
||||
.size = bufferSize,
|
||||
},
|
||||
.name = "VelocityYNextBuffer",
|
||||
});
|
||||
velocityZNextBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||
.sourceData =
|
||||
{
|
||||
.size = bufferSize,
|
||||
},
|
||||
.name = "VelocityZNextBuffer",
|
||||
});
|
||||
velocityXBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||
.sourceData =
|
||||
{
|
||||
.size = bufferSize,
|
||||
},
|
||||
.name = "VelocityXBuffer",
|
||||
});
|
||||
velocityYBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||
.sourceData =
|
||||
{
|
||||
.size = bufferSize,
|
||||
},
|
||||
.name = "VelocityYBuffer",
|
||||
});
|
||||
velocityZBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||
.sourceData =
|
||||
{
|
||||
.size = bufferSize,
|
||||
},
|
||||
.name = "VelocityZBuffer",
|
||||
});
|
||||
velocityX0Buffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||
.sourceData =
|
||||
{
|
||||
.size = bufferSize,
|
||||
.data = (uint8 *)initialVelocityX.data(),
|
||||
},
|
||||
.name = "VelocityX0Buffer",
|
||||
});
|
||||
velocityY0Buffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||
.sourceData =
|
||||
{
|
||||
.size = bufferSize,
|
||||
.data = (uint8 *)initialVelocityY.data(),
|
||||
},
|
||||
.name = "VelocityY0Buffer",
|
||||
});
|
||||
velocityZ0Buffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||
.sourceData =
|
||||
{
|
||||
.size = bufferSize,
|
||||
.data = (uint8 *)initialVelocityZ.data(),
|
||||
},
|
||||
.name = "VelocityZ0Buffer",
|
||||
});
|
||||
}
|
||||
|
||||
SimulationComputePass::~SimulationComputePass() {}
|
||||
|
||||
void SimulationComputePass::beginFrame(
|
||||
const Seele::Component::Camera &camera,
|
||||
const Seele::Component::Transform &transform) {
|
||||
setBounds.descriptorLayout->reset();
|
||||
linearSolve.descriptorLayout->reset();
|
||||
computeDivergence.descriptorLayout->reset();
|
||||
project.descriptorLayout->reset();
|
||||
advect.descriptorLayout->reset();
|
||||
reinitialize.descriptorLayout->reset();
|
||||
}
|
||||
|
||||
void SimulationComputePass::render() {
|
||||
graphics->beginDebugRegion("Diffuse");
|
||||
for (uint iteration = 0; iteration < 4; ++iteration) {
|
||||
float a = dt * viscosity * (gridSize - 2) * (gridSize - 2) * (gridSize - 2);
|
||||
float c = 1 + 6 * a;
|
||||
linearSolvePass(velocityXNextBuffer, velocityXBuffer, velocityX0Buffer, a,
|
||||
c);
|
||||
linearSolvePass(velocityYNextBuffer, velocityYBuffer, velocityY0Buffer, a,
|
||||
c);
|
||||
linearSolvePass(velocityZNextBuffer, velocityZBuffer, velocityZ0Buffer, a,
|
||||
c);
|
||||
|
||||
setBoundsPass(velocityXNextBuffer, 1);
|
||||
setBoundsPass(velocityYNextBuffer, 2);
|
||||
setBoundsPass(velocityZNextBuffer, 3);
|
||||
|
||||
SWAP(velocityXBuffer, velocityXNextBuffer);
|
||||
SWAP(velocityYBuffer, velocityYNextBuffer);
|
||||
SWAP(velocityZBuffer, velocityZNextBuffer);
|
||||
}
|
||||
|
||||
SWAP(velocityX0Buffer, velocityXBuffer);
|
||||
SWAP(velocityY0Buffer, velocityYBuffer);
|
||||
SWAP(velocityZ0Buffer, velocityZBuffer);
|
||||
graphics->endDebugRegion();
|
||||
|
||||
graphics->beginDebugRegion("Project");
|
||||
Gfx::PShaderBuffer divergence = velocityXBuffer;
|
||||
Gfx::PShaderBuffer pressureCurrent = velocityYBuffer;
|
||||
Gfx::PShaderBuffer pressureNext = velocityZBuffer;
|
||||
divergencePass(divergence, pressureCurrent, velocityX0Buffer,
|
||||
velocityY0Buffer, velocityZ0Buffer);
|
||||
|
||||
for (int iteration = 0; iteration < 4; ++iteration) {
|
||||
linearSolvePass(pressureNext, pressureCurrent, divergence, 1, 6);
|
||||
|
||||
setBoundsPass(pressureNext, 0);
|
||||
|
||||
// swap pressure buffers
|
||||
SWAP(pressureCurrent, pressureNext);
|
||||
}
|
||||
|
||||
projectPass(velocityX0Buffer, velocityY0Buffer, velocityZ0Buffer,
|
||||
pressureCurrent);
|
||||
|
||||
setBoundsPass(velocityX0Buffer, 1);
|
||||
setBoundsPass(velocityY0Buffer, 2);
|
||||
setBoundsPass(velocityZ0Buffer, 3);
|
||||
graphics->endDebugRegion();
|
||||
|
||||
graphics->beginDebugRegion("Advect");
|
||||
advectPass(velocityXBuffer, velocityX0Buffer, velocityX0Buffer,
|
||||
velocityY0Buffer, velocityZ0Buffer, dt);
|
||||
advectPass(velocityYBuffer, velocityY0Buffer, velocityX0Buffer,
|
||||
velocityY0Buffer, velocityZ0Buffer, dt);
|
||||
advectPass(velocityZBuffer, velocityZ0Buffer, velocityX0Buffer,
|
||||
velocityY0Buffer, velocityZ0Buffer, dt);
|
||||
|
||||
setBoundsPass(velocityXBuffer, 1);
|
||||
setBoundsPass(velocityYBuffer, 2);
|
||||
setBoundsPass(velocityZBuffer, 3);
|
||||
graphics->endDebugRegion();
|
||||
|
||||
// swap velocity buffers
|
||||
SWAP(velocityX0Buffer, velocityXBuffer);
|
||||
SWAP(velocityY0Buffer, velocityYBuffer);
|
||||
SWAP(velocityZ0Buffer, velocityZBuffer);
|
||||
|
||||
// diffuse density
|
||||
graphics->beginDebugRegion("DiffuseDensity");
|
||||
Gfx::PShaderBuffer densityCurrent = densityBuffer;
|
||||
Gfx::PShaderBuffer densityNext = scratchBuffer;
|
||||
Gfx::PShaderBuffer density0 = density0Buffer;
|
||||
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 * diffusion * (gridSize - 2) * (gridSize - 2) * (gridSize - 2);
|
||||
float c = 1 + 6 * a;
|
||||
linearSolvePass(densityNext, densityCurrent, density0, a, c);
|
||||
setBoundsPass(densityNext, 0);
|
||||
SWAP(densityCurrent, densityNext);
|
||||
}
|
||||
graphics->endDebugRegion();
|
||||
graphics->beginDebugRegion("AdvectDensity");
|
||||
advectPass(density0Buffer, densityCurrent, velocityX0Buffer, velocityY0Buffer,
|
||||
velocityZ0Buffer, dt);
|
||||
setBoundsPass(density0Buffer, 0);
|
||||
graphics->endDebugRegion();
|
||||
|
||||
graphics->beginDebugRegion("AdvectLevelSet");
|
||||
advectPass(phiBuffer, phi0Buffer, velocityX0Buffer, velocityY0Buffer,
|
||||
velocityZ0Buffer, dt);
|
||||
setBoundsPass(phiBuffer, 0);
|
||||
|
||||
// Reinitialize level set every N frames to restore |grad phi| = 1
|
||||
if (frameCounter % reinitInterval == 0) {
|
||||
reinitializeLevelSetPass(phiBuffer, phi0Buffer);
|
||||
}
|
||||
++frameCounter;
|
||||
|
||||
phiBuffer->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);
|
||||
graphics->copyBuffer(phiBuffer, phi0Buffer);
|
||||
phi0Buffer->pipelineBarrier(
|
||||
Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
Gfx::SE_ACCESS_TRANSFER_READ_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT);
|
||||
graphics->endDebugRegion();
|
||||
}
|
||||
|
||||
void SimulationComputePass::endFrame() {}
|
||||
|
||||
void SimulationComputePass::publishOutputs() {
|
||||
resources->registerBufferOutput("PHI", phi0Buffer);
|
||||
}
|
||||
|
||||
void SimulationComputePass::createRenderPass() {}
|
||||
|
||||
void SimulationComputePass::setBoundsPass(Gfx::PShaderBuffer grid, int b) {
|
||||
Gfx::ODescriptorSet bounds =
|
||||
setBounds.descriptorLayout->allocateDescriptorSet();
|
||||
bounds->updateConstants("b", 0, &b);
|
||||
bounds->updateBuffer("grid", 0, grid);
|
||||
bounds->writeChanges();
|
||||
Gfx::OComputeCommand boundsCommand = graphics->createComputeCommand();
|
||||
boundsCommand->bindPipeline(setBounds.pipeline);
|
||||
boundsCommand->bindDescriptor(bounds);
|
||||
boundsCommand->dispatch(gridSize / setBounds.threadGroupSize.x,
|
||||
gridSize / setBounds.threadGroupSize.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,
|
||||
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
||||
|
||||
Gfx::OComputeCommand edgesCommand = graphics->createComputeCommand();
|
||||
edgesCommand->bindPipeline(setBounds.pipelineEdges);
|
||||
edgesCommand->bindDescriptor(bounds);
|
||||
edgesCommand->dispatch(gridSize / setBounds.threadGroupSize.x, 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,
|
||||
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
||||
|
||||
Gfx::OComputeCommand cornersCommand = graphics->createComputeCommand();
|
||||
cornersCommand->bindPipeline(setBounds.pipelineCorners);
|
||||
cornersCommand->bindDescriptor(bounds);
|
||||
cornersCommand->dispatch(1, 1, 1);
|
||||
graphics->executeCommands(std::move(cornersCommand));
|
||||
|
||||
grid->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::linearSolvePass(Gfx::PShaderBuffer next,
|
||||
Gfx::PShaderBuffer current,
|
||||
Gfx::PShaderBuffer grid0, float a,
|
||||
float c) {
|
||||
Gfx::ODescriptorSet solve =
|
||||
linearSolve.descriptorLayout->allocateDescriptorSet();
|
||||
solve->updateBuffer("next", 0, next);
|
||||
solve->updateBuffer("current", 0, current);
|
||||
solve->updateBuffer("grid0", 0, grid0);
|
||||
solve->updateConstants("a", 0, &a);
|
||||
solve->updateConstants("c", 0, &c);
|
||||
solve->writeChanges();
|
||||
Gfx::OComputeCommand solveCommand = graphics->createComputeCommand();
|
||||
solveCommand->bindPipeline(linearSolve.pipeline);
|
||||
solveCommand->bindDescriptor(solve);
|
||||
solveCommand->dispatch(gridSize / linearSolve.threadGroupSize.x,
|
||||
gridSize / linearSolve.threadGroupSize.y,
|
||||
gridSize / linearSolve.threadGroupSize.z);
|
||||
graphics->executeCommands(std::move(solveCommand));
|
||||
|
||||
next->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::divergencePass(
|
||||
Seele::Gfx::PShaderBuffer divergence, Seele::Gfx::PShaderBuffer pressure,
|
||||
Seele::Gfx::PShaderBuffer velocityX, Seele::Gfx::PShaderBuffer velocityY,
|
||||
Seele::Gfx::PShaderBuffer velocityZ) {
|
||||
Gfx::ODescriptorSet divergenceSet =
|
||||
computeDivergence.descriptorLayout->allocateDescriptorSet();
|
||||
divergenceSet->updateBuffer("velocityX", 0, velocityX);
|
||||
divergenceSet->updateBuffer("velocityY", 0, velocityY);
|
||||
divergenceSet->updateBuffer("velocityZ", 0, velocityZ);
|
||||
divergenceSet->updateBuffer("divergence", 0, divergence);
|
||||
divergenceSet->updateBuffer("pressure", 0, pressure);
|
||||
divergenceSet->writeChanges();
|
||||
Gfx::OComputeCommand divergenceCommand = graphics->createComputeCommand();
|
||||
divergenceCommand->bindPipeline(computeDivergence.pipeline);
|
||||
divergenceCommand->bindDescriptor(divergenceSet);
|
||||
divergenceCommand->dispatch(gridSize / computeDivergence.threadGroupSize.x,
|
||||
gridSize / computeDivergence.threadGroupSize.y,
|
||||
gridSize / computeDivergence.threadGroupSize.z);
|
||||
graphics->executeCommands(std::move(divergenceCommand));
|
||||
// divergence is now in velocityXBuffer, pressure is in velocityYBuffer
|
||||
divergence->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);
|
||||
pressure->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::projectPass(Seele::Gfx::PShaderBuffer velocityX,
|
||||
Seele::Gfx::PShaderBuffer velocityY,
|
||||
Seele::Gfx::PShaderBuffer velocityZ,
|
||||
Seele::Gfx::PShaderBuffer pressure) {
|
||||
Gfx::ODescriptorSet projectSet =
|
||||
project.descriptorLayout->allocateDescriptorSet();
|
||||
projectSet->updateBuffer("velocityX", 0, velocityX);
|
||||
projectSet->updateBuffer("velocityY", 0, velocityY);
|
||||
projectSet->updateBuffer("velocityZ", 0, velocityZ);
|
||||
projectSet->updateBuffer("pressure", 0, pressure);
|
||||
projectSet->writeChanges();
|
||||
Gfx::OComputeCommand projectCommand = graphics->createComputeCommand();
|
||||
projectCommand->bindPipeline(project.pipeline);
|
||||
projectCommand->bindDescriptor(projectSet);
|
||||
projectCommand->dispatch(gridSize / project.threadGroupSize.x,
|
||||
gridSize / project.threadGroupSize.y,
|
||||
gridSize / project.threadGroupSize.z);
|
||||
graphics->executeCommands(std::move(projectCommand));
|
||||
|
||||
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::advectPass(Gfx::PShaderBuffer quantity,
|
||||
Gfx::PShaderBuffer quantity0,
|
||||
Gfx::PShaderBuffer velocityX,
|
||||
Gfx::PShaderBuffer velocityY,
|
||||
Gfx::PShaderBuffer velocityZ, float dt) {
|
||||
Gfx::ODescriptorSet advectSet =
|
||||
this->advect.descriptorLayout->allocateDescriptorSet();
|
||||
advectSet->updateBuffer("density", 0, quantity);
|
||||
advectSet->updateBuffer("density0", 0, quantity0);
|
||||
advectSet->updateBuffer("velocityX", 0, velocityX);
|
||||
advectSet->updateBuffer("velocityY", 0, velocityY);
|
||||
advectSet->updateBuffer("velocityZ", 0, velocityZ);
|
||||
advectSet->updateConstants("dt", 0, &dt);
|
||||
advectSet->writeChanges();
|
||||
Gfx::OComputeCommand advectCommand = graphics->createComputeCommand();
|
||||
advectCommand->bindPipeline(advect.pipeline);
|
||||
advectCommand->bindDescriptor(advectSet);
|
||||
advectCommand->dispatch(gridSize / advect.threadGroupSize.x,
|
||||
gridSize / advect.threadGroupSize.y,
|
||||
gridSize / advect.threadGroupSize.z);
|
||||
graphics->executeCommands(std::move(advectCommand));
|
||||
|
||||
quantity->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) {
|
||||
graphics->beginDebugRegion("ReinitializeLevelSet");
|
||||
// Snapshot current phi into phi0 for the sign function
|
||||
phi->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);
|
||||
graphics->copyBuffer(phi, phi0);
|
||||
phi0->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);
|
||||
phi->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_READ_BIT,
|
||||
Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
Gfx::SE_ACCESS_SHADER_READ_BIT | Gfx::SE_ACCESS_SHADER_WRITE_BIT,
|
||||
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
||||
|
||||
float dtau = reinitDtau;
|
||||
for (int i = 0; i < reinitIterations; ++i) {
|
||||
Gfx::ODescriptorSet reinitSet =
|
||||
reinitialize.descriptorLayout->allocateDescriptorSet();
|
||||
reinitSet->updateConstants("dtau", 0, &dtau);
|
||||
reinitSet->updateBuffer("phi", 0, phi);
|
||||
reinitSet->updateBuffer("phi0", 0, phi0);
|
||||
reinitSet->writeChanges();
|
||||
Gfx::OComputeCommand reinitCommand = graphics->createComputeCommand();
|
||||
reinitCommand->bindPipeline(reinitialize.pipeline);
|
||||
reinitCommand->bindDescriptor(reinitSet);
|
||||
reinitCommand->dispatch(gridSize / reinitialize.threadGroupSize.x,
|
||||
gridSize / reinitialize.threadGroupSize.y,
|
||||
gridSize / reinitialize.threadGroupSize.z);
|
||||
graphics->executeCommands(std::move(reinitCommand));
|
||||
|
||||
phi->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);
|
||||
setBoundsPass(phi, 0);
|
||||
SWAP(phi, phi0);
|
||||
}
|
||||
graphics->endDebugRegion();
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
#pragma once
|
||||
#include "Graphics/Buffer.h"
|
||||
#include "Graphics/Descriptor.h"
|
||||
#include "Graphics/Initializer.h"
|
||||
#include "Graphics/RenderPass/RenderPass.h"
|
||||
#include "Graphics/Resources.h"
|
||||
#include <sys/types.h>
|
||||
|
||||
class SimulationComputePass : public Seele::RenderPass {
|
||||
public:
|
||||
SimulationComputePass(Seele::Gfx::PGraphics graphics);
|
||||
virtual ~SimulationComputePass() override;
|
||||
virtual void beginFrame(const Seele::Component::Camera &camera, const Seele::Component::Transform &transform) override;
|
||||
virtual void render() override;
|
||||
virtual void endFrame() override;
|
||||
virtual void publishOutputs() override;
|
||||
virtual void createRenderPass() override;
|
||||
|
||||
private:
|
||||
void setBoundsPass(Seele::Gfx::PShaderBuffer buffer, int b);
|
||||
void linearSolvePass(Seele::Gfx::PShaderBuffer next, Seele::Gfx::PShaderBuffer current, Seele::Gfx::PShaderBuffer grid0, float a, float c);
|
||||
void divergencePass(Seele::Gfx::PShaderBuffer divergence, Seele::Gfx::PShaderBuffer pressure, Seele::Gfx::PShaderBuffer velocityX, Seele::Gfx::PShaderBuffer velocityY, Seele::Gfx::PShaderBuffer velocityZ);
|
||||
void projectPass(Seele::Gfx::PShaderBuffer velocityX, Seele::Gfx::PShaderBuffer velocityY, Seele::Gfx::PShaderBuffer velocityZ, Seele::Gfx::PShaderBuffer pressure);
|
||||
void advectPass(Seele::Gfx::PShaderBuffer quantity, Seele::Gfx::PShaderBuffer quantity0, Seele::Gfx::PShaderBuffer velocityX, Seele::Gfx::PShaderBuffer velocityY, Seele::Gfx::PShaderBuffer velocityZ, float dt);
|
||||
void reinitializeLevelSetPass(Seele::Gfx::PShaderBuffer phi, Seele::Gfx::PShaderBuffer phi0);
|
||||
struct SetBounds
|
||||
{
|
||||
Seele::Gfx::OPipelineLayout pipelineLayout;
|
||||
Seele::Gfx::ODescriptorLayout descriptorLayout;
|
||||
Seele::Gfx::OComputeShader shader;
|
||||
Seele::Gfx::PComputePipeline pipeline;
|
||||
Seele::Gfx::OComputeShader shaderEdges;
|
||||
Seele::Gfx::PComputePipeline pipelineEdges;
|
||||
Seele::Gfx::OComputeShader shaderCorners;
|
||||
Seele::Gfx::PComputePipeline pipelineCorners;
|
||||
constexpr static Seele::UVector threadGroupSize = {32, 8, 1};
|
||||
} setBounds;
|
||||
struct LinearSolve
|
||||
{
|
||||
Seele::Gfx::OPipelineLayout pipelineLayout;
|
||||
Seele::Gfx::ODescriptorLayout descriptorLayout;
|
||||
Seele::Gfx::OComputeShader shader;
|
||||
Seele::Gfx::PComputePipeline pipeline;
|
||||
constexpr static Seele::UVector threadGroupSize = {32, 8, 1};
|
||||
} linearSolve;
|
||||
struct ComputeDivergence
|
||||
{
|
||||
Seele::Gfx::OPipelineLayout pipelineLayout;
|
||||
Seele::Gfx::ODescriptorLayout descriptorLayout;
|
||||
Seele::Gfx::OComputeShader shader;
|
||||
Seele::Gfx::PComputePipeline pipeline;
|
||||
constexpr static Seele::UVector threadGroupSize = {32, 8, 1};
|
||||
} computeDivergence;
|
||||
struct Project
|
||||
{
|
||||
Seele::Gfx::OPipelineLayout pipelineLayout;
|
||||
Seele::Gfx::ODescriptorLayout descriptorLayout;
|
||||
Seele::Gfx::OComputeShader shader;
|
||||
Seele::Gfx::PComputePipeline pipeline;
|
||||
constexpr static Seele::UVector threadGroupSize = {32, 8, 1};
|
||||
} project;
|
||||
struct Advect
|
||||
{
|
||||
Seele::Gfx::OPipelineLayout pipelineLayout;
|
||||
Seele::Gfx::ODescriptorLayout descriptorLayout;
|
||||
Seele::Gfx::OComputeShader shader;
|
||||
Seele::Gfx::PComputePipeline pipeline;
|
||||
constexpr static Seele::UVector threadGroupSize = {32, 8, 1};
|
||||
} advect;
|
||||
struct Reinitialize
|
||||
{
|
||||
Seele::Gfx::OPipelineLayout pipelineLayout;
|
||||
Seele::Gfx::ODescriptorLayout descriptorLayout;
|
||||
Seele::Gfx::OComputeShader shader;
|
||||
Seele::Gfx::PComputePipeline pipeline;
|
||||
constexpr static Seele::UVector threadGroupSize = {32, 8, 1};
|
||||
} reinitialize;
|
||||
Seele::Gfx::OShaderBuffer phiBuffer;
|
||||
Seele::Gfx::OShaderBuffer phi0Buffer;
|
||||
Seele::Gfx::OShaderBuffer densityBuffer;
|
||||
Seele::Gfx::OShaderBuffer scratchBuffer;
|
||||
Seele::Gfx::OShaderBuffer density0Buffer;
|
||||
Seele::Gfx::OShaderBuffer velocityXNextBuffer;
|
||||
Seele::Gfx::OShaderBuffer velocityYNextBuffer;
|
||||
Seele::Gfx::OShaderBuffer velocityZNextBuffer;
|
||||
Seele::Gfx::OShaderBuffer velocityXBuffer;
|
||||
Seele::Gfx::OShaderBuffer velocityYBuffer;
|
||||
Seele::Gfx::OShaderBuffer velocityZBuffer;
|
||||
Seele::Gfx::OShaderBuffer velocityX0Buffer;
|
||||
Seele::Gfx::OShaderBuffer velocityY0Buffer;
|
||||
Seele::Gfx::OShaderBuffer velocityZ0Buffer;
|
||||
uint32 frameCounter = 0;
|
||||
};
|
||||
DEFINE_REF(SimulationComputePass)
|
||||
@@ -1,502 +0,0 @@
|
||||
#include "SurfaceExtractPass.h"
|
||||
#include "Common.h"
|
||||
#include "Graphics/Enums.h"
|
||||
#include "Graphics/Graphics.h"
|
||||
#include "Math/Vector.h"
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
// 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 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 int 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
|
||||
|
||||
// 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(Seele::Gfx::PGraphics graphics)
|
||||
: RenderPass(graphics) {
|
||||
vertexBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||
.name = "SurfaceExtractVertexBuffer",
|
||||
});
|
||||
indexBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||
.name = "SurfaceExtractIndexBuffer",
|
||||
});
|
||||
surfaceCounts = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||
.sourceData =
|
||||
{
|
||||
.size = sizeof(uint32) * 4,
|
||||
},
|
||||
.numElements = 4,
|
||||
.usage = Gfx::SE_BUFFER_USAGE_INDIRECT_BUFFER_BIT,
|
||||
.name = "SurfaceExtractCountsBuffer",
|
||||
});
|
||||
}
|
||||
|
||||
SurfaceExtractPass::~SurfaceExtractPass() {}
|
||||
|
||||
void SurfaceExtractPass::beginFrame(
|
||||
const Seele::Component::Camera &camera,
|
||||
const Seele::Component::Transform &transform) {}
|
||||
|
||||
void SurfaceExtractPass::render() {
|
||||
Array<float> levelSet(gridSize * gridSize * gridSize);
|
||||
phiBuffer->readContents(0, levelSet.size() * sizeof(float),
|
||||
levelSet.data());
|
||||
|
||||
Array<Vector> vertices;
|
||||
Array<uint32> indices;
|
||||
vertices.reserve(1024);
|
||||
indices.reserve(1024);
|
||||
|
||||
const float isolevel = 0.0f;
|
||||
const float cellSize = 1.0f / static_cast<float>(gridSize);
|
||||
|
||||
// Helper to sample the level set with bounds checking
|
||||
auto sample = [&](uint32 x, uint32 y, uint32 z) -> float {
|
||||
return levelSet[z * gridSize * gridSize + y * gridSize + x];
|
||||
};
|
||||
|
||||
// Helper to compute world-space position from grid coordinates
|
||||
auto gridPos = [&](uint32 x, uint32 y, uint32 z) -> Vector {
|
||||
return Vector(static_cast<float>(x) * cellSize,
|
||||
static_cast<float>(y) * cellSize,
|
||||
static_cast<float>(z) * cellSize);
|
||||
};
|
||||
|
||||
// Marching Cubes: iterate over all cells in the grid
|
||||
for (uint32 z = 1; z < gridSize - 2; ++z) {
|
||||
for (uint32 y = 1; y < gridSize - 2; ++y) {
|
||||
for (uint32 x = 1; x < gridSize - 2; ++x) {
|
||||
// Fetch the 8 corner values of this cell
|
||||
float val[8];
|
||||
val[0] = sample(x, y, z);
|
||||
val[1] = sample(x + 1, y, z);
|
||||
val[2] = sample(x + 1, y + 1, z);
|
||||
val[3] = sample(x, y + 1, z);
|
||||
val[4] = sample(x, y, z + 1);
|
||||
val[5] = sample(x + 1, y, z + 1);
|
||||
val[6] = sample(x + 1, y + 1, z + 1);
|
||||
val[7] = sample(x, y + 1, z + 1);
|
||||
|
||||
// Determine the cube index based on which corners are inside
|
||||
uint32 cubeIndex = 0;
|
||||
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;
|
||||
|
||||
// Skip if entirely inside or outside
|
||||
if (edgeTable[cubeIndex] == 0)
|
||||
continue;
|
||||
|
||||
// Compute the 8 corner positions
|
||||
Vector 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);
|
||||
|
||||
// Interpolate vertices along the 12 edges where the surface crosses
|
||||
Vector vertList[12];
|
||||
if (edgeTable[cubeIndex] & 1)
|
||||
vertList[0] = vertexInterp(isolevel, pos[0], pos[1], val[0], val[1]);
|
||||
if (edgeTable[cubeIndex] & 2)
|
||||
vertList[1] = vertexInterp(isolevel, pos[1], pos[2], val[1], val[2]);
|
||||
if (edgeTable[cubeIndex] & 4)
|
||||
vertList[2] = vertexInterp(isolevel, pos[2], pos[3], val[2], val[3]);
|
||||
if (edgeTable[cubeIndex] & 8)
|
||||
vertList[3] = vertexInterp(isolevel, pos[3], pos[0], val[3], val[0]);
|
||||
if (edgeTable[cubeIndex] & 16)
|
||||
vertList[4] = vertexInterp(isolevel, pos[4], pos[5], val[4], val[5]);
|
||||
if (edgeTable[cubeIndex] & 32)
|
||||
vertList[5] = vertexInterp(isolevel, pos[5], pos[6], val[5], val[6]);
|
||||
if (edgeTable[cubeIndex] & 64)
|
||||
vertList[6] = vertexInterp(isolevel, pos[6], pos[7], val[6], val[7]);
|
||||
if (edgeTable[cubeIndex] & 128)
|
||||
vertList[7] = vertexInterp(isolevel, pos[7], pos[4], val[7], val[4]);
|
||||
if (edgeTable[cubeIndex] & 256)
|
||||
vertList[8] = vertexInterp(isolevel, pos[0], pos[4], val[0], val[4]);
|
||||
if (edgeTable[cubeIndex] & 512)
|
||||
vertList[9] = vertexInterp(isolevel, pos[1], pos[5], val[1], val[5]);
|
||||
if (edgeTable[cubeIndex] & 1024)
|
||||
vertList[10] = vertexInterp(isolevel, pos[2], pos[6], val[2], val[6]);
|
||||
if (edgeTable[cubeIndex] & 2048)
|
||||
vertList[11] = vertexInterp(isolevel, pos[3], pos[7], val[3], val[7]);
|
||||
|
||||
// Emit triangles from the triangle table
|
||||
for (int i = 0; triTable[cubeIndex][i] != -1; i += 3) {
|
||||
uint32 base = static_cast<uint32>(vertices.size());
|
||||
vertices.add(vertList[triTable[cubeIndex][i]]);
|
||||
vertices.add(vertList[triTable[cubeIndex][i + 1]]);
|
||||
vertices.add(vertList[triTable[cubeIndex][i + 2]]);
|
||||
indices.add(base);
|
||||
indices.add(base + 1);
|
||||
indices.add(base + 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32 counts[4] = {
|
||||
static_cast<uint32>(indices.size()), // index count
|
||||
1, // instance count
|
||||
0, // first index
|
||||
0, // first instance
|
||||
};
|
||||
|
||||
const uint64 vertexBytes = std::max<uint64>(
|
||||
1, static_cast<uint64>(vertices.size()) * sizeof(Vector));
|
||||
const uint64 indexBytes =
|
||||
std::max<uint64>(1, static_cast<uint64>(indices.size()) * sizeof(uint32));
|
||||
|
||||
vertexBuffer->rotateBuffer(vertexBytes, false);
|
||||
indexBuffer->rotateBuffer(indexBytes, false);
|
||||
surfaceCounts->rotateBuffer(sizeof(counts), false);
|
||||
|
||||
if (!vertices.empty()) {
|
||||
vertexBuffer->updateContents(0, vertices.size() * sizeof(Vector),
|
||||
vertices.data());
|
||||
vertexBuffer->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_WRITE_BIT,
|
||||
Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
Gfx::SE_ACCESS_SHADER_READ_BIT,
|
||||
Gfx::SE_PIPELINE_STAGE_VERTEX_SHADER_BIT);
|
||||
}
|
||||
if (!indices.empty()) {
|
||||
indexBuffer->updateContents(0, indices.size() * sizeof(uint32),
|
||||
indices.data());
|
||||
indexBuffer->pipelineBarrier(
|
||||
Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
Gfx::SE_ACCESS_INDEX_READ_BIT, Gfx::SE_PIPELINE_STAGE_VERTEX_INPUT_BIT);
|
||||
}
|
||||
surfaceCounts->updateContents(0, sizeof(counts), counts);
|
||||
surfaceCounts->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_WRITE_BIT,
|
||||
Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
Gfx::SE_ACCESS_INDIRECT_COMMAND_READ_BIT,
|
||||
Gfx::SE_PIPELINE_STAGE_DRAW_INDIRECT_BIT);
|
||||
}
|
||||
|
||||
void SurfaceExtractPass::endFrame() {}
|
||||
|
||||
void SurfaceExtractPass::publishOutputs() {
|
||||
resources->registerBufferOutput("SURFACE_VERTICES", vertexBuffer);
|
||||
resources->registerBufferOutput("SURFACE_INDICES", indexBuffer);
|
||||
resources->registerBufferOutput("SURFACE_COUNTS", surfaceCounts);
|
||||
}
|
||||
|
||||
void SurfaceExtractPass::createRenderPass() {
|
||||
phiBuffer = resources->requestBuffer("PHI");
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
#pragma once
|
||||
#include "Graphics/Graphics.h"
|
||||
#include "Graphics/RenderPass/RenderPass.h"
|
||||
#include "Graphics/Resources.h"
|
||||
#include <cstdint>
|
||||
|
||||
class SurfaceExtractPass : public Seele::RenderPass {
|
||||
public:
|
||||
SurfaceExtractPass(Seele::Gfx::PGraphics graphics);
|
||||
virtual ~SurfaceExtractPass() override;
|
||||
virtual void
|
||||
beginFrame(const Seele::Component::Camera &camera,
|
||||
const Seele::Component::Transform &transform) override;
|
||||
virtual void render() override;
|
||||
virtual void endFrame() override;
|
||||
virtual void publishOutputs() override;
|
||||
virtual void createRenderPass() override;
|
||||
|
||||
private:
|
||||
Seele::Gfx::OShaderBuffer vertexBuffer;
|
||||
Seele::Gfx::OShaderBuffer indexBuffer;
|
||||
Seele::Gfx::OShaderBuffer surfaceCounts;
|
||||
Seele::Gfx::PShaderBuffer phiBuffer;
|
||||
};
|
||||
DEFINE_REF(SurfaceExtractPass)
|
||||
@@ -1,34 +0,0 @@
|
||||
#include "FluidSimulationView.h"
|
||||
#include "Graphics/Initializer.h"
|
||||
#include "Graphics/Vulkan/Graphics.h"
|
||||
#include "Window/WindowManager.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
int main() {
|
||||
OWindowManager windowManager = new WindowManager();
|
||||
Gfx::OGraphics graphics = new Vulkan::Graphics();
|
||||
graphics->init(GraphicsInitializer());
|
||||
auto window = windowManager->addWindow(graphics, WindowCreateInfo{
|
||||
.width = 1280,
|
||||
.height = 720,
|
||||
.title = "FluidSimulation",
|
||||
});
|
||||
auto view = new FluidSimulationView(graphics, window,
|
||||
ViewportCreateInfo{
|
||||
.dimensions =
|
||||
{
|
||||
.size =
|
||||
{
|
||||
1280,
|
||||
720,
|
||||
},
|
||||
},
|
||||
});
|
||||
view->setFocused();
|
||||
window->show();
|
||||
while(!window->shouldClose()) {
|
||||
windowManager->render();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user