Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FLIP fluid simulation example #145

Open
wants to merge 84 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
84 commits
Select commit Hold shift + click to select a range
dcaead3
init new example
keptsecret Jul 16, 2024
dbf97a8
test compute shader pipeline
keptsecret Jul 23, 2024
1ca6ea2
fixed bug and made compute pipeline func
keptsecret Jul 23, 2024
b910ce5
test create buffer and init particles
keptsecret Jul 25, 2024
b4125e6
Merge branch 'Devsh-Graphics-Programming:master' into master
keptsecret Jul 26, 2024
8f267c8
required utils and show window
keptsecret Jul 29, 2024
fbb696d
fixed shader and removed unused funcs
keptsecret Jul 30, 2024
37d9ac4
test struct vector types in hlsl
keptsecret Jul 30, 2024
f463a0b
shaders to render particles
keptsecret Jul 31, 2024
98fee14
fix bugs, render still not working
keptsecret Aug 1, 2024
7001b1e
first test particle render
keptsecret Aug 3, 2024
18b7cc9
fix errors at runtime, still broken
keptsecret Aug 3, 2024
29db701
fixed most rendering pipeline bugs
keptsecret Aug 5, 2024
eaf034a
added pipeline barriers, on-demand particle init
keptsecret Aug 5, 2024
3a4fc2d
working compute shader render
keptsecret Aug 6, 2024
d89692b
fix particle color
keptsecret Aug 6, 2024
0a7845a
test new particle shader
keptsecret Aug 7, 2024
0b38b07
more utils
keptsecret Aug 7, 2024
ea269e2
simplified fluid rendering
keptsecret Aug 7, 2024
80ac1da
shaders for particle-grid
keptsecret Aug 9, 2024
90c5a5a
files for radix sort
keptsecret Aug 13, 2024
586b70b
fixed shader typos
keptsecret Aug 13, 2024
1a6205c
Merge branch 'Devsh-Graphics-Programming:master' into flip-progress
keptsecret Aug 14, 2024
869b974
first prefix sum impl
keptsecret Aug 14, 2024
9013205
fixed typo bugs
keptsecret Aug 14, 2024
fdf9dde
radix sorting v1, wonky descriptors
keptsecret Aug 20, 2024
e9f2489
alt radix sort impl
keptsecret Aug 21, 2024
b9353f3
fixed sort shader bugs
keptsecret Aug 21, 2024
6676476
prepare grids with sort
keptsecret Aug 23, 2024
0710f23
implement dispatch particle-grid stuffs
keptsecret Aug 26, 2024
51b59f5
moving away from reflection
keptsecret Aug 27, 2024
be4bbfe
fix sort buffers init bug
keptsecret Aug 27, 2024
5f11de4
manual descriptor bindings in shared header
keptsecret Aug 28, 2024
a9816ac
impl body forces
keptsecret Aug 30, 2024
f801ab1
Merge branch 'Devsh-Graphics-Programming:master' into flip-sort-alt
keptsecret Sep 2, 2024
b600e4a
fixed shader and some sync bugs
keptsecret Sep 2, 2024
4943b3c
Merge branch 'flip-sort-alt' of https://github.com/keptsecret/Nabla-E…
keptsecret Sep 2, 2024
2e85153
fixed cell mat bug
keptsecret Sep 2, 2024
f85443b
removed sort temporarily (broken)
keptsecret Sep 2, 2024
d51970d
switched to global memory barriers
keptsecret Sep 2, 2024
fe99f53
solve pressure pipeline
keptsecret Sep 3, 2024
99cfee8
fixed sort bug
keptsecret Sep 3, 2024
f125b05
fixed typo bugs and some sync
keptsecret Sep 3, 2024
4309860
fixed particle disappearing bug
keptsecret Sep 5, 2024
b733b16
impl apply diffusion
keptsecret Sep 6, 2024
9d7f215
fixed descriptors and shader bugs
keptsecret Sep 6, 2024
5a22471
fixed pressure calc bug
keptsecret Sep 9, 2024
869b0c8
cosmetic changes and another sim preset
keptsecret Sep 9, 2024
a87c1d7
more specific barriers
keptsecret Sep 9, 2024
36dd333
slightly improved and fixed radix sort
keptsecret Sep 13, 2024
846df9e
fixed some bugs, still not working
keptsecret Sep 16, 2024
3fcfc30
fix descriptor bug
keptsecret Sep 17, 2024
0b623d5
minor removals
keptsecret Sep 18, 2024
e0a715a
fixed some bugs (sync & more)
keptsecret Sep 20, 2024
e0914d9
updated sort barriers
keptsecret Sep 23, 2024
ce2d305
switch vel field to texture for hardware sampling
keptsecret Sep 23, 2024
c44f474
use tricubic interp
keptsecret Sep 25, 2024
4aaa0b7
Merge branch 'Devsh-Graphics-Programming:master' into flip-sort-alt
keptsecret Sep 27, 2024
b57aca2
removed unused shaders + gravity adj
keptsecret Sep 27, 2024
41d16bf
func for writing k-v to buffers
keptsecret Sep 30, 2024
c95daef
fixed depth test and added source references
keptsecret Oct 1, 2024
55a950b
use default example
keptsecret Oct 1, 2024
fd18c2b
Create README.md with demo gif
keptsecret Oct 1, 2024
ea47f35
split velocities by axis
keptsecret Oct 16, 2024
aac75f1
update to origin
keptsecret Oct 16, 2024
f8cfe65
Merge branch 'master' into flip-opt-changes
keptsecret Oct 16, 2024
99b9837
merge master and fixed conflicts
keptsecret Oct 16, 2024
e819c9d
tabs spaces
keptsecret Oct 16, 2024
70d73f2
fixed velocity in pressure bug
keptsecret Oct 17, 2024
4f66d96
cell material buffer to texture
keptsecret Oct 17, 2024
26cbbff
diffusion grids buffer to texture
keptsecret Oct 17, 2024
e6c8526
pressure grids buffer to texture
keptsecret Oct 17, 2024
3880f0e
1D to 3D dispatch for grid
keptsecret Oct 18, 2024
5168747
changes in preparation for future stuff
keptsecret Oct 18, 2024
09fb9f8
condensed update fluid cells step
keptsecret Oct 22, 2024
2d00c1e
better pressure solve iteration
keptsecret Oct 23, 2024
38a3cc2
fix and clean new pressure solve
keptsecret Oct 23, 2024
c8393de
better diffusion iterations
keptsecret Oct 24, 2024
12391e6
merged particle vel update into advectParticles
keptsecret Oct 26, 2024
1ad5819
switch to use BDAs
keptsecret Oct 28, 2024
1e1360a
Merge branch 'flip-opt-changes' into flip-sort-alt
keptsecret Oct 28, 2024
77561f2
Merge branch 'Devsh-Graphics-Programming:master' into flip-sort-alt
keptsecret Oct 28, 2024
af0b661
fixed with api changes
keptsecret Oct 28, 2024
516515f
simplified particle data structure
keptsecret Oct 29, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions 70_FLIPFluids/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
include(common RESULT_VARIABLE RES)
if(NOT RES)
message(FATAL_ERROR "common.cmake not found. Should be in {repo_root}/cmake directory")
endif()

