glre 0.43.0 → 0.45.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
@@ -112,7 +112,7 @@ interface NodeContext {
112
112
  fragInputs: Map<string, string>;
113
113
  vertInputs: Map<string, string>;
114
114
  vertOutputs: Map<string, string>;
115
- vertVaryings: Map<string, string>;
115
+ vertVaryings: Map<string, VaryingInfo>;
116
116
  computeInputs: Map<string, string>;
117
117
  dependencies: Map<string, Set<string>>;
118
118
  structStructFields: Map<string, StructFields>;
@@ -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
  */
@@ -158,6 +208,10 @@ type Mat4 = XImpl<'mat4'>;
158
208
  type Texture$1 = XImpl<'texture'>;
159
209
  type Sampler2D = XImpl<'sampler2D'>;
160
210
  type StructBase = XImpl<'struct'>;
211
+ interface VaryingInfo {
212
+ node: Y;
213
+ code?: string;
214
+ }
161
215
  interface ConstantsToType {
162
216
  void: Void;
163
217
  bool: Bool;
@@ -190,10 +244,11 @@ interface ConstantsToType {
190
244
  type XImpl<T extends C> = _X<T> & {
191
245
  [K in string as K extends Methods ? never : K]: any;
192
246
  } & {
193
- [K in Swizzles]: X<InferSwizzleType<K>>;
247
+ [K in Swizzles]: X<InferSwizzleType<T, K>>;
194
248
  };
195
249
  type C = Constants;
196
250
  type X<T extends C = C> = T extends keyof ConstantsToType ? ConstantsToType[T] : _X<T>;
251
+ type Y<T extends C = C> = number | number[] | string | boolean | undefined | HTMLElement | X<T>;
197
252
  type Methods = Functions | Operators | Conversions | Swizzles | '__nodeType' | 'type' | 'props' | 'isProxy' | 'assign' | 'toVar' | 'toString' | 'element' | 'select';
198
253
  interface _X<T extends C> {
199
254
  readonly __nodeType?: T;
@@ -270,7 +325,7 @@ interface _X<T extends C> {
270
325
  any(): Bool;
271
326
  determinant(): T extends 'mat2' | 'mat3' | 'mat4' ? Float : never;
272
327
  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;
328
+ 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
329
  length(): T extends 'vec2' | 'vec3' | 'vec4' ? Float : never;
275
330
  lengthSq(): Float;
276
331
  luminance(): Float;
@@ -350,6 +405,7 @@ type GL = EventState<{
350
405
  count: number;
351
406
  instanceCount: number;
352
407
  particleCount: number | [number, number] | [number, number, number];
408
+ precision: 'lowp' | 'mediump' | 'highp';
353
409
  loading: number;
354
410
  el: HTMLCanvasElement;
355
411
  vs?: string | Vec4;
@@ -452,9 +508,9 @@ interface WebGPUState {
452
508
  * for webgl
453
509
  */
454
510
  interface WebGLState {
455
- context: WebGLRenderingContext;
511
+ context: WebGL2RenderingContext;
456
512
  program: WebGLProgram;
457
- storages: any;
513
+ uniforms: Nested<WebGLUniformLocation | null>;
458
514
  }
459
515
 
460
516
  declare const isGL: (a: unknown) => a is EventState<GL>;
@@ -476,6 +532,7 @@ declare const createGL: (props?: Partial<GL>) => EventState<{
476
532
  count: number;
477
533
  instanceCount: number;
478
534
  particleCount: number | [number, number] | [number, number, number];
535
+ precision: "lowp" | "mediump" | "highp";
479
536
  loading: number;
480
537
  el: HTMLCanvasElement;
481
538
  vs?: string | Vec4;
package/dist/solid.d.ts CHANGED
@@ -112,7 +112,7 @@ interface NodeContext {
112
112
  fragInputs: Map<string, string>;
113
113
  vertInputs: Map<string, string>;
114
114
  vertOutputs: Map<string, string>;
115
- vertVaryings: Map<string, string>;
115
+ vertVaryings: Map<string, VaryingInfo>;
116
116
  computeInputs: Map<string, string>;
117
117
  dependencies: Map<string, Set<string>>;
118
118
  structStructFields: Map<string, StructFields>;
@@ -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
  */
@@ -158,6 +208,10 @@ type Mat4 = XImpl<'mat4'>;
158
208
  type Texture$1 = XImpl<'texture'>;
159
209
  type Sampler2D = XImpl<'sampler2D'>;
160
210
  type StructBase = XImpl<'struct'>;
211
+ interface VaryingInfo {
212
+ node: Y;
213
+ code?: string;
214
+ }
161
215
  interface ConstantsToType {
162
216
  void: Void;
163
217
  bool: Bool;
@@ -190,10 +244,11 @@ interface ConstantsToType {
190
244
  type XImpl<T extends C> = _X<T> & {
191
245
  [K in string as K extends Methods ? never : K]: any;
192
246
  } & {
193
- [K in Swizzles]: X<InferSwizzleType<K>>;
247
+ [K in Swizzles]: X<InferSwizzleType<T, K>>;
194
248
  };
195
249
  type C = Constants;
196
250
  type X<T extends C = C> = T extends keyof ConstantsToType ? ConstantsToType[T] : _X<T>;
251
+ type Y<T extends C = C> = number | number[] | string | boolean | undefined | HTMLElement | X<T>;
197
252
  type Methods = Functions | Operators | Conversions | Swizzles | '__nodeType' | 'type' | 'props' | 'isProxy' | 'assign' | 'toVar' | 'toString' | 'element' | 'select';
198
253
  interface _X<T extends C> {
199
254
  readonly __nodeType?: T;
@@ -270,7 +325,7 @@ interface _X<T extends C> {
270
325
  any(): Bool;
271
326
  determinant(): T extends 'mat2' | 'mat3' | 'mat4' ? Float : never;
272
327
  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;
328
+ 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
329
  length(): T extends 'vec2' | 'vec3' | 'vec4' ? Float : never;
275
330
  lengthSq(): Float;
276
331
  luminance(): Float;
@@ -350,6 +405,7 @@ type GL = EventState<{
350
405
  count: number;
351
406
  instanceCount: number;
352
407
  particleCount: number | [number, number] | [number, number, number];
408
+ precision: 'lowp' | 'mediump' | 'highp';
353
409
  loading: number;
354
410
  el: HTMLCanvasElement;
355
411
  vs?: string | Vec4;
@@ -452,9 +508,9 @@ interface WebGPUState {
452
508
  * for webgl
453
509
  */
454
510
  interface WebGLState {
455
- context: WebGLRenderingContext;
511
+ context: WebGL2RenderingContext;
456
512
  program: WebGLProgram;
457
- storages: any;
513
+ uniforms: Nested<WebGLUniformLocation | null>;
458
514
  }
459
515
 
460
516
  declare const isGL: (a: unknown) => a is EventState<GL>;
@@ -476,6 +532,7 @@ declare const createGL: (props?: Partial<GL>) => EventState<{
476
532
  count: number;
477
533
  instanceCount: number;
478
534
  particleCount: number | [number, number] | [number, number, number];
535
+ precision: "lowp" | "mediump" | "highp";
479
536
  loading: number;
480
537
  el: HTMLCanvasElement;
481
538
  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.45.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() {')
@@ -70,6 +104,7 @@ export const fragment = (x: X, c: NodeContext = {}) => {
70
104
  export const vertex = (x: X, c: NodeContext = {}) => {
71
105
  c.code?.headers?.clear()
72
106
  c.label = 'vert' // for varying inputs or outputs
107
+ if (c.code) for (const [id, { node }] of c.code.vertVaryings.entries()) c.code.vertVaryings.set(id, { node, code: code(node, c) }) // ① prebuild varying.code because the scope (e.g. output function definitions) is fixed to vertex.
73
108
  const [head, lines, ret] = build(x, c)
74
109
  const result = []
75
110
  if (c.isWebGL) {
@@ -80,7 +115,7 @@ export const vertex = (x: X, c: NodeContext = {}) => {
80
115
  result.push('void main() {')
81
116
  result.push(` ${lines}`)
82
117
  result.push(` gl_Position = ${ret};`)
83
- for (const [id, code] of c.code?.vertVaryings?.entries() || []) result.push(` ${id} = ${code};`)
118
+ if (c.code) for (const [id, varying] of c.code.vertVaryings.entries()) result.push(` ${id} = ${varying.code!};`) // ② varying.code is already prebuilt
84
119
  } else {
85
120
  if (c.code?.vertInputs?.size) result.push(generateStruct('In', c.code.vertInputs))
86
121
  if (c.code?.vertOutputs?.size) result.push(generateStruct('Out', c.code.vertOutputs))
@@ -90,7 +125,7 @@ export const vertex = (x: X, c: NodeContext = {}) => {
90
125
  result.push(' var out: Out;')
91
126
  result.push(` ${lines}`)
92
127
  result.push(` out.position = ${ret};`)
93
- for (const [id, code] of c.code?.vertVaryings?.entries() || []) result.push(` out.${id} = ${code};`)
128
+ if (c.code) for (const [id, varying] of c.code.vertVaryings.entries()) result.push(` out.${id} = ${varying.code!};`)
94
129
  result.push(' return out;')
95
130
  }
96
131
  result.push('}')
@@ -106,7 +141,7 @@ export const compute = (x: X, c: NodeContext = {}) => {
106
141
  const result = []
107
142
  if (c.isWebGL) {
108
143
  result.push('#version 300 es')
109
- result.push('precision mediump float;')
144
+ precisionHead(result, 'highp')
110
145
  result.push(head)
111
146
  result.push('void main() {')
112
147
  result.push(` ${lines}`)
package/src/node/types.ts CHANGED
@@ -90,7 +90,7 @@ export interface NodeContext {
90
90
  fragInputs: Map<string, string>
91
91
  vertInputs: Map<string, string>
92
92
  vertOutputs: Map<string, string>
93
- vertVaryings: Map<string, string>
93
+ vertVaryings: Map<string, VaryingInfo>
94
94
  computeInputs: Map<string, string>
95
95
  dependencies: Map<string, Set<string>>
96
96
  structStructFields: Map<string, StructFields>
@@ -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'>
@@ -179,6 +202,12 @@ export type Mat4 = XImpl<'mat4'>
179
202
  export type Texture = XImpl<'texture'>
180
203
  export type Sampler2D = XImpl<'sampler2D'>
181
204
  export type StructBase = XImpl<'struct'>
205
+
206
+ export interface VaryingInfo {
207
+ node: Y
208
+ code?: string
209
+ }
210
+
182
211
  export type Struct<T extends StructFields = any> = Omit<StructBase, keyof T> & {
183
212
  [K in keyof T]: T[K] extends X<infer U> ? X<U> : never
184
213
  } & {
@@ -218,7 +247,7 @@ export interface ConstantsToType {
218
247
  type XImpl<T extends C> = _X<T> & {
219
248
  [K in string as K extends Methods ? never : K]: any
220
249
  } & {
221
- [K in Swizzles]: X<InferSwizzleType<K>>
250
+ [K in Swizzles]: X<InferSwizzleType<T, K>>
222
251
  }
223
252
 
224
253
  type C = Constants
@@ -333,16 +362,8 @@ interface _X<T extends C> {
333
362
 
334
363
  // 2. WGSL-compliant return types with individual function constraints
335
364
  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
365
+ distance<U extends C>(y: T extends 'vec2' | 'vec3' | 'vec4' ? (U extends T ? number | X<U> : never) : never): Float
366
+ 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
367
  length(): T extends 'vec2' | 'vec3' | 'vec4' ? Float : never
347
368
  lengthSq(): Float
348
369
  luminance(): Float
@@ -405,13 +426,8 @@ interface _X<T extends C> {
405
426
  min<U extends C>(y: number | X<U>): X<InferOperator<T, U>>
406
427
  mix<U extends C>(y: number | X<U>, a: number | Float | X<U>): X<InferOperator<T, U>>
407
428
  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
429
+ reflect<U extends C>(N: T extends 'vec2' | 'vec3' | 'vec4' ? (U extends T ? number | X<U> : never) : never): X<T>
430
+ 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
431
 
416
432
  // 2. Functions where not first argument determines return type with unified parameter types
417
433
  smoothstep<U extends C>(edge0: number | X<U>, edge1: number | X<U>): X<InferOperator<T, U>>