@buley/hexgrid-3d 3.2.1 → 3.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/algorithms/FluidSimulation3DGPU.d.ts.map +1 -1
- package/dist/algorithms/FluidSimulation3DGPU.js +1 -142
- package/dist/webgpu/shaders/fluid_sim.generated.d.ts +3 -0
- package/dist/webgpu/shaders/fluid_sim.generated.d.ts.map +1 -0
- package/dist/webgpu/shaders/fluid_sim.generated.js +144 -0
- package/package.json +12 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FluidSimulation3DGPU.d.ts","sourceRoot":"","sources":["../../src/algorithms/FluidSimulation3DGPU.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"FluidSimulation3DGPU.d.ts","sourceRoot":"","sources":["../../src/algorithms/FluidSimulation3DGPU.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGzD,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,IAAI,CAAS;IAErB,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,MAAM,CAA0B;IAGxC,OAAO,CAAC,eAAe,CAAyC;IAChE,OAAO,CAAC,gBAAgB,CAAyC;IACjE,OAAO,CAAC,gBAAgB,CAAyC;IACjE,OAAO,CAAC,iBAAiB,CAA2B;IAGpD,OAAO,CAAC,cAAc,CAAmC;IACzD,OAAO,CAAC,eAAe,CAAmC;IAC1D,OAAO,CAAC,kBAAkB,CAAmC;IAC7D,OAAO,CAAC,wBAAwB,CAAmC;IAEnE,OAAO,CAAC,OAAO,CAA2B;IAC1C,OAAO,CAAC,aAAa,CAA0B;IAC/C,OAAO,CAAC,YAAY,CAA0B;IAE9C,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,UAAU,CAAS;gBAEf,MAAM,EAAE,aAAa;IAY3B,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC;IAuE9B,IAAI,CAAC,EAAE,EAAE,MAAM;IAsCrB,OAAO,CAAC,cAAc;IA6BtB,OAAO,CAAC,eAAe;IAkDvB,OAAO,CAAC,kBAAkB;IAkB1B,OAAO,CAAC,gBAAgB;IAgExB,OAAO,CAAC,wBAAwB;IA2BhC,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAyB1E,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM;IAsBrD,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM;IAKlC,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO;IAIpC,KAAK;CAGN"}
|
|
@@ -3,148 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { Vector3 } from '../math/Vector3';
|
|
5
5
|
import { WebGPUContext } from '../webgpu/WebGPUContext';
|
|
6
|
-
|
|
7
|
-
const shaderSource = `// fluid_sim.wgsl
|
|
8
|
-
// 3D Fluid Simulation Compute Shaders
|
|
9
|
-
|
|
10
|
-
struct FluidUniforms {
|
|
11
|
-
dt: f32,
|
|
12
|
-
width: f32,
|
|
13
|
-
height: f32,
|
|
14
|
-
depth: f32,
|
|
15
|
-
decay: f32,
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
@group(0) @binding(0) var<uniform> uniforms: FluidUniforms;
|
|
19
|
-
|
|
20
|
-
// Bindings for Double-Buffering (Read -> Write)
|
|
21
|
-
// Group 1: Velocity / Density
|
|
22
|
-
@group(1) @binding(0) var field_in: texture_3d<f32>;
|
|
23
|
-
@group(1) @binding(1) var field_out: texture_storage_3d<rgba16float, write>;
|
|
24
|
-
|
|
25
|
-
// Sampler for linear interpolation
|
|
26
|
-
@group(1) @binding(2) var field_sampler: sampler;
|
|
27
|
-
|
|
28
|
-
// ----------------------------------------------------------------------------
|
|
29
|
-
// ADVECTION
|
|
30
|
-
// Moves quantities along the velocity field
|
|
31
|
-
// ----------------------------------------------------------------------------
|
|
32
|
-
@group(2) @binding(0) var velocity_field: texture_3d<f32>;
|
|
33
|
-
|
|
34
|
-
@compute @workgroup_size(8, 8, 8)
|
|
35
|
-
fn advect(@builtin(global_invocation_id) global_id: vec3<u32>) {
|
|
36
|
-
let dims = vec3<f32>(uniforms.width, uniforms.height, uniforms.depth);
|
|
37
|
-
let coords = vec3<f32>(global_id);
|
|
38
|
-
|
|
39
|
-
if (any(coords >= dims)) { return; }
|
|
40
|
-
|
|
41
|
-
// 1. Sample velocity at current position
|
|
42
|
-
// Note: textureSampleLevel requires normalized coordinates [0, 1]
|
|
43
|
-
let uvw = (coords + 0.5) / dims;
|
|
44
|
-
let vel = textureSampleLevel(velocity_field, field_sampler, uvw, 0.0).xyz;
|
|
45
|
-
|
|
46
|
-
// 2. Trace back in time
|
|
47
|
-
let dt = uniforms.dt;
|
|
48
|
-
// Scale velocity back to grid units?
|
|
49
|
-
// Uniforms velocity tends to be in grid-units per second.
|
|
50
|
-
// Backtrace coordinate:
|
|
51
|
-
let back_pos = coords - vel * dt;
|
|
52
|
-
|
|
53
|
-
// 3. Sample field at previous position
|
|
54
|
-
let back_uvw = (back_pos + 0.5) / dims;
|
|
55
|
-
let new_val = textureSampleLevel(field_in, field_sampler, back_uvw, 0.0);
|
|
56
|
-
|
|
57
|
-
// 4. Apply decay
|
|
58
|
-
let decayed = new_val * uniforms.decay;
|
|
59
|
-
|
|
60
|
-
textureStore(field_out, global_id, decayed);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// ----------------------------------------------------------------------------
|
|
64
|
-
// DIFFUSION (Jacobi Iteration)
|
|
65
|
-
// ----------------------------------------------------------------------------
|
|
66
|
-
// x_new = (x_old + alpha * neighbor_sum) * inverse_beta
|
|
67
|
-
struct JacobiUniforms {
|
|
68
|
-
alpha: f32,
|
|
69
|
-
rBeta: f32,
|
|
70
|
-
};
|
|
71
|
-
@group(3) @binding(0) var<uniform> jacobi: JacobiUniforms;
|
|
72
|
-
@group(3) @binding(1) var b_field: texture_3d<f32>; // The 'b' vector in Ax=b (usually previous state or inputs)
|
|
73
|
-
@group(3) @binding(2) var x_field: texture_3d<f32>; // The 'x' vector (current guess)
|
|
74
|
-
|
|
75
|
-
@compute @workgroup_size(8, 8, 8)
|
|
76
|
-
fn diffuse(@builtin(global_invocation_id) global_id: vec3<u32>) {
|
|
77
|
-
let dims = vec3<i32>(uniforms.width, uniforms.height, uniforms.depth);
|
|
78
|
-
let pos = vec3<i32>(global_id);
|
|
79
|
-
|
|
80
|
-
if (any(pos >= dims)) { return; }
|
|
81
|
-
|
|
82
|
-
// Neighbors
|
|
83
|
-
let left = textureLoad(x_field, pos + vec3<i32>(-1, 0, 0), 0);
|
|
84
|
-
let right = textureLoad(x_field, pos + vec3<i32>(1, 0, 0), 0);
|
|
85
|
-
let down = textureLoad(x_field, pos + vec3<i32>(0, -1, 0), 0);
|
|
86
|
-
let up = textureLoad(x_field, pos + vec3<i32>(0, 1, 0), 0);
|
|
87
|
-
let back = textureLoad(x_field, pos + vec3<i32>(0, 0, -1), 0);
|
|
88
|
-
let front = textureLoad(x_field, pos + vec3<i32>(0, 0, 1), 0);
|
|
89
|
-
|
|
90
|
-
let bC = textureLoad(b_field, pos, 0);
|
|
91
|
-
|
|
92
|
-
// Jacobi step
|
|
93
|
-
let result = (left + right + down + up + back + front) * jacobi.alpha + bC;
|
|
94
|
-
let next_val = result * jacobi.rBeta;
|
|
95
|
-
|
|
96
|
-
textureStore(field_out, global_id, next_val);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// ----------------------------------------------------------------------------
|
|
100
|
-
// DIVERGENCE
|
|
101
|
-
// ----------------------------------------------------------------------------
|
|
102
|
-
@compute @workgroup_size(8, 8, 8)
|
|
103
|
-
fn divergence(@builtin(global_invocation_id) global_id: vec3<u32>) {
|
|
104
|
-
let dims = vec3<i32>(uniforms.width, uniforms.height, uniforms.depth);
|
|
105
|
-
let pos = vec3<i32>(global_id);
|
|
106
|
-
|
|
107
|
-
if (any(pos >= dims)) { return; }
|
|
108
|
-
|
|
109
|
-
let left = textureLoad(field_in, pos + vec3<i32>(-1, 0, 0), 0).x;
|
|
110
|
-
let right = textureLoad(field_in, pos + vec3<i32>(1, 0, 0), 0).x;
|
|
111
|
-
let down = textureLoad(field_in, pos + vec3<i32>(0, -1, 0), 0).y;
|
|
112
|
-
let up = textureLoad(field_in, pos + vec3<i32>(0, 1, 0), 0).y;
|
|
113
|
-
let back = textureLoad(field_in, pos + vec3<i32>(0, 0, -1), 0).z;
|
|
114
|
-
let front = textureLoad(field_in, pos + vec3<i32>(0, 0, 1), 0).z;
|
|
115
|
-
|
|
116
|
-
let div = 0.5 * ((right - left) + (up - down) + (front - back));
|
|
117
|
-
|
|
118
|
-
textureStore(field_out, global_id, vec4<f32>(div, 0.0, 0.0, 1.0));
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// ----------------------------------------------------------------------------
|
|
122
|
-
// GRADIENT SUBTRACTION
|
|
123
|
-
// u_new = u_old - gradient(p)
|
|
124
|
-
// ----------------------------------------------------------------------------
|
|
125
|
-
@group(4) @binding(0) var pressure_field: texture_3d<f32>;
|
|
126
|
-
|
|
127
|
-
@compute @workgroup_size(8, 8, 8)
|
|
128
|
-
fn subtract_gradient(@builtin(global_invocation_id) global_id: vec3<u32>) {
|
|
129
|
-
let dims = vec3<i32>(uniforms.width, uniforms.height, uniforms.depth);
|
|
130
|
-
let pos = vec3<i32>(global_id);
|
|
131
|
-
|
|
132
|
-
if (any(pos >= dims)) { return; }
|
|
133
|
-
|
|
134
|
-
let pLeft = textureLoad(pressure_field, pos + vec3<i32>(-1, 0, 0), 0).x;
|
|
135
|
-
let pRight = textureLoad(pressure_field, pos + vec3<i32>(1, 0, 0), 0).x;
|
|
136
|
-
let pDown = textureLoad(pressure_field, pos + vec3<i32>(0, -1, 0), 0).x;
|
|
137
|
-
let pUp = textureLoad(pressure_field, pos + vec3<i32>(0, 1, 0), 0).x;
|
|
138
|
-
let pBack = textureLoad(pressure_field, pos + vec3<i32>(0, 0, -1), 0).x;
|
|
139
|
-
let pFront = textureLoad(pressure_field, pos + vec3<i32>(0, 0, 1), 0).x;
|
|
140
|
-
|
|
141
|
-
let old_vel = textureLoad(field_in, pos, 0).xyz;
|
|
142
|
-
let grad = vec3<f32>(pRight - pLeft, pUp - pDown, pFront - pBack) * 0.5;
|
|
143
|
-
let new_vel = old_vel - grad;
|
|
144
|
-
|
|
145
|
-
textureStore(field_out, global_id, vec4<f32>(new_vel, 1.0));
|
|
146
|
-
}
|
|
147
|
-
`;
|
|
6
|
+
import { fluidSimShader as shaderSource } from '../webgpu/shaders/fluid_sim.generated';
|
|
148
7
|
export class FluidSimulation3DGPU {
|
|
149
8
|
constructor(config) {
|
|
150
9
|
this.device = null;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare const fluidSimShader = "// fluid_sim.wgsl\n// 3D Fluid Simulation Compute Shaders\n\nstruct FluidUniforms {\n dt: f32,\n width: f32,\n height: f32,\n depth: f32,\n decay: f32,\n};\n\n@group(0) @binding(0) var<uniform> uniforms: FluidUniforms;\n\n// Bindings for Double-Buffering (Read -> Write)\n// Group 1: Velocity / Density\n@group(1) @binding(0) var field_in: texture_3d<f32>;\n@group(1) @binding(1) var field_out: texture_storage_3d<rgba16float, write>;\n\n// Sampler for linear interpolation\n@group(1) @binding(2) var field_sampler: sampler;\n\n// ----------------------------------------------------------------------------\n// ADVECTION\n// Moves quantities along the velocity field\n// ----------------------------------------------------------------------------\n@group(2) @binding(0) var velocity_field: texture_3d<f32>;\n\n@compute @workgroup_size(8, 8, 8)\nfn advect(@builtin(global_invocation_id) global_id: vec3<u32>) {\n let dims = vec3<f32>(uniforms.width, uniforms.height, uniforms.depth);\n let coords = vec3<f32>(global_id);\n\n if (any(coords >= dims)) { return; }\n\n // 1. Sample velocity at current position\n // Note: textureSampleLevel requires normalized coordinates [0, 1]\n let uvw = (coords + 0.5) / dims;\n let vel = textureSampleLevel(velocity_field, field_sampler, uvw, 0.0).xyz;\n\n // 2. Trace back in time\n let dt = uniforms.dt;\n // Scale velocity back to grid units?\n // Uniforms velocity tends to be in grid-units per second.\n // Backtrace coordinate:\n let back_pos = coords - vel * dt;\n\n // 3. Sample field at previous position\n let back_uvw = (back_pos + 0.5) / dims;\n let new_val = textureSampleLevel(field_in, field_sampler, back_uvw, 0.0);\n\n // 4. Apply decay\n let decayed = new_val * uniforms.decay;\n\n textureStore(field_out, global_id, decayed);\n}\n\n// ----------------------------------------------------------------------------\n// DIFFUSION (Jacobi Iteration)\n// ----------------------------------------------------------------------------\n// x_new = (x_old + alpha * neighbor_sum) * inverse_beta\nstruct JacobiUniforms {\n alpha: f32,\n rBeta: f32,\n};\n@group(3) @binding(0) var<uniform> jacobi: JacobiUniforms;\n@group(3) @binding(1) var b_field: texture_3d<f32>; // The 'b' vector in Ax=b (usually previous state or inputs)\n@group(3) @binding(2) var x_field: texture_3d<f32>; // The 'x' vector (current guess)\n\n@compute @workgroup_size(8, 8, 8)\nfn diffuse(@builtin(global_invocation_id) global_id: vec3<u32>) {\n let dims = vec3<i32>(i32(uniforms.width), i32(uniforms.height), i32(uniforms.depth));\n let pos = vec3<i32>(global_id);\n \n if (any(pos >= dims)) { return; }\n\n // Neighbors\n let left = textureLoad(x_field, pos + vec3<i32>(-1, 0, 0), 0);\n let right = textureLoad(x_field, pos + vec3<i32>(1, 0, 0), 0);\n let down = textureLoad(x_field, pos + vec3<i32>(0, -1, 0), 0);\n let up = textureLoad(x_field, pos + vec3<i32>(0, 1, 0), 0);\n let back = textureLoad(x_field, pos + vec3<i32>(0, 0, -1), 0);\n let front = textureLoad(x_field, pos + vec3<i32>(0, 0, 1), 0);\n\n let bC = textureLoad(b_field, pos, 0);\n\n // Jacobi step\n let result = (left + right + down + up + back + front) * jacobi.alpha + bC;\n let next_val = result * jacobi.rBeta;\n\n textureStore(field_out, global_id, next_val);\n}\n\n// ----------------------------------------------------------------------------\n// DIVERGENCE\n// ----------------------------------------------------------------------------\n@compute @workgroup_size(8, 8, 8)\nfn divergence(@builtin(global_invocation_id) global_id: vec3<u32>) {\n let dims = vec3<i32>(i32(uniforms.width), i32(uniforms.height), i32(uniforms.depth));\n let pos = vec3<i32>(global_id);\n\n if (any(pos >= dims)) { return; }\n\n let left = textureLoad(field_in, pos + vec3<i32>(-1, 0, 0), 0).x;\n let right = textureLoad(field_in, pos + vec3<i32>(1, 0, 0), 0).x;\n let down = textureLoad(field_in, pos + vec3<i32>(0, -1, 0), 0).y;\n let up = textureLoad(field_in, pos + vec3<i32>(0, 1, 0), 0).y;\n let back = textureLoad(field_in, pos + vec3<i32>(0, 0, -1), 0).z;\n let front = textureLoad(field_in, pos + vec3<i32>(0, 0, 1), 0).z;\n\n let div = 0.5 * ((right - left) + (up - down) + (front - back));\n\n textureStore(field_out, global_id, vec4<f32>(div, 0.0, 0.0, 1.0));\n}\n\n// ----------------------------------------------------------------------------\n// GRADIENT SUBTRACTION\n// u_new = u_old - gradient(p)\n// ----------------------------------------------------------------------------\n@group(4) @binding(0) var pressure_field: texture_3d<f32>;\n\n@compute @workgroup_size(8, 8, 8)\nfn subtract_gradient(@builtin(global_invocation_id) global_id: vec3<u32>) {\n let dims = vec3<i32>(i32(uniforms.width), i32(uniforms.height), i32(uniforms.depth));\n let pos = vec3<i32>(global_id);\n\n if (any(pos >= dims)) { return; }\n\n let pLeft = textureLoad(pressure_field, pos + vec3<i32>(-1, 0, 0), 0).x;\n let pRight = textureLoad(pressure_field, pos + vec3<i32>(1, 0, 0), 0).x;\n let pDown = textureLoad(pressure_field, pos + vec3<i32>(0, -1, 0), 0).x;\n let pUp = textureLoad(pressure_field, pos + vec3<i32>(0, 1, 0), 0).x;\n let pBack = textureLoad(pressure_field, pos + vec3<i32>(0, 0, -1), 0).x;\n let pFront = textureLoad(pressure_field, pos + vec3<i32>(0, 0, 1), 0).x;\n\n let old_vel = textureLoad(field_in, pos, 0).xyz;\n let grad = vec3<f32>(pRight - pLeft, pUp - pDown, pFront - pBack) * 0.5;\n let new_vel = old_vel - grad;\n\n textureStore(field_out, global_id, vec4<f32>(new_vel, 1.0));\n}\n";
|
|
2
|
+
export default fluidSimShader;
|
|
3
|
+
//# sourceMappingURL=fluid_sim.generated.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fluid_sim.generated.d.ts","sourceRoot":"","sources":["../../../src/webgpu/shaders/fluid_sim.generated.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,cAAc,09KA4I1B,CAAC;AAEF,eAAe,cAAc,CAAC"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
// AUTO-GENERATED FILE - DO NOT EDIT
|
|
2
|
+
// Generated from .wgsl source by scripts/build-shaders.ts
|
|
3
|
+
export const fluidSimShader = `// fluid_sim.wgsl
|
|
4
|
+
// 3D Fluid Simulation Compute Shaders
|
|
5
|
+
|
|
6
|
+
struct FluidUniforms {
|
|
7
|
+
dt: f32,
|
|
8
|
+
width: f32,
|
|
9
|
+
height: f32,
|
|
10
|
+
depth: f32,
|
|
11
|
+
decay: f32,
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
@group(0) @binding(0) var<uniform> uniforms: FluidUniforms;
|
|
15
|
+
|
|
16
|
+
// Bindings for Double-Buffering (Read -> Write)
|
|
17
|
+
// Group 1: Velocity / Density
|
|
18
|
+
@group(1) @binding(0) var field_in: texture_3d<f32>;
|
|
19
|
+
@group(1) @binding(1) var field_out: texture_storage_3d<rgba16float, write>;
|
|
20
|
+
|
|
21
|
+
// Sampler for linear interpolation
|
|
22
|
+
@group(1) @binding(2) var field_sampler: sampler;
|
|
23
|
+
|
|
24
|
+
// ----------------------------------------------------------------------------
|
|
25
|
+
// ADVECTION
|
|
26
|
+
// Moves quantities along the velocity field
|
|
27
|
+
// ----------------------------------------------------------------------------
|
|
28
|
+
@group(2) @binding(0) var velocity_field: texture_3d<f32>;
|
|
29
|
+
|
|
30
|
+
@compute @workgroup_size(8, 8, 8)
|
|
31
|
+
fn advect(@builtin(global_invocation_id) global_id: vec3<u32>) {
|
|
32
|
+
let dims = vec3<f32>(uniforms.width, uniforms.height, uniforms.depth);
|
|
33
|
+
let coords = vec3<f32>(global_id);
|
|
34
|
+
|
|
35
|
+
if (any(coords >= dims)) { return; }
|
|
36
|
+
|
|
37
|
+
// 1. Sample velocity at current position
|
|
38
|
+
// Note: textureSampleLevel requires normalized coordinates [0, 1]
|
|
39
|
+
let uvw = (coords + 0.5) / dims;
|
|
40
|
+
let vel = textureSampleLevel(velocity_field, field_sampler, uvw, 0.0).xyz;
|
|
41
|
+
|
|
42
|
+
// 2. Trace back in time
|
|
43
|
+
let dt = uniforms.dt;
|
|
44
|
+
// Scale velocity back to grid units?
|
|
45
|
+
// Uniforms velocity tends to be in grid-units per second.
|
|
46
|
+
// Backtrace coordinate:
|
|
47
|
+
let back_pos = coords - vel * dt;
|
|
48
|
+
|
|
49
|
+
// 3. Sample field at previous position
|
|
50
|
+
let back_uvw = (back_pos + 0.5) / dims;
|
|
51
|
+
let new_val = textureSampleLevel(field_in, field_sampler, back_uvw, 0.0);
|
|
52
|
+
|
|
53
|
+
// 4. Apply decay
|
|
54
|
+
let decayed = new_val * uniforms.decay;
|
|
55
|
+
|
|
56
|
+
textureStore(field_out, global_id, decayed);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// ----------------------------------------------------------------------------
|
|
60
|
+
// DIFFUSION (Jacobi Iteration)
|
|
61
|
+
// ----------------------------------------------------------------------------
|
|
62
|
+
// x_new = (x_old + alpha * neighbor_sum) * inverse_beta
|
|
63
|
+
struct JacobiUniforms {
|
|
64
|
+
alpha: f32,
|
|
65
|
+
rBeta: f32,
|
|
66
|
+
};
|
|
67
|
+
@group(3) @binding(0) var<uniform> jacobi: JacobiUniforms;
|
|
68
|
+
@group(3) @binding(1) var b_field: texture_3d<f32>; // The 'b' vector in Ax=b (usually previous state or inputs)
|
|
69
|
+
@group(3) @binding(2) var x_field: texture_3d<f32>; // The 'x' vector (current guess)
|
|
70
|
+
|
|
71
|
+
@compute @workgroup_size(8, 8, 8)
|
|
72
|
+
fn diffuse(@builtin(global_invocation_id) global_id: vec3<u32>) {
|
|
73
|
+
let dims = vec3<i32>(i32(uniforms.width), i32(uniforms.height), i32(uniforms.depth));
|
|
74
|
+
let pos = vec3<i32>(global_id);
|
|
75
|
+
|
|
76
|
+
if (any(pos >= dims)) { return; }
|
|
77
|
+
|
|
78
|
+
// Neighbors
|
|
79
|
+
let left = textureLoad(x_field, pos + vec3<i32>(-1, 0, 0), 0);
|
|
80
|
+
let right = textureLoad(x_field, pos + vec3<i32>(1, 0, 0), 0);
|
|
81
|
+
let down = textureLoad(x_field, pos + vec3<i32>(0, -1, 0), 0);
|
|
82
|
+
let up = textureLoad(x_field, pos + vec3<i32>(0, 1, 0), 0);
|
|
83
|
+
let back = textureLoad(x_field, pos + vec3<i32>(0, 0, -1), 0);
|
|
84
|
+
let front = textureLoad(x_field, pos + vec3<i32>(0, 0, 1), 0);
|
|
85
|
+
|
|
86
|
+
let bC = textureLoad(b_field, pos, 0);
|
|
87
|
+
|
|
88
|
+
// Jacobi step
|
|
89
|
+
let result = (left + right + down + up + back + front) * jacobi.alpha + bC;
|
|
90
|
+
let next_val = result * jacobi.rBeta;
|
|
91
|
+
|
|
92
|
+
textureStore(field_out, global_id, next_val);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// ----------------------------------------------------------------------------
|
|
96
|
+
// DIVERGENCE
|
|
97
|
+
// ----------------------------------------------------------------------------
|
|
98
|
+
@compute @workgroup_size(8, 8, 8)
|
|
99
|
+
fn divergence(@builtin(global_invocation_id) global_id: vec3<u32>) {
|
|
100
|
+
let dims = vec3<i32>(i32(uniforms.width), i32(uniforms.height), i32(uniforms.depth));
|
|
101
|
+
let pos = vec3<i32>(global_id);
|
|
102
|
+
|
|
103
|
+
if (any(pos >= dims)) { return; }
|
|
104
|
+
|
|
105
|
+
let left = textureLoad(field_in, pos + vec3<i32>(-1, 0, 0), 0).x;
|
|
106
|
+
let right = textureLoad(field_in, pos + vec3<i32>(1, 0, 0), 0).x;
|
|
107
|
+
let down = textureLoad(field_in, pos + vec3<i32>(0, -1, 0), 0).y;
|
|
108
|
+
let up = textureLoad(field_in, pos + vec3<i32>(0, 1, 0), 0).y;
|
|
109
|
+
let back = textureLoad(field_in, pos + vec3<i32>(0, 0, -1), 0).z;
|
|
110
|
+
let front = textureLoad(field_in, pos + vec3<i32>(0, 0, 1), 0).z;
|
|
111
|
+
|
|
112
|
+
let div = 0.5 * ((right - left) + (up - down) + (front - back));
|
|
113
|
+
|
|
114
|
+
textureStore(field_out, global_id, vec4<f32>(div, 0.0, 0.0, 1.0));
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// ----------------------------------------------------------------------------
|
|
118
|
+
// GRADIENT SUBTRACTION
|
|
119
|
+
// u_new = u_old - gradient(p)
|
|
120
|
+
// ----------------------------------------------------------------------------
|
|
121
|
+
@group(4) @binding(0) var pressure_field: texture_3d<f32>;
|
|
122
|
+
|
|
123
|
+
@compute @workgroup_size(8, 8, 8)
|
|
124
|
+
fn subtract_gradient(@builtin(global_invocation_id) global_id: vec3<u32>) {
|
|
125
|
+
let dims = vec3<i32>(i32(uniforms.width), i32(uniforms.height), i32(uniforms.depth));
|
|
126
|
+
let pos = vec3<i32>(global_id);
|
|
127
|
+
|
|
128
|
+
if (any(pos >= dims)) { return; }
|
|
129
|
+
|
|
130
|
+
let pLeft = textureLoad(pressure_field, pos + vec3<i32>(-1, 0, 0), 0).x;
|
|
131
|
+
let pRight = textureLoad(pressure_field, pos + vec3<i32>(1, 0, 0), 0).x;
|
|
132
|
+
let pDown = textureLoad(pressure_field, pos + vec3<i32>(0, -1, 0), 0).x;
|
|
133
|
+
let pUp = textureLoad(pressure_field, pos + vec3<i32>(0, 1, 0), 0).x;
|
|
134
|
+
let pBack = textureLoad(pressure_field, pos + vec3<i32>(0, 0, -1), 0).x;
|
|
135
|
+
let pFront = textureLoad(pressure_field, pos + vec3<i32>(0, 0, 1), 0).x;
|
|
136
|
+
|
|
137
|
+
let old_vel = textureLoad(field_in, pos, 0).xyz;
|
|
138
|
+
let grad = vec3<f32>(pRight - pLeft, pUp - pDown, pFront - pBack) * 0.5;
|
|
139
|
+
let new_vel = old_vel - grad;
|
|
140
|
+
|
|
141
|
+
textureStore(field_out, global_id, vec4<f32>(new_vel, 1.0));
|
|
142
|
+
}
|
|
143
|
+
`;
|
|
144
|
+
export default fluidSimShader;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@buley/hexgrid-3d",
|
|
3
|
-
"version": "3.2.
|
|
3
|
+
"version": "3.2.3",
|
|
4
4
|
"description": "3D hexagonal grid visualization component for React",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -20,23 +20,30 @@
|
|
|
20
20
|
"exports": {
|
|
21
21
|
".": {
|
|
22
22
|
"types": "./dist/index.d.ts",
|
|
23
|
-
"import": "./dist/index.js"
|
|
23
|
+
"import": "./dist/index.js",
|
|
24
|
+
"default": "./dist/index.js"
|
|
24
25
|
},
|
|
25
26
|
"./components": {
|
|
26
27
|
"types": "./dist/components/index.d.ts",
|
|
27
|
-
"import": "./dist/components/index.js"
|
|
28
|
+
"import": "./dist/components/index.js",
|
|
29
|
+
"default": "./dist/components/index.js"
|
|
28
30
|
},
|
|
29
31
|
"./stores": {
|
|
30
32
|
"types": "./dist/stores/index.d.ts",
|
|
31
|
-
"import": "./dist/stores/index.js"
|
|
33
|
+
"import": "./dist/stores/index.js",
|
|
34
|
+
"default": "./dist/stores/index.js"
|
|
32
35
|
},
|
|
33
36
|
"./algorithms": {
|
|
34
37
|
"types": "./dist/algorithms/index.d.ts",
|
|
35
|
-
"import": "./dist/algorithms/index.js"
|
|
38
|
+
"import": "./dist/algorithms/index.js",
|
|
39
|
+
"default": "./dist/algorithms/index.js"
|
|
36
40
|
}
|
|
37
41
|
},
|
|
38
42
|
"scripts": {
|
|
43
|
+
"build:shaders": "bun run scripts/build-shaders.ts",
|
|
44
|
+
"prebuild": "bun run build:shaders",
|
|
39
45
|
"build": "tsc -p tsconfig.build.json",
|
|
46
|
+
"lint:wgsl": "bun run scripts/build-shaders.ts",
|
|
40
47
|
"dev": "tsc --watch",
|
|
41
48
|
"test": "bun test",
|
|
42
49
|
"test:watch": "bun test --watch",
|