nbl_create_executable_project("" "" "" "" "${NBL_EXECUTABLE_PROJECT_CREATION_PCH_TARGET}")

if(NBL_EMBED_BUILTIN_RESOURCES)
set(_BR_TARGET_ ${EXECUTABLE_NAME}_builtinResourceData)
set(RESOURCE_DIR "app_resources")

get_filename_component(_SEARCH_DIRECTORIES_ "${CMAKE_CURRENT_SOURCE_DIR}" ABSOLUTE)
get_filename_component(_OUTPUT_DIRECTORY_SOURCE_ "${CMAKE_CURRENT_BINARY_DIR}/src" ABSOLUTE)
get_filename_component(_OUTPUT_DIRECTORY_HEADER_ "${CMAKE_CURRENT_BINARY_DIR}/include" ABSOLUTE)

file(GLOB_RECURSE BUILTIN_RESOURCE_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/${RESOURCE_DIR}" CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${RESOURCE_DIR}/*")
foreach(RES_FILE ${BUILTIN_RESOURCE_FILES})
LIST_BUILTIN_RESOURCE(RESOURCES_TO_EMBED "${RES_FILE}")
endforeach()

ADD_CUSTOM_BUILTIN_RESOURCES(${_BR_TARGET_} RESOURCES_TO_EMBED "${_SEARCH_DIRECTORIES_}" "${RESOURCE_DIR}" "nbl::this_example::builtin" "${_OUTPUT_DIRECTORY_HEADER_}" "${_OUTPUT_DIRECTORY_SOURCE_}")

