glre 0.39.0 → 0.40.0
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/README.md +8 -4
- package/dist/addons.cjs +1 -1
- package/dist/addons.cjs.map +1 -1
- package/dist/addons.d.ts +849 -19
- package/dist/addons.js +1 -1
- package/dist/addons.js.map +1 -1
- package/dist/index.cjs +8 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +38 -20
- package/dist/index.js +8 -8
- package/dist/index.js.map +1 -1
- package/dist/native.d.ts +48 -22
- package/dist/node.cjs +59 -30
- package/dist/node.cjs.map +1 -1
- package/dist/node.d.ts +34 -22
- package/dist/node.js +59 -30
- package/dist/node.js.map +1 -1
- package/dist/react.d.ts +38 -20
- package/dist/solid.d.ts +38 -20
- package/package.json +24 -24
- package/src/addons/animation/easing/backIn.ts +10 -0
- package/src/addons/animation/easing/backInOut.ts +12 -0
- package/src/addons/animation/easing/backOut.ts +10 -0
- package/src/addons/animation/easing/bounceIn.ts +10 -0
- package/src/addons/animation/easing/bounceInOut.ts +13 -0
- package/src/addons/animation/easing/bounceOut.ts +30 -0
- package/src/addons/animation/easing/circularIn.ts +9 -0
- package/src/addons/animation/easing/circularInOut.ts +11 -0
- package/src/addons/animation/easing/circularOut.ts +9 -0
- package/src/addons/animation/easing/cubicIn.ts +9 -0
- package/src/addons/animation/easing/cubicInOut.ts +11 -0
- package/src/addons/animation/easing/cubicOut.ts +10 -0
- package/src/addons/animation/easing/elasticIn.ts +10 -0
- package/src/addons/animation/easing/elasticInOut.ts +21 -0
- package/src/addons/animation/easing/elasticOut.ts +12 -0
- package/src/addons/animation/easing/exponentialIn.ts +9 -0
- package/src/addons/animation/easing/exponentialInOut.ts +13 -0
- package/src/addons/animation/easing/exponentialOut.ts +9 -0
- package/src/addons/animation/easing/index.ts +33 -0
- package/src/addons/animation/easing/linearIn.ts +9 -0
- package/src/addons/animation/easing/linearInOut.ts +9 -0
- package/src/addons/animation/easing/linearOut.ts +9 -0
- package/src/addons/animation/easing/quadraticIn.ts +9 -0
- package/src/addons/animation/easing/quadraticInOut.ts +10 -0
- package/src/addons/animation/easing/quadraticOut.ts +9 -0
- package/src/addons/animation/easing/quarticIn.ts +9 -0
- package/src/addons/animation/easing/quarticInOut.ts +11 -0
- package/src/addons/animation/easing/quarticOut.ts +10 -0
- package/src/addons/animation/easing/quinticIn.ts +9 -0
- package/src/addons/animation/easing/quinticInOut.ts +11 -0
- package/src/addons/animation/easing/quinticOut.ts +9 -0
- package/src/addons/animation/easing/sineIn.ts +10 -0
- package/src/addons/animation/easing/sineInOut.ts +10 -0
- package/src/addons/animation/easing/sineOut.ts +10 -0
- package/src/addons/color/palette/macbeth.ts +42 -0
- package/src/addons/color/space/cmyk2rgb.ts +12 -0
- package/src/addons/color/space/gamma2linear.ts +19 -0
- package/src/addons/color/space/hsl2rgb.ts +20 -0
- package/src/addons/color/space/hsv2rgb.ts +18 -0
- package/src/addons/color/space/hue2rgb.ts +12 -0
- package/src/addons/color/space/index.ts +29 -0
- package/src/addons/color/space/lab2lch.ts +22 -0
- package/src/addons/color/space/lab2rgb.ts +19 -0
- package/src/addons/color/space/lab2xyz.ts +32 -0
- package/src/addons/color/space/lch2lab.ts +21 -0
- package/src/addons/color/space/lch2rgb.ts +22 -0
- package/src/addons/color/space/linear2gamma.ts +19 -0
- package/src/addons/color/space/oklab2rgb.ts +35 -0
- package/src/addons/color/space/rgb2cmyk.ts +13 -0
- package/src/addons/color/space/rgb2hcv.ts +29 -0
- package/src/addons/color/space/rgb2hsl.ts +23 -0
- package/src/addons/color/space/rgb2hsv.ts +36 -0
- package/src/addons/color/space/rgb2hue.ts +29 -0
- package/src/addons/color/space/rgb2lab.ts +19 -0
- package/src/addons/color/space/rgb2lch.ts +22 -0
- package/src/addons/color/space/rgb2oklab.ts +45 -0
- package/src/addons/color/space/rgb2srgb.ts +34 -0
- package/src/addons/color/space/rgb2xyz.ts +20 -0
- package/src/addons/color/space/rgb2yiq.ts +22 -0
- package/src/addons/color/space/rgb2yuv.ts +32 -0
- package/src/addons/color/space/srgb2rgb.ts +34 -0
- package/src/addons/color/space/xyz2lab.ts +27 -0
- package/src/addons/color/space/xyz2rgb.ts +30 -0
- package/src/addons/color/space/yiq2rgb.ts +22 -0
- package/src/addons/color/space/yuv2rgb.ts +32 -0
- package/src/addons/draw/arrows.ts +75 -0
- package/src/addons/draw/axis.ts +57 -0
- package/src/addons/draw/bridge.ts +81 -0
- package/src/addons/draw/char.ts +30 -0
- package/src/addons/draw/circle.ts +29 -0
- package/src/addons/draw/fill.ts +25 -0
- package/src/addons/draw/flip.ts +45 -0
- package/src/addons/draw/hex.ts +29 -0
- package/src/addons/draw/index.ts +13 -0
- package/src/addons/draw/line.ts +16 -0
- package/src/addons/draw/point.ts +30 -0
- package/src/addons/draw/rect.ts +52 -0
- package/src/addons/draw/stroke.ts +31 -0
- package/src/addons/draw/tri.ts +29 -0
- package/src/addons/generative/cnoise.ts +239 -0
- package/src/addons/generative/curl.ts +64 -0
- package/src/addons/generative/fbm.ts +69 -0
- package/src/addons/generative/gerstnerWave.ts +21 -0
- package/src/addons/generative/gnoise.ts +113 -0
- package/src/addons/generative/index.ts +15 -0
- package/src/addons/generative/noised.ts +139 -0
- package/src/addons/generative/pnoise.ts +249 -0
- package/src/addons/generative/psrdnoise.ts +277 -0
- package/src/addons/generative/random.ts +136 -0
- package/src/addons/generative/snoise.ts +199 -0
- package/src/addons/generative/srandom.ts +90 -0
- package/src/addons/generative/voronoi.ts +134 -0
- package/src/addons/generative/voronoise.ts +69 -0
- package/src/addons/generative/wavelet.ts +77 -0
- package/src/addons/generative/worley.ts +99 -0
- package/src/addons/geometry/aabb/aabb.ts +8 -0
- package/src/addons/geometry/aabb/centroid.ts +10 -0
- package/src/addons/geometry/aabb/contain.ts +19 -0
- package/src/addons/geometry/aabb/diagonal.ts +10 -0
- package/src/addons/geometry/aabb/expand.ts +16 -0
- package/src/addons/geometry/aabb/index.ts +7 -0
- package/src/addons/geometry/aabb/intersect.ts +20 -0
- package/src/addons/geometry/aabb/square.ts +17 -0
- package/src/addons/geometry/index.ts +2 -0
- package/src/addons/geometry/triangle/area.ts +10 -0
- package/src/addons/geometry/triangle/barycentric.ts +50 -0
- package/src/addons/geometry/triangle/centroid.ts +10 -0
- package/src/addons/geometry/triangle/closestPoint.ts +85 -0
- package/src/addons/geometry/triangle/contain.ts +19 -0
- package/src/addons/geometry/triangle/distanceSq.ts +38 -0
- package/src/addons/geometry/triangle/index.ts +10 -0
- package/src/addons/geometry/triangle/intersect.ts +49 -0
- package/src/addons/geometry/triangle/normal.ts +12 -0
- package/src/addons/geometry/triangle/signedDistance.ts +31 -0
- package/src/addons/geometry/triangle/triangle.ts +9 -0
- package/src/addons/index.ts +8 -6
- package/src/addons/lighting/ray.ts +8 -0
- package/src/addons/math/aafloor.ts +13 -0
- package/src/addons/math/aafract.ts +38 -0
- package/src/addons/math/aamirror.ts +12 -0
- package/src/addons/math/aastep.ts +14 -0
- package/src/addons/math/absi.ts +9 -0
- package/src/addons/math/adaptiveThreshold.ts +24 -0
- package/src/addons/math/bump.ts +20 -0
- package/src/addons/math/const.ts +19 -0
- package/src/addons/math/cubic.ts +101 -0
- package/src/addons/math/cubicMix.ts +49 -0
- package/src/addons/math/decimate.ts +12 -0
- package/src/addons/math/dist.ts +143 -0
- package/src/addons/math/fcos.ts +11 -0
- package/src/addons/math/frac.ts +9 -0
- package/src/addons/math/gain.ts +14 -0
- package/src/addons/math/gaussian.ts +14 -0
- package/src/addons/math/grad4.ts +19 -0
- package/src/addons/math/hammersley.ts +54 -0
- package/src/addons/math/highPass.ts +12 -0
- package/src/addons/math/index.ts +63 -0
- package/src/addons/math/inside.ts +68 -0
- package/src/addons/math/invCubic.ts +9 -0
- package/src/addons/math/invQuartic.ts +9 -0
- package/src/addons/math/inverse.ts +9 -0
- package/src/addons/math/lengthSq.ts +10 -0
- package/src/addons/math/map.ts +27 -0
- package/src/addons/math/mirror.ts +12 -0
- package/src/addons/math/mmax.ts +27 -0
- package/src/addons/math/mmin.ts +28 -0
- package/src/addons/math/mmix.ts +47 -0
- package/src/addons/math/mod2.ts +44 -0
- package/src/addons/math/mod289.ts +46 -0
- package/src/addons/math/modi.ts +15 -0
- package/src/addons/math/nyquist.ts +15 -0
- package/src/addons/math/pack.ts +15 -0
- package/src/addons/math/parabola.ts +12 -0
- package/src/addons/math/permute.ts +42 -0
- package/src/addons/math/pow2.ts +10 -0
- package/src/addons/math/pow3.ts +9 -0
- package/src/addons/math/pow5.ts +10 -0
- package/src/addons/math/pow7.ts +12 -0
- package/src/addons/math/powFast.ts +18 -0
- package/src/addons/math/quartic.ts +15 -0
- package/src/addons/math/quat/index.ts +14 -0
- package/src/addons/math/quat/quat2mat3.ts +28 -0
- package/src/addons/math/quat/quat2mat4.ts +16 -0
- package/src/addons/math/quat/quatAdd.ts +18 -0
- package/src/addons/math/quat/quatConj.ts +14 -0
- package/src/addons/math/quat/quatDiv.ts +18 -0
- package/src/addons/math/quat/quatIdentity.ts +9 -0
- package/src/addons/math/quat/quatInverse.ts +17 -0
- package/src/addons/math/quat/quatLength.ts +15 -0
- package/src/addons/math/quat/quatLengthSq.ts +14 -0
- package/src/addons/math/quat/quatLerp.ts +40 -0
- package/src/addons/math/quat/quatMul.ts +38 -0
- package/src/addons/math/quat/quatNeg.ts +14 -0
- package/src/addons/math/quat/quatNorm.ts +16 -0
- package/src/addons/math/quat/quatSub.ts +18 -0
- package/src/addons/math/quintic.ts +16 -0
- package/src/addons/math/rotate2d.ts +16 -0
- package/src/addons/math/rotate3d.ts +37 -0
- package/src/addons/math/rotate3dX.ts +20 -0
- package/src/addons/math/rotate3dY.ts +20 -0
- package/src/addons/math/rotate3dZ.ts +20 -0
- package/src/addons/math/rotate4d.ts +41 -0
- package/src/addons/math/rotate4dX.ts +21 -0
- package/src/addons/math/rotate4dY.ts +16 -0
- package/src/addons/math/rotate4dZ.ts +21 -0
- package/src/addons/math/saturateMediump.ts +11 -0
- package/src/addons/math/scale2d.ts +44 -0
- package/src/addons/math/scale3d.ts +17 -0
- package/src/addons/math/scale4d.ts +50 -0
- package/src/addons/math/smootherstep.ts +16 -0
- package/src/addons/math/taylorInvSqrt.ts +9 -0
- package/src/addons/math/toMat3.ts +14 -0
- package/src/addons/math/toMat4.ts +14 -0
- package/src/addons/math/translate4d.ts +31 -0
- package/src/addons/math/unpack.ts +88 -0
- package/src/addons/sdf/boxSDF.ts +24 -0
- package/src/addons/sdf/circleSDF.ts +20 -0
- package/src/addons/sdf/crossSDF.ts +17 -0
- package/src/addons/sdf/hexSDF.ts +18 -0
- package/src/addons/sdf/index.ts +7 -0
- package/src/addons/sdf/lineSDF.ts +33 -0
- package/src/addons/sdf/rectSDF.ts +46 -0
- package/src/addons/sdf/sphereSDF.ts +20 -0
- package/src/addons/sdf/triSDF.ts +14 -0
- package/src/addons/space/aspect.ts +14 -0
- package/src/addons/space/bracketing.ts +44 -0
- package/src/addons/space/brickTile.ts +44 -0
- package/src/addons/space/cart2polar.ts +20 -0
- package/src/addons/space/center.ts +32 -0
- package/src/addons/space/checkerTile.ts +41 -0
- package/src/addons/space/depth2viewZ.ts +43 -0
- package/src/addons/space/displace.ts +55 -0
- package/src/addons/space/equirect2xyz.ts +17 -0
- package/src/addons/space/eulerView.ts +19 -0
- package/src/addons/space/fisheye2xyz.ts +18 -0
- package/src/addons/space/flipY.ts +25 -0
- package/src/addons/space/hexTile.ts +18 -0
- package/src/addons/space/index.ts +38 -0
- package/src/addons/space/kaleidoscope.ts +48 -0
- package/src/addons/space/linearizeDepth.ts +17 -0
- package/src/addons/space/lookAt.ts +49 -0
- package/src/addons/space/lookAtView.ts +40 -0
- package/src/addons/space/mirrorTile.ts +73 -0
- package/src/addons/space/nearest.ts +13 -0
- package/src/addons/space/orthographic.ts +25 -0
- package/src/addons/space/parallaxMapping.ts +149 -0
- package/src/addons/space/perspective.ts +24 -0
- package/src/addons/space/polar2cart.ts +24 -0
- package/src/addons/space/ratio.ts +14 -0
- package/src/addons/space/rotate.ts +37 -0
- package/src/addons/space/rotateX.ts +54 -0
- package/src/addons/space/rotateY.ts +54 -0
- package/src/addons/space/rotateZ.ts +54 -0
- package/src/addons/space/scale.ts +13 -0
- package/src/addons/space/sprite.ts +16 -0
- package/src/addons/space/sqTile.ts +20 -0
- package/src/addons/space/tbn.ts +26 -0
- package/src/addons/space/translate.ts +12 -0
- package/src/addons/space/triTile.ts +32 -0
- package/src/addons/space/uncenter.ts +32 -0
- package/src/addons/space/unratio.ts +12 -0
- package/src/addons/space/viewZ2depth.ts +25 -0
- package/src/addons/space/windmillTile.ts +58 -0
- package/src/addons/space/xyz2equirect.ts +10 -0
- package/src/index.ts +5 -2
- package/src/node/build.ts +62 -52
- package/src/node/create.ts +3 -0
- package/src/node/index.ts +1 -2
- package/src/node/scope.ts +26 -25
- package/src/node/types.ts +15 -11
- package/src/node/utils/const.ts +12 -11
- package/src/node/utils/index.ts +14 -12
- package/src/node/utils/infer.ts +15 -5
- package/src/node/utils/parse.ts +37 -13
- package/src/node/utils/utils.ts +46 -23
- package/src/types.ts +9 -2
- package/src/utils/helpers.ts +56 -0
- package/src/utils/pipeline.ts +21 -5
- package/src/utils/program.ts +57 -38
- package/src/utils/webgl.ts +41 -35
- package/src/utils/webgpu.ts +19 -35
package/src/node/utils/parse.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { infer } from './infer'
|
|
|
3
3
|
import { getConversions, addDependency } from './utils'
|
|
4
4
|
import { is } from '../../utils/helpers'
|
|
5
5
|
import type { Constants, NodeContext, NodeProps, StructFields, Y } from '../types'
|
|
6
|
+
import { storageSize } from '../../utils/program'
|
|
6
7
|
|
|
7
8
|
export const parseArray = (children: Y[], c: NodeContext) => {
|
|
8
9
|
return children
|
|
@@ -22,9 +23,9 @@ export const parseGather = (c: NodeContext, x: Y, y: Y, target: Y) => {
|
|
|
22
23
|
throw new Error(`Unsupported storage scatter type: ${valueType}`)
|
|
23
24
|
}
|
|
24
25
|
const indexVar = code(y, c)
|
|
25
|
-
const
|
|
26
|
-
const coordX = `int(${indexVar}) % ${
|
|
27
|
-
const coordY = `int(${indexVar}) / ${
|
|
26
|
+
const size = storageSize(c.gl?.particleCount)
|
|
27
|
+
const coordX = `int(${indexVar}) % ${size.x}`
|
|
28
|
+
const coordY = `int(${indexVar}) / ${size.x}`
|
|
28
29
|
return `texelFetch(${code(x, c)}, ivec2(${coordX}, ${coordY}), 0)${parseSwizzle()}`
|
|
29
30
|
}
|
|
30
31
|
|
|
@@ -123,16 +124,13 @@ export const parseStruct = (c: NodeContext, id: string, instanceId = '', initial
|
|
|
123
124
|
export const parseDefine = (c: NodeContext, props: NodeProps, target: Y) => {
|
|
124
125
|
const { id, children = [], layout } = props
|
|
125
126
|
const [x, ...args] = children
|
|
126
|
-
const argParams: [name: string, type:
|
|
127
|
+
const argParams: [name: string, type: Constants][] = []
|
|
127
128
|
const params: string[] = []
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
for (let i = 0; i < args.length; i++) {
|
|
134
|
-
argParams.push([`p${i}`, infer(args[i], c)])
|
|
135
|
-
}
|
|
129
|
+
for (let i = 0; i < args.length; i++) {
|
|
130
|
+
const input = layout?.inputs?.[i]
|
|
131
|
+
if (!input) argParams.push([`p${i}`, infer(args[i], c)])
|
|
132
|
+
else argParams.push([input.name, input.type === 'auto' ? infer(args[i], c) : input.type])
|
|
133
|
+
}
|
|
136
134
|
const scopeCode = code(x, c) // build struct headers before inferring returnType
|
|
137
135
|
const returnType = infer(target, c)
|
|
138
136
|
const ret = []
|
|
@@ -158,7 +156,7 @@ export const parseDefine = (c: NodeContext, props: NodeProps, target: Y) => {
|
|
|
158
156
|
/**
|
|
159
157
|
* headers
|
|
160
158
|
*/
|
|
161
|
-
export const parseVaryingHead = (c: NodeContext, id: string, type:
|
|
159
|
+
export const parseVaryingHead = (c: NodeContext, id: string, type: Constants) => {
|
|
162
160
|
return c.isWebGL
|
|
163
161
|
? `${type} ${id};`
|
|
164
162
|
: `@location(${c.code?.vertVaryings?.size || 0}) ${id}: ${getConversions(type, c)}`
|
|
@@ -201,6 +199,32 @@ export const parseStorageHead = (c: NodeContext, id: string, type: Constants) =>
|
|
|
201
199
|
return `@group(${group}) @binding(${binding}) var<storage, read_write> ${id}: array<${wgslType}>;`
|
|
202
200
|
}
|
|
203
201
|
|
|
202
|
+
export const parseLoop = (c: NodeContext, x: Y, y: Y, id: string) => {
|
|
203
|
+
const conditionType = infer(x, c)
|
|
204
|
+
const bodyCode = code(y, c)
|
|
205
|
+
const conditionCode = code(x, c)
|
|
206
|
+
if (c.isWebGL) {
|
|
207
|
+
if (conditionType === 'int')
|
|
208
|
+
return `for (int ${id} = 0; ${id} < ${conditionCode}; ${id} += 1) {\n${bodyCode}\n}`
|
|
209
|
+
if (conditionType === 'float')
|
|
210
|
+
return `for (float ${id} = 0.0; ${id} < ${conditionCode}; ${id} += 1.0) {\n${bodyCode}\n}`
|
|
211
|
+
if (conditionType === 'vec2')
|
|
212
|
+
return `for (vec2 ${id} = vec2(0.0); ${id}.x < ${conditionCode}.x && ${id}.y < ${conditionCode}.y; ${id} += vec2(1.0)) {\n${bodyCode}\n}`
|
|
213
|
+
if (conditionType === 'vec3')
|
|
214
|
+
return `for (vec3 ${id} = vec3(0.0); ${id}.x < ${conditionCode}.x && ${id}.y < ${conditionCode}.y && ${id}.z < ${conditionCode}.z; ${id} += vec3(1.0)) {\n${bodyCode}\n}`
|
|
215
|
+
return `for (int ${id} = 0; ${id} < ${conditionCode}; ${id} += 1) {\n${bodyCode}\n}`
|
|
216
|
+
}
|
|
217
|
+
if (conditionType === 'int')
|
|
218
|
+
return `for (var ${id}: i32 = 0; ${id} < ${conditionCode}; ${id}++) {\n${bodyCode}\n}`
|
|
219
|
+
if (conditionType === 'float')
|
|
220
|
+
return `for (var ${id}: f32 = 0.0; ${id} < ${conditionCode}; ${id} += 1.0) {\n${bodyCode}\n}`
|
|
221
|
+
if (conditionType === 'vec2')
|
|
222
|
+
return `for (var ${id}: vec2f = vec2f(0.0); ${id}.x < ${conditionCode}.x && ${id}.y < ${conditionCode}.y; ${id} += vec2f(1.0)) {\n${bodyCode}\n}`
|
|
223
|
+
if (conditionType === 'vec3')
|
|
224
|
+
return `for (var ${id}: vec3f = vec3f(0.0); ${id}.x < ${conditionCode}.x && ${id}.y < ${conditionCode}.y && ${id}.z < ${conditionCode}.z; ${id} += vec3f(1.0)) {\n${bodyCode}\n}`
|
|
225
|
+
return `for (var ${id}: i32 = 0; ${id} < ${conditionCode}; ${id}++) {\n${bodyCode}\n}`
|
|
226
|
+
}
|
|
227
|
+
|
|
204
228
|
export const parseConstantHead = (c: NodeContext, id: string, type: Constants, value: string) => {
|
|
205
229
|
return c.isWebGL ? `const ${type} ${id} = ${value};` : `const ${id}: ${getConversions(type, c)} = ${value};`
|
|
206
230
|
}
|
package/src/node/utils/utils.ts
CHANGED
|
@@ -8,7 +8,18 @@ import {
|
|
|
8
8
|
WGSL_TO_GLSL_BUILTIN,
|
|
9
9
|
} from './const'
|
|
10
10
|
import { is } from '../../utils/helpers'
|
|
11
|
-
import type {
|
|
11
|
+
import type {
|
|
12
|
+
Constants as C,
|
|
13
|
+
Conversions,
|
|
14
|
+
Functions,
|
|
15
|
+
NodeContext,
|
|
16
|
+
NodeTypes,
|
|
17
|
+
Operators,
|
|
18
|
+
Swizzles,
|
|
19
|
+
X,
|
|
20
|
+
Y,
|
|
21
|
+
} from '../types'
|
|
22
|
+
import { storageSize } from '../../utils/program'
|
|
12
23
|
|
|
13
24
|
export const isSwizzle = (key: unknown): key is Swizzles => {
|
|
14
25
|
return is.str(key) && /^[xyzwrgbastpq]{1,4}$/.test(key)
|
|
@@ -50,8 +61,8 @@ export const getId = () => `x${count++}`
|
|
|
50
61
|
|
|
51
62
|
export const getBluiltin = (c: NodeContext, id: string) => {
|
|
52
63
|
if (id === 'global_invocation_id') {
|
|
53
|
-
const size =
|
|
54
|
-
return `uvec3(uint(gl_FragCoord.y) * uint(${size}) + uint(gl_FragCoord.x), 0u, 0u)`
|
|
64
|
+
const size = storageSize(c.gl?.particleCount)
|
|
65
|
+
return `uvec3(uint(gl_FragCoord.y) * uint(${size.x}) + uint(gl_FragCoord.x), 0u, 0u)`
|
|
55
66
|
}
|
|
56
67
|
const ret = WGSL_TO_GLSL_BUILTIN[id as keyof typeof WGSL_TO_GLSL_BUILTIN]
|
|
57
68
|
if (!ret) throw new Error(`Error: unknown builtin variable ${id}`)
|
|
@@ -73,26 +84,6 @@ export const getConstant = (conversionKey: string): C => {
|
|
|
73
84
|
return index !== -1 ? CONSTANTS[index] : 'float'
|
|
74
85
|
}
|
|
75
86
|
|
|
76
|
-
export const getEventFun = (c: NodeContext, id: string, isAttribute = false, isTexture = false) => {
|
|
77
|
-
if (c.isWebGL) {
|
|
78
|
-
if (isAttribute) return (value: any) => c.gl?.attribute?.(id, value)
|
|
79
|
-
if (isTexture) return (value: any) => c.gl?.texture?.(id, value)
|
|
80
|
-
return (value: any) => c.gl?.uniform?.(id, value)
|
|
81
|
-
}
|
|
82
|
-
if (isAttribute) return (value: any) => c.gl?._attribute?.(id, value)
|
|
83
|
-
if (isTexture) return (value: any) => c.gl?._texture?.(id, value)
|
|
84
|
-
return (value: any) => c.gl?._uniform?.(id, value)
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export const safeEventCall = <T extends C>(x: X<T>, fun: (value: unknown) => void) => {
|
|
88
|
-
if (is.und(x)) return
|
|
89
|
-
if (!isX(x)) return fun(x) // for uniform(0) or uniform([0, 1])
|
|
90
|
-
if (x.type !== 'conversion') return
|
|
91
|
-
const args = x.props.children?.slice(1)
|
|
92
|
-
if (is.und(args?.[0])) return // ignore if uniform(vec2())
|
|
93
|
-
fun(args.map((x) => x ?? args[0])) // for uniform(vec2(1)) or uniform(vec2(1, 1))
|
|
94
|
-
}
|
|
95
|
-
|
|
96
87
|
export const initNodeContext = (c: NodeContext) => {
|
|
97
88
|
if (c.code) return c
|
|
98
89
|
c.code = {
|
|
@@ -119,3 +110,35 @@ export const addDependency = (c: NodeContext, id = '', type: string) => {
|
|
|
119
110
|
if (!c.code?.dependencies?.has(id)) c.code!.dependencies.set(id, new Set())
|
|
120
111
|
if (!isConstants(type)) c.code!.dependencies.get(id)!.add(type)
|
|
121
112
|
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* uniform ant attribute event listeners
|
|
116
|
+
*/
|
|
117
|
+
const getEventFun = (c: NodeContext, id: string, type: string) => {
|
|
118
|
+
if (c.isWebGL) {
|
|
119
|
+
if (type === 'attribute') return (value: any) => c.gl?.attribute?.(id, value)
|
|
120
|
+
if (type === 'instance') return (value: any) => c.gl?.instance?.(id, value)
|
|
121
|
+
if (type === 'texture') return (value: any) => c.gl?.texture?.(id, value)
|
|
122
|
+
return (value: any) => c.gl?.uniform?.(id, value)
|
|
123
|
+
}
|
|
124
|
+
if (type === 'attribute') return (value: any) => c.gl?._attribute?.(id, value)
|
|
125
|
+
if (type === 'instance') return (value: any) => c.gl?._instance?.(id, value)
|
|
126
|
+
if (type === 'texture') return (value: any) => c.gl?._texture?.(id, value)
|
|
127
|
+
return (value: any) => c.gl?._uniform?.(id, value)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const safeEventCall = <T extends C>(x: X<T>, fun: (value: unknown) => void) => {
|
|
131
|
+
if (is.und(x)) return
|
|
132
|
+
if (!isX(x)) return fun(x) // for uniform(0) or uniform([0, 1])
|
|
133
|
+
if (x.type !== 'conversion') return
|
|
134
|
+
const args = x.props.children?.slice(1)
|
|
135
|
+
if (is.und(args?.[0])) return // ignore if uniform(vec2())
|
|
136
|
+
fun(args.map((x) => x ?? args[0])) // for uniform(vec2(1)) or uniform(vec2(1, 1))
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export const setupEvent = (c: NodeContext, id: string, type: string, target: X, child: X) => {
|
|
140
|
+
const fun = getEventFun(c, id, type)
|
|
141
|
+
safeEventCall(child, fun)
|
|
142
|
+
target.listeners.add(fun)
|
|
143
|
+
return fun
|
|
144
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -10,14 +10,17 @@ export type GL = EventState<{
|
|
|
10
10
|
isWebGL: boolean
|
|
11
11
|
isError: boolean
|
|
12
12
|
isLoop: boolean
|
|
13
|
+
isDebug: boolean
|
|
14
|
+
isDepth: boolean
|
|
13
15
|
isGL: true
|
|
14
16
|
width?: number
|
|
15
17
|
height?: number
|
|
16
18
|
size: [number, number]
|
|
17
19
|
mouse: [number, number]
|
|
18
20
|
count: number
|
|
21
|
+
instanceCount: number
|
|
22
|
+
particleCount: number | [number, number] | [number, number, number]
|
|
19
23
|
loading: number
|
|
20
|
-
particles: 64 | 256 | 576 | 1024 | 1600 | 2304 | 3136 | 4096 | 4096 | 5184 | 6400 // (8k)^2
|
|
21
24
|
el: HTMLCanvasElement
|
|
22
25
|
vs?: string | Vec4
|
|
23
26
|
cs?: string | Void
|
|
@@ -46,7 +49,7 @@ export type GL = EventState<{
|
|
|
46
49
|
error(e?: string): void
|
|
47
50
|
render(): void
|
|
48
51
|
resize(e?: Event): void
|
|
49
|
-
mousemove(e:
|
|
52
|
+
mousemove(e: MouseEvent): void
|
|
50
53
|
loop(): void
|
|
51
54
|
|
|
52
55
|
/**
|
|
@@ -61,6 +64,9 @@ export type GL = EventState<{
|
|
|
61
64
|
_attribute?(key: string, value: Attribute, iboValue?: Attribute): GL
|
|
62
65
|
attribute(key: string, value: Attribute, iboValue?: Attribute): GL
|
|
63
66
|
attribute(target: { [key: string]: Attribute }): GL
|
|
67
|
+
_instance?(key: string, value: Attribute, at?: number): GL
|
|
68
|
+
instance(key: string, value: Attribute, at?: number): GL
|
|
69
|
+
instance(target: { [key: string]: Attribute }): GL
|
|
64
70
|
_storage?(key: string, value: Storage): GL
|
|
65
71
|
storage(key: string, value: Storage): GL
|
|
66
72
|
storage(target: { [key: string]: Storage }): GL
|
|
@@ -93,6 +99,7 @@ export interface AttribData {
|
|
|
93
99
|
buffer: GPUBuffer
|
|
94
100
|
location: number
|
|
95
101
|
stride: number
|
|
102
|
+
isInstance?: boolean
|
|
96
103
|
}
|
|
97
104
|
|
|
98
105
|
export interface StorageData {
|
package/src/utils/helpers.ts
CHANGED
|
@@ -58,3 +58,59 @@ export const loadingImage = (gl: GL, src: string, fun: (source: HTMLImageElement
|
|
|
58
58
|
gl.loading--
|
|
59
59
|
})
|
|
60
60
|
}
|
|
61
|
+
|
|
62
|
+
const isValidStride = (stride: number) => [1, 2, 3, 4, 9, 16].includes(stride)
|
|
63
|
+
|
|
64
|
+
const calcStride = (arrayLength: number, count = 3) => {
|
|
65
|
+
if (arrayLength % count === 0) return Math.floor(arrayLength / count)
|
|
66
|
+
return -1
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export const getStride = (arrayLength: number, count = 1, error = console.warn) => {
|
|
70
|
+
const ret = calcStride(arrayLength, count)
|
|
71
|
+
if (!isValidStride(ret))
|
|
72
|
+
error(
|
|
73
|
+
`glre attribute error: Invalid attribute length ${arrayLength}. Must divide by vertex count (${count}) with valid stride (1,2,3,4,9,16)`
|
|
74
|
+
)
|
|
75
|
+
return ret
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export const GLSL_FS = /* cpp */ `
|
|
79
|
+
#version 300 es
|
|
80
|
+
precision mediump float;
|
|
81
|
+
out vec4 fragColor;
|
|
82
|
+
uniform vec2 iResolution;
|
|
83
|
+
void main() {
|
|
84
|
+
fragColor = vec4(fract((gl_FragCoord.xy / iResolution)), 0.0, 1.0);
|
|
85
|
+
}
|
|
86
|
+
`
|
|
87
|
+
|
|
88
|
+
export const GLSL_VS = /* cpp */ `
|
|
89
|
+
#version 300 es
|
|
90
|
+
void main() {
|
|
91
|
+
float x = float(gl_VertexID % 2) * 4.0 - 1.0;
|
|
92
|
+
float y = float(gl_VertexID / 2) * 4.0 - 1.0;
|
|
93
|
+
gl_Position = vec4(x, y, 0.0, 1.0);
|
|
94
|
+
}`
|
|
95
|
+
|
|
96
|
+
export const WGSL_VS = /* rust */ `
|
|
97
|
+
struct In { @builtin(vertex_index) vertex_index: u32 }
|
|
98
|
+
struct Out { @builtin(position) position: vec4f }
|
|
99
|
+
@vertex
|
|
100
|
+
fn main(in: In) -> Out {
|
|
101
|
+
var out: Out;
|
|
102
|
+
var x = f32(in.vertex_index % 2) * 4.0 - 1.0;
|
|
103
|
+
var y = f32(in.vertex_index / 2) * 4.0 - 1.0;
|
|
104
|
+
out.position = vec4f(x, y, 0.0, 1.0);
|
|
105
|
+
return out;
|
|
106
|
+
}
|
|
107
|
+
`.trim()
|
|
108
|
+
|
|
109
|
+
export const WGSL_FS = /* rust */ `
|
|
110
|
+
struct Out { @builtin(position) position: vec4f }
|
|
111
|
+
@group(0) @binding(0) var<uniform> iResolution: vec2f;
|
|
112
|
+
@fragment
|
|
113
|
+
fn main(out: Out) -> @location(0) vec4f {
|
|
114
|
+
return vec4f(fract((out.position.xy / iResolution)), 0.0, 1.0);
|
|
115
|
+
}
|
|
116
|
+
`
|
package/src/utils/pipeline.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isFloat32 } from './helpers'
|
|
1
|
+
import { is, isFloat32 } from './helpers'
|
|
2
2
|
import type { AttribData, TextureData, UniformData, StorageData } from '../types'
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -58,18 +58,21 @@ const getVertexFormat = (stride: number): GPUVertexFormat => {
|
|
|
58
58
|
return 'float32'
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
export const createVertexBuffers = (attribs: Iterable<AttribData>) => {
|
|
61
|
+
export const createVertexBuffers = (attribs: Iterable<AttribData & { isInstance?: boolean }>) => {
|
|
62
62
|
const vertexBuffers: GPUBuffer[] = []
|
|
63
63
|
const bufferLayouts: GPUVertexBufferLayout[] = []
|
|
64
|
-
for (const { buffer, location, stride } of attribs) {
|
|
64
|
+
for (const { buffer, location, stride, isInstance } of attribs) {
|
|
65
65
|
vertexBuffers[location] = buffer
|
|
66
|
+
const componentSize = Math.min(Math.max(Math.floor(stride), 1), 4)
|
|
67
|
+
const arrayStride = Math.max(4, Math.ceil((componentSize * 4) / 4) * 4)
|
|
66
68
|
bufferLayouts[location] = {
|
|
67
|
-
arrayStride
|
|
69
|
+
arrayStride,
|
|
70
|
+
stepMode: isInstance ? 'instance' : 'vertex',
|
|
68
71
|
attributes: [
|
|
69
72
|
{
|
|
70
73
|
shaderLocation: location,
|
|
71
74
|
offset: 0,
|
|
72
|
-
format: getVertexFormat(
|
|
75
|
+
format: getVertexFormat(componentSize),
|
|
73
76
|
},
|
|
74
77
|
],
|
|
75
78
|
}
|
|
@@ -203,3 +206,16 @@ export const createDepthTexture = (device: GPUDevice, width: number, height: num
|
|
|
203
206
|
usage: GPUTextureUsage.RENDER_ATTACHMENT,
|
|
204
207
|
})
|
|
205
208
|
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* utils
|
|
212
|
+
*/
|
|
213
|
+
export const workgroupCount = (particleCount: number | number[], workgroupSize = 32) => {
|
|
214
|
+
if (is.num(particleCount)) particleCount = [particleCount]
|
|
215
|
+
const [x, y = 1, z = 1] = particleCount
|
|
216
|
+
return {
|
|
217
|
+
x: Math.min((x * y * z) / workgroupSize, 65535),
|
|
218
|
+
y: 1,
|
|
219
|
+
z: 1,
|
|
220
|
+
}
|
|
221
|
+
}
|
package/src/utils/program.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { is } from './helpers'
|
|
2
2
|
import type { GL } from '../types'
|
|
3
3
|
|
|
4
|
-
const createShader = (c:
|
|
4
|
+
const createShader = (c: WebGL2RenderingContext, source: string, type: number, onError = console.warn) => {
|
|
5
5
|
const shader = c.createShader(type)
|
|
6
6
|
if (!shader) return onError('Failed to create shader')
|
|
7
7
|
c.shaderSource(shader, source.trim())
|
|
@@ -12,7 +12,7 @@ const createShader = (c: WebGLRenderingContext, source: string, type: number, on
|
|
|
12
12
|
onError(`Could not compile shader: ${error}\n\n↓↓↓generated↓↓↓\n${source}`)
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
export const createProgram = (c:
|
|
15
|
+
export const createProgram = (c: WebGL2RenderingContext, frag: string, vert: string, gl: GL) => {
|
|
16
16
|
const pg = c.createProgram()
|
|
17
17
|
const fs = createShader(c, frag, c.FRAGMENT_SHADER, gl.error)
|
|
18
18
|
const vs = createShader(c, vert, c.VERTEX_SHADER, gl.error)
|
|
@@ -26,45 +26,38 @@ export const createProgram = (c: WebGLRenderingContext, frag: string, vert: stri
|
|
|
26
26
|
gl.error(`Could not link program: ${error}`)
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
const
|
|
29
|
+
export const createArrayBuffer = (c: WebGL2RenderingContext, data: number[]) => {
|
|
30
|
+
const array = new Float32Array(data)
|
|
30
31
|
const buffer = c.createBuffer()
|
|
31
|
-
|
|
32
|
-
c.bufferData(c.ARRAY_BUFFER, new Float32Array(data), c.STATIC_DRAW)
|
|
33
|
-
c.bindBuffer(c.ARRAY_BUFFER, null)
|
|
34
|
-
return buffer
|
|
32
|
+
return { array, buffer }
|
|
35
33
|
}
|
|
36
34
|
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
35
|
+
export const setArrayBuffer = (
|
|
36
|
+
c: WebGL2RenderingContext,
|
|
37
|
+
array: Float32Array,
|
|
38
|
+
buffer: WebGLBuffer,
|
|
39
|
+
value: number[]
|
|
40
|
+
) => {
|
|
41
|
+
array.set(value)
|
|
42
|
+
c.bindBuffer(c.ARRAY_BUFFER, buffer)
|
|
43
|
+
c.bufferData(c.ARRAY_BUFFER, array, c.STATIC_DRAW)
|
|
44
|
+
c.bindBuffer(c.ARRAY_BUFFER, null)
|
|
43
45
|
}
|
|
44
46
|
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
export const updateAttrib = (c: WebGL2RenderingContext, loc: number, stride: number, buffer: WebGLBuffer) => {
|
|
48
|
+
c.bindBuffer(c.ARRAY_BUFFER, buffer)
|
|
49
|
+
c.enableVertexAttribArray(loc)
|
|
50
|
+
c.vertexAttribPointer(loc, stride, c.FLOAT, false, 0, 0)
|
|
49
51
|
}
|
|
50
52
|
|
|
51
|
-
export const
|
|
52
|
-
c
|
|
53
|
-
loc: number,
|
|
54
|
-
count: number,
|
|
55
|
-
value: number[],
|
|
56
|
-
iboValue: number[]
|
|
57
|
-
) => {
|
|
58
|
-
const vbo = createVbo(c, value)
|
|
59
|
-
const ibo = createIbo(c, iboValue)
|
|
60
|
-
const str = getStride(count, value, iboValue)
|
|
61
|
-
c.bindBuffer(c.ARRAY_BUFFER, vbo)
|
|
53
|
+
export const updateInstance = (c: WebGL2RenderingContext, loc: number, stride: number, buffer: WebGLBuffer) => {
|
|
54
|
+
c.bindBuffer(c.ARRAY_BUFFER, buffer)
|
|
62
55
|
c.enableVertexAttribArray(loc)
|
|
63
|
-
c.vertexAttribPointer(loc,
|
|
64
|
-
|
|
56
|
+
c.vertexAttribPointer(loc, stride, c.FLOAT, false, 0, 0)
|
|
57
|
+
c.vertexAttribDivisor(loc, 1) // divisor is 1
|
|
65
58
|
}
|
|
66
59
|
|
|
67
|
-
export const
|
|
60
|
+
export const updateUniform = (c: WebGL2RenderingContext, loc: WebGLUniformLocation, value: number | number[]) => {
|
|
68
61
|
if (is.num(value)) return c.uniform1f(loc, value)
|
|
69
62
|
let l = value.length
|
|
70
63
|
if (l <= 4) return c[`uniform${l as 2}fv`](loc, value)
|
|
@@ -73,7 +66,7 @@ export const createUniform = (c: WebGLRenderingContext, loc: WebGLUniformLocatio
|
|
|
73
66
|
}
|
|
74
67
|
|
|
75
68
|
export const createTexture = (
|
|
76
|
-
c:
|
|
69
|
+
c: WebGL2RenderingContext,
|
|
77
70
|
img: HTMLImageElement,
|
|
78
71
|
loc: WebGLUniformLocation,
|
|
79
72
|
unit: number
|
|
@@ -103,28 +96,29 @@ interface TextureBuffer {
|
|
|
103
96
|
export const createStorage = (
|
|
104
97
|
c: WebGL2RenderingContext,
|
|
105
98
|
value: number[],
|
|
106
|
-
|
|
99
|
+
width: number,
|
|
100
|
+
height: number,
|
|
107
101
|
ping: TextureBuffer,
|
|
108
102
|
pong: TextureBuffer,
|
|
109
103
|
unit: number,
|
|
110
104
|
array: Float32Array
|
|
111
105
|
) => {
|
|
112
|
-
const
|
|
113
|
-
const vectorSize = value.length /
|
|
114
|
-
for (let i = 0; i <
|
|
106
|
+
const particleCount = width * height
|
|
107
|
+
const vectorSize = value.length / particleCount
|
|
108
|
+
for (let i = 0; i < particleCount; i++) {
|
|
115
109
|
for (let j = 0; j < Math.min(vectorSize, 4); j++) {
|
|
116
110
|
array[4 * i + j] = value[i * vectorSize + j] || 0
|
|
117
111
|
}
|
|
118
112
|
}
|
|
119
113
|
c.activeTexture(c.TEXTURE0 + unit)
|
|
120
114
|
c.bindTexture(c.TEXTURE_2D, ping.texture)
|
|
121
|
-
c.texImage2D(c.TEXTURE_2D, 0, c.RGBA32F,
|
|
115
|
+
c.texImage2D(c.TEXTURE_2D, 0, c.RGBA32F, width, height, 0, c.RGBA, c.FLOAT, array)
|
|
122
116
|
c.texParameteri(c.TEXTURE_2D, c.TEXTURE_MIN_FILTER, c.NEAREST)
|
|
123
117
|
c.texParameteri(c.TEXTURE_2D, c.TEXTURE_MAG_FILTER, c.NEAREST)
|
|
124
118
|
c.texParameteri(c.TEXTURE_2D, c.TEXTURE_WRAP_S, c.CLAMP_TO_EDGE)
|
|
125
119
|
c.texParameteri(c.TEXTURE_2D, c.TEXTURE_WRAP_T, c.CLAMP_TO_EDGE)
|
|
126
120
|
c.bindTexture(c.TEXTURE_2D, pong.texture)
|
|
127
|
-
c.texImage2D(c.TEXTURE_2D, 0, c.RGBA32F,
|
|
121
|
+
c.texImage2D(c.TEXTURE_2D, 0, c.RGBA32F, width, height, 0, c.RGBA, c.FLOAT, array)
|
|
128
122
|
c.texParameteri(c.TEXTURE_2D, c.TEXTURE_MIN_FILTER, c.NEAREST)
|
|
129
123
|
c.texParameteri(c.TEXTURE_2D, c.TEXTURE_MAG_FILTER, c.NEAREST)
|
|
130
124
|
c.texParameteri(c.TEXTURE_2D, c.TEXTURE_WRAP_S, c.CLAMP_TO_EDGE)
|
|
@@ -159,3 +153,28 @@ export const createAttachment = (
|
|
|
159
153
|
c.framebufferTexture2D(c.FRAMEBUFFER, attachment, c.TEXTURE_2D, o.texture, 0)
|
|
160
154
|
return attachment
|
|
161
155
|
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* utils
|
|
159
|
+
*/
|
|
160
|
+
export const storageSize = (particleCount: number | number[] = 1024) => {
|
|
161
|
+
if (is.num(particleCount)) {
|
|
162
|
+
const sqrt = Math.sqrt(particleCount)
|
|
163
|
+
const size = Math.ceil(sqrt)
|
|
164
|
+
if (!Number.isInteger(sqrt)) {
|
|
165
|
+
console.warn(
|
|
166
|
+
`GLRE Storage Warning: particleCount (${particleCount}) is not a square. Using ${size}x${size} texture may waste GPU memory. Consider using [width, height] format for optimal storage.`
|
|
167
|
+
)
|
|
168
|
+
}
|
|
169
|
+
return { x: size, y: size }
|
|
170
|
+
}
|
|
171
|
+
const [x, y, z] = particleCount
|
|
172
|
+
if (z !== undefined) {
|
|
173
|
+
const yz = y * z
|
|
174
|
+
console.warn(
|
|
175
|
+
`GLRE Storage Warning: 3D particleCount [${x}, ${y}, ${z}] specified but WebGL storage textures only support 2D. Flattening to 2D by multiplying height=${y} * depth=${z} = ${yz}.`
|
|
176
|
+
)
|
|
177
|
+
return { x, y: yz }
|
|
178
|
+
}
|
|
179
|
+
return { x, y }
|
|
180
|
+
}
|
package/src/utils/webgl.ts
CHANGED
|
@@ -1,34 +1,20 @@
|
|
|
1
1
|
import { nested as cached } from 'reev'
|
|
2
|
-
import { is, loadingImage } from './helpers'
|
|
2
|
+
import { is, loadingImage, getStride, GLSL_VS, GLSL_FS } from './helpers'
|
|
3
3
|
import {
|
|
4
|
+
createArrayBuffer,
|
|
4
5
|
cleanStorage,
|
|
5
6
|
createAttachment,
|
|
6
|
-
createAttrib,
|
|
7
7
|
createProgram,
|
|
8
8
|
createStorage,
|
|
9
9
|
createTexture,
|
|
10
|
-
|
|
10
|
+
setArrayBuffer,
|
|
11
|
+
storageSize,
|
|
12
|
+
updateAttrib,
|
|
13
|
+
updateInstance,
|
|
14
|
+
updateUniform,
|
|
11
15
|
} from './program'
|
|
12
16
|
import type { GL, WebGLState } from '../types'
|
|
13
17
|
|
|
14
|
-
const DEFAULT_FRAGMENT = /* cpp */ `
|
|
15
|
-
#version 300 es
|
|
16
|
-
precision mediump float;
|
|
17
|
-
out vec4 fragColor;
|
|
18
|
-
uniform vec2 iResolution;
|
|
19
|
-
void main() {
|
|
20
|
-
fragColor = vec4(fract((gl_FragCoord.xy / iResolution)), 0.0, 1.0);
|
|
21
|
-
}
|
|
22
|
-
`
|
|
23
|
-
|
|
24
|
-
const DEFAULT_VERTEX = /* cpp */ `
|
|
25
|
-
#version 300 es
|
|
26
|
-
void main() {
|
|
27
|
-
float x = float(gl_VertexID % 2) * 4.0 - 1.0;
|
|
28
|
-
float y = float(gl_VertexID / 2) * 4.0 - 1.0;
|
|
29
|
-
gl_Position = vec4(x, y, 0.0, 1.0);
|
|
30
|
-
}`
|
|
31
|
-
|
|
32
18
|
const computeProgram = (gl: GL, c: WebGL2RenderingContext) => {
|
|
33
19
|
if (!gl.cs) return null // ignore if no compute shader
|
|
34
20
|
c.getExtension('EXT_color_buffer_float')
|
|
@@ -38,12 +24,12 @@ const computeProgram = (gl: GL, c: WebGL2RenderingContext) => {
|
|
|
38
24
|
|
|
39
25
|
const units = cached(() => activeUnit++)
|
|
40
26
|
const cs = is.str(gl.cs) ? gl.cs : gl.cs!.compute({ isWebGL: true, gl, units })
|
|
41
|
-
const pg = createProgram(c, cs,
|
|
42
|
-
const size =
|
|
27
|
+
const pg = createProgram(c, cs, GLSL_VS, gl)!
|
|
28
|
+
const size = storageSize(gl.particleCount)
|
|
43
29
|
|
|
44
30
|
const uniforms = cached((key) => c.getUniformLocation(pg, key)!)
|
|
45
31
|
const storages = cached((key) => {
|
|
46
|
-
const array = new Float32Array(size * size * 4) // RGBA texture data
|
|
32
|
+
const array = new Float32Array(size.x * size.y * 4) // RGBA texture data
|
|
47
33
|
const ping = { texture: c.createTexture(), buffer: c.createFramebuffer() }
|
|
48
34
|
const pong = { texture: c.createTexture(), buffer: c.createFramebuffer() }
|
|
49
35
|
return { ping, pong, array, loc: uniforms(key), unit: units(key) }
|
|
@@ -51,12 +37,12 @@ const computeProgram = (gl: GL, c: WebGL2RenderingContext) => {
|
|
|
51
37
|
|
|
52
38
|
const _uniform = (key: string, value: number | number[]) => {
|
|
53
39
|
c.useProgram(pg)
|
|
54
|
-
|
|
40
|
+
updateUniform(c, uniforms(key), value)
|
|
55
41
|
}
|
|
56
42
|
|
|
57
43
|
const _storage = (key: string, value: number[]) => {
|
|
58
44
|
const { ping, pong, unit, array } = storages(key)
|
|
59
|
-
createStorage(c, value, size, ping, pong, unit, array)
|
|
45
|
+
createStorage(c, value, size.x, size.y, ping, pong, unit, array)
|
|
60
46
|
}
|
|
61
47
|
|
|
62
48
|
const clean = () => {
|
|
@@ -83,25 +69,38 @@ export const webgl = async (gl: GL) => {
|
|
|
83
69
|
const config = { isWebGL: true, gl }
|
|
84
70
|
const c = gl.el!.getContext('webgl2')!
|
|
85
71
|
const cp = computeProgram(gl, c)
|
|
86
|
-
const fs = gl.fs ? (is.str(gl.fs) ? gl.fs : gl.fs!.fragment(config)) :
|
|
87
|
-
const vs = gl.vs ? (is.str(gl.vs) ? gl.vs : gl.vs!.vertex(config)) :
|
|
72
|
+
const fs = gl.fs ? (is.str(gl.fs) ? gl.fs : gl.fs!.fragment(config)) : GLSL_FS
|
|
73
|
+
const vs = gl.vs ? (is.str(gl.vs) ? gl.vs : gl.vs!.vertex(config)) : GLSL_VS
|
|
88
74
|
const pg = createProgram(c, fs, vs, gl)!
|
|
89
75
|
c.useProgram(pg)
|
|
90
76
|
|
|
91
77
|
let activeUnit = 0 // for texture units
|
|
92
78
|
|
|
93
79
|
const units = cached(() => activeUnit++)
|
|
94
|
-
const attribs = cached((key) => c.getAttribLocation(pg, key))
|
|
95
80
|
const uniforms = cached((key) => c.getUniformLocation(pg, key))
|
|
96
81
|
|
|
97
|
-
const
|
|
98
|
-
const
|
|
99
|
-
|
|
82
|
+
const attribs = cached((key, value: number[], isInstance = false) => {
|
|
83
|
+
const stride = getStride(value.length, isInstance ? gl.instanceCount : gl.count, gl.error)
|
|
84
|
+
const location = c.getAttribLocation(pg, key)
|
|
85
|
+
const { array, buffer } = createArrayBuffer(c, value)
|
|
86
|
+
return { array, buffer, location, stride }
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
const _attribute = (key = '', value: number[]) => {
|
|
90
|
+
const { array, buffer, location, stride } = attribs(key, value)
|
|
91
|
+
setArrayBuffer(c, array, buffer, value)
|
|
92
|
+
updateAttrib(c, location, stride, buffer)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const _instance = (key: string, value: number[]) => {
|
|
96
|
+
const { array, buffer, location, stride } = attribs(key, value, true)
|
|
97
|
+
setArrayBuffer(c, array, buffer, value)
|
|
98
|
+
updateInstance(c, location, stride, buffer)
|
|
100
99
|
}
|
|
101
100
|
|
|
102
101
|
const _uniform = (key: string, value: number | number[]) => {
|
|
103
102
|
c.useProgram(pg)
|
|
104
|
-
|
|
103
|
+
updateUniform(c, uniforms(key)!, value)
|
|
105
104
|
cp?._uniform(key, value)
|
|
106
105
|
}
|
|
107
106
|
|
|
@@ -122,11 +121,18 @@ export const webgl = async (gl: GL) => {
|
|
|
122
121
|
cp?.render()
|
|
123
122
|
c.useProgram(pg)
|
|
124
123
|
c.viewport(0, 0, ...gl.size)
|
|
125
|
-
|
|
124
|
+
if (gl.instanceCount > 1) {
|
|
125
|
+
c.drawArraysInstanced(c.TRIANGLES, 0, gl.count, gl.instanceCount)
|
|
126
|
+
} else c.drawArrays(c.TRIANGLES, 0, gl.count)
|
|
126
127
|
c.bindFramebuffer(c.FRAMEBUFFER, null)
|
|
127
128
|
}
|
|
128
129
|
|
|
130
|
+
if (gl.isDepth) {
|
|
131
|
+
c.depthFunc(c.LEQUAL)
|
|
132
|
+
c.enable(c.CULL_FACE)
|
|
133
|
+
}
|
|
134
|
+
|
|
129
135
|
const webgl: WebGLState = { context: c, program: pg, storages: cp?.storages }
|
|
130
136
|
|
|
131
|
-
return { webgl, render, clean, _attribute, _uniform, _texture, _storage: cp?._storage }
|
|
137
|
+
return { webgl, render, clean, _attribute, _instance, _uniform, _texture, _storage: cp?._storage }
|
|
132
138
|
}
|