glre 0.26.0 → 0.28.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.
Files changed (53) hide show
  1. package/README.md +10 -9
  2. package/dist/index.cjs +66 -0
  3. package/dist/index.cjs.map +1 -0
  4. package/dist/index.d.cts +547 -0
  5. package/dist/index.js +39 -21
  6. package/dist/index.js.map +1 -1
  7. package/dist/native.cjs +66 -0
  8. package/dist/native.cjs.map +1 -0
  9. package/dist/native.d.cts +53 -0
  10. package/dist/native.js +39 -21
  11. package/dist/native.js.map +1 -1
  12. package/dist/react.cjs +66 -0
  13. package/dist/react.cjs.map +1 -0
  14. package/dist/react.d.cts +8 -0
  15. package/dist/react.js +40 -22
  16. package/dist/react.js.map +1 -1
  17. package/dist/solid.cjs +66 -0
  18. package/dist/solid.cjs.map +1 -0
  19. package/dist/solid.d.cts +8 -0
  20. package/dist/solid.js +40 -22
  21. package/dist/solid.js.map +1 -1
  22. package/package.json +2 -1
  23. package/src/index.ts +0 -2
  24. package/src/native.ts +2 -2
  25. package/src/node/code.ts +103 -0
  26. package/src/node/const.ts +158 -98
  27. package/src/node/index.ts +109 -82
  28. package/src/node/infer.ts +93 -0
  29. package/src/node/node.ts +43 -92
  30. package/src/node/scope.ts +121 -0
  31. package/src/node/types.ts +120 -86
  32. package/src/node/utils.ts +95 -0
  33. package/src/utils/pipeline.ts +4 -5
  34. package/src/utils/program.ts +13 -9
  35. package/src/webgl.ts +1 -1
  36. package/src/webgpu.ts +2 -2
  37. package/dist/index.d.ts +0 -399
  38. package/dist/index.mjs +0 -48
  39. package/dist/index.mjs.map +0 -1
  40. package/dist/native.d.ts +0 -53
  41. package/dist/native.mjs +0 -48
  42. package/dist/native.mjs.map +0 -1
  43. package/dist/react.d.ts +0 -8
  44. package/dist/react.mjs +0 -48
  45. package/dist/react.mjs.map +0 -1
  46. package/dist/solid.d.ts +0 -8
  47. package/dist/solid.mjs +0 -48
  48. package/dist/solid.mjs.map +0 -1
  49. package/src/code/glsl.ts +0 -148
  50. package/src/code/wgsl.ts +0 -134
  51. package/src/node/cache.ts +0 -60
  52. package/src/node/conv.ts +0 -111
  53. package/src/node/uniform.ts +0 -92