LINK_BUILTIN_RESOURCES_TO_TARGET(${EXECUTABLE_NAME} ${_BR_TARGET_})
endif()
1 change: 1 addition & 0 deletions 70_FLIPFluids/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
https://github.com/user-attachments/assets/fc8bfac9-c8fb-49f1-87d6-251aae015945
182 changes: 182 additions & 0 deletions 70_FLIPFluids/app_resources/cellUtils.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
#ifndef _FLIP_EXAMPLE_CELL_UTILS_HLSL
#define _FLIP_EXAMPLE_CELL_UTILS_HLSL

#ifdef __HLSL_VERSION
static const uint CM_SOLID = 0;
static const uint CM_FLUID = 1;
static const uint CM_AIR = 2;
Comment on lines +5 to +7

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also HLSL has enums


static const uint CellMatMask = 0x00000003u;
static const uint CellMatMaskShift = 0;
static const uint XPrevMatMask = 0x0000000cu;
static const uint XPrevMatMaskShift = 2;
static const uint XNextMatMask = 0x00000030u;
static const uint XNextMatMaskShift = 4;
static const uint YPrevMatMask = 0x000000c0u;
static const uint YPrevMatMaskShift = 6;
static const uint YNextMatMask = 0x00000300u;
static const uint YNextMatMaskShift = 8;
static const uint ZPrevMatMask = 0x00000c00u;
static const uint ZPrevMatMaskShift = 10;
static const uint ZNextMatMask = 0x00003000u;
static const uint ZNextMatMaskShift = 12;
Comment on lines +5 to +22

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HLSL has bitfields.

struct Cell
{
   uint32_t cellMaterial : 2;
   ...etc...
};


