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.
- package/README.md +10 -9
- package/dist/index.cjs +66 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +547 -0
- package/dist/index.js +39 -21
- package/dist/index.js.map +1 -1
- package/dist/native.cjs +66 -0
- package/dist/native.cjs.map +1 -0
- package/dist/native.d.cts +53 -0
- package/dist/native.js +39 -21
- package/dist/native.js.map +1 -1
- package/dist/react.cjs +66 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +8 -0
- package/dist/react.js +40 -22
- package/dist/react.js.map +1 -1
- package/dist/solid.cjs +66 -0
- package/dist/solid.cjs.map +1 -0
- package/dist/solid.d.cts +8 -0
- package/dist/solid.js +40 -22
- package/dist/solid.js.map +1 -1
- package/package.json +2 -1
- package/src/index.ts +0 -2
- package/src/native.ts +2 -2
- package/src/node/code.ts +103 -0
- package/src/node/const.ts +158 -98
- package/src/node/index.ts +109 -82
- package/src/node/infer.ts +93 -0
- package/src/node/node.ts +43 -92
- package/src/node/scope.ts +121 -0
- package/src/node/types.ts +120 -86
- package/src/node/utils.ts +95 -0
- package/src/utils/pipeline.ts +4 -5
- package/src/utils/program.ts +13 -9
- package/src/webgl.ts +1 -1
- package/src/webgpu.ts +2 -2
- package/dist/index.d.ts +0 -399
- package/dist/index.mjs +0 -48
- package/dist/index.mjs.map +0 -1
- package/dist/native.d.ts +0 -53
- package/dist/native.mjs +0 -48
- package/dist/native.mjs.map +0 -1
- package/dist/react.d.ts +0 -8
- package/dist/react.mjs +0 -48
- package/dist/react.mjs.map +0 -1
- package/dist/solid.d.ts +0 -8
- package/dist/solid.mjs +0 -48
- package/dist/solid.mjs.map +0 -1
- package/src/code/glsl.ts +0 -148
- package/src/code/wgsl.ts +0 -134
- package/src/node/cache.ts +0 -60
- package/src/node/conv.ts +0 -111
- package/src/node/uniform.ts +0 -92
package/src/node/node.ts
CHANGED
|
@@ -1,100 +1,51 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import type {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
return
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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
|
-
|
|
71
|
-
}
|
|
72
|
-
|
|
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
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
-
|
|
28
|
+
type _Swizzles<T extends string> = T | `${T}${T}` | `${T}${T}${T}` | `${T}${T}${T}${T}`
|
|
61
29
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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
|
-
|
|
85
|
-
(
|
|
86
|
-
|
|
87
|
-
}
|
|
77
|
+
// Variable manipulation
|
|
78
|
+
assign(n: X): NodeProxy
|
|
79
|
+
toVar(name?: string): NodeProxy
|
|
80
|
+
toConst(name?: string): NodeProxy
|
|
88
81
|
|
|
89
|
-
//
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
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
|
-
//
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
+
}
|
package/src/utils/pipeline.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
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
|
|
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.
|
|
42
|
-
if (is.
|
|
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: {
|
package/src/utils/program.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
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
|
-
|
|
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.
|
|
41
|
-
if (is.
|
|
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
|
-
|
|
44
|
-
|
|
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
|
-
|
|
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
|
|