glre 0.28.0 → 0.30.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/index-q8W5cl04.d.cts +358 -0
- package/dist/index.cjs +38 -34
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -546
- package/dist/index.js +38 -34
- package/dist/index.js.map +1 -1
- package/dist/native.cjs +38 -34
- package/dist/native.cjs.map +1 -1
- package/dist/native.d.cts +9 -9
- package/dist/native.js +38 -34
- package/dist/native.js.map +1 -1
- package/dist/react.cjs +38 -34
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +2 -2
- package/dist/react.js +38 -34
- package/dist/react.js.map +1 -1
- package/dist/solid.cjs +38 -34
- package/dist/solid.cjs.map +1 -1
- package/dist/solid.d.cts +2 -2
- package/dist/solid.js +38 -34
- package/dist/solid.js.map +1 -1
- package/package.json +23 -23
- package/src/index.ts +0 -1
- package/src/node/code.ts +74 -62
- package/src/node/const.ts +60 -20
- package/src/node/index.ts +43 -40
- package/src/node/infer.ts +63 -64
- package/src/node/node.ts +38 -37
- package/src/node/scope.ts +70 -80
- package/src/node/types.ts +51 -24
- package/src/node/utils.ts +91 -26
- package/src/types.ts +7 -7
- package/src/utils/pipeline.ts +6 -6
- package/src/utils/program.ts +6 -6
- package/src/webgl.ts +1 -2
package/src/node/node.ts
CHANGED
|
@@ -1,51 +1,52 @@
|
|
|
1
1
|
import { code } from './code'
|
|
2
|
-
import { assign, toVar
|
|
3
|
-
import {
|
|
2
|
+
import { assign, toVar } from './scope'
|
|
3
|
+
import { conversionToConstant, isConversion, isFunction, isOperator, isSwizzle } from './utils'
|
|
4
4
|
import type { Functions, NodeProps, NodeProxy, NodeTypes, Operators, Swizzles, X } from './types'
|
|
5
5
|
|
|
6
|
-
const toPrimitive = (x: X) => {
|
|
7
|
-
|
|
8
|
-
if (hint === 'string') return code(x)
|
|
9
|
-
}
|
|
6
|
+
const toPrimitive = (x: X, hint: string) => {
|
|
7
|
+
if (hint === 'string') return code(x)
|
|
10
8
|
}
|
|
11
9
|
|
|
12
10
|
export const node = (type: NodeTypes, props?: NodeProps | null, ...args: X[]) => {
|
|
13
11
|
if (!props) props = {}
|
|
14
12
|
if (args.length) props.children = args
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
},
|
|
37
|
-
}) as unknown as NodeProxy
|
|
13
|
+
const get = (_: unknown, key: string | Symbol) => {
|
|
14
|
+
if (key === 'type') return type
|
|
15
|
+
if (key === 'props') return props
|
|
16
|
+
if (key === 'toVar') return toVar.bind(null, x)
|
|
17
|
+
if (key === 'assign') return assign.bind(null, x)
|
|
18
|
+
if (key === 'isProxy') return true
|
|
19
|
+
if (key === 'toString') return code.bind(null, x)
|
|
20
|
+
if (key === Symbol.toPrimitive) return toPrimitive.bind(null, x)
|
|
21
|
+
if (isSwizzle(key)) return swizzle(key, x)
|
|
22
|
+
if (isOperator(key)) return (...y: X[]) => operator(key, x, ...y)
|
|
23
|
+
if (isFunction(key)) return (...y: X[]) => function_(key, x, ...y)
|
|
24
|
+
if (isConversion(key)) return () => conversion(conversionToConstant(key), x)
|
|
25
|
+
}
|
|
26
|
+
const set = (_: unknown, key: string, y: X) => {
|
|
27
|
+
if (isSwizzle(key)) {
|
|
28
|
+
swizzle(key, x).assign(y)
|
|
29
|
+
return true
|
|
30
|
+
}
|
|
31
|
+
return false
|
|
32
|
+
}
|
|
33
|
+
const x = new Proxy({}, { get, set }) as unknown as NodeProxy
|
|
38
34
|
return x
|
|
39
35
|
}
|
|
40
36
|
|
|
41
|
-
//
|
|
42
|
-
export const
|
|
43
|
-
export const
|
|
44
|
-
export const
|
|
45
|
-
export const
|
|
46
|
-
export const
|
|
37
|
+
// headers
|
|
38
|
+
export const attribute = (x: X, id?: string) => node('varying', { id }, x)
|
|
39
|
+
export const uniform = (x: X, id?: string) => node('uniform', { id }, x)
|
|
40
|
+
export const varying = (x: X, id?: string) => node('varying', { id }, x)
|
|
41
|
+
export const constant = (x: X, id?: string) => node('constant', { id }, x)
|
|
42
|
+
export const variable = (id: string) => node('variable', { id })
|
|
43
|
+
export const builtin = (id: string) => node('builtin', { id })
|
|
47
44
|
|
|
48
|
-
//
|
|
49
|
-
export const
|
|
45
|
+
// Node shorthands
|
|
46
|
+
export const swizzle = (key: Swizzles, arg: X) => node('swizzle', null, key, arg)
|
|
47
|
+
export const operator = (key: Operators, ...args: X[]) => node('operator', null, key, ...args)
|
|
48
|
+
export const function_ = (key: Functions, ...args: X[]) => node('function', null, key, ...args)
|
|
49
|
+
export const conversion = (key: string, ...args: X[]) => node('conversion', null, key, ...args)
|
|
50
50
|
|
|
51
|
+
// x ? y : z
|
|
51
52
|
export const select = (x: X, y: X, z: X) => node('ternary', null, x, y, z)
|
package/src/node/scope.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { node } from './node'
|
|
1
|
+
import { int } from '.'
|
|
2
|
+
import { conversion, node } from './node'
|
|
3
3
|
import { getId } from './utils'
|
|
4
|
-
import type { NodeProxy, X } from './types'
|
|
4
|
+
import type { FnLayout, NodeProps, NodeProxy, X } from './types'
|
|
5
5
|
|
|
6
6
|
let _scope: NodeProxy | null = null
|
|
7
7
|
|
|
8
|
-
const scoped = (x: NodeProxy | null,
|
|
8
|
+
const scoped = (x: NodeProxy | null, fun = () => {}) => {
|
|
9
9
|
const prev = _scope
|
|
10
10
|
_scope = x
|
|
11
|
-
|
|
11
|
+
fun()
|
|
12
12
|
_scope = prev
|
|
13
13
|
}
|
|
14
14
|
|
|
@@ -18,104 +18,94 @@ const addToScope = (x: NodeProxy) => {
|
|
|
18
18
|
_scope.props.children.push(x)
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
export const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const
|
|
21
|
+
export const toVar = (x: X, id?: string) => {
|
|
22
|
+
if (!id) id = getId()
|
|
23
|
+
const y = node('variable', { id, inferFrom: x })
|
|
24
|
+
const z = node('declare', null, x, y)
|
|
25
|
+
addToScope(z)
|
|
26
|
+
return y
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export const assign = (x: X, y: X) => {
|
|
30
|
+
const z = node('assign', null, x, y)
|
|
31
|
+
addToScope(z)
|
|
32
|
+
return x
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export const If = (x: X, fun: () => void) => {
|
|
36
|
+
const y = node('scope')
|
|
37
|
+
scoped(y, fun)
|
|
38
|
+
const ifNode = node('if', null, x, y)
|
|
25
39
|
addToScope(ifNode)
|
|
26
|
-
const
|
|
27
|
-
ElseIf: (
|
|
28
|
-
const
|
|
29
|
-
scoped(
|
|
30
|
-
ifNode.props.children!.push(
|
|
31
|
-
return
|
|
40
|
+
const ret = () => ({
|
|
41
|
+
ElseIf: (_x: X, _fun: () => void) => {
|
|
42
|
+
const _y = node('scope')
|
|
43
|
+
scoped(_y, _fun)
|
|
44
|
+
ifNode.props.children!.push(_x, _y)
|
|
45
|
+
return ret()
|
|
32
46
|
},
|
|
33
|
-
Else: (
|
|
34
|
-
const
|
|
35
|
-
scoped(
|
|
36
|
-
ifNode.props.children!.push(
|
|
47
|
+
Else: (_fun: () => void) => {
|
|
48
|
+
const _x = node('scope')
|
|
49
|
+
scoped(_x, _fun)
|
|
50
|
+
ifNode.props.children!.push(_x)
|
|
37
51
|
},
|
|
38
52
|
})
|
|
39
|
-
return
|
|
53
|
+
return ret()
|
|
40
54
|
}
|
|
41
55
|
|
|
42
|
-
export const Loop = (x: X,
|
|
56
|
+
export const Loop = (x: X, fun: (params: { i: NodeProxy }) => void) => {
|
|
43
57
|
const y = node('scope')
|
|
44
|
-
scoped(y, () =>
|
|
58
|
+
scoped(y, () => fun({ i: node('variable', { id: 'i', inferFrom: int(0) }) }))
|
|
45
59
|
const ret = node('loop', null, x, y)
|
|
46
60
|
addToScope(ret)
|
|
47
61
|
return ret
|
|
48
62
|
}
|
|
49
63
|
|
|
50
|
-
export const Switch = (
|
|
51
|
-
const switchNode = node('switch', null,
|
|
64
|
+
export const Switch = (x: X) => {
|
|
65
|
+
const switchNode = node('switch', null, x)
|
|
52
66
|
addToScope(switchNode)
|
|
53
|
-
const
|
|
67
|
+
const ret = () => ({
|
|
54
68
|
Case: (...values: X[]) => {
|
|
55
|
-
return (
|
|
56
|
-
const
|
|
57
|
-
scoped(
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
return createChain()
|
|
69
|
+
return (fun: () => void) => {
|
|
70
|
+
const y = node('scope')
|
|
71
|
+
scoped(y, fun)
|
|
72
|
+
for (const _x of values) switchNode.props.children!.push(_x, y)
|
|
73
|
+
return ret()
|
|
61
74
|
}
|
|
62
75
|
},
|
|
63
|
-
Default: (
|
|
64
|
-
const
|
|
65
|
-
scoped(
|
|
66
|
-
|
|
67
|
-
switchNode.props.children!.push(defaultNode)
|
|
76
|
+
Default: (fun: () => void) => {
|
|
77
|
+
const scope = node('scope')
|
|
78
|
+
scoped(scope, fun)
|
|
79
|
+
switchNode.props.children!.push(scope)
|
|
68
80
|
},
|
|
69
81
|
})
|
|
70
82
|
|
|
71
|
-
return
|
|
83
|
+
return ret()
|
|
72
84
|
}
|
|
73
85
|
|
|
74
|
-
export const Fn = (
|
|
75
|
-
|
|
76
|
-
|
|
86
|
+
export const Fn = (fun: (paramVars: NodeProxy[]) => NodeProxy) => {
|
|
87
|
+
let layout: FnLayout
|
|
88
|
+
const ret = (...args: X[]) => {
|
|
89
|
+
const id = layout?.name || getId()
|
|
77
90
|
const x = node('scope')
|
|
78
91
|
let y: NodeProxy | undefined
|
|
79
92
|
const paramVars: NodeProxy[] = []
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
93
|
+
const paramDefs: NodeProps[] = []
|
|
94
|
+
if (layout?.inputs)
|
|
95
|
+
for (const input of layout.inputs) {
|
|
96
|
+
paramDefs.push({ id: input.name, inferFrom: conversion(input.type) })
|
|
97
|
+
}
|
|
98
|
+
else
|
|
99
|
+
for (let i = 0; i < args.length; i++) {
|
|
100
|
+
paramDefs.push({ id: `p${i}`, inferFrom: args[i] })
|
|
101
|
+
}
|
|
102
|
+
for (const props of paramDefs) paramVars.push(node('variable', props))
|
|
103
|
+
scoped(x, () => (y = fun(paramVars)))
|
|
104
|
+
return node('define', { id, layout }, x, y, ...args)
|
|
90
105
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
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
|
|
106
|
+
ret.setLayout = (newLayout: FnLayout) => {
|
|
107
|
+
layout = newLayout
|
|
108
|
+
return ret
|
|
109
|
+
}
|
|
110
|
+
return ret
|
|
121
111
|
}
|
package/src/node/types.ts
CHANGED
|
@@ -8,21 +8,30 @@ export type Functions = (typeof FUNCTIONS)[number]
|
|
|
8
8
|
|
|
9
9
|
export type Operators = (typeof OPERATOR_KEYS)[number]
|
|
10
10
|
|
|
11
|
+
export interface FnLayout {
|
|
12
|
+
name: string
|
|
13
|
+
type: Constants | 'auto'
|
|
14
|
+
inputs?: Array<{
|
|
15
|
+
name: string
|
|
16
|
+
type: Constants
|
|
17
|
+
}>
|
|
18
|
+
}
|
|
19
|
+
|
|
11
20
|
export interface NodeProps {
|
|
12
21
|
id?: string
|
|
13
22
|
args?: X[]
|
|
14
23
|
type?: string
|
|
15
24
|
children?: X[]
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
paramInfo?: Array<{ name: string; type: string }>
|
|
25
|
+
inferFrom?: X
|
|
26
|
+
layout?: FnLayout
|
|
19
27
|
}
|
|
20
28
|
|
|
21
29
|
export interface NodeConfig {
|
|
22
30
|
isWebGL?: boolean
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
31
|
+
binding?: number
|
|
32
|
+
infers?: WeakMap<NodeProxy, Constants>
|
|
33
|
+
headers?: Map<string, string>
|
|
34
|
+
onMount?: (name: string) => void
|
|
26
35
|
}
|
|
27
36
|
|
|
28
37
|
type _Swizzles<T extends string> = T | `${T}${T}` | `${T}${T}${T}` | `${T}${T}${T}${T}`
|
|
@@ -34,30 +43,29 @@ export type Swizzles =
|
|
|
34
43
|
| _Swizzles<'s' | 't'>
|
|
35
44
|
|
|
36
45
|
export type NodeTypes =
|
|
46
|
+
// headers
|
|
47
|
+
| 'attribute'
|
|
37
48
|
| 'uniform'
|
|
49
|
+
| 'varying'
|
|
50
|
+
| 'constant'
|
|
51
|
+
// variables
|
|
38
52
|
| 'variable'
|
|
39
53
|
| 'swizzle'
|
|
54
|
+
| 'ternary'
|
|
55
|
+
| 'builtin'
|
|
56
|
+
| 'conversion'
|
|
40
57
|
| 'operator'
|
|
41
|
-
| '
|
|
42
|
-
|
|
43
|
-
| '
|
|
58
|
+
| 'function'
|
|
59
|
+
// scopes
|
|
60
|
+
| 'scope'
|
|
44
61
|
| 'assign'
|
|
45
|
-
| 'fn_def'
|
|
46
|
-
| 'fn_run'
|
|
47
|
-
| 'if'
|
|
48
62
|
| 'loop'
|
|
49
|
-
| '
|
|
63
|
+
| 'define'
|
|
64
|
+
| 'if'
|
|
50
65
|
| 'switch'
|
|
51
|
-
| '
|
|
52
|
-
| 'default'
|
|
53
|
-
| 'ternary'
|
|
54
|
-
| 'attribute'
|
|
55
|
-
| 'varying'
|
|
56
|
-
| 'builtin'
|
|
57
|
-
| 'constant'
|
|
58
|
-
| 'vertex_stage'
|
|
66
|
+
| 'declare'
|
|
59
67
|
|
|
60
|
-
export interface NodeProxy extends Record<Swizzles
|
|
68
|
+
export interface NodeProxy extends Record<Swizzles, NodeProxy> {
|
|
61
69
|
// Operators
|
|
62
70
|
add(n: X): NodeProxy
|
|
63
71
|
sub(n: X): NodeProxy
|
|
@@ -77,7 +85,6 @@ export interface NodeProxy extends Record<Swizzles | Conversions, NodeProxy> {
|
|
|
77
85
|
// Variable manipulation
|
|
78
86
|
assign(n: X): NodeProxy
|
|
79
87
|
toVar(name?: string): NodeProxy
|
|
80
|
-
toConst(name?: string): NodeProxy
|
|
81
88
|
|
|
82
89
|
// Math function methods
|
|
83
90
|
abs(): NodeProxy
|
|
@@ -126,10 +133,30 @@ export interface NodeProxy extends Record<Swizzles | Conversions, NodeProxy> {
|
|
|
126
133
|
fwidth(): NodeProxy
|
|
127
134
|
|
|
128
135
|
// System properties
|
|
136
|
+
toBool(): NodeProxy
|
|
137
|
+
toUint(): NodeProxy
|
|
138
|
+
toInt(): NodeProxy
|
|
139
|
+
toFloat(): NodeProxy
|
|
140
|
+
toBvec2(): NodeProxy
|
|
141
|
+
toIvec2(): NodeProxy
|
|
142
|
+
toUvec2(): NodeProxy
|
|
143
|
+
toVec2(): NodeProxy
|
|
144
|
+
toBvec3(): NodeProxy
|
|
145
|
+
toIvec3(): NodeProxy
|
|
146
|
+
toUvec3(): NodeProxy
|
|
147
|
+
toVec3(): NodeProxy
|
|
148
|
+
toBvec4(): NodeProxy
|
|
149
|
+
toIvec4(): NodeProxy
|
|
150
|
+
toUvec4(): NodeProxy
|
|
151
|
+
toVec4(): NodeProxy
|
|
152
|
+
toColor(): NodeProxy
|
|
153
|
+
toMat2(): NodeProxy
|
|
154
|
+
toMat3(): NodeProxy
|
|
155
|
+
toMat4(): NodeProxy
|
|
129
156
|
toString(c?: NodeConfig): string
|
|
130
157
|
type: NodeTypes
|
|
131
158
|
props: NodeProps
|
|
132
159
|
isProxy: true
|
|
133
160
|
}
|
|
134
161
|
|
|
135
|
-
export type X = NodeProxy | number | string | boolean |
|
|
162
|
+
export type X = NodeProxy | number | string | boolean | undefined
|
package/src/node/utils.ts
CHANGED
|
@@ -1,7 +1,26 @@
|
|
|
1
1
|
import { is } from '../utils/helpers'
|
|
2
2
|
import { code } from './code'
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
3
|
+
import { infer } from './infer'
|
|
4
|
+
import {
|
|
5
|
+
CONSTANTS,
|
|
6
|
+
CONVERSIONS,
|
|
7
|
+
FUNCTIONS,
|
|
8
|
+
OPERATOR_KEYS,
|
|
9
|
+
OPERATORS,
|
|
10
|
+
TYPE_MAPPING,
|
|
11
|
+
WGSL_TO_GLSL_BUILTIN,
|
|
12
|
+
} from './const'
|
|
13
|
+
import type {
|
|
14
|
+
Constants,
|
|
15
|
+
Conversions,
|
|
16
|
+
Functions,
|
|
17
|
+
NodeConfig,
|
|
18
|
+
NodeProps,
|
|
19
|
+
NodeProxy,
|
|
20
|
+
Operators,
|
|
21
|
+
Swizzles,
|
|
22
|
+
X,
|
|
23
|
+
} from './types'
|
|
5
24
|
|
|
6
25
|
export const isSwizzle = (key: unknown): key is Swizzles => {
|
|
7
26
|
return is.str(key) && /^[xyzwrgbastpq]{1,4}$/.test(key)
|
|
@@ -21,12 +40,10 @@ export const isConversion = (key: unknown): key is Conversions => {
|
|
|
21
40
|
|
|
22
41
|
export const isNodeProxy = (x: unknown): x is NodeProxy => {
|
|
23
42
|
if (!x) return false
|
|
24
|
-
if (
|
|
43
|
+
if (typeof x !== 'object') return false // @ts-ignore
|
|
25
44
|
return x.isProxy
|
|
26
45
|
}
|
|
27
46
|
|
|
28
|
-
let count = 0
|
|
29
|
-
|
|
30
47
|
export const hex2rgb = (hex: number) => {
|
|
31
48
|
const r = ((hex >> 16) & 0xff) / 255
|
|
32
49
|
const g = ((hex >> 8) & 0xff) / 255
|
|
@@ -34,6 +51,8 @@ export const hex2rgb = (hex: number) => {
|
|
|
34
51
|
return [r, g, b]
|
|
35
52
|
}
|
|
36
53
|
|
|
54
|
+
let count = 0
|
|
55
|
+
|
|
37
56
|
export const getId = () => `i${count++}`
|
|
38
57
|
|
|
39
58
|
export const joins = (children: X[], c: NodeConfig) => {
|
|
@@ -53,43 +72,89 @@ export const getOperator = (op: X) => {
|
|
|
53
72
|
return OPERATORS[op as keyof typeof OPERATORS] || op
|
|
54
73
|
}
|
|
55
74
|
|
|
75
|
+
export const getBluiltin = (id: string) => {
|
|
76
|
+
return WGSL_TO_GLSL_BUILTIN[id as keyof typeof WGSL_TO_GLSL_BUILTIN]
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export const conversionToConstant = (conversionKey: string): Constants => {
|
|
80
|
+
const index = CONVERSIONS.indexOf(conversionKey as Conversions)
|
|
81
|
+
return index !== -1 ? CONSTANTS[index] : 'float'
|
|
82
|
+
}
|
|
83
|
+
|
|
56
84
|
const generateHead = (c: NodeConfig) => {
|
|
57
|
-
|
|
58
|
-
.map((
|
|
59
|
-
if (c.isWebGL) return `uniform ${uniform};`
|
|
60
|
-
else return `@group(0) @binding(${i}) var<uniform> ${uniform};`
|
|
61
|
-
})
|
|
85
|
+
return Array.from(c.headers!)
|
|
86
|
+
.map(([, v]) => v)
|
|
62
87
|
.join('\n')
|
|
63
|
-
const functions = Array.from(c.functions!).join('\n')
|
|
64
|
-
return `${uniforms}\n${functions}`
|
|
65
88
|
}
|
|
66
89
|
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
90
|
+
export const generateDefine = (props: NodeProps, c: NodeConfig) => {
|
|
91
|
+
const { id, children = [], layout } = props
|
|
92
|
+
const [x, y, ...args] = children
|
|
93
|
+
const returnType = layout?.type && layout?.type !== 'auto' ? layout?.type : y ? infer(y, c) : 'void'
|
|
94
|
+
const argParams: [name: string, type: string][] = []
|
|
95
|
+
const params: string[] = []
|
|
96
|
+
if (layout?.inputs)
|
|
97
|
+
for (const input of layout.inputs) {
|
|
98
|
+
argParams.push([input.name, input.type])
|
|
99
|
+
}
|
|
100
|
+
else
|
|
101
|
+
for (let i = 0; i < args.length; i++) {
|
|
102
|
+
argParams.push([`p${i}`, infer(args[i], c)])
|
|
103
|
+
}
|
|
104
|
+
let ret = ''
|
|
105
|
+
if (c?.isWebGL) {
|
|
106
|
+
for (const [id, type] of argParams) params.push(`${type} ${id}`)
|
|
107
|
+
ret += `${returnType} ${id}(${params}) {\n`
|
|
108
|
+
} else {
|
|
109
|
+
for (const [id, type] of argParams) params.push(`${id}: ${formatConversions(type, c)}`)
|
|
110
|
+
ret += `fn ${id}(${params}) -> ${formatConversions(returnType, c)} {\n`
|
|
111
|
+
}
|
|
112
|
+
const scopeCode = code(x, c)
|
|
113
|
+
if (scopeCode) ret += scopeCode + '\n'
|
|
114
|
+
if (y) ret += `return ${code(y, c)};`
|
|
115
|
+
ret += '\n}'
|
|
116
|
+
return ret
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const GLSL_FRAGMENT_HEAD = `
|
|
70
120
|
#version 300 es
|
|
71
121
|
precision mediump float;
|
|
72
122
|
out vec4 fragColor;
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}`.trim()
|
|
77
|
-
return `
|
|
78
|
-
${head}
|
|
123
|
+
`.trim()
|
|
124
|
+
|
|
125
|
+
const WGSL_FRAGMENT_HEAD = `
|
|
79
126
|
@fragment
|
|
80
127
|
fn main(@builtin(position) position: vec4f) -> @location(0) vec4f {
|
|
81
|
-
|
|
82
|
-
|
|
128
|
+
`.trim()
|
|
129
|
+
|
|
130
|
+
const generateFragmentMain = (body: string, head: string, isWebGL = true) => {
|
|
131
|
+
let ret = ''
|
|
132
|
+
if (isWebGL) ret += GLSL_FRAGMENT_HEAD
|
|
133
|
+
if (head) ret += '\n' + head + '\n'
|
|
134
|
+
if (isWebGL) ret += `void main() {\n fragColor = ${body};`
|
|
135
|
+
else {
|
|
136
|
+
ret += WGSL_FRAGMENT_HEAD + '\n'
|
|
137
|
+
ret += ` return ${body};`
|
|
138
|
+
}
|
|
139
|
+
ret += '\n}'
|
|
140
|
+
return ret
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const generateVertexMain = (_body: string, _head: string, isWebGL = true) => {
|
|
144
|
+
if (isWebGL) return ``
|
|
145
|
+
return ``
|
|
83
146
|
}
|
|
84
147
|
|
|
85
|
-
export const fragment = (x: X, c: NodeConfig) => {
|
|
148
|
+
export const fragment = (x: X, c: NodeConfig = {}) => {
|
|
86
149
|
const body = code(x, c)
|
|
87
150
|
const head = generateHead(c)
|
|
88
|
-
|
|
151
|
+
const main = generateFragmentMain(body, head, c.isWebGL)
|
|
152
|
+
console.log(`// ↓↓↓ generated ↓↓↓\n\n${main}\n\n`)
|
|
153
|
+
return main
|
|
89
154
|
}
|
|
90
155
|
|
|
91
156
|
export const vertex = (x: X, c: NodeConfig) => {
|
|
92
157
|
const body = code(x, c)
|
|
93
158
|
const head = generateHead(c)
|
|
94
|
-
return
|
|
159
|
+
return generateVertexMain(body, head, c.isWebGL)
|
|
95
160
|
}
|
package/src/types.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { EventState } from 'reev'
|
|
2
2
|
import type { Fun, Queue, Frame } from 'refr'
|
|
3
|
-
import type {
|
|
3
|
+
import type { NodeProxy } from './node'
|
|
4
4
|
export type { Fun, Queue, Frame }
|
|
5
5
|
export type GPUContext = any // GPUCanvasContext https://developer.mozilla.org/en-US/docs/Web/API/GPUCanvasContext
|
|
6
6
|
export type GPUDevice = any //
|
|
@@ -52,12 +52,12 @@ export type GL = EventState<{
|
|
|
52
52
|
mouse: [number, number]
|
|
53
53
|
count: number
|
|
54
54
|
el: HTMLCanvasElement
|
|
55
|
-
vs: string |
|
|
56
|
-
fs: string |
|
|
57
|
-
vert: string |
|
|
58
|
-
frag: string |
|
|
59
|
-
vertex: string |
|
|
60
|
-
fragment: string |
|
|
55
|
+
vs: string | NodeProxy
|
|
56
|
+
fs: string | NodeProxy
|
|
57
|
+
vert: string | NodeProxy
|
|
58
|
+
frag: string | NodeProxy
|
|
59
|
+
vertex: string | NodeProxy
|
|
60
|
+
fragment: string | NodeProxy
|
|
61
61
|
|
|
62
62
|
/**
|
|
63
63
|
* core state
|
package/src/utils/pipeline.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { fragment,
|
|
2
|
-
import {
|
|
1
|
+
import { fragment, isNodeProxy, vertex } from '../node'
|
|
2
|
+
import type { NodeProxy } from '../node'
|
|
3
3
|
import type { GPUContext, GPUDevice, GPUPipeline } from '../types'
|
|
4
4
|
|
|
5
5
|
const defaultVertexWGSL = `
|
|
@@ -34,11 +34,11 @@ export const createPipeline = (
|
|
|
34
34
|
format: string,
|
|
35
35
|
bufferLayouts: any[],
|
|
36
36
|
bindGroupLayouts: any[],
|
|
37
|
-
vs: string |
|
|
38
|
-
fs: string |
|
|
37
|
+
vs: string | NodeProxy = defaultVertexWGSL,
|
|
38
|
+
fs: string | NodeProxy = defaultFragmentWGSL
|
|
39
39
|
) => {
|
|
40
|
-
if (
|
|
41
|
-
if (
|
|
40
|
+
if (isNodeProxy(vs)) vs = vertex(vs, { isWebGL: false })
|
|
41
|
+
if (isNodeProxy(fs)) fs = fragment(fs, { isWebGL: false })
|
|
42
42
|
const layout = device.createPipelineLayout({ bindGroupLayouts })
|
|
43
43
|
return device.createRenderPipeline({
|
|
44
44
|
vertex: {
|
package/src/utils/program.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { fragment,
|
|
2
|
-
import {
|
|
1
|
+
import { fragment, isNodeProxy, vertex } from '../node'
|
|
2
|
+
import type { NodeProxy } from '../node'
|
|
3
3
|
|
|
4
4
|
export const defaultVertexGLSL = /* cpp */ `
|
|
5
5
|
#version 300 es
|
|
@@ -33,12 +33,12 @@ const createShader = (c: WebGLRenderingContext, source: string, type: number) =>
|
|
|
33
33
|
|
|
34
34
|
export const createProgram = (
|
|
35
35
|
c: WebGLRenderingContext,
|
|
36
|
-
vs: string |
|
|
37
|
-
fs: string |
|
|
36
|
+
vs: string | NodeProxy = defaultVertexGLSL,
|
|
37
|
+
fs: string | NodeProxy = defaultFragmentGLSL,
|
|
38
38
|
onError = () => {}
|
|
39
39
|
) => {
|
|
40
|
-
if (
|
|
41
|
-
if (
|
|
40
|
+
if (isNodeProxy(fs)) fs = fragment(fs, { isWebGL: true })
|
|
41
|
+
if (isNodeProxy(vs)) vs = vertex(fs, { isWebGL: true })
|
|
42
42
|
const pg = c.createProgram()
|
|
43
43
|
const _vs = createShader(c, vs, c.VERTEX_SHADER)
|
|
44
44
|
const _fs = createShader(c, fs, c.FRAGMENT_SHADER)
|
package/src/webgl.ts
CHANGED
|
@@ -6,13 +6,12 @@ import type { GL, WebGLState } from './types'
|
|
|
6
6
|
export const webgl = async (gl: Partial<GL>) => {
|
|
7
7
|
const c = gl.el!.getContext('webgl2')!
|
|
8
8
|
const pg = createProgram(c, gl.vs, gl.fs, () => void (gl.isLoop = false))!
|
|
9
|
-
const state = { context: c, program: pg } as WebGLState
|
|
10
9
|
c.useProgram(pg)
|
|
11
|
-
|
|
12
10
|
let _activeUnit = 0
|
|
13
11
|
const uniforms = cached((key) => c.getUniformLocation(pg, key))
|
|
14
12
|
const attribs = cached((key) => c.getAttribLocation(pg, key))
|
|
15
13
|
const units = cached(() => _activeUnit++)
|
|
14
|
+
const state = { context: c, program: pg } as WebGLState
|
|
16
15
|
|
|
17
16
|
const clean = () => c.deleteProgram(pg)
|
|
18
17
|
|