inline void setCellMaterial(inout uint cellMaterials, uint cellMaterial)
{
cellMaterials = (cellMaterials & ~CellMatMask) | ((cellMaterial << CellMatMaskShift) & CellMatMask);
}
inline uint getCellMaterial(uint cellMaterials)
{
return (cellMaterials & CellMatMask) >> CellMatMaskShift;
}
inline void setXPrevMaterial(inout uint cellMaterials, uint cellMaterial)
{
cellMaterials = (cellMaterials & ~XPrevMatMask) | ((cellMaterial << XPrevMatMaskShift) & XPrevMatMask);
}
inline uint getXPrevMaterial(uint cellMaterials)
{
return (cellMaterials & XPrevMatMask) >> XPrevMatMaskShift;
}
inline void setXNextMaterial(inout uint cellMaterials, uint cellMaterial)
{
cellMaterials = (cellMaterials & ~XNextMatMask) | ((cellMaterial << XNextMatMaskShift) & XNextMatMask);
}
inline uint getXNextMaterial(uint cellMaterials)
{
return (cellMaterials & XNextMatMask) >> XNextMatMaskShift;
}
inline void setYPrevMaterial(inout uint cellMaterials, uint cellMaterial)
{
cellMaterials = (cellMaterials & ~YPrevMatMask) | ((cellMaterial << YPrevMatMaskShift) & YPrevMatMask);
}
inline uint getYPrevMaterial(uint cellMaterials)
{
return (cellMaterials & YPrevMatMask) >> YPrevMatMaskShift;
}
inline void setYNextMaterial(inout uint cellMaterials, uint cellMaterial)
{
cellMaterials = (cellMaterials & ~YNextMatMask) | ((cellMaterial << YNextMatMaskShift) & YNextMatMask);
}
inline uint getYNextMaterial(uint cellMaterials)
{
return (cellMaterials & YNextMatMask) >> YNextMatMaskShift;
}
inline void setZPrevMaterial(inout uint cellMaterials, uint cellMaterial)
{
cellMaterials = (cellMaterials & ~ZPrevMatMask) | ((cellMaterial << ZPrevMatMaskShift) & ZPrevMatMask);
}
inline uint getZPrevMaterial(uint cellMaterials)
{
return (cellMaterials & ZPrevMatMask) >> ZPrevMatMaskShift;
}
inline void setZNextMaterial(inout uint cellMaterials, uint cellMaterial)
{
cellMaterials = (cellMaterials & ~ZNextMatMask) | ((cellMaterial << ZNextMatMaskShift) & ZNextMatMask);
}
inline uint getZNextMaterial(uint cellMaterials)
{
return (cellMaterials & ZNextMatMask) >> ZNextMatMaskShift;
}


inline void setCellMaterial(inout uint3 cellMaterials, uint3 cellMaterial)
{
cellMaterials = (cellMaterials & ~CellMatMask) | ((cellMaterial << CellMatMaskShift) & CellMatMask);
}
inline uint3 getCellMaterial(uint3 cellMaterials)
{
return (cellMaterials & CellMatMask) >> CellMatMaskShift;
}
inline void setXPrevMaterial(inout uint3 cellMaterials, uint3 cellMaterial)
{
cellMaterials = (cellMaterials & ~XPrevMatMask) | ((cellMaterial << XPrevMatMaskShift) & XPrevMatMask);
}
inline uint3 getXPrevMaterial(uint3 cellMaterials)
{
return (cellMaterials & XPrevMatMask) >> XPrevMatMaskShift;
}
inline void setXNextMaterial(inout uint3 cellMaterials, uint3 cellMaterial)
{
cellMaterials = (cellMaterials & ~XNextMatMask) | ((cellMaterial << XNextMatMaskShift) & XNextMatMask);
}
inline uint3 getXNextMaterial(uint3 cellMaterials)
{
return (cellMaterials & XNextMatMask) >> XNextMatMaskShift;
}
inline void setYPrevMaterial(inout uint3 cellMaterials, uint3 cellMaterial)
{
cellMaterials = (cellMaterials & ~YPrevMatMask) | ((cellMaterial << YPrevMatMaskShift) & YPrevMatMask);
}
inline uint3 getYPrevMaterial(uint3 cellMaterials)
{
return (cellMaterials & YPrevMatMask) >> YPrevMatMaskShift;
}
inline void setYNextMaterial(inout uint3 cellMaterials, uint3 cellMaterial)
{
cellMaterials = (cellMaterials & ~YNextMatMask) | ((cellMaterial << YNextMatMaskShift) & YNextMatMask);
}
inline uint3 getYNextMaterial(uint3 cellMaterials)
{
return (cellMaterials & YNextMatMask) >> YNextMatMaskShift;
}
inline void setZPrevMaterial(inout uint3 cellMaterials, uint3 cellMaterial)
{
cellMaterials = (cellMaterials & ~ZPrevMatMask) | ((cellMaterial << ZPrevMatMaskShift) & ZPrevMatMask);
}
inline uint3 getZPrevMaterial(uint3 cellMaterials)
{
return (cellMaterials & ZPrevMatMask) >> ZPrevMatMaskShift;
}
inline void setZNextMaterial(inout uint3 cellMaterials, uint3 cellMaterial)
{
cellMaterials = (cellMaterials & ~ZNextMatMask) | ((cellMaterial << ZNextMatMaskShift) & ZNextMatMask);
}
inline uint3 getZNextMaterial(uint3 cellMaterials)
{
return (cellMaterials & ZNextMatMask) >> ZNextMatMaskShift;
}


