glre 0.43.0 → 0.44.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/dist/react.d.ts CHANGED
@@ -121,14 +121,64 @@ interface NodeContext {
121
121
  /**
122
122
  * infer
123
123
  */
124
- type _StringLength<A extends string> = A extends `${infer _}${infer A}` ? A extends '' ? 1 : A extends `${infer _}${infer B}` ? B extends '' ? 2 : B extends `${infer _}${infer C}` ? C extends '' ? 3 : 4 : never : never : never;
125
124
  type InferOperator<L extends C, R extends C> = L extends R ? L : L extends 'float' | 'int' ? R : R extends 'float' | 'int' ? L : L extends 'mat4' ? R extends 'vec4' ? R : L : L extends 'mat3' ? R extends 'vec3' ? R : L : L extends 'mat2' ? R extends 'vec2' ? R : L : L extends 'vec4' ? R extends 'mat4' ? L : L : L extends 'vec3' ? R extends 'mat3' ? L : L : L extends 'vec2' ? R extends 'mat2' ? L : L : L;
126
125
  type InferArrayElement<T extends C> = T extends 'mat4' ? 'vec4' : T extends 'mat3' ? 'vec3' : T extends 'mat2' ? 'vec2' : 'float';
126
+ type _OperatorTypeRulesMap = typeof OPERATOR_TYPE_RULES;
127
127
  type ExtractPairs<T> = T extends readonly [infer L, infer R, string] ? [L, R] | [R, L] : never;
128
- type OperatorTypeRules = ExtractPairs<(typeof OPERATOR_TYPE_RULES)[number]>;
128
+ type OperatorTypeRules = ExtractPairs<_OperatorTypeRulesMap[number]>;
129
129
  type IsInRules<L extends C, R extends C> = [L, R] extends OperatorTypeRules ? 1 : 0;
130
130
  type ValidateOperator<L extends C, R extends C> = L extends R ? 1 : IsInRules<L, R>;
131
- type InferSwizzleType<S extends string> = _StringLength<S> extends 4 ? 'vec4' : _StringLength<S> extends 3 ? 'vec3' : _StringLength<S> extends 2 ? 'vec2' : 'float';
131
+ /**
132
+ * swizzle
133
+ */
134
+ type _SwizzleLength<A extends string> = A extends `${infer _}${infer A}` ? A extends '' ? 1 : A extends `${infer _}${infer B}` ? B extends '' ? 2 : B extends `${infer _}${infer C}` ? C extends '' ? 3 : 4 : never : never : never;
135
+ type _SwizzleBaseMap = {
136
+ float: 'float';
137
+ vec2: 'float';
138
+ vec3: 'float';
139
+ vec4: 'float';
140
+ int: 'int';
141
+ ivec2: 'int';
142
+ ivec3: 'int';
143
+ ivec4: 'int';
144
+ uint: 'uint';
145
+ uvec2: 'uint';
146
+ uvec3: 'uint';
147
+ uvec4: 'uint';
148
+ bool: 'bool';
149
+ bvec2: 'bool';
150
+ bvec3: 'bool';
151
+ bvec4: 'bool';
152
+ };
153
+ type _SwizzleResultMap = {
154
+ float: {
155
+ 1: 'float';
156
+ 2: 'vec2';
157
+ 3: 'vec3';
158
+ 4: 'vec4';
159
+ };
160
+ int: {
161
+ 1: 'int';
162
+ 2: 'ivec2';
163
+ 3: 'ivec3';
164
+ 4: 'ivec4';
165
+ };
166
+ uint: {
167
+ 1: 'uint';
168
+ 2: 'uvec2';
169
+ 3: 'uvec3';
170
+ 4: 'uvec4';
171
+ };
172
+ bool: {
173
+ 1: 'bool';
174
+ 2: 'bvec2';
175
+ 3: 'bvec3';
176
+ 4: 'bvec4';
177
+ };
178
+ };
179
+ type _SwizzleBase<T extends C> = T extends keyof _SwizzleBaseMap ? _SwizzleBaseMap[T] : never;
180
+ type _SwizzleResult<T extends C, L extends 1 | 2 | 3 | 4> = _SwizzleResultMap[_SwizzleBase<T>][L];
181
+ type InferSwizzleType<T extends C, S extends string> = _SwizzleLength<S> extends infer L extends 1 | 2 | 3 | 4 ? _SwizzleResult<_SwizzleBase<T>, L> : never;
132
182
  /**
133
183
  * Swizzles
134
184
  */
@@ -190,7 +240,7 @@ interface ConstantsToType {
190
240
  type XImpl<T extends C> = _X<T> & {
191
241
  [K in string as K extends Methods ? never : K]: any;
192
242
  } & {
193
- [K in Swizzles]: X<InferSwizzleType<K>>;
243
+ [K in Swizzles]: X<InferSwizzleType<T, K>>;
194
244
  };
195
245
  type C = Constants;
196
246
  type X<T extends C = C> = T extends keyof ConstantsToType ? ConstantsToType[T] : _X<T>;
@@ -270,7 +320,7 @@ interface _X<T extends C> {
270
320
  any(): Bool;
271
321
  determinant(): T extends 'mat2' | 'mat3' | 'mat4' ? Float : never;
272
322
  distance<U extends C>(y: T extends 'vec2' | 'vec3' | 'vec4' ? (U extends T ? number | X<U> : never) : never): Float;
273
- dot<U extends C>(y: T extends 'vec2' | 'vec3' | 'vec4' | 'ivec2' | 'ivec3' | 'ivec4' ? U extends T ? number | X<U> : never : never): T extends `ivec${string}` ? Int : Float;
323
+ dot<U extends C>(y: T extends 'vec2' | 'vec3' | 'vec4' | 'ivec2' | 'ivec3' | 'ivec4' ? (U extends T ? number | X<U> : never) : never): T extends `ivec${string}` ? Int : Float;
274
324
  length(): T extends 'vec2' | 'vec3' | 'vec4' ? Float : never;
275
325
  lengthSq(): Float;
276
326
  luminance(): Float;
@@ -350,6 +400,7 @@ type GL = EventState<{
350
400
  count: number;
351
401
  instanceCount: number;
352
402
  particleCount: number | [number, number] | [number, number, number];
403
+ precision: 'lowp' | 'mediump' | 'highp';
353
404
  loading: number;
354
405
  el: HTMLCanvasElement;
355
406
  vs?: string | Vec4;
@@ -452,9 +503,9 @@ interface WebGPUState {
452
503
  * for webgl
453
504
  */
454
505
  interface WebGLState {
455
- context: WebGLRenderingContext;
506
+ context: WebGL2RenderingContext;
456
507
  program: WebGLProgram;
457
- storages: any;
508
+ uniforms: Nested<WebGLUniformLocation | null>;
458
509
  }
459
510
 
460
511
  declare const isGL: (a: unknown) => a is EventState<GL>;
@@ -476,6 +527,7 @@ declare const createGL: (props?: Partial<GL>) => EventState<{
476
527
  count: number;
477
528
  instanceCount: number;
478
529
  particleCount: number | [number, number] | [number, number, number];
530
+ precision: "lowp" | "mediump" | "highp";
479
531
  loading: number;
480
532
  el: HTMLCanvasElement;
481
533
  vs?: string | Vec4;
package/dist/solid.d.ts CHANGED
@@ -121,14 +121,64 @@ interface NodeContext {
121
121
  /**
122
122
  * infer
123
123
  */
124
- type _StringLength<A extends string> = A extends `${infer _}${infer A}` ? A extends '' ? 1 : A extends `${infer _}${infer B}` ? B extends '' ? 2 : B extends `${infer _}${infer C}` ? C extends '' ? 3 : 4 : never : never : never;
125
124
  type InferOperator<L extends C, R extends C> = L extends R ? L : L extends 'float' | 'int' ? R : R extends 'float' | 'int' ? L : L extends 'mat4' ? R extends 'vec4' ? R : L : L extends 'mat3' ? R extends 'vec3' ? R : L : L extends 'mat2' ? R extends 'vec2' ? R : L : L extends 'vec4' ? R extends 'mat4' ? L : L : L extends 'vec3' ? R extends 'mat3' ? L : L : L extends 'vec2' ? R extends 'mat2' ? L : L : L;
126
125
  type InferArrayElement<T extends C> = T extends 'mat4' ? 'vec4' : T extends 'mat3' ? 'vec3' : T extends 'mat2' ? 'vec2' : 'float';
126
+ type _OperatorTypeRulesMap = typeof OPERATOR_TYPE_RULES;
127
127
  type ExtractPairs<T> = T extends readonly [infer L, infer R, string] ? [L, R] | [R, L] : never;
128
- type OperatorTypeRules = ExtractPairs<(typeof OPERATOR_TYPE_RULES)[number]>;
128
+ type OperatorTypeRules = ExtractPairs<_OperatorTypeRulesMap[number]>;
129
129
  type IsInRules<L extends C, R extends C> = [L, R] extends OperatorTypeRules ? 1 : 0;
130
130
  type ValidateOperator<L extends C, R extends C> = L extends R ? 1 : IsInRules<L, R>;
131
- type InferSwizzleType<S extends string> = _StringLength<S> extends 4 ? 'vec4' : _StringLength<S> extends 3 ? 'vec3' : _StringLength<S> extends 2 ? 'vec2' : 'float';
131
+ /**
132
+ * swizzle
133
+ */
134
+ type _SwizzleLength<A extends string> = A extends `${infer _}${infer A}` ? A extends '' ? 1 : A extends `${infer _}${infer B}` ? B extends '' ? 2 : B extends `${infer _}${infer C}` ? C extends '' ? 3 : 4 : never : never : never;
135
+ type _SwizzleBaseMap = {
136
+ float: 'float';
137
+ vec2: 'float';
138
+ vec3: 'float';
139
+ vec4: 'float';
140
+ int: 'int';
141
+ ivec2: 'int';
142
+ ivec3: 'int';
143
+ ivec4: 'int';
144
+ uint: 'uint';
145
+ uvec2: 'uint';
146
+ uvec3: 'uint';
147
+ uvec4: 'uint';
148
+ bool: 'bool';
149
+ bvec2: 'bool';
150
+ bvec3: 'bool';
151
+ bvec4: 'bool';
152
+ };
153
+ type _SwizzleResultMap = {
154
+ float: {
155
+ 1: 'float';
156
+ 2: 'vec2';
157
+ 3: 'vec3';
158
+ 4: 'vec4';
159
+ };
160
+ int: {
161
+ 1: 'int';
162
+ 2: 'ivec2';
163
+ 3: 'ivec3';
164
+ 4: 'ivec4';
165
+ };
166
+ uint: {
167
+ 1: 'uint';
168
+ 2: 'uvec2';
169
+ 3: 'uvec3';
170
+ 4: 'uvec4';
171
+ };
172
+ bool: {
173
+ 1: 'bool';
174
+ 2: 'bvec2';
175
+ 3: 'bvec3';
176
+ 4: 'bvec4';
177
+ };
178
+ };
179
+ type _SwizzleBase<T extends C> = T extends keyof _SwizzleBaseMap ? _SwizzleBaseMap[T] : never;
180
+ type _SwizzleResult<T extends C, L extends 1 | 2 | 3 | 4> = _SwizzleResultMap[_SwizzleBase<T>][L];
181
+ type InferSwizzleType<T extends C, S extends string> = _SwizzleLength<S> extends infer L extends 1 | 2 | 3 | 4 ? _SwizzleResult<_SwizzleBase<T>, L> : never;
132
182
  /**
133
183
  * Swizzles
134
184
  */
@@ -190,7 +240,7 @@ interface ConstantsToType {
190
240
  type XImpl<T extends C> = _X<T> & {
191
241
  [K in string as K extends Methods ? never : K]: any;
192
242
  } & {
193
- [K in Swizzles]: X<InferSwizzleType<K>>;
243
+ [K in Swizzles]: X<InferSwizzleType<T, K>>;
194
244
  };
195
245
  type C = Constants;
196
246
  type X<T extends C = C> = T extends keyof ConstantsToType ? ConstantsToType[T] : _X<T>;
@@ -270,7 +320,7 @@ interface _X<T extends C> {
270
320
  any(): Bool;
271
321
  determinant(): T extends 'mat2' | 'mat3' | 'mat4' ? Float : never;
272
322
  distance<U extends C>(y: T extends 'vec2' | 'vec3' | 'vec4' ? (U extends T ? number | X<U> : never) : never): Float;
273
- dot<U extends C>(y: T extends 'vec2' | 'vec3' | 'vec4' | 'ivec2' | 'ivec3' | 'ivec4' ? U extends T ? number | X<U> : never : never): T extends `ivec${string}` ? Int : Float;
323
+ dot<U extends C>(y: T extends 'vec2' | 'vec3' | 'vec4' | 'ivec2' | 'ivec3' | 'ivec4' ? (U extends T ? number | X<U> : never) : never): T extends `ivec${string}` ? Int : Float;
274
324
  length(): T extends 'vec2' | 'vec3' | 'vec4' ? Float : never;
275
325
  lengthSq(): Float;
276
326
  luminance(): Float;
@@ -350,6 +400,7 @@ type GL = EventState<{
350
400
  count: number;
351
401
  instanceCount: number;
352
402
  particleCount: number | [number, number] | [number, number, number];
403
+ precision: 'lowp' | 'mediump' | 'highp';
353
404
  loading: number;
354
405
  el: HTMLCanvasElement;
355
406
  vs?: string | Vec4;
@@ -452,9 +503,9 @@ interface WebGPUState {
452
503
  * for webgl
453
504
  */
454
505
  interface WebGLState {
455
- context: WebGLRenderingContext;
506
+ context: WebGL2RenderingContext;
456
507
  program: WebGLProgram;
457
- storages: any;
508
+ uniforms: Nested<WebGLUniformLocation | null>;
458
509
  }
459
510
 
460
511
  declare const isGL: (a: unknown) => a is EventState<GL>;
@@ -476,6 +527,7 @@ declare const createGL: (props?: Partial<GL>) => EventState<{
476
527
  count: number;
477
528
  instanceCount: number;
478
529
  particleCount: number | [number, number] | [number, number, number];
530
+ precision: "lowp" | "mediump" | "highp";
479
531
  loading: number;
480
532
  el: HTMLCanvasElement;
481
533
  vs?: string | Vec4;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "glre",
3
- "version": "0.43.0",
3
+ "version": "0.44.0",
4
4
  "author": "tseijp",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -1,4 +1,4 @@
1
- import { Fn, Vec2, Vec3, Vec4, Float, vec2, vec3, vec4, mix, step } from '../../node'
1
+ import { Fn, Vec2, Vec3, Vec4, Float, vec2, vec3, vec4 } from '../../node'
2
2
  import { mod289Vec3, mod289Vec4 } from '../math/mod289'
3
3
  import { permuteVec4 } from '../math/permute'
4
4
  import { taylorInvSqrt } from '../math/taylorInvSqrt'
@@ -181,30 +181,22 @@ export const cnoiseVec4 = Fn(([P]: [Vec4]): Float => {
181
181
  const g1011 = vec4(gx11.y, gy11.y, gz11.y, gw11.y).toVar('g1011')
182
182
  const g0111 = vec4(gx11.z, gy11.z, gz11.z, gw11.z).toVar('g0111')
183
183
  const g1111 = vec4(gx11.w, gy11.w, gz11.w, gw11.w).toVar('g1111')
184
- const norm00 = taylorInvSqrt(
185
- vec4(g0000.dot(g0000), g0100.dot(g0100), g1000.dot(g1000), g1100.dot(g1100))
186
- ).toVar('norm00')
184
+ const norm00 = taylorInvSqrt(vec4(g0000.dot(g0000), g0100.dot(g0100), g1000.dot(g1000), g1100.dot(g1100))).toVar('norm00')
187
185
  g0000.mulAssign(norm00.x)
188
186
  g0100.mulAssign(norm00.y)
189
187
  g1000.mulAssign(norm00.z)
190
188
  g1100.mulAssign(norm00.w)
191
- const norm01 = taylorInvSqrt(
192
- vec4(g0001.dot(g0001), g0101.dot(g0101), g1001.dot(g1001), g1101.dot(g1101))
193
- ).toVar('norm01')
189
+ const norm01 = taylorInvSqrt(vec4(g0001.dot(g0001), g0101.dot(g0101), g1001.dot(g1001), g1101.dot(g1101))).toVar('norm01')
194
190
  g0001.mulAssign(norm01.x)
195
191
  g0101.mulAssign(norm01.y)
196
192
  g1001.mulAssign(norm01.z)
197
193
  g1101.mulAssign(norm01.w)
198
- const norm10 = taylorInvSqrt(
199
- vec4(g0010.dot(g0010), g0110.dot(g0110), g1010.dot(g1010), g1110.dot(g1110))
200
- ).toVar('norm10')
194
+ const norm10 = taylorInvSqrt(vec4(g0010.dot(g0010), g0110.dot(g0110), g1010.dot(g1010), g1110.dot(g1110))).toVar('norm10')
201
195
  g0010.mulAssign(norm10.x)
202
196
  g0110.mulAssign(norm10.y)
203
197
  g1010.mulAssign(norm10.z)
204
198
  g1110.mulAssign(norm10.w)
205
- const norm11 = taylorInvSqrt(
206
- vec4(g0011.dot(g0011), g0111.dot(g0111), g1011.dot(g1011), g1111.dot(g1111))
207
- ).toVar('norm11')
199
+ const norm11 = taylorInvSqrt(vec4(g0011.dot(g0011), g0111.dot(g0111), g1011.dot(g1011), g1111.dot(g1111))).toVar('norm11')
208
200
  g0011.mulAssign(norm11.x)
209
201
  g0111.mulAssign(norm11.y)
210
202
  g1011.mulAssign(norm11.z)
@@ -1,4 +1,4 @@
1
- import { Fn, Vec2, Float, vec3, dot, sqrt, float } from '../../node'
1
+ import { Fn, Vec2, Float, vec3, float } from '../../node'
2
2
  import { PI } from '../math/const'
3
3
 
4
4
  export const gerstnerWave = Fn(([_uv, _dir, _steepness, _wavelength, _time]: [Vec2, Vec2, Float, Float, Float]) => {
@@ -78,7 +78,6 @@ export const snoiseVec3 = Fn(([v]: [Vec3]): Float => {
78
78
  const p2 = vec3(a1.xy, h.z).toVar('p2')
79
79
  const p3 = vec3(a1.zw, h.w).toVar('p3')
80
80
  const norm = taylorInvSqrt(vec4(p0.dot(p0), p1.dot(p1), p2.dot(p2), p3.dot(p3))).toVar('norm')
81
- p0.mulAssign(norm.x)
82
81
  p1.mulAssign(norm.y)
83
82
  p2.mulAssign(norm.z)
84
83
  p3.mulAssign(norm.w)
@@ -2,7 +2,7 @@ import { Fn, Vec2, X, vec4 } from '../../node'
2
2
 
3
3
  // 2D modulo function that returns both cell coordinates and wrapped position
4
4
  // Returns vec4(cellX, cellY, wrappedX, wrappedY)
5
- export const mod2 = Fn(([p, s]: [Vec2, X]): X => {
5
+ export const mod2 = Fn(([p, s]) => {
6
6
  const halfS = s.div(2).toVar()
7
7
  const pShifted = p.add(halfS).toVar()
8
8
  const c = pShifted.div(s).floor().toVar()
@@ -1,6 +1,6 @@
1
- import { Fn, X } from '../../node'
1
+ import { Fn, int } from '../../node'
2
2
 
3
- export const taylorInvSqrt = Fn(([r]: [X]): X => {
3
+ export const taylorInvSqrt = Fn(([r]) => {
4
4
  return r.mul(-0.85373472095314).add(1.79284291400159)
5
5
  }).setLayout({
6
6
  name: 'taylorInvSqrt',
package/src/index.ts CHANGED
@@ -39,6 +39,7 @@ export const createGL = (props?: Partial<GL>) => {
39
39
  count: 6,
40
40
  instanceCount: 1,
41
41
  particleCount: 1024,
42
+ precision: 'highp',
42
43
  webgl: {},
43
44
  webgpu: {},
44
45
  loading: 0,
package/src/node/build.ts CHANGED
@@ -1,12 +1,6 @@
1
1
  import { code } from './utils'
2
2
  import type { NodeContext, X } from './types'
3
3
 
4
- const GLSL_FRAGMENT_HEAD = `
5
- #version 300 es
6
- precision mediump float;
7
- out vec4 fragColor;
8
- `.trim()
9
-
10
4
  const topological = (headers: Map<string, string>, dependencies: Map<string, Set<string>>) => {
11
5
  const sorted: [string, string][] = []
12
6
  const visited = new Set<string>()
@@ -42,13 +36,53 @@ const generateStruct = (id: string, map: Map<string, string>) => {
42
36
  return `struct ${id} {\n ${Array.from(map.values()).join(',\n ')}\n}`
43
37
  }
44
38
 
39
+ const precisionHead = (result: string[], precision = 'highp') => {
40
+ result.push(`precision ${precision} float;`)
41
+ result.push(`precision ${precision} int;`)
42
+ result.push(`precision ${precision} sampler2D;`)
43
+ result.push(`precision ${precision} samplerCube;`)
44
+ result.push(`precision ${precision} sampler3D;`)
45
+ result.push(`precision ${precision} sampler2DArray;`)
46
+ result.push(`precision ${precision} sampler2DShadow;`)
47
+ result.push(`precision ${precision} samplerCubeShadow;`)
48
+ result.push(`precision ${precision} sampler2DArrayShadow;`)
49
+ result.push(`precision ${precision} isampler2D;`)
50
+ result.push(`precision ${precision} isampler3D;`)
51
+ result.push(`precision ${precision} isamplerCube;`)
52
+ result.push(`precision ${precision} isampler2DArray;`)
53
+ result.push(`precision ${precision} usampler2D;`)
54
+ result.push(`precision ${precision} usampler3D;`)
55
+ result.push(`precision ${precision} usamplerCube;`)
56
+ result.push(`precision ${precision} usampler2DArray;`)
57
+ }
58
+
59
+ // ref: https://github.com/mrdoob/three.js/blob/master/src/renderers/webgl/WebGLCapabilities.js
60
+ const getMaxPrecision = (c?: WebGL2RenderingContext, precision = 'highp') => {
61
+ if (!c) return 'highp'
62
+ if (precision === 'highp') {
63
+ const p0 = c.getShaderPrecisionFormat(c.VERTEX_SHADER, c.HIGH_FLOAT)
64
+ const p1 = c.getShaderPrecisionFormat(c.FRAGMENT_SHADER, c.HIGH_FLOAT)
65
+ if (p0 && p0.precision > 0 && p1 && p1.precision > 0) return 'highp'
66
+ precision = 'mediump'
67
+ }
68
+ if (precision === 'mediump') {
69
+ const p0 = c.getShaderPrecisionFormat(c.VERTEX_SHADER, c.MEDIUM_FLOAT)
70
+ const p1 = c.getShaderPrecisionFormat(c.FRAGMENT_SHADER, c.MEDIUM_FLOAT)
71
+ if (p0 && p0.precision > 0 && p1 && p1.precision > 0) return 'mediump'
72
+ precision = 'lowp'
73
+ }
74
+ return 'lowp'
75
+ }
76
+
45
77
  export const fragment = (x: X, c: NodeContext = {}) => {
46
78
  c.code?.headers?.clear()
47
79
  c.label = 'frag' // for varying inputs or outputs
48
80
  const [head, lines, ret] = build(x, c)
49
81
  const result = []
50
82
  if (c.isWebGL) {
51
- result.push(GLSL_FRAGMENT_HEAD)
83
+ result.push('#version 300 es')
84
+ precisionHead(result, getMaxPrecision(c.gl?.webgl?.context, c.gl?.precision))
85
+ result.push('out vec4 fragColor;')
52
86
  for (const code of c.code?.fragInputs?.values() || []) result.push(`in ${code}`)
53
87
  result.push(head)
54
88
  result.push('void main() {')
@@ -106,7 +140,7 @@ export const compute = (x: X, c: NodeContext = {}) => {
106
140
  const result = []
107
141
  if (c.isWebGL) {
108
142
  result.push('#version 300 es')
109
- result.push('precision mediump float;')
143
+ precisionHead(result, 'highp')
110
144
  result.push(head)
111
145
  result.push('void main() {')
112
146
  result.push(` ${lines}`)
package/src/node/types.ts CHANGED
@@ -100,14 +100,6 @@ export interface NodeContext {
100
100
  /**
101
101
  * infer
102
102
  */
103
- // Optimized string length using direct pattern matching
104
- // prettier-ignore
105
- type _StringLength<A extends string> =
106
- A extends `${infer _}${infer A}` ? A extends '' ? 1 :
107
- A extends `${infer _}${infer B}` ? B extends '' ? 2 :
108
- B extends `${infer _}${infer C}` ? C extends '' ? 3 :
109
- 4 : never : never : never
110
-
111
103
  // Unified logic with infer.ts inferOperator function
112
104
  // prettier-ignore
113
105
  type InferOperator<L extends C, R extends C> =
@@ -132,28 +124,59 @@ type InferArrayElement<T extends C> =
132
124
  T extends 'mat2' ? 'vec2' :
133
125
  'float'
134
126
 
127
+ type _OperatorTypeRulesMap = typeof OPERATOR_TYPE_RULES
135
128
  type ExtractPairs<T> = T extends readonly [infer L, infer R, string] ? [L, R] | [R, L] : never
136
- type OperatorTypeRules = ExtractPairs<(typeof OPERATOR_TYPE_RULES)[number]>
129
+ type OperatorTypeRules = ExtractPairs<_OperatorTypeRulesMap[number]>
137
130
  type IsInRules<L extends C, R extends C> = [L, R] extends OperatorTypeRules ? 1 : 0
138
131
  type ValidateOperator<L extends C, R extends C> = L extends R ? 1 : IsInRules<L, R>
139
132
 
133
+ /**
134
+ * swizzle
135
+ */
136
+ // Optimized string length using direct pattern matching
140
137
  // prettier-ignore
141
- type InferSwizzleType<S extends string> =
142
- _StringLength<S> extends 4 ? 'vec4' :
143
- _StringLength<S> extends 3 ? 'vec3' :
144
- _StringLength<S> extends 2 ? 'vec2' :
145
- 'float'
138
+ type _SwizzleLength<A extends string> =
139
+ A extends `${infer _}${infer A}` ? A extends '' ? 1 :
140
+ A extends `${infer _}${infer B}` ? B extends '' ? 2 :
141
+ B extends `${infer _}${infer C}` ? C extends '' ? 3 :
142
+ 4 : never : never : never
143
+
144
+ type _SwizzleBaseMap = {
145
+ float: 'float'
146
+ vec2: 'float'
147
+ vec3: 'float'
148
+ vec4: 'float'
149
+ int: 'int'
150
+ ivec2: 'int'
151
+ ivec3: 'int'
152
+ ivec4: 'int'
153
+ uint: 'uint'
154
+ uvec2: 'uint'
155
+ uvec3: 'uint'
156
+ uvec4: 'uint'
157
+ bool: 'bool'
158
+ bvec2: 'bool'
159
+ bvec3: 'bool'
160
+ bvec4: 'bool'
161
+ }
162
+
163
+ type _SwizzleResultMap = {
164
+ float: { 1: 'float'; 2: 'vec2'; 3: 'vec3'; 4: 'vec4' }
165
+ int: { 1: 'int'; 2: 'ivec2'; 3: 'ivec3'; 4: 'ivec4' }
166
+ uint: { 1: 'uint'; 2: 'uvec2'; 3: 'uvec3'; 4: 'uvec4' }
167
+ bool: { 1: 'bool'; 2: 'bvec2'; 3: 'bvec3'; 4: 'bvec4' }
168
+ }
169
+
170
+ type _SwizzleBase<T extends C> = T extends keyof _SwizzleBaseMap ? _SwizzleBaseMap[T] : never
171
+ type _SwizzleResult<T extends C, L extends 1 | 2 | 3 | 4> = _SwizzleResultMap[_SwizzleBase<T>][L]
172
+ type InferSwizzleType<T extends C, S extends string> = _SwizzleLength<S> extends infer L extends 1 | 2 | 3 | 4 ? _SwizzleResult<_SwizzleBase<T>, L> : never
146
173
 
147
174
  /**
148
175
  * Swizzles
149
176
  */
150
177
  type _Swizzles<T extends string> = T | `${T}${T}` | `${T}${T}${T}` | `${T}${T}${T}${T}`
151
178
 
152
- export type Swizzles =
153
- | _Swizzles<'x' | 'y' | 'z' | 'w'>
154
- | _Swizzles<'r' | 'g' | 'b' | 'a'>
155
- | _Swizzles<'p' | 'q'>
156
- | _Swizzles<'s' | 't'>
179
+ export type Swizzles = _Swizzles<'x' | 'y' | 'z' | 'w'> | _Swizzles<'r' | 'g' | 'b' | 'a'> | _Swizzles<'p' | 'q'> | _Swizzles<'s' | 't'>
157
180
 
158
181
  export type Void = XImpl<'void'>
159
182
  export type Bool = XImpl<'bool'>
@@ -218,7 +241,7 @@ export interface ConstantsToType {
218
241
  type XImpl<T extends C> = _X<T> & {
219
242
  [K in string as K extends Methods ? never : K]: any
220
243
  } & {
221
- [K in Swizzles]: X<InferSwizzleType<K>>
244
+ [K in Swizzles]: X<InferSwizzleType<T, K>>
222
245
  }
223
246
 
224
247
  type C = Constants
@@ -333,16 +356,8 @@ interface _X<T extends C> {
333
356
 
334
357
  // 2. WGSL-compliant return types with individual function constraints
335
358
  determinant(): T extends 'mat2' | 'mat3' | 'mat4' ? Float : never
336
- distance<U extends C>(
337
- y: T extends 'vec2' | 'vec3' | 'vec4' ? (U extends T ? number | X<U> : never) : never
338
- ): Float
339
- dot<U extends C>(
340
- y: T extends 'vec2' | 'vec3' | 'vec4' | 'ivec2' | 'ivec3' | 'ivec4'
341
- ? U extends T
342
- ? number | X<U>
343
- : never
344
- : never
345
- ): T extends `ivec${string}` ? Int : Float
359
+ distance<U extends C>(y: T extends 'vec2' | 'vec3' | 'vec4' ? (U extends T ? number | X<U> : never) : never): Float
360
+ dot<U extends C>(y: T extends 'vec2' | 'vec3' | 'vec4' | 'ivec2' | 'ivec3' | 'ivec4' ? (U extends T ? number | X<U> : never) : never): T extends `ivec${string}` ? Int : Float
346
361
  length(): T extends 'vec2' | 'vec3' | 'vec4' ? Float : never
347
362
  lengthSq(): Float
348
363
  luminance(): Float
@@ -405,13 +420,8 @@ interface _X<T extends C> {
405
420
  min<U extends C>(y: number | X<U>): X<InferOperator<T, U>>
406
421
  mix<U extends C>(y: number | X<U>, a: number | Float | X<U>): X<InferOperator<T, U>>
407
422
  pow<U extends C>(y: number | X<U>): X<T>
408
- reflect<U extends C>(
409
- N: T extends 'vec2' | 'vec3' | 'vec4' ? (U extends T ? number | X<U> : never) : never
410
- ): X<T>
411
- refract<U extends C>(
412
- N: T extends 'vec2' | 'vec3' | 'vec4' ? (U extends T ? number | X<U> : never) : never,
413
- eta: number | Float
414
- ): T extends 'vec2' | 'vec3' | 'vec4' ? X<T> : never
423
+ reflect<U extends C>(N: T extends 'vec2' | 'vec3' | 'vec4' ? (U extends T ? number | X<U> : never) : never): X<T>
424
+ refract<U extends C>(N: T extends 'vec2' | 'vec3' | 'vec4' ? (U extends T ? number | X<U> : never) : never, eta: number | Float): T extends 'vec2' | 'vec3' | 'vec4' ? X<T> : never
415
425
 
416
426
  // 2. Functions where not first argument determines return type with unified parameter types
417
427
  smoothstep<U extends C>(edge0: number | X<U>, edge1: number | X<U>): X<InferOperator<T, U>>
@@ -1,28 +1,7 @@
1
1
  export const SWIZZLES = ['x', 'y', 'z', 'w', 'r', 'g', 'b', 'a', 's', 't', 'p', 'q'] as const
2
2
 
3
3
  // Unified order with TYPE_MAPPING array
4
- export const CONVERSIONS = [
5
- 'toBool',
6
- 'toUInt',
7
- 'toInt',
8
- 'toFloat',
9
- 'toBVec2',
10
- 'toIVec2',
11
- 'toUVec2',
12
- 'toVec2',
13
- 'toBVec3',
14
- 'toIVec3',
15
- 'toUVec3',
16
- 'toVec3',
17
- 'toBVec4',
18
- 'toIVec4',
19
- 'toUVec4',
20
- 'toVec4',
21
- 'toColor',
22
- 'toMat2',
23
- 'toMat3',
24
- 'toMat4',
25
- ] as const
4
+ export const CONVERSIONS = ['toBool', 'toUInt', 'toInt', 'toFloat', 'toBVec2', 'toIVec2', 'toUVec2', 'toVec2', 'toBVec3', 'toIVec3', 'toUVec3', 'toVec3', 'toBVec4', 'toIVec4', 'toUVec4', 'toVec4', 'toColor', 'toMat2', 'toMat3', 'toMat4'] as const
26
5
 
27
6
  // Unified order with CONVERSIONS array
28
7
  export const TYPE_MAPPING = {
@@ -134,14 +113,7 @@ export const BUILTIN_TYPES = {
134
113
  color: 'vec4',
135
114
  } as const
136
115
 
137
- export const COMPARISON_OPERATORS = [
138
- 'equal',
139
- 'notEqual',
140
- 'lessThan',
141
- 'lessThanEqual',
142
- 'greaterThan',
143
- 'greaterThanEqual',
144
- ] as const
116
+ export const COMPARISON_OPERATORS = ['equal', 'notEqual', 'lessThan', 'lessThanEqual', 'greaterThan', 'greaterThanEqual'] as const
145
117
 
146
118
  export const LOGICAL_OPERATORS = ['and', 'or'] as const
147
119
 
@@ -270,9 +242,7 @@ const isSameType = (L: string, R: string): boolean => L === R
270
242
 
271
243
  // Check if combination exists in rules (handles bidirectional matching)
272
244
  const isValidCombination = (L: string, R: string): boolean => {
273
- return OPERATOR_TYPE_RULES.some(
274
- ([left, right, _]) => (left === L && right === R) || (left === R && right === L)
275
- )
245
+ return OPERATOR_TYPE_RULES.some(([left, right, _]) => (left === L && right === R) || (left === R && right === L))
276
246
  }
277
247
 
278
248
  // Type constraint validation for operators ([L, R, Result] format)
@@ -287,8 +257,6 @@ export const getOperatorResultType = (L: string, R: string, op: string): string
287
257
  if (COMPARISON_OPERATORS.includes(op as any) || LOGICAL_OPERATORS.includes(op as any)) return 'bool'
288
258
  // Same type operations return the same type
289
259
  if (isSameType(L, R)) return L
290
- const rule = OPERATOR_TYPE_RULES.find(
291
- ([left, right, _]) => (left === L && right === R) || (left === R && right === L)
292
- )
260
+ const rule = OPERATOR_TYPE_RULES.find(([left, right, _]) => (left === L && right === R) || (left === R && right === L))
293
261
  return rule ? rule[2] : L
294
262
  }
package/src/types.ts CHANGED
@@ -21,6 +21,7 @@ export type GL = EventState<{
21
21
  count: number
22
22
  instanceCount: number
23
23
  particleCount: number | [number, number] | [number, number, number]
24
+ precision: 'lowp' | 'mediump' | 'highp'
24
25
  loading: number
25
26
  el: HTMLCanvasElement
26
27
  vs?: string | Vec4
@@ -123,7 +124,7 @@ export interface WebGPUState {
123
124
  * for webgl
124
125
  */
125
126
  export interface WebGLState {
126
- context: WebGLRenderingContext
127
+ context: WebGL2RenderingContext
127
128
  program: WebGLProgram
128
- storages: any
129
+ uniforms: Nested<WebGLUniformLocation | null>
129
130
  }
@@ -94,7 +94,8 @@ export const getStride = (arrayLength: number, count = 1, error = console.warn)
94
94
 
95
95
  export const GLSL_FS = /* cpp */ `
96
96
  #version 300 es
97
- precision mediump float;
97
+ precision highp float;
98
+ precision highp int;
98
99
  out vec4 fragColor;
99
100
  uniform vec2 iResolution;
100
101
  void main() {