package/src/node/node.ts CHANGED
@@ -1,100 +1,51 @@
1
- import { OPERATORS, FUNCTIONS, SWIZZLES } from './const'
2
- import { is } from '../utils/helpers'
3
- import type { NodeType } from './const'
4
- import type { Node, ProxyCallback, X } from './types'
5
-
6
- let nodeIdCounter = 0
7
-
8
- // ノードIDを生成
9
- const generateNodeId = () => `node_${++nodeIdCounter}`
10
-
11
- // ノードを作成
12
- export const createNode = (type: NodeType, value?: any, options?: Partial<Node>): Node => {
13
- return {
14
- id: generateNodeId(),
15
- type,
16
- value,
17
- children: [],
18
- ...options,
1
+ import { code } from './code'
2
+ import { assign, toVar, toConst } from './scope'
3
+ import { getId, isConversion, isFunction, isOperator, isSwizzle } from './utils'
4
+ import type { Functions, NodeProps, NodeProxy, NodeTypes, Operators, Swizzles, X } from './types'
5
+
6
+ const toPrimitive = (x: X) => {
7
+ return (hint: string) => {
8
+ if (hint === 'string') return code(x)
19
9
  }
20
10
  }
21
11
 
22
- const isSwizzleProperty = (key = '') => SWIZZLES.includes(key as any)
23
- const isOperatorMethod = (key = '') => OPERATORS.includes(key as any)
24
- const isMathMethod = (key = '') => FUNCTIONS.includes(key as any)
25
-
26
- // Proxyハンドラーを作成
27
- const createNodeProxy = (node: Node, callback?: (info: ProxyCallback) => X) => {
28
- const get = (_target: unknown, key: unknown) => {
29
- if (!is.str(key) || key === 'then') return void 0
30
-
31
- if (key === 'id') return node.id
32
- if (key === 'type') return node.type
33
- if (key === 'value') return node.value
34
- if (key === 'property') return node.property
35
-
36
- // swizzle prooerty
37
- if (isSwizzleProperty(key))
38
- return createNodeProxy(
39
- createNode(getSwizzleType(key), undefined, {
40
- parent: node,
41
- property: key,
42
- }),
43
- callback
44
- )
45
-
46
- // 演算子メソッド
47
- if (isOperatorMethod(key))
48
- return (...args: any[]) => {
49
- return createNodeProxy(
50
- createNode(node.type, undefined, {
51
- operator: key as any,
52
- children: [node, ...args],
53
- }),
54
- callback
55
- )
56
- }
57
-
58
- // 数学関数メソッド
59
- if (isMathMethod(key))
60
- return (...args: any[]) => {
61
- return createNodeProxy(
62
- createNode(getMathReturnType(key, node.type), undefined, {
63
- mathFunction: key as any,
64
- children: [node, ...args],
65
- }),
66
- callback
67
- )
12
+ export const node = (type: NodeTypes, props?: NodeProps | null, ...args: X[]) => {
13
+ if (!props) props = {}
14
+ if (args.length) props.children = args
15
+ const x = new Proxy(() => {}, {
16
+ get(_, key) {
17
+ if (key === 'type') return type
18
+ if (key === 'props') return props
19
+ if (key === 'toVar') return toVar(x)
20
+ if (key === 'toConst') return toConst(x)
21
+ if (key === 'assign') return assign(x)
22
+ if (key === 'isProxy') return true
23
+ if (key === 'toString') return code.bind(null, x)
24
+ if (key === Symbol.toPrimitive) return toPrimitive(x)
25
+ if (isSwizzle(key)) return s(key, x)
26
+ if (isOperator(key)) return (...y: X[]) => o(key, x, ...y)
27
+ if (isFunction(key)) return (...y: X[]) => f(key, x, ...y)
28
+ if (isConversion(key)) return n(key, x)
29
+ },
30
+ set(_, key, value) {
31
+ if (isSwizzle(key)) {
32
+ s(key, x).assign(value)
33
+ return true
68
34
  }
69
-
70
- return callback?.({ path: [key], args: [] })
71
- }
72
- const apply = (_target: unknown, _thisArg: unknown, args: any) => {
73
- return callback?.({ path: [], args })
74
- }
75
-
76
- return new Proxy(() => {}, { get, apply }) as X
35
+ return false
36
+ },
37
+ }) as unknown as NodeProxy
38
+ return x
77
39
  }
78
40
 
79
- // スウィズルの戻り値型を取得
80
- const getSwizzleType = (swizzle: string): NodeType => {
81
- if (swizzle.length === 1) return 'float'
82
- if (swizzle.length === 2) return 'vec2'
83
- if (swizzle.length === 3) return 'vec3'
84
- if (swizzle.length === 4) return 'vec4'
85
- return 'float'
86
- }
41
+ // Node shorthands
42
+ export const v = (...args: X[]) => node('variable', { id: getId() }, ...args)
43
+ export const s = (key: Swizzles, arg: X) => node('swizzle', null, key, arg)
44
+ export const n = (key: string, ...args: X[]) => node('conversions', null, key, ...args)
45
+ export const o = (key: Operators, ...args: X[]) => node('operator', null, key, ...args)
46
+ export const f = (key: Functions, ...args: X[]) => node('math_fun', null, key, ...args)
87
47
 
88
- // 数学関数の戻り値型を取得
89
- const getMathReturnType = (func: string, inputType: NodeType): NodeType => {
90
- if (func === 'length') return 'float'
91
- if (func === 'normalize') return inputType
92
- if (func === 'toVar') return inputType
93
- return inputType
94
- }
48
+ // uniform and attribute
49
+ export const u = (id: string, value?: number | number[] | boolean) => node('uniform', { id, value })
95
50
 
96
- // 公開API
97
- export const node = (type: NodeType, value?: any, options?: Partial<Node>) => {
98
- const nodeInstance = createNode(type, value, options)
99
- return createNodeProxy(nodeInstance)
100
- }
51
+ export const select = (x: X, y: X, z: X) => node('ternary', null, x, y, z)
@@ -0,0 +1,121 @@
1
+ import { infer } from './infer'
2
+ import { node } from './node'
3
+ import { getId } from './utils'
4
+ import type { NodeProxy, X } from './types'
5
+
6
+ let _scope: NodeProxy | null = null
7
+
8
+ const scoped = (x: NodeProxy | null, callback = () => {}) => {
9
+ const prev = _scope
10
+ _scope = x
11
+ callback()
12
+ _scope = prev
13
+ }
14
+
15
+ const addToScope = (x: NodeProxy) => {
16
+ if (!_scope) return // ignore
17
+ if (!_scope.props.children) _scope.props.children = []
18
+ _scope.props.children.push(x)
19
+ }
20
+
21
+ export const If = (condition: X, callback: () => void) => {
22
+ const scope = node('scope')
23
+ scoped(scope, callback)
24
+ const ifNode = node('if', null, condition, scope)
25
+ addToScope(ifNode)
26
+ const createChain = () => ({
27
+ ElseIf: (newCondition: X, elseIfCallback: () => void) => {
28
+ const elseIfScope = node('scope')
29
+ scoped(elseIfScope, elseIfCallback)
30
+ ifNode.props.children!.push(newCondition, elseIfScope)
31
+ return createChain()
32
+ },
33
+ Else: (elseCallback: () => void) => {
34
+ const elseScope = node('scope')
35
+ scoped(elseScope, elseCallback)
36
+ ifNode.props.children!.push(elseScope)
37
+ },
38
+ })
39
+ return createChain()
40
+ }
41
+
42
+ export const Loop = (x: X, callback?: (params: { i: NodeProxy }) => void) => {
43
+ const y = node('scope')
44
+ scoped(y, () => callback?.({ i: node('variable', { id: 'i' }) }))
45
+ const ret = node('loop', null, x, y)
46
+ addToScope(ret)
47
+ return ret
48
+ }
49
+
50
+ export const Switch = (value: X) => {
51
+ const switchNode = node('switch', null, value)
52
+ addToScope(switchNode)
53
+ const createChain = () => ({
54
+ Case: (...values: X[]) => {
55
+ return (callback: () => void) => {
56
+ const caseScope = node('scope')
57
+ scoped(caseScope, callback)
58
+ const caseNode = node('case', null, ...values, caseScope)
59
+ switchNode.props.children!.push(caseNode)
60
+ return createChain()
61
+ }
62
+ },
63
+ Default: (callback: () => void) => {
64
+ const defaultScope = node('scope')
65
+ scoped(defaultScope, callback)
66
+ const defaultNode = node('default', null, defaultScope)
67
+ switchNode.props.children!.push(defaultNode)
68
+ },
69
+ })
70
+
71
+ return createChain()
72
+ }
73
+
74
+ export const Fn = (callback: (args: NodeProxy[]) => NodeProxy) => {
75
+ const id = getId()
76
+ return (...args: NodeProxy[]) => {
77
+ const x = node('scope')
78
+ let y: NodeProxy | undefined
79
+ const paramVars: NodeProxy[] = []
80
+ for (let i = 0; i < args.length; i++) {
81
+ const paramId = `p${i}`
82
+ const paramVar = node('variable', { id: paramId })
83
+ paramVars.push(paramVar)
84
+ }
85
+ scoped(x, () => (y = callback(paramVars)))
86
+ const returnType = y ? infer(y) : 'void'
87
+ const paramInfo = args.map((arg, i) => ({ name: `p${i}`, type: infer(arg) }))
88
+ const def = node('fn_def', { id, returnType, paramInfo, args }, x, y)
89
+ return node('fn_run', { id, returnType }, def, ...paramVars)
90
+ }
91
+ }
92
+
93
+ export const toVar = (x: X) => (id?: string) => {
94
+ if (!id) id = getId()
95
+ const y = node('variable', { id })
96
+ const z = node('declare', null, y, x)
97
+ addToScope(z)
98
+ return y
99
+ }
100
+
101
+ export const toConst = (x: X) => (id?: string) => {
102
+ if (!id) id = getId()
103
+ const y = node('constant', { id })
104
+ const z = node('declare', null, y, x)
105
+ addToScope(z)
106
+ return y
107
+ }
108
+
109
+ export const assign = (x: X) => (y: X) => {
110
+ const assignNode = node('assign', null, x, y)
111
+ addToScope(assignNode)
112
+ return x
113
+ }
114
+
115
+ export const varying = (value: X, name?: string) => {
116
+ if (!name) name = getId()
117
+ const varyingVar = node('varying', { id: name })
118
+ const declaration = node('declare', null, varyingVar, value)
119
+ addToScope(declaration)
120
+ return varyingVar
121
+ }
package/src/node/types.ts CHANGED
@@ -1,101 +1,135 @@
1
- import type { NodeType, Operator, MathFunction, Swillzes } from './const'
1
+ import { CONSTANTS, CONVERSIONS, FUNCTIONS, OPERATOR_KEYS } from './const'
2
2
 
3
- // ノードの基本インターフェース
4
- export interface Node {
5
- id: string
6
- type: NodeType
7
- value?: any
8
- property?: string
9
- parent?: Node
10
- children?: Node[]
11
- operator?: Operator
12
- mathFunction?: MathFunction
13
- }
3
+ export type Constants = (typeof CONSTANTS)[number] | 'void'
14
4
 
15
- // Proxyハンドラーのコールバック型
16
- export interface ProxyCallback {
17
- path: string[]
18
- args: any[]
19
- }
5
+ export type Conversions = (typeof CONVERSIONS)[number]
6
+
7
+ export type Functions = (typeof FUNCTIONS)[number]
20
8
 
21
- // ノード作成関数の型
22
- export type NodeCreator = (value?: any) => X
9
+ export type Operators = (typeof OPERATOR_KEYS)[number]
23
10
 
24
- // 演算子メソッドの型
25
- export interface OperatorMethods {
26
- add(x: X | number): X
27
- sub(x: X | number): X
28
- mul(x: X | number): X
29
- div(x: X | number): X
30
- mod(x: X | number): X
31
- equal(x: X | number): X
32
- notEqual(x: X | number): X
33
- lessThan(x: X | number): X
34
- lessThanEqual(x: X | number): X
35
- greaterThan(x: X | number): X
36
- greaterThanEqual(x: X | number): X
37
- and(x: X): X
38
- or(x: X): X
39
- not(): X
11
+ export interface NodeProps {
12
+ id?: string
13
+ args?: X[]
14
+ type?: string
15
+ children?: X[]
16
+ returnType?: Constants
17
+ value?: number | number[] | boolean
18
+ paramInfo?: Array<{ name: string; type: string }>
40
19
  }
41
20
 
42
- // 数学関数メソッドの型
43
- export interface MathMethods {
44
- abs(): X
45
- acos(): X
46
- asin(): X
47
- atan(): X
48
- ceil(): X
49
- cos(): X
50
- floor(): X
51
- fract(): X
52
- length(): X
53
- normalize(): X
54
- sin(): X
55
- sqrt(): X
56
- tan(): X
57
- toVar(): X
21
+ export interface NodeConfig {
22
+ isWebGL?: boolean
23
+ uniforms?: Set<string>
24
+ functions?: Set<string>
25
+ onUniform?: (name: string, value: any) => void
58
26
  }
59
27
 
60
- // 全てのswizzleパターンをまとめる型
28
+ type _Swizzles<T extends string> = T | `${T}${T}` | `${T}${T}${T}` | `${T}${T}${T}${T}`
61
29
 
62
- // スウィズルプロパティの型
63
- export type SwizzleProperties = {
64
- [k in Swillzes]: X
65
- }
30
+ export type Swizzles =
31
+ | _Swizzles<'x' | 'y' | 'z' | 'w'>
32
+ | _Swizzles<'r' | 'g' | 'b' | 'a'>
33
+ | _Swizzles<'p' | 'q'>
34
+ | _Swizzles<'s' | 't'>
66
35
 
67
- // ノードProxy型
68
- export interface X extends MathMethods, OperatorMethods, SwizzleProperties {
69
- readonly id: string
70
- readonly type: NodeType
71
- readonly value: any
72
- readonly property: string
73
- (...args: any[]): X
74
- }
36
+ export type NodeTypes =
37
+ | 'uniform'
38
+ | 'variable'
39
+ | 'swizzle'
40
+ | 'operator'
41
+ | 'conversions'
42
+ | 'math_fun'
43
+ | 'declare'
44
+ | 'assign'
45
+ | 'fn_def'
46
+ | 'fn_run'
47
+ | 'if'
48
+ | 'loop'
49
+ | 'scope'
50
+ | 'switch'
51
+ | 'case'
52
+ | 'default'
53
+ | 'ternary'
54
+ | 'attribute'
55
+ | 'varying'
56
+ | 'builtin'
57
+ | 'constant'
58
+ | 'vertex_stage'
75
59
 
76
- // ユニフォーム変数の型
77
- export interface UniformNode extends X {
78
- set(value: any): void
79
- onObjectUpdate(callback: (context: any) => any): UniformNode
80
- onRenderUpdate(callback: (context: any) => any): UniformNode
81
- }
60
+ export interface NodeProxy extends Record<Swizzles | Conversions, NodeProxy> {
61
+ // Operators
62
+ add(n: X): NodeProxy
63
+ sub(n: X): NodeProxy
64
+ mul(n: X): NodeProxy
65
+ div(n: X): NodeProxy
66
+ mod(n: X): NodeProxy
67
+ equal(n: X): NodeProxy
68
+ notEqual(n: X): NodeProxy
69
+ lessThan(n: X): NodeProxy
70
+ lessThanEqual(n: X): NodeProxy
71
+ greaterThan(n: X): NodeProxy
72
+ greaterThanEqual(n: X): NodeProxy
73
+ and(n: X): NodeProxy
74
+ or(n: X): NodeProxy
75
+ not(): NodeProxy
82
76
 
83
- // 関数定義の型
84
- export interface FunctionNode {
85
- (...args: any[]): X
86
- call(x: X[]): X
87
- }
77
+ // Variable manipulation
78
+ assign(n: X): NodeProxy
79
+ toVar(name?: string): NodeProxy
80
+ toConst(name?: string): NodeProxy
88
81
 
89
- // 条件分岐の型
90
- export interface ConditionalNode {
91
- ElseIf(condition: X, callback: () => void): ConditionalNode
92
- Else(callback: () => void): void
93
- }
82
+ // Math function methods
83
+ abs(): NodeProxy
84
+ sin(): NodeProxy
85
+ cos(): NodeProxy
86
+ tan(): NodeProxy
87
+ asin(): NodeProxy
88
+ acos(): NodeProxy
89
+ atan(): NodeProxy
90
+ atan2(x: X): NodeProxy
91
+ pow(y: X): NodeProxy
92
+ pow2(): NodeProxy
93
+ pow3(): NodeProxy
94
+ pow4(): NodeProxy
95
+ sqrt(): NodeProxy
96
+ inverseSqrt(): NodeProxy
97
+ exp(): NodeProxy
98
+ exp2(): NodeProxy
99
+ log(): NodeProxy
100
+ log2(): NodeProxy
101
+ floor(): NodeProxy
102
+ ceil(): NodeProxy
103
+ round(): NodeProxy
104
+ fract(): NodeProxy
105
+ trunc(): NodeProxy
106
+ min(y: X): NodeProxy
107
+ max(y: X): NodeProxy
108
+ clamp(min: X, max: X): NodeProxy
109
+ saturate(): NodeProxy
110
+ mix(y: X, a: X): NodeProxy
111
+ step(edge: X): NodeProxy
112
+ smoothstep(edge0: X, edge1: X): NodeProxy
113
+ length(): NodeProxy
114
+ distance(y: X): NodeProxy
115
+ dot(y: X): NodeProxy
116
+ cross(y: X): NodeProxy
117
+ normalize(): NodeProxy
118
+ reflect(N: X): NodeProxy
119
+ refract(N: X, eta: X): NodeProxy
120
+ sign(): NodeProxy
121
+ oneMinus(): NodeProxy
122
+ reciprocal(): NodeProxy
123
+ negate(): NodeProxy
124
+ dFdx(): NodeProxy
125
+ dFdy(): NodeProxy
126
+ fwidth(): NodeProxy
94
127
 
95
- // WebGL/WebGPU変換コンテキスト
96
- export interface ConversionContext {
97
- target: 'webgl' | 'webgpu'
98
- nodes: Map<string, Node>
99
- variables: Map<string, string>
100
- functions: Map<string, string>
128
+ // System properties
129
+ toString(c?: NodeConfig): string
130
+ type: NodeTypes
131
+ props: NodeProps
132
+ isProxy: true
101
133
  }
134
+
135
+ export type X = NodeProxy | number | string | boolean | null | undefined
@@ -0,0 +1,95 @@
1
+ import { is } from '../utils/helpers'
2
+ import { code } from './code'
3
+ import { CONVERSIONS, FUNCTIONS, OPERATOR_KEYS, OPERATORS, TYPE_MAPPING } from './const'
4
+ import type { Conversions, Functions, NodeConfig, NodeProxy, Operators, Swizzles, X } from './types'
5
+
6
+ export const isSwizzle = (key: unknown): key is Swizzles => {
7
+ return is.str(key) && /^[xyzwrgbastpq]{1,4}$/.test(key)
8
+ }
9
+
10
+ export const isOperator = (key: unknown): key is Operators => {
11
+ return OPERATOR_KEYS.includes(key as Operators)
12
+ }
13
+
14
+ export const isFunction = (key: unknown): key is Functions => {
15
+ return FUNCTIONS.includes(key as Functions)
16
+ }
17
+
18
+ export const isConversion = (key: unknown): key is Conversions => {
19
+ return CONVERSIONS.includes(key as Conversions)
20
+ }
21
+
22
+ export const isNodeProxy = (x: unknown): x is NodeProxy => {
23
+ if (!x) return false
24
+ if (!is.fun(x)) return false // @ts-ignore
25
+ return x.isProxy
26
+ }
27
+
28
+ let count = 0
29
+
30
+ export const hex2rgb = (hex: number) => {
31
+ const r = ((hex >> 16) & 0xff) / 255
32
+ const g = ((hex >> 8) & 0xff) / 255
33
+ const b = (hex & 0xff) / 255
34
+ return [r, g, b]
35
+ }
36
+
37
+ export const getId = () => `i${count++}`
38
+
39
+ export const joins = (children: X[], c: NodeConfig) => {
40
+ return children
41
+ .filter((x) => !is.und(x) && !is.nul(x))
42
+ .map((x) => code(x, c))
43
+ .join(', ')
44
+ }
45
+
46
+ export const formatConversions = (x: X, c?: NodeConfig) => {
47
+ if (!is.str(x)) return ''
48
+ if (c?.isWebGL) return x
49
+ return TYPE_MAPPING[x as keyof typeof TYPE_MAPPING]
50
+ }
51
+
52
+ export const getOperator = (op: X) => {
53
+ return OPERATORS[op as keyof typeof OPERATORS] || op
54
+ }
55
+
56
+ const generateHead = (c: NodeConfig) => {
57
+ const uniforms = Array.from(c.uniforms!)
58
+ .map((uniform, i) => {
59
+ if (c.isWebGL) return `uniform ${uniform};`
60
+ else return `@group(0) @binding(${i}) var<uniform> ${uniform};`
61
+ })
62
+ .join('\n')
63
+ const functions = Array.from(c.functions!).join('\n')
64
+ return `${uniforms}\n${functions}`
65
+ }
66
+
67
+ const generateFragmentMain = (body: string, head: string, isWebGL = true) => {
68
+ if (isWebGL)
69
+ return `
70
+ #version 300 es
71
+ precision mediump float;
72
+ out vec4 fragColor;
73
+ ${head}
74
+ void main() {
75
+ fragColor = ${body};
76
+ }`.trim()
77
+ return `
78
+ ${head}
79
+ @fragment
80
+ fn main(@builtin(position) position: vec4f) -> @location(0) vec4f {
81
+ return ${body};
82
+ }`.trim()
83
+ }
84
+
85
+ export const fragment = (x: X, c: NodeConfig) => {
86
+ const body = code(x, c)
87
+ const head = generateHead(c)
88
+ return generateFragmentMain(body, head, c.isWebGL)
89
+ }
90
+
91
+ export const vertex = (x: X, c: NodeConfig) => {
92
+ const body = code(x, c)
93
+ const head = generateHead(c)
94
+ return generateFragmentMain(body, head, c.isWebGL)
95
+ }
@@ -1,5 +1,4 @@
1
- import { wgsl } from '../code/wgsl'
2
- import { X } from '../node'
1
+ import { fragment, vertex, X } from '../node'
3
2
  import { is } from './helpers'
4
3
  import type { GPUContext, GPUDevice, GPUPipeline } from '../types'
5
4
 
@@ -21,7 +20,7 @@ fn main(@builtin(position) position: vec4f) -> @location(0) vec4f {
21
20
  }
22
21
  `
23
22
 
24
- export const createDevive = async (c: GPUContext) => {
23
+ export const createDevice = async (c: GPUContext) => {
25
24
  const gpu = (navigator as any).gpu
26
25
  const format = gpu.getPreferredCanvasFormat()
27
26
  const adapter = await gpu.requestAdapter()
@@ -38,8 +37,8 @@ export const createPipeline = (
38
37
  vs: string | X = defaultVertexWGSL,
39
38
  fs: string | X = defaultFragmentWGSL
40
39
  ) => {
41
- if (is.obj(fs)) fs = wgsl(fs)
42
- if (is.obj(vs)) vs = wgsl(vs)
40
+ if (!is.str(fs)) fs = fragment(fs, { isWebGL: false })
41
+ if (!is.str(vs)) vs = vertex(vs, { isWebGL: false })
43
42
  const layout = device.createPipelineLayout({ bindGroupLayouts })
44
43
  return device.createRenderPipeline({
45
44
  vertex: {
@@ -1,5 +1,4 @@
1
- import { glsl } from '../code/glsl'
2
- import { X } from '../node'
1
+ import { fragment, vertex, X } from '../node'
3
2
  import { is } from './helpers'
4
3
 
5
4
  export const defaultVertexGLSL = /* cpp */ `
@@ -29,24 +28,29 @@ const createShader = (c: WebGLRenderingContext, source: string, type: number) =>
29
28
  if (c.getShaderParameter(shader, c.COMPILE_STATUS)) return shader
30
29
  const error = c.getShaderInfoLog(shader)
31
30
  c.deleteShader(shader)
32
- throw new Error(`Could not compile shader: ${error}`)
31
+ console.warn(`Could not compile shader: ${error}`)
33
32
  }
34
33
 
35
34
  export const createProgram = (
36
35
  c: WebGLRenderingContext,
37
36
  vs: string | X = defaultVertexGLSL,
38
- fs: string | X = defaultFragmentGLSL
37
+ fs: string | X = defaultFragmentGLSL,
38
+ onError = () => {}
39
39
  ) => {
40
- if (is.obj(fs)) fs = glsl(fs as X)
41
- if (is.obj(vs)) vs = glsl(vs as X)
40
+ if (!is.str(fs)) fs = fragment(fs, { isWebGL: true })
41
+ if (!is.str(vs)) vs = vertex(fs, { isWebGL: true })
42
42
  const pg = c.createProgram()
43
- c.attachShader(pg, createShader(c, vs, c.VERTEX_SHADER))
44
- c.attachShader(pg, createShader(c, fs, c.FRAGMENT_SHADER))
43
+ const _vs = createShader(c, vs, c.VERTEX_SHADER)
44
+ const _fs = createShader(c, fs, c.FRAGMENT_SHADER)
45
+ if (!_vs || !_fs) return onError()
46
+ c.attachShader(pg, _vs)
47
+ c.attachShader(pg, _fs)
45
48
  c.linkProgram(pg)
46
49
  if (c.getProgramParameter(pg, c.LINK_STATUS)) return pg
47
50
  const error = c.getProgramInfoLog(pg)
48
51
  c.deleteProgram(pg)
49
- throw new Error(`Could not link pg: ${error}`)
52
+ onError()
53
+ console.warn(`Could not link pg: ${error}`)
50
54
  }
51
55
 
52
56
  export const createVbo = (c: WebGLRenderingContext, data: number[]) => {
package/src/webgl.ts CHANGED
@@ -5,7 +5,7 @@ import type { GL, WebGLState } from './types'
5
5
 
6
6
  export const webgl = async (gl: Partial<GL>) => {
7
7
  const c = gl.el!.getContext('webgl2')!
8
- const pg = createProgram(c, gl.vs, gl.fs)
8
+ const pg = createProgram(c, gl.vs, gl.fs, () => void (gl.isLoop = false))!
9
9
  const state = { context: c, program: pg } as WebGLState
10
10
  c.useProgram(pg)
11
11