inline bool isSolidCell(uint cellMaterial)
{
return cellMaterial == CM_SOLID;
}
inline bool isFluidCell(uint cellMaterial)
{
return cellMaterial == CM_FLUID;
}
inline bool isAirCell(uint cellMaterial)
{
return cellMaterial == CM_AIR;
}

inline bool3 isSolidCell(uint3 cellMaterial)
{
return cellMaterial == (uint3)CM_SOLID;
}
inline bool3 isFluidCell(uint3 cellMaterial)
{
return cellMaterial == (uint3)CM_FLUID;
}
inline bool3 isAirCell(uint3 cellMaterial)
{
return cellMaterial == (uint3)CM_AIR;
}

void enforceBoundaryCondition(inout float3 velocity, uint cellMaterial)
{
bool3 is_solid_cell =
or((bool3)isSolidCell(getCellMaterial(cellMaterial)),
bool3(isSolidCell(getXPrevMaterial(cellMaterial)), isSolidCell(getYPrevMaterial(cellMaterial)), isSolidCell(getZPrevMaterial(cellMaterial))));
Comment on lines +168 to +170
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

general algorithm question, is this a staggered grid?

c --- s --- c
|           |
s           s
|           |
c --- s --- c

and the solid flags are kept between cells?

velocity = select(is_solid_cell, 0.0f, velocity);
}

// handling solid obstacles
inline bool3 isSolidCell(float3 position)
{
// no obstacles for now, in cuboid sim area
return false;
}

#endif
#endif
33 changes: 33 additions & 0 deletions 70_FLIPFluids/app_resources/common.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#ifndef _FLIP_EXAMPLE_COMMON_HLSL
#define _FLIP_EXAMPLE_COMMON_HLSL

#include "nbl/builtin/hlsl/cpp_compat.hlsl"

NBL_CONSTEXPR uint32_t WorkgroupSize = 128;
NBL_CONSTEXPR uint32_t WorkgroupGridDim = 8;
NBL_CONSTEXPR float ratioFLIPPIC = 0.95;
NBL_CONSTEXPR float deltaTime = 1.0f / 90.0f;
NBL_CONSTEXPR float gravity = 15.0f;

#ifdef __HLSL_VERSION

static const float FLT_MIN = 1.175494351e-38;
static const float FLT_MAX = 3.402823466e+38;
Comment on lines +14 to +15

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

slight nitpick, we have this https://github.com/Devsh-Graphics-Programming/Nabla/blob/master/include/nbl/builtin/hlsl/limits.hlsl

because there's no constexpr functions in HLSL and constexpr float variables were introduced in C++20 the usage is

numeric_limits<float>::min;


struct Particle
{
float32_t3 position;
float32_t3 velocity;
};
struct SMVPParams
{
float4 camPos;

float4x4 MVP;
float4x4 M;
float4x4 V;
Comment on lines +27 to +28

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

non projective matrices are 3x4 , last row is always 0,0,0,1 and can be discarded

float4x4 P;
};
#endif

#endif
57 changes: 57 additions & 0 deletions 70_FLIPFluids/app_resources/compute/advectParticles.comp.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#include "../common.hlsl"
#include "../gridSampling.hlsl"
#include "../descriptor_bindings.hlsl"

struct SPushConstants
{
uint64_t particlePosAddress;
uint64_t particleVelAddress;
};

[[vk::push_constant]] SPushConstants pc;

[[vk::binding(b_apGridData, s_ap)]]
cbuffer GridData
{
SGridData gridData;
};
Comment on lines +13 to +17

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We tend to use BDA for everything but this is actually a use of an UBO I can commend, globals that don't change, ever

(although it would probably fit in push constants - which are slightly faster)


