glre 0.31.0 → 0.33.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.cjs +34 -64
- package/dist/index.cjs.map +1 -1
- package/dist/{index.d.cts → index.d.ts} +184 -191
- package/dist/index.js +34 -64
- package/dist/index.js.map +1 -1
- package/dist/native.cjs +34 -64
- package/dist/native.cjs.map +1 -1
- package/dist/native.d.ts +54 -0
- package/dist/native.js +34 -64
- package/dist/native.js.map +1 -1
- package/dist/react.cjs +34 -64
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.ts +8 -0
- package/dist/react.js +34 -64
- package/dist/react.js.map +1 -1
- package/dist/solid.cjs +34 -64
- package/dist/solid.cjs.map +1 -1
- package/dist/solid.d.ts +8 -0
- package/dist/solid.js +34 -64
- package/dist/solid.js.map +1 -1
- package/package.json +7 -6
- package/src/index.ts +19 -5
- package/src/node/code.ts +79 -77
- package/src/node/const.ts +27 -44
- package/src/node/index.ts +98 -12
- package/src/node/infer.ts +32 -15
- package/src/node/node.ts +20 -21
- package/src/node/parse.ts +160 -0
- package/src/node/scope.ts +48 -23
- package/src/node/types.ts +100 -57
- package/src/node/utils.ts +63 -94
- package/src/types.ts +32 -16
- package/src/utils/pipeline.ts +136 -95
- package/src/utils/program.ts +7 -36
- package/src/webgl.ts +7 -3
- package/src/webgpu.ts +82 -58
- package/dist/native.d.cts +0 -53
- package/dist/react.d.cts +0 -8
- package/dist/solid.d.cts +0 -8
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { is } from '../utils/helpers'
|
|
2
|
+
import { code } from './code'
|
|
3
|
+
import { infer } from './infer'
|
|
4
|
+
import { formatConversions, isConstants, addDependency } from './utils'
|
|
5
|
+
import type { Constants, NodeContext, NodeProps, NodeProxy, X } from './types'
|
|
6
|
+
|
|
7
|
+
export const parseArray = (children: X[], c: NodeContext) => {
|
|
8
|
+
return children
|
|
9
|
+
.filter((x) => !is.und(x) && !is.nul(x))
|
|
10
|
+
.map((x) => code(x, c))
|
|
11
|
+
.join(', ')
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const parseTexture = (c: NodeContext, y: X, z: X, w: X) => {
|
|
15
|
+
if (c.isWebGL) {
|
|
16
|
+
const args = w ? [y, z, w] : [y, z]
|
|
17
|
+
return `texture(${parseArray(args, c)})`
|
|
18
|
+
}
|
|
19
|
+
const _y = code(y, c)
|
|
20
|
+
const args = [_y, _y + 'Sampler', code(z, c)]
|
|
21
|
+
if (!w) return `textureSample(${args})`
|
|
22
|
+
args.push(code(w, c))
|
|
23
|
+
return `textureSampleLevel(${args})`
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* scopes
|
|
28
|
+
*/
|
|
29
|
+
export const parseIf = (c: NodeContext, x: X, y: X, children: X[]) => {
|
|
30
|
+
let ret = `if (${code(x, c)}) {\n${code(y, c)}\n}`
|
|
31
|
+
for (let i = 2; i < children.length; i += 2) {
|
|
32
|
+
const isElse = i >= children.length - 1
|
|
33
|
+
ret += !isElse
|
|
34
|
+
? ` else if (${code(children[i], c)}) {\n${code(children[i + 1], c)}\n}`
|
|
35
|
+
: ` else {\n${code(children[i], c)}\n}`
|
|
36
|
+
}
|
|
37
|
+
return ret
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export const parseSwitch = (c: NodeContext, x: X, children: X[]) => {
|
|
41
|
+
let ret = `switch (${code(x, c)}) {\n`
|
|
42
|
+
for (let i = 1; i < children.length; i += 2) {
|
|
43
|
+
const isDefault = i >= children.length - 1
|
|
44
|
+
if (isDefault && children.length % 2 === 0) {
|
|
45
|
+
ret += `default:\n${code(children[i], c)}\nbreak;\n`
|
|
46
|
+
} else if (i + 1 < children.length)
|
|
47
|
+
ret += `case ${code(children[i], c)}:\n${code(children[i + 1], c)}\nbreak;\n`
|
|
48
|
+
}
|
|
49
|
+
ret += '}'
|
|
50
|
+
return ret
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export const parseDeclare = (c: NodeContext, x: X, y: X) => {
|
|
54
|
+
const type = infer(x, c)
|
|
55
|
+
const varName = (y as any)?.props?.id
|
|
56
|
+
if (c.isWebGL) return `${type} ${varName} = ${code(x, c)};`
|
|
57
|
+
const wgslType = formatConversions(type)
|
|
58
|
+
return `var ${varName}: ${wgslType} = ${code(x, c)};`
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export const parseDefine = (c: NodeContext, props: NodeProps, returnType: Constants | string) => {
|
|
62
|
+
const { id, children = [], layout } = props
|
|
63
|
+
const [x, ...args] = children
|
|
64
|
+
const argParams: [name: string, type: string][] = []
|
|
65
|
+
const params: string[] = []
|
|
66
|
+
if (layout?.inputs)
|
|
67
|
+
for (const input of layout.inputs) {
|
|
68
|
+
argParams.push([input.name, input.type])
|
|
69
|
+
}
|
|
70
|
+
else
|
|
71
|
+
for (let i = 0; i < args.length; i++) {
|
|
72
|
+
argParams.push([`p${i}`, infer(args[i], c)])
|
|
73
|
+
}
|
|
74
|
+
const ret = []
|
|
75
|
+
if (c?.isWebGL) {
|
|
76
|
+
for (const [paramId, type] of argParams) {
|
|
77
|
+
addDependency(c, id!, type)
|
|
78
|
+
params.push(`${type} ${paramId}`)
|
|
79
|
+
}
|
|
80
|
+
addDependency(c, id!, returnType)
|
|
81
|
+
ret.push(`${returnType} ${id}(${params}) {`)
|
|
82
|
+
} else {
|
|
83
|
+
for (const [paramId, type] of argParams) params.push(`${paramId}: ${formatConversions(type, c)}`)
|
|
84
|
+
ret.push(`fn ${id}(${params}) -> ${formatConversions(returnType, c)} {`)
|
|
85
|
+
}
|
|
86
|
+
const scopeCode = code(x, c)
|
|
87
|
+
if (scopeCode) ret.push(scopeCode)
|
|
88
|
+
ret.push('}')
|
|
89
|
+
return ret.join('\n')
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export const parseStructHead = (c: NodeContext, id: string, fields: Record<string, NodeProxy> = {}) => {
|
|
93
|
+
const lines: string[] = []
|
|
94
|
+
for (const key in fields) {
|
|
95
|
+
const fieldType = fields[key]
|
|
96
|
+
const type = infer(fieldType, c)
|
|
97
|
+
if (c.isWebGL) addDependency(c, id, type)
|
|
98
|
+
lines.push(c.isWebGL ? `${type} ${key};` : `${key}: ${formatConversions(type, c)},`)
|
|
99
|
+
}
|
|
100
|
+
const ret = lines.join('\n ')
|
|
101
|
+
return `struct ${id} {\n ${ret}\n};`
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export const parseStruct = (
|
|
105
|
+
c: NodeContext,
|
|
106
|
+
id: string,
|
|
107
|
+
instanceId = '',
|
|
108
|
+
fields?: Record<string, NodeProxy>,
|
|
109
|
+
initialValues?: Record<string, NodeProxy>
|
|
110
|
+
) => {
|
|
111
|
+
if (c.isWebGL) {
|
|
112
|
+
if (initialValues) {
|
|
113
|
+
const ordered = []
|
|
114
|
+
for (const key in fields) ordered.push(initialValues[key])
|
|
115
|
+
return `${id} ${instanceId} = ${id}(${parseArray(ordered, c)});`
|
|
116
|
+
} else return `${id} ${instanceId};`
|
|
117
|
+
} else {
|
|
118
|
+
if (initialValues) {
|
|
119
|
+
const ordered = []
|
|
120
|
+
for (const key in fields) ordered.push(initialValues[key])
|
|
121
|
+
return `var ${instanceId}: ${id} = ${id}(${parseArray(ordered, c)});`
|
|
122
|
+
} else return `var ${instanceId}: ${id};`
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* headers
|
|
128
|
+
*/
|
|
129
|
+
export const parseVaryingHead = (c: NodeContext, id: string, type: string) => {
|
|
130
|
+
return c.isWebGL ? `${type} ${id};` : `@location(${c.code?.vertVaryings?.size || 0}) ${id}: ${formatConversions(type, c)}`
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export const parseUniformHead = (c: NodeContext, id: string, type: Constants) => {
|
|
134
|
+
const isTexture = type === 'sampler2D' || type === 'texture'
|
|
135
|
+
if (c.isWebGL)
|
|
136
|
+
return isTexture //
|
|
137
|
+
? `uniform sampler2D ${id};`
|
|
138
|
+
: `uniform ${type} ${id};`
|
|
139
|
+
if (isTexture) {
|
|
140
|
+
const { group = 1, binding = 0 } = c.gl?.webgpu?.textures.map.get(id) || {}
|
|
141
|
+
return (
|
|
142
|
+
`@group(${group}) @binding(${binding}) var ${id}Sampler: sampler;\n` +
|
|
143
|
+
`@group(${group}) @binding(${binding + 1}) var ${id}: texture_2d<f32>;`
|
|
144
|
+
)
|
|
145
|
+
}
|
|
146
|
+
const { group = 0, binding = 0 } = c.gl?.webgpu?.uniforms.map.get(id) || {}
|
|
147
|
+
const wgslType = formatConversions(type, c)
|
|
148
|
+
return `@group(${group}) @binding(${binding}) var<uniform> ${id}: ${wgslType};`
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export const parseAttribHead = (c: NodeContext, id: string, type: Constants) => {
|
|
152
|
+
if (c.isWebGL) return `${type} ${id};`
|
|
153
|
+
const { location = 0 } = c.gl?.webgpu?.attribs.map.get(id) || {}
|
|
154
|
+
const wgslType = formatConversions(type, c)
|
|
155
|
+
return `@location(${location}) ${id}: ${wgslType}`
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export const parseConstantHead = (c: NodeContext, id: string, type: Constants, value: string) => {
|
|
159
|
+
return c.isWebGL ? `const ${type} ${id} = ${value};` : `const ${id}: ${formatConversions(type, c)} = ${value};`
|
|
160
|
+
}
|
package/src/node/scope.ts
CHANGED
|
@@ -3,24 +3,22 @@ import { conversion, node } from './node'
|
|
|
3
3
|
import { getId } from './utils'
|
|
4
4
|
import type { FnLayout, NodeProps, NodeProxy, X } from './types'
|
|
5
5
|
|
|
6
|
-
let
|
|
7
|
-
|
|
8
|
-
const scoped = (x: NodeProxy | null, fun = () => {}) => {
|
|
9
|
-
const prev = _scope
|
|
10
|
-
_scope = x
|
|
11
|
-
fun()
|
|
12
|
-
_scope = prev
|
|
13
|
-
}
|
|
6
|
+
let scope: NodeProxy | null = null
|
|
7
|
+
let define: NodeProxy | null = null
|
|
14
8
|
|
|
15
9
|
const addToScope = (x: NodeProxy) => {
|
|
16
|
-
if (!
|
|
17
|
-
if (!
|
|
18
|
-
|
|
10
|
+
if (!scope) return
|
|
11
|
+
if (!scope.props.children) scope.props.children = []
|
|
12
|
+
scope.props.children.push(x)
|
|
13
|
+
if (x.type !== 'return' || !define) return
|
|
14
|
+
const { props } = define
|
|
15
|
+
if (!props.inferFrom) props.inferFrom = []
|
|
16
|
+
props.inferFrom.push(x)
|
|
19
17
|
}
|
|
20
18
|
|
|
21
19
|
export const toVar = (x: X, id?: string) => {
|
|
22
20
|
if (!id) id = getId()
|
|
23
|
-
const y = node('variable', { id, inferFrom: x })
|
|
21
|
+
const y = node('variable', { id, inferFrom: [x] })
|
|
24
22
|
const z = node('declare', null, x, y)
|
|
25
23
|
addToScope(z)
|
|
26
24
|
return y
|
|
@@ -32,6 +30,37 @@ export const assign = (x: X, y: X) => {
|
|
|
32
30
|
return x
|
|
33
31
|
}
|
|
34
32
|
|
|
33
|
+
export const Return = (x: X) => {
|
|
34
|
+
const y = node('return', { inferFrom: [x] }, x)
|
|
35
|
+
addToScope(y)
|
|
36
|
+
return y
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Struct functions
|
|
40
|
+
export const struct = (fields: Record<string, NodeProxy>, id = getId()) => {
|
|
41
|
+
return (initialValues: Record<string, NodeProxy> = {}, instanceId = getId()) => {
|
|
42
|
+
const x = node('variable', { id: instanceId, inferFrom: [id] })
|
|
43
|
+
const y = node('struct', { id, fields, initialValues }, x)
|
|
44
|
+
addToScope(y)
|
|
45
|
+
return x
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const scoped = (x: NodeProxy, fun: () => NodeProxy | void, y = define) => {
|
|
50
|
+
// cache to revert
|
|
51
|
+
const _scope = scope
|
|
52
|
+
const _define = define
|
|
53
|
+
// update
|
|
54
|
+
scope = x
|
|
55
|
+
define = y
|
|
56
|
+
if (_scope) x.props.parent = _scope
|
|
57
|
+
const z = fun()
|
|
58
|
+
if (z) Return(z)
|
|
59
|
+
// revert
|
|
60
|
+
scope = _scope
|
|
61
|
+
define = _define
|
|
62
|
+
}
|
|
63
|
+
|
|
35
64
|
export const If = (x: X, fun: () => void) => {
|
|
36
65
|
const y = node('scope')
|
|
37
66
|
scoped(y, fun)
|
|
@@ -55,7 +84,7 @@ export const If = (x: X, fun: () => void) => {
|
|
|
55
84
|
|
|
56
85
|
export const Loop = (x: X, fun: (params: { i: NodeProxy }) => void) => {
|
|
57
86
|
const y = node('scope')
|
|
58
|
-
scoped(y, () => fun({ i: node('variable', { id: 'i', inferFrom: int(0) }) }))
|
|
87
|
+
scoped(y, () => fun({ i: node('variable', { id: 'i', inferFrom: [int(0)] }) }))
|
|
59
88
|
const ret = node('loop', null, x, y)
|
|
60
89
|
addToScope(ret)
|
|
61
90
|
return ret
|
|
@@ -79,7 +108,6 @@ export const Switch = (x: X) => {
|
|
|
79
108
|
switchNode.props.children!.push(scope)
|
|
80
109
|
},
|
|
81
110
|
})
|
|
82
|
-
|
|
83
111
|
return ret()
|
|
84
112
|
}
|
|
85
113
|
|
|
@@ -88,24 +116,21 @@ export const Fn = (fun: (paramVars: NodeProxy[]) => NodeProxy) => {
|
|
|
88
116
|
const ret = (...args: X[]) => {
|
|
89
117
|
const id = layout?.name || getId()
|
|
90
118
|
const x = node('scope')
|
|
91
|
-
let y: NodeProxy | undefined
|
|
92
119
|
const paramVars: NodeProxy[] = []
|
|
93
120
|
const paramDefs: NodeProps[] = []
|
|
94
121
|
if (layout?.inputs)
|
|
95
122
|
for (const input of layout.inputs) {
|
|
96
|
-
paramDefs.push({ id: input.name, inferFrom: conversion(input.type) })
|
|
123
|
+
paramDefs.push({ id: input.name, inferFrom: [conversion(input.type)] })
|
|
97
124
|
}
|
|
98
125
|
else
|
|
99
126
|
for (let i = 0; i < args.length; i++) {
|
|
100
|
-
paramDefs.push({ id: `p${i}`, inferFrom: args[i] })
|
|
127
|
+
paramDefs.push({ id: `p${i}`, inferFrom: [args[i]] })
|
|
101
128
|
}
|
|
102
129
|
for (const props of paramDefs) paramVars.push(node('variable', props))
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
ret.setLayout = (newLayout: FnLayout) => {
|
|
107
|
-
layout = newLayout
|
|
108
|
-
return ret
|
|
130
|
+
const y = node('define', { id, layout }, x, ...args)
|
|
131
|
+
scoped(x, () => fun(paramVars), y)
|
|
132
|
+
return y
|
|
109
133
|
}
|
|
134
|
+
ret.setLayout = (_layout: FnLayout) => void (layout = _layout)
|
|
110
135
|
return ret
|
|
111
136
|
}
|
package/src/node/types.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { GL } from '../types'
|
|
1
2
|
import { CONSTANTS, CONVERSIONS, FUNCTIONS, OPERATOR_KEYS } from './const'
|
|
2
3
|
|
|
3
4
|
export type Constants = (typeof CONSTANTS)[number] | 'void'
|
|
@@ -17,23 +18,68 @@ export interface FnLayout {
|
|
|
17
18
|
}>
|
|
18
19
|
}
|
|
19
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Node
|
|
23
|
+
*/
|
|
24
|
+
export type NodeTypes =
|
|
25
|
+
// headers
|
|
26
|
+
| 'attribute'
|
|
27
|
+
| 'uniform'
|
|
28
|
+
| 'constant'
|
|
29
|
+
// variables
|
|
30
|
+
| 'variable'
|
|
31
|
+
| 'varying'
|
|
32
|
+
| 'ternary'
|
|
33
|
+
| 'builtin'
|
|
34
|
+
| 'conversion'
|
|
35
|
+
| 'operator'
|
|
36
|
+
| 'function'
|
|
37
|
+
// struct
|
|
38
|
+
| 'struct'
|
|
39
|
+
| 'member'
|
|
40
|
+
// scopes
|
|
41
|
+
| 'scope'
|
|
42
|
+
| 'assign'
|
|
43
|
+
| 'loop'
|
|
44
|
+
| 'define'
|
|
45
|
+
| 'if'
|
|
46
|
+
| 'switch'
|
|
47
|
+
| 'declare'
|
|
48
|
+
| 'return'
|
|
49
|
+
|
|
20
50
|
export interface NodeProps {
|
|
21
51
|
id?: string
|
|
22
52
|
args?: X[]
|
|
23
53
|
type?: string
|
|
24
54
|
children?: X[]
|
|
25
|
-
inferFrom?: X
|
|
55
|
+
inferFrom?: X[]
|
|
26
56
|
layout?: FnLayout
|
|
57
|
+
parent?: NodeProxy
|
|
58
|
+
// for struct
|
|
59
|
+
fields?: Record<string, NodeProxy>
|
|
60
|
+
initialValues?: Record<string, NodeProxy>
|
|
27
61
|
}
|
|
28
62
|
|
|
29
|
-
export interface
|
|
63
|
+
export interface NodeContext {
|
|
64
|
+
gl?: Partial<GL>
|
|
65
|
+
isFrag?: boolean
|
|
30
66
|
isWebGL?: boolean
|
|
31
67
|
binding?: number
|
|
32
68
|
infers?: WeakMap<NodeProxy, Constants>
|
|
33
|
-
headers?: Map<string, string>
|
|
34
69
|
onMount?: (name: string) => void
|
|
70
|
+
code?: {
|
|
71
|
+
headers: Map<string, string>
|
|
72
|
+
fragInputs: Map<string, string>
|
|
73
|
+
vertInputs: Map<string, string>
|
|
74
|
+
vertOutputs: Map<string, string>
|
|
75
|
+
vertVaryings: Map<string, string>
|
|
76
|
+
dependencies: Map<string, Set<string>>
|
|
77
|
+
}
|
|
35
78
|
}
|
|
36
79
|
|
|
80
|
+
/**
|
|
81
|
+
* NodeProxy
|
|
82
|
+
*/
|
|
37
83
|
type _Swizzles<T extends string> = T | `${T}${T}` | `${T}${T}${T}` | `${T}${T}${T}${T}`
|
|
38
84
|
|
|
39
85
|
export type Swizzles =
|
|
@@ -42,31 +88,34 @@ export type Swizzles =
|
|
|
42
88
|
| _Swizzles<'p' | 'q'>
|
|
43
89
|
| _Swizzles<'s' | 't'>
|
|
44
90
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
|
48
|
-
|
|
|
49
|
-
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
| '
|
|
53
|
-
| '
|
|
54
|
-
| 'ternary'
|
|
55
|
-
| 'builtin'
|
|
56
|
-
| 'conversion'
|
|
57
|
-
| 'operator'
|
|
58
|
-
| 'function'
|
|
59
|
-
// scopes
|
|
60
|
-
| 'scope'
|
|
91
|
+
type NodeProxyMethods =
|
|
92
|
+
| Functions
|
|
93
|
+
| Operators
|
|
94
|
+
| Conversions
|
|
95
|
+
| Swizzles
|
|
96
|
+
// system property
|
|
97
|
+
| 'type'
|
|
98
|
+
| 'props'
|
|
99
|
+
| 'isProxy'
|
|
61
100
|
| 'assign'
|
|
62
|
-
| '
|
|
63
|
-
| '
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
101
|
+
| 'toVar'
|
|
102
|
+
| 'toString'
|
|
103
|
+
|
|
104
|
+
export type ReadNodeProxy = {
|
|
105
|
+
[K in string as K extends NodeProxyMethods ? never : K]: X
|
|
106
|
+
}
|
|
67
107
|
|
|
68
|
-
export interface
|
|
69
|
-
//
|
|
108
|
+
export interface BaseNodeProxy extends Record<Swizzles, NodeProxy> {
|
|
109
|
+
// System properties
|
|
110
|
+
assign(n: X): NodeProxy
|
|
111
|
+
toVar(name?: string): NodeProxy
|
|
112
|
+
toString(c?: NodeContext): string
|
|
113
|
+
type: NodeTypes
|
|
114
|
+
props: NodeProps
|
|
115
|
+
isProxy: true
|
|
116
|
+
listeners: Set<(value: any) => void>
|
|
117
|
+
|
|
118
|
+
// Operators methods
|
|
70
119
|
add(n: X): NodeProxy
|
|
71
120
|
sub(n: X): NodeProxy
|
|
72
121
|
mul(n: X): NodeProxy
|
|
@@ -82,11 +131,29 @@ export interface NodeProxy extends Record<Swizzles, NodeProxy> {
|
|
|
82
131
|
or(n: X): NodeProxy
|
|
83
132
|
not(): NodeProxy
|
|
84
133
|
|
|
85
|
-
//
|
|
86
|
-
|
|
87
|
-
|
|
134
|
+
// Conversations methods
|
|
135
|
+
toBool(): NodeProxy
|
|
136
|
+
toUint(): NodeProxy
|
|
137
|
+
toInt(): NodeProxy
|
|
138
|
+
toFloat(): NodeProxy
|
|
139
|
+
toBvec2(): NodeProxy
|
|
140
|
+
toIvec2(): NodeProxy
|
|
141
|
+
toUvec2(): NodeProxy
|
|
142
|
+
toVec2(): NodeProxy
|
|
143
|
+
toBvec3(): NodeProxy
|
|
144
|
+
toIvec3(): NodeProxy
|
|
145
|
+
toUvec3(): NodeProxy
|
|
146
|
+
toVec3(): NodeProxy
|
|
147
|
+
toBvec4(): NodeProxy
|
|
148
|
+
toIvec4(): NodeProxy
|
|
149
|
+
toUvec4(): NodeProxy
|
|
150
|
+
toVec4(): NodeProxy
|
|
151
|
+
toColor(): NodeProxy
|
|
152
|
+
toMat2(): NodeProxy
|
|
153
|
+
toMat3(): NodeProxy
|
|
154
|
+
toMat4(): NodeProxy
|
|
88
155
|
|
|
89
|
-
//
|
|
156
|
+
// Function methods
|
|
90
157
|
abs(): NodeProxy
|
|
91
158
|
sin(): NodeProxy
|
|
92
159
|
cos(): NodeProxy
|
|
@@ -131,32 +198,8 @@ export interface NodeProxy extends Record<Swizzles, NodeProxy> {
|
|
|
131
198
|
dFdx(): NodeProxy
|
|
132
199
|
dFdy(): NodeProxy
|
|
133
200
|
fwidth(): NodeProxy
|
|
134
|
-
|
|
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
|
|
156
|
-
toString(c?: NodeConfig): string
|
|
157
|
-
type: NodeTypes
|
|
158
|
-
props: NodeProps
|
|
159
|
-
isProxy: true
|
|
160
201
|
}
|
|
161
202
|
|
|
162
|
-
export type
|
|
203
|
+
export type NodeProxy = BaseNodeProxy & ReadNodeProxy
|
|
204
|
+
|
|
205
|
+
export type X = X[] | (NodeProxy | number | string | boolean | undefined)
|
package/src/node/utils.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import { is } from '../utils/helpers'
|
|
2
|
-
import { code } from './code'
|
|
3
|
-
import { infer } from './infer'
|
|
4
2
|
import {
|
|
5
3
|
CONSTANTS,
|
|
6
4
|
CONVERSIONS,
|
|
@@ -10,17 +8,7 @@ import {
|
|
|
10
8
|
TYPE_MAPPING,
|
|
11
9
|
WGSL_TO_GLSL_BUILTIN,
|
|
12
10
|
} 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'
|
|
11
|
+
import type { Constants, Conversions, Functions, NodeContext, NodeProxy, Operators, Swizzles, X } from './types'
|
|
24
12
|
|
|
25
13
|
export const isSwizzle = (key: unknown): key is Swizzles => {
|
|
26
14
|
return is.str(key) && /^[xyzwrgbastpq]{1,4}$/.test(key)
|
|
@@ -44,6 +32,11 @@ export const isNodeProxy = (x: unknown): x is NodeProxy => {
|
|
|
44
32
|
return x.isProxy
|
|
45
33
|
}
|
|
46
34
|
|
|
35
|
+
export const isConstants = (type?: unknown): type is Constants => {
|
|
36
|
+
if (!is.str(type)) return false
|
|
37
|
+
return CONSTANTS.includes(type)
|
|
38
|
+
}
|
|
39
|
+
|
|
47
40
|
export const hex2rgb = (hex: number) => {
|
|
48
41
|
const r = ((hex >> 16) & 0xff) / 255
|
|
49
42
|
const g = ((hex >> 8) & 0xff) / 255
|
|
@@ -55,17 +48,10 @@ let count = 0
|
|
|
55
48
|
|
|
56
49
|
export const getId = () => `i${count++}`
|
|
57
50
|
|
|
58
|
-
export const
|
|
59
|
-
return children
|
|
60
|
-
.filter((x) => !is.und(x) && !is.nul(x))
|
|
61
|
-
.map((x) => code(x, c))
|
|
62
|
-
.join(', ')
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export const formatConversions = (x: X, c?: NodeConfig) => {
|
|
51
|
+
export const formatConversions = (x: X, c?: NodeContext) => {
|
|
66
52
|
if (!is.str(x)) return ''
|
|
67
53
|
if (c?.isWebGL) return x
|
|
68
|
-
return TYPE_MAPPING[x as keyof typeof TYPE_MAPPING]
|
|
54
|
+
return TYPE_MAPPING[x as keyof typeof TYPE_MAPPING] || x // for struct type
|
|
69
55
|
}
|
|
70
56
|
|
|
71
57
|
export const getOperator = (op: X) => {
|
|
@@ -81,80 +67,63 @@ export const conversionToConstant = (conversionKey: string): Constants => {
|
|
|
81
67
|
return index !== -1 ? CONSTANTS[index] : 'float'
|
|
82
68
|
}
|
|
83
69
|
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
.
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
if (
|
|
97
|
-
|
|
98
|
-
|
|
70
|
+
export const getEventFun = (c: NodeContext, id: string, isAttribute = false, isTexture = false) => {
|
|
71
|
+
if (c.isWebGL) {
|
|
72
|
+
if (isAttribute) return (value: any) => c.gl?.attribute?.(id, value)
|
|
73
|
+
if (isTexture) return (value: any) => c.gl?.texture?.(id, value)
|
|
74
|
+
return (value: any) => c.gl?.uniform?.(id, value)
|
|
75
|
+
}
|
|
76
|
+
if (isAttribute) return (value: any) => c.gl?._attribute?.(id, value)
|
|
77
|
+
if (isTexture) return (value: any) => c.gl?._texture?.(id, value)
|
|
78
|
+
return (value: any) => c.gl?._uniform?.(id, value)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export const safeEventCall = (x: X, fun: (value: unknown) => void) => {
|
|
82
|
+
if (!x) return
|
|
83
|
+
if (!isNodeProxy(x)) return fun(x) // for uniform(1)
|
|
84
|
+
if (x.type !== 'conversion') return
|
|
85
|
+
const value = x.props.children?.slice(1).filter(Boolean)
|
|
86
|
+
if (!value?.length) return // for uniform(vec2())
|
|
87
|
+
fun(value)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export const initNodeContext = (c: NodeContext) => {
|
|
91
|
+
if (!c.code) {
|
|
92
|
+
c.code = {
|
|
93
|
+
headers: new Map(),
|
|
94
|
+
fragInputs: new Map(),
|
|
95
|
+
vertInputs: new Map(),
|
|
96
|
+
vertOutputs: new Map(),
|
|
97
|
+
vertVaryings: new Map(),
|
|
98
|
+
dependencies: new Map(),
|
|
99
99
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
100
|
+
if (!c.isWebGL) {
|
|
101
|
+
c.code.fragInputs.set('position', '@builtin(position) position: vec4f')
|
|
102
|
+
c.code.vertOutputs.set('position', '@builtin(position) position: vec4f')
|
|
103
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
104
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
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};`
|
|
105
|
+
return c
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export const addDependency = (c: NodeContext, id = '', type: string) => {
|
|
109
|
+
if (!c.code?.dependencies?.has(id)) c.code!.dependencies.set(id, new Set())
|
|
110
|
+
if (!isConstants(type)) c.code!.dependencies.get(id)!.add(type)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export const sortHeadersByDependencies = (headers: Map<string, string>, dependencies: Map<string, Set<string>>) => {
|
|
114
|
+
const sorted: [string, string][] = []
|
|
115
|
+
const visited = new Set<string>()
|
|
116
|
+
const visiting = new Set<string>()
|
|
117
|
+
const visit = (id: string) => {
|
|
118
|
+
if (visiting.has(id)) return
|
|
119
|
+
if (visited.has(id)) return
|
|
120
|
+
visiting.add(id)
|
|
121
|
+
const deps = dependencies.get(id) || new Set()
|
|
122
|
+
for (const dep of deps) if (headers.has(dep)) visit(dep)
|
|
123
|
+
visiting.delete(id)
|
|
124
|
+
visited.add(id)
|
|
125
|
+
if (headers.has(id)) sorted.push([id, headers.get(id)!])
|
|
138
126
|
}
|
|
139
|
-
|
|
140
|
-
return
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
const generateVertexMain = (_body: string, _head: string, isWebGL = true) => {
|
|
144
|
-
if (isWebGL) return ``
|
|
145
|
-
return ``
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
export const fragment = (x: X, c: NodeConfig = {}) => {
|
|
149
|
-
const body = code(x, c)
|
|
150
|
-
const head = generateHead(c)
|
|
151
|
-
const main = generateFragmentMain(body, head, c.isWebGL)
|
|
152
|
-
console.log(`// ↓↓↓ generated ↓↓↓\n\n${main}\n\n`)
|
|
153
|
-
return main
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
export const vertex = (x: X, c: NodeConfig) => {
|
|
157
|
-
const body = code(x, c)
|
|
158
|
-
const head = generateHead(c)
|
|
159
|
-
return generateVertexMain(body, head, c.isWebGL)
|
|
127
|
+
for (const [id] of headers) visit(id)
|
|
128
|
+
return sorted
|
|
160
129
|
}
|