[[vk::binding(b_apVelFieldBuffer, s_ap)]] Texture3D<float> velocityFieldBuffer[3];
[[vk::binding(b_apPrevVelFieldBuffer, s_ap)]] Texture3D<float> prevVelocityFieldBuffer[3];
[[vk::binding(b_apVelSampler, s_ap)]] SamplerState velocityFieldSampler;

// delta time push constant?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good idea.


[numthreads(WorkgroupSize, 1, 1)]
void main(uint32_t3 ID : SV_DispatchThreadID)
{
uint32_t pid = ID.x;
Comment on lines +26 to +28

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we have nbl::hlsl::glsl::gl_GlobalInvocationID which I'd rather use than the : SV_ nonsense

Particle p;

int offset = sizeof(float32_t3) * pid;
p.position = vk::RawBufferLoad<float32_t3>(pc.particlePosAddress + offset);
p.velocity = vk::RawBufferLoad<float32_t3>(pc.particleVelAddress + offset);

// advect velocity
float3 gridPrevVel = sampleVelocityAt(p.position, prevVelocityFieldBuffer, velocityFieldSampler, gridData);
float3 gridVel = sampleVelocityAt(p.position, velocityFieldBuffer, velocityFieldSampler, gridData);

float3 picVel = gridVel;
float3 flipVel = p.velocity + gridVel - gridPrevVel;

p.velocity = lerp(picVel, flipVel, ratioFLIPPIC);

// move particle, use RK4
float3 k1 = gridVel;
float3 k2 = sampleVelocityAt(p.position + k1 * 0.5f * deltaTime, velocityFieldBuffer, velocityFieldSampler, gridData);
float3 k3 = sampleVelocityAt(p.position + k2 * 0.5f * deltaTime, velocityFieldBuffer, velocityFieldSampler, gridData);
float3 k4 = sampleVelocityAt(p.position + k3 * deltaTime, velocityFieldBuffer, velocityFieldSampler, gridData);
float3 velocity = (k1 + 2.0f * k2 + 2.0f * k3 + k4) / 6.0f;

p.position += velocity * deltaTime;

p.position = clampPosition(p.position, gridData.worldMin, gridData.worldMax);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wouldn't you want to reflect/bounce the particle off the wall (with some dampening ofc) instead of making it come to an abrupt stop?


vk::RawBufferStore<float32_t3>(pc.particlePosAddress + offset, p.position);
vk::RawBufferStore<float32_t3>(pc.particleVelAddress + offset, p.velocity);
}
33 changes: 33 additions & 0 deletions 70_FLIPFluids/app_resources/compute/applyBodyForces.comp.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#include "../common.hlsl"
#include "../gridUtils.hlsl"
#include "../cellUtils.hlsl"
#include "../descriptor_bindings.hlsl"

[[vk::binding(b_abfGridData, s_abf)]]
cbuffer GridData
{
SGridData gridData;
};

[[vk::binding(b_abfVelFieldBuffer, s_abf)]] RWTexture3D<float> velocityFieldBuffer[3];
[[vk::binding(b_abfCMBuffer, s_abf)]] RWTexture3D<uint> cellMaterialBuffer;

[numthreads(WorkgroupGridDim, WorkgroupGridDim, WorkgroupGridDim)]
void main(uint32_t3 ID : SV_DispatchThreadID)
{
// only gravity for now
int3 cIdx = ID;

float3 velocity;
velocity.x = velocityFieldBuffer[0][cIdx];
velocity.y = velocityFieldBuffer[1][cIdx];
velocity.z = velocityFieldBuffer[2][cIdx];

velocity += float3(0, -1, 0) * gravity * deltaTime;

enforceBoundaryCondition(velocity, cellMaterialBuffer[cIdx]);

velocityFieldBuffer[0][cIdx] = velocity.x;
velocityFieldBuffer[1][cIdx] = velocity.y;
velocityFieldBuffer[2][cIdx] = velocity.z;
}
Loading