glre 0.20.0 → 0.22.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 +150 -80
- package/dist/index.d.ts +442 -236
- package/dist/index.js +46 -13
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +46 -13
- package/dist/index.mjs.map +1 -1
- package/dist/native.d.ts +7 -530
- package/dist/native.js +46 -13
- package/dist/native.js.map +1 -1
- package/dist/native.mjs +46 -13
- package/dist/native.mjs.map +1 -1
- package/dist/react.d.ts +7 -478
- package/dist/react.js +46 -13
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +46 -13
- package/dist/react.mjs.map +1 -1
- package/dist/solid.d.ts +7 -424
- package/dist/solid.js +46 -13
- package/dist/solid.js.map +1 -1
- package/dist/solid.mjs +46 -13
- package/dist/solid.mjs.map +1 -1
- package/package.json +26 -61
- package/src/code/glsl.ts +186 -0
- package/src/code/wgsl.ts +170 -0
- package/src/index.ts +105 -0
- package/src/native.ts +24 -0
- package/src/node/cache.ts +67 -0
- package/src/node/const.ts +147 -0
- package/src/node/conv.ts +122 -0
- package/src/node/index.ts +96 -0
- package/src/node/node.ts +114 -0
- package/src/node/types.ts +101 -0
- package/src/node/uniform.ts +99 -0
- package/src/react.ts +18 -0
- package/src/solid.ts +15 -0
- package/src/types.ts +90 -0
- package/src/utils.ts +53 -0
- package/src/webgl/buffer.ts +78 -0
- package/src/webgl/index.ts +79 -0
- package/src/webgl/program.ts +61 -0
- package/src/webgl/shader.ts +60 -0
- package/src/webgl/texture.ts +93 -0
- package/src/webgpu/buffer.ts +96 -0
- package/src/webgpu/device.ts +91 -0
- package/src/webgpu/index.ts +40 -0
- package/src/webgpu/pipeline.ts +94 -0
- package/src/webgpu/texture.ts +139 -0
- package/dist/types-2792569d.d.ts +0 -7
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
// 基本型定数
|
|
2
|
+
export const TYPES = [
|
|
3
|
+
'float',
|
|
4
|
+
'int',
|
|
5
|
+
'uint',
|
|
6
|
+
'bool',
|
|
7
|
+
'color',
|
|
8
|
+
'vec2',
|
|
9
|
+
'vec3',
|
|
10
|
+
'vec4',
|
|
11
|
+
'mat2',
|
|
12
|
+
'mat3',
|
|
13
|
+
'mat4',
|
|
14
|
+
'ivec2',
|
|
15
|
+
'ivec3',
|
|
16
|
+
'ivec4',
|
|
17
|
+
'uvec2',
|
|
18
|
+
'uvec3',
|
|
19
|
+
'uvec4',
|
|
20
|
+
'bvec2',
|
|
21
|
+
'bvec3',
|
|
22
|
+
'bvec4',
|
|
23
|
+
] as const
|
|
24
|
+
|
|
25
|
+
export type NodeType = (typeof TYPES)[number]
|
|
26
|
+
|
|
27
|
+
// スウィズル定数
|
|
28
|
+
export const SWIZZLES = [
|
|
29
|
+
'x',
|
|
30
|
+
'y',
|
|
31
|
+
'z',
|
|
32
|
+
'w',
|
|
33
|
+
'r',
|
|
34
|
+
'g',
|
|
35
|
+
'b',
|
|
36
|
+
'a',
|
|
37
|
+
's',
|
|
38
|
+
't',
|
|
39
|
+
'p',
|
|
40
|
+
'q',
|
|
41
|
+
] as const
|
|
42
|
+
|
|
43
|
+
type AllSwizzles<T extends string> =
|
|
44
|
+
| T
|
|
45
|
+
| `${T}${T}`
|
|
46
|
+
| `${T}${T}${T}`
|
|
47
|
+
| `${T}${T}${T}${T}`
|
|
48
|
+
|
|
49
|
+
export type Swillzes =
|
|
50
|
+
| AllSwizzles<'x' | 'y' | 'z' | 'w'>
|
|
51
|
+
| AllSwizzles<'r' | 'g' | 'b' | 'a'>
|
|
52
|
+
| AllSwizzles<'p' | 'q'>
|
|
53
|
+
| AllSwizzles<'s' | 't'>
|
|
54
|
+
|
|
55
|
+
// 演算子定数
|
|
56
|
+
export const OPERATORS = [
|
|
57
|
+
'add',
|
|
58
|
+
'sub',
|
|
59
|
+
'mul',
|
|
60
|
+
'div',
|
|
61
|
+
'mod',
|
|
62
|
+
'equal',
|
|
63
|
+
'notEqual',
|
|
64
|
+
'lessThan',
|
|
65
|
+
'lessThanEqual',
|
|
66
|
+
'greaterThan',
|
|
67
|
+
'greaterThanEqual',
|
|
68
|
+
'and',
|
|
69
|
+
'or',
|
|
70
|
+
'not',
|
|
71
|
+
'assign',
|
|
72
|
+
'xor',
|
|
73
|
+
'bitAnd',
|
|
74
|
+
'bitNot',
|
|
75
|
+
'bitOr',
|
|
76
|
+
'bitXor',
|
|
77
|
+
'shiftLeft',
|
|
78
|
+
'shiftRight',
|
|
79
|
+
] as const
|
|
80
|
+
|
|
81
|
+
export type Operator = (typeof OPERATORS)[number]
|
|
82
|
+
|
|
83
|
+
// 数学関数定数
|
|
84
|
+
export const FUNCTIONS = [
|
|
85
|
+
'abs',
|
|
86
|
+
'acos',
|
|
87
|
+
'asin',
|
|
88
|
+
'atan',
|
|
89
|
+
'atan2',
|
|
90
|
+
'ceil',
|
|
91
|
+
'clamp',
|
|
92
|
+
'cos',
|
|
93
|
+
'cross',
|
|
94
|
+
'degrees',
|
|
95
|
+
'distance',
|
|
96
|
+
'dot',
|
|
97
|
+
'exp',
|
|
98
|
+
'exp2',
|
|
99
|
+
'faceforward',
|
|
100
|
+
'floor',
|
|
101
|
+
'fract',
|
|
102
|
+
'length',
|
|
103
|
+
'all',
|
|
104
|
+
'any',
|
|
105
|
+
'bitcast',
|
|
106
|
+
'cbrt',
|
|
107
|
+
'dFdx',
|
|
108
|
+
'dFdy',
|
|
109
|
+
'difference',
|
|
110
|
+
'equals',
|
|
111
|
+
'fwidth',
|
|
112
|
+
'inverseSqrt',
|
|
113
|
+
'lengthSq',
|
|
114
|
+
'log',
|
|
115
|
+
'log2',
|
|
116
|
+
'max',
|
|
117
|
+
'min',
|
|
118
|
+
'mix',
|
|
119
|
+
'negate',
|
|
120
|
+
'normalize',
|
|
121
|
+
'oneMinus',
|
|
122
|
+
'pow',
|
|
123
|
+
'pow2',
|
|
124
|
+
'pow3',
|
|
125
|
+
'pow4',
|
|
126
|
+
'radians',
|
|
127
|
+
'reciprocal',
|
|
128
|
+
'reflect',
|
|
129
|
+
'refract',
|
|
130
|
+
'round',
|
|
131
|
+
'saturate',
|
|
132
|
+
'sign',
|
|
133
|
+
'sin',
|
|
134
|
+
'smoothstep',
|
|
135
|
+
'sqrt',
|
|
136
|
+
'step',
|
|
137
|
+
'tan',
|
|
138
|
+
'transformDirection',
|
|
139
|
+
'trunc',
|
|
140
|
+
] as const
|
|
141
|
+
|
|
142
|
+
export type MathFunction = (typeof FUNCTIONS)[number]
|
|
143
|
+
|
|
144
|
+
// キャッシュ用定数
|
|
145
|
+
export const CACHE_BOOLS = [true, false] as const
|
|
146
|
+
export const CACHE_INTS = [0, 1, 2, 3, 4, 5] as const
|
|
147
|
+
export const CACHE_FLOATS = [0.0, 1.0, 0.5, 2.0] as const
|
package/src/node/conv.ts
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { node } from '.'
|
|
2
|
+
import { getCachedBool, getCachedInt, getCachedFloat } from './cache'
|
|
3
|
+
import { is } from '../utils'
|
|
4
|
+
import type { X } from './types'
|
|
5
|
+
|
|
6
|
+
// JavaScript値をノードに変換
|
|
7
|
+
export const convertToNode = (x: unknown): X => {
|
|
8
|
+
if (is.bol(x)) return getCachedBool(x)
|
|
9
|
+
if (is.num(x)) {
|
|
10
|
+
if (is.int(x)) return getCachedInt(x)
|
|
11
|
+
return getCachedFloat(x)
|
|
12
|
+
}
|
|
13
|
+
if (is.arr(x)) return convertArrayToNode(x)
|
|
14
|
+
if (is.obj(x)) return convertObjectToNode(x)
|
|
15
|
+
return node('float', 0)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// 配列をベクトル/行列ノードに変換
|
|
19
|
+
const convertArrayToNode = (array: number[]): X => {
|
|
20
|
+
const len = array.length
|
|
21
|
+
if (len === 2) return node('vec2', array)
|
|
22
|
+
if (len === 3) return node('vec3', array)
|
|
23
|
+
if (len === 4) return node('vec4', array)
|
|
24
|
+
if (len === 9) return node('mat3', array)
|
|
25
|
+
if (len === 16) return node('mat4', array)
|
|
26
|
+
return node('float', array[0])
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// オブジェクトをノードに変換
|
|
30
|
+
const convertObjectToNode = (obj: any): X => {
|
|
31
|
+
// カラーオブジェクトの検出
|
|
32
|
+
if ('r' in obj && 'g' in obj && 'b' in obj) {
|
|
33
|
+
const arr = [obj.r, obj.g, obj.b]
|
|
34
|
+
if ('a' in obj) arr.push(obj.a)
|
|
35
|
+
return node('color', arr)
|
|
36
|
+
}
|
|
37
|
+
// ベクトルライクオブジェクトの検出
|
|
38
|
+
if ('x' in obj && 'y' in obj) {
|
|
39
|
+
const arr = [obj.x, obj.y]
|
|
40
|
+
if ('z' in obj) arr.push(obj.z)
|
|
41
|
+
if ('w' in obj) arr.push(obj.w)
|
|
42
|
+
return convertArrayToNode(arr)
|
|
43
|
+
}
|
|
44
|
+
return node('float', 0)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// 型変換関数
|
|
48
|
+
export const float = (x: unknown): X => {
|
|
49
|
+
if (is.num(x)) return getCachedFloat(x)
|
|
50
|
+
return node('float', Number(x))
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export const int = (x: unknown): X => {
|
|
54
|
+
if (is.num(x) && Number.isInteger(x)) return getCachedInt(x)
|
|
55
|
+
return node('int', Math.floor(Number(x)))
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export const bool = (x: unknown): X => {
|
|
59
|
+
return getCachedBool(Boolean(x))
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export const vec2 = (x?: any, y?: any): X => {
|
|
63
|
+
if (is.und(x)) return node('vec2', [0, 0])
|
|
64
|
+
if (is.und(y)) {
|
|
65
|
+
if (is.arr(x)) return node('vec2', x.slice(0, 2))
|
|
66
|
+
if (is.obj(x) && 'x' in x && 'y' in x)
|
|
67
|
+
return node('vec2', [x.x, x.y])
|
|
68
|
+
return node('vec2', [Number(x), Number(x)])
|
|
69
|
+
}
|
|
70
|
+
return node('vec2', [Number(x), Number(y)])
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export const vec3 = (x?: any, y?: any, z?: any): X => {
|
|
74
|
+
if (is.und(x)) return node('vec3', [0, 0, 0])
|
|
75
|
+
if (is.und(y)) {
|
|
76
|
+
if (is.arr(x)) return node('vec3', x.slice(0, 3))
|
|
77
|
+
if (is.obj(x) && 'x' in x && 'y' in x && 'z' in x)
|
|
78
|
+
return node('vec3', [x.x, x.y, x.z])
|
|
79
|
+
return node('vec3', [Number(x), Number(x), Number(x)])
|
|
80
|
+
}
|
|
81
|
+
if (z === undefined) {
|
|
82
|
+
return node('vec3', [Number(x), Number(y), 0])
|
|
83
|
+
}
|
|
84
|
+
return node('vec3', [Number(x), Number(y), Number(z)])
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export const vec4 = (x?: any, y?: any, z?: any, w?: any): X => {
|
|
88
|
+
if (is.und(x)) return node('vec4', [0, 0, 0, 1])
|
|
89
|
+
if (is.und(y)) {
|
|
90
|
+
if (is.arr(x)) return node('vec4', x.slice(0, 4))
|
|
91
|
+
if (is.obj(x) && 'x' in x && 'y' in x && 'z' in x && 'w' in x)
|
|
92
|
+
return node('vec4', [x.x, x.y, x.z, x.w])
|
|
93
|
+
return node('vec4', [Number(x), Number(x), Number(x), 1])
|
|
94
|
+
}
|
|
95
|
+
return node('vec4', [Number(x), Number(y), Number(z), Number(w)])
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export const color = (r?: any, g?: any, b?: any): X => {
|
|
99
|
+
if (r === undefined) return node('color', [1, 1, 1])
|
|
100
|
+
|
|
101
|
+
// 16進数カラーの処理
|
|
102
|
+
if (is.str(r) && r.startsWith('#')) {
|
|
103
|
+
const hex = r.slice(1)
|
|
104
|
+
const num = parseInt(hex, 16)
|
|
105
|
+
return node('color', [
|
|
106
|
+
((num >> 16) & 255) / 255,
|
|
107
|
+
((num >> 8) & 255) / 255,
|
|
108
|
+
(num & 255) / 255,
|
|
109
|
+
])
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// 数値カラーの処理
|
|
113
|
+
if (is.num(r) && g === undefined && b === undefined) {
|
|
114
|
+
return node('color', [
|
|
115
|
+
((r >> 16) & 255) / 255,
|
|
116
|
+
((r >> 8) & 255) / 255,
|
|
117
|
+
(r & 255) / 255,
|
|
118
|
+
])
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return vec3(r, g, b)
|
|
122
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { node } from './node'
|
|
2
|
+
import { uniform } from './uniform'
|
|
3
|
+
import { float } from './conv'
|
|
4
|
+
import { is } from '../utils'
|
|
5
|
+
import type { X, FunctionNode, ConditionalNode } from './types'
|
|
6
|
+
export type { X, FunctionNode, ConditionalNode }
|
|
7
|
+
export * from './cache'
|
|
8
|
+
export * from './const'
|
|
9
|
+
export * from './conv'
|
|
10
|
+
export * from './node'
|
|
11
|
+
export * from './types'
|
|
12
|
+
export * from './uniform'
|
|
13
|
+
|
|
14
|
+
// 関数定義
|
|
15
|
+
export const Fn = (jsFunc: Function): FunctionNode => {
|
|
16
|
+
const functionNode = (...args: any[]) => {
|
|
17
|
+
const inputs = args.map((arg) => {
|
|
18
|
+
if (is.obj(arg) && 'type' in arg && arg.type) return arg
|
|
19
|
+
return float(arg)
|
|
20
|
+
})
|
|
21
|
+
const result = jsFunc(inputs)
|
|
22
|
+
return result || float(0)
|
|
23
|
+
}
|
|
24
|
+
functionNode.call = (inputs: X[]) => jsFunc(inputs)
|
|
25
|
+
return functionNode as FunctionNode
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// 条件分岐
|
|
29
|
+
export const If = (condition: X, callback: () => void): ConditionalNode => {
|
|
30
|
+
callback()
|
|
31
|
+
|
|
32
|
+
const conditionalNode = {
|
|
33
|
+
ElseIf(
|
|
34
|
+
newCondition: X,
|
|
35
|
+
newCallback: () => void
|
|
36
|
+
): ConditionalNode {
|
|
37
|
+
newCallback()
|
|
38
|
+
return conditionalNode
|
|
39
|
+
},
|
|
40
|
+
Else(elseCallback: () => void) {
|
|
41
|
+
elseCallback()
|
|
42
|
+
},
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return conditionalNode
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// 組み込み変数
|
|
49
|
+
export const gl_FragCoord = node('vec4', undefined)
|
|
50
|
+
export const gl_Position = node('vec4', undefined)
|
|
51
|
+
export const iTime = uniform(0.0)
|
|
52
|
+
export const iResolution = uniform([1920, 1080])
|
|
53
|
+
export const iMouse = uniform([0, 0])
|
|
54
|
+
|
|
55
|
+
// 数学関数
|
|
56
|
+
export const abs = (x: X) => x.abs()
|
|
57
|
+
export const sin = (x: X) => x.sin()
|
|
58
|
+
export const cos = (x: X) => x.cos()
|
|
59
|
+
export const tan = (x: X) => x.tan()
|
|
60
|
+
export const sqrt = (x: X) => x.sqrt()
|
|
61
|
+
export const floor = (x: X) => x.floor()
|
|
62
|
+
export const ceil = (x: X) => x.ceil()
|
|
63
|
+
export const fract = (x: X) => x.fract()
|
|
64
|
+
export const normalize = (x: X) => x.normalize()
|
|
65
|
+
export const length = (x: X) => x.length()
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* @TODO FIX
|
|
69
|
+
export const min = (a: X, b: X) => {
|
|
70
|
+
return node('float', undefined, {
|
|
71
|
+
mathFunction: 'min',
|
|
72
|
+
children: [a as any, b as any],
|
|
73
|
+
})
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export const max = (a: X, b: X) => {
|
|
77
|
+
return node('float', undefined, {
|
|
78
|
+
mathFunction: 'max',
|
|
79
|
+
children: [a as any, b as any],
|
|
80
|
+
})
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export const mix = (a: X, b: X, t: X) => {
|
|
84
|
+
return node('float', undefined, {
|
|
85
|
+
mathFunction: 'mix',
|
|
86
|
+
children: [a as any, b as any, t as any],
|
|
87
|
+
})
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export const clamp = (x: X, min: X, max: X) => {
|
|
91
|
+
return node('float', undefined, {
|
|
92
|
+
mathFunction: 'clamp',
|
|
93
|
+
children: [x as any, min as any, max as any],
|
|
94
|
+
})
|
|
95
|
+
}
|
|
96
|
+
*/
|
package/src/node/node.ts
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { OPERATORS, FUNCTIONS, SWIZZLES, NodeType } from './const'
|
|
2
|
+
import { is } from '../utils'
|
|
3
|
+
import type { Node, ProxyCallback, X } from './types'
|
|
4
|
+
|
|
5
|
+
let nodeIdCounter = 0
|
|
6
|
+
|
|
7
|
+
// ノードIDを生成
|
|
8
|
+
const generateNodeId = () => `node_${++nodeIdCounter}`
|
|
9
|
+
|
|
10
|
+
// ノードを作成
|
|
11
|
+
export const createNode = (
|
|
12
|
+
type: NodeType,
|
|
13
|
+
value?: any,
|
|
14
|
+
options?: Partial<Node>
|
|
15
|
+
): Node => {
|
|
16
|
+
return {
|
|
17
|
+
id: generateNodeId(),
|
|
18
|
+
type,
|
|
19
|
+
value,
|
|
20
|
+
children: [],
|
|
21
|
+
...options,
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const isSwizzleProperty = (key = '') => SWIZZLES.includes(key as any)
|
|
26
|
+
const isOperatorMethod = (key = '') => OPERATORS.includes(key as any)
|
|
27
|
+
const isMathMethod = (key = '') => FUNCTIONS.includes(key as any)
|
|
28
|
+
|
|
29
|
+
// Proxyハンドラーを作成
|
|
30
|
+
const createNodeProxy = (node: Node, callback?: (info: ProxyCallback) => X) => {
|
|
31
|
+
const get = (_target: unknown, key: unknown) => {
|
|
32
|
+
if (!is.str(key) || key === 'then') return void 0
|
|
33
|
+
|
|
34
|
+
if (key === 'id') return node.id
|
|
35
|
+
if (key === 'type') return node.type
|
|
36
|
+
if (key === 'value') return node.value
|
|
37
|
+
if (key === 'property') return node.property
|
|
38
|
+
|
|
39
|
+
// swizzle prooerty
|
|
40
|
+
if (isSwizzleProperty(key))
|
|
41
|
+
return createNodeProxy(
|
|
42
|
+
createNode(getSwizzleType(key), undefined, {
|
|
43
|
+
parent: node,
|
|
44
|
+
property: key,
|
|
45
|
+
}),
|
|
46
|
+
callback
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
// 演算子メソッド
|
|
50
|
+
if (isOperatorMethod(key))
|
|
51
|
+
return (...args: any[]) => {
|
|
52
|
+
return createNodeProxy(
|
|
53
|
+
createNode(node.type, undefined, {
|
|
54
|
+
operator: key as any,
|
|
55
|
+
children: [node, ...args],
|
|
56
|
+
}),
|
|
57
|
+
callback
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// 数学関数メソッド
|
|
62
|
+
if (isMathMethod(key))
|
|
63
|
+
return (...args: any[]) => {
|
|
64
|
+
return createNodeProxy(
|
|
65
|
+
createNode(
|
|
66
|
+
getMathReturnType(
|
|
67
|
+
key,
|
|
68
|
+
node.type
|
|
69
|
+
),
|
|
70
|
+
undefined,
|
|
71
|
+
{
|
|
72
|
+
mathFunction:
|
|
73
|
+
key as any,
|
|
74
|
+
children: [
|
|
75
|
+
node,
|
|
76
|
+
...args,
|
|
77
|
+
],
|
|
78
|
+
}
|
|
79
|
+
),
|
|
80
|
+
callback
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return callback?.({ path: [key], args: [] })
|
|
85
|
+
}
|
|
86
|
+
const apply = (_target: unknown, _thisArg: unknown, args: any) => {
|
|
87
|
+
return callback?.({ path: [], args })
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return new Proxy(() => {}, { get, apply }) as X
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// スウィズルの戻り値型を取得
|
|
94
|
+
const getSwizzleType = (swizzle: string): NodeType => {
|
|
95
|
+
if (swizzle.length === 1) return 'float'
|
|
96
|
+
if (swizzle.length === 2) return 'vec2'
|
|
97
|
+
if (swizzle.length === 3) return 'vec3'
|
|
98
|
+
if (swizzle.length === 4) return 'vec4'
|
|
99
|
+
return 'float'
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// 数学関数の戻り値型を取得
|
|
103
|
+
const getMathReturnType = (func: string, inputType: NodeType): NodeType => {
|
|
104
|
+
if (func === 'length') return 'float'
|
|
105
|
+
if (func === 'normalize') return inputType
|
|
106
|
+
if (func === 'toVar') return inputType
|
|
107
|
+
return inputType
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// 公開API
|
|
111
|
+
export const node = (type: NodeType, value?: any, options?: Partial<Node>) => {
|
|
112
|
+
const nodeInstance = createNode(type, value, options)
|
|
113
|
+
return createNodeProxy(nodeInstance)
|
|
114
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import type { NodeType, Operator, MathFunction, Swillzes } from './const'
|
|
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
|
+
}
|
|
14
|
+
|
|
15
|
+
// Proxyハンドラーのコールバック型
|
|
16
|
+
export interface ProxyCallback {
|
|
17
|
+
path: string[]
|
|
18
|
+
args: any[]
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// ノード作成関数の型
|
|
22
|
+
export type NodeCreator = (value?: any) => X
|
|
23
|
+
|
|
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
|
|
40
|
+
}
|
|
41
|
+
|
|
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
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// 全てのswizzleパターンをまとめる型
|
|
61
|
+
|
|
62
|
+
// スウィズルプロパティの型
|
|
63
|
+
export type SwizzleProperties = {
|
|
64
|
+
[k in Swillzes]: X
|
|
65
|
+
}
|
|
66
|
+
|
|
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
|
+
}
|
|
75
|
+
|
|
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
|
+
}
|
|
82
|
+
|
|
83
|
+
// 関数定義の型
|
|
84
|
+
export interface FunctionNode {
|
|
85
|
+
(...args: any[]): X
|
|
86
|
+
call(x: X[]): X
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// 条件分岐の型
|
|
90
|
+
export interface ConditionalNode {
|
|
91
|
+
ElseIf(condition: X, callback: () => void): ConditionalNode
|
|
92
|
+
Else(callback: () => void): void
|
|
93
|
+
}
|
|
94
|
+
|
|
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>
|
|
101
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { node } from './node'
|
|
2
|
+
import { is } from '../utils'
|
|
3
|
+
import type { UniformNode } from './types'
|
|
4
|
+
import type { NodeType } from './const'
|
|
5
|
+
|
|
6
|
+
// ユニフォーム更新コンテキスト
|
|
7
|
+
interface UpdateContext {
|
|
8
|
+
object?: any
|
|
9
|
+
camera?: any
|
|
10
|
+
renderer?: any
|
|
11
|
+
scene?: any
|
|
12
|
+
time?: number
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// ユニフォーム値の型を推定
|
|
16
|
+
const inferUniformType = (value: any): NodeType => {
|
|
17
|
+
if (is.num(value)) return 'float'
|
|
18
|
+
if (is.bol(value)) return 'bool'
|
|
19
|
+
if (is.arr(value)) {
|
|
20
|
+
const len = value.length
|
|
21
|
+
if (len === 2) return 'vec2'
|
|
22
|
+
if (len === 3) return 'vec3'
|
|
23
|
+
if (len === 4) return 'vec4'
|
|
24
|
+
if (len === 9) return 'mat3'
|
|
25
|
+
if (len === 16) return 'mat4'
|
|
26
|
+
}
|
|
27
|
+
if (is.obj(value) && 'r' in value && 'g' in value && 'b' in value)
|
|
28
|
+
return 'color'
|
|
29
|
+
return 'float'
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// ユニフォーム変数を作成
|
|
33
|
+
export const uniform = (initialValue: any): UniformNode => {
|
|
34
|
+
const type = inferUniformType(initialValue)
|
|
35
|
+
let currentValue = initialValue
|
|
36
|
+
let objectUpdateCallback: ((context: UpdateContext) => any) | null =
|
|
37
|
+
null
|
|
38
|
+
let renderUpdateCallback: ((context: UpdateContext) => any) | null =
|
|
39
|
+
null
|
|
40
|
+
|
|
41
|
+
const baseNode = node(type, currentValue) as any
|
|
42
|
+
|
|
43
|
+
// 値を設定
|
|
44
|
+
const set = (value: any) => {
|
|
45
|
+
currentValue = value
|
|
46
|
+
baseNode.value = value
|
|
47
|
+
}
|
|
48
|
+
// オブジェクト更新時のコールバックを設定
|
|
49
|
+
const onObjectUpdate = (
|
|
50
|
+
callback: (context: UpdateContext) => any
|
|
51
|
+
): UniformNode => {
|
|
52
|
+
objectUpdateCallback = callback
|
|
53
|
+
return uniformNode
|
|
54
|
+
}
|
|
55
|
+
// レンダー更新時のコールバックを設定
|
|
56
|
+
const onRenderUpdate = (
|
|
57
|
+
callback: (context: UpdateContext) => any
|
|
58
|
+
): UniformNode => {
|
|
59
|
+
renderUpdateCallback = callback
|
|
60
|
+
return uniformNode
|
|
61
|
+
}
|
|
62
|
+
// 内部更新関数(外部から呼び出される)
|
|
63
|
+
const _updateFromContext = (context: UpdateContext) => {
|
|
64
|
+
if (objectUpdateCallback) {
|
|
65
|
+
const newValue = objectUpdateCallback(context)
|
|
66
|
+
if (newValue !== undefined) set(newValue)
|
|
67
|
+
}
|
|
68
|
+
if (renderUpdateCallback) {
|
|
69
|
+
const newValue = renderUpdateCallback(context)
|
|
70
|
+
if (newValue !== undefined) set(newValue)
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// UniformNodeインターフェースを実装
|
|
74
|
+
const uniformNode = Object.create(baseNode)
|
|
75
|
+
uniformNode.set = set
|
|
76
|
+
uniformNode.onObjectUpdate = onObjectUpdate
|
|
77
|
+
uniformNode.onRenderUpdate = onRenderUpdate
|
|
78
|
+
uniformNode._updateFromContext = _updateFromContext
|
|
79
|
+
uniformNode.isUniform = true
|
|
80
|
+
return uniformNode as UniformNode
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// 組み込みユニフォーム変数
|
|
84
|
+
export const iTime = uniform(0.0)
|
|
85
|
+
export const iPrevTime = uniform(0.0)
|
|
86
|
+
export const iDeltaTime = uniform(0.0)
|
|
87
|
+
export const iResolution = uniform([1920, 1080])
|
|
88
|
+
export const iMouse = uniform([0, 0])
|
|
89
|
+
|
|
90
|
+
// ユニフォーム変数の更新(レンダーループで呼び出される)
|
|
91
|
+
export const updateUniforms = (context: UpdateContext) => {
|
|
92
|
+
// 時間の更新
|
|
93
|
+
if (context.time !== undefined) {
|
|
94
|
+
const prevTime = iTime.value || 0
|
|
95
|
+
iTime.set(context.time)
|
|
96
|
+
iPrevTime.set(prevTime)
|
|
97
|
+
iDeltaTime.set(context.time - prevTime)
|
|
98
|
+
}
|
|
99
|
+
}
|
package/src/react.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { useState } from 'react'
|
|
2
|
+
import { createGL, isGL } from './index'
|
|
3
|
+
import type { GL } from './types'
|
|
4
|
+
export * from './index'
|
|
5
|
+
|
|
6
|
+
export const useGL = (props: Partial<GL> = {}) => {
|
|
7
|
+
return useState(() => {
|
|
8
|
+
const gl = isGL(props) ? props : createGL(props)
|
|
9
|
+
gl.ref = (el: HTMLCanvasElement | null) => {
|
|
10
|
+
if (el) {
|
|
11
|
+
gl.el = el
|
|
12
|
+
gl.gl = el.getContext('webgl2')
|
|
13
|
+
gl.mount()
|
|
14
|
+
} else gl.clean()
|
|
15
|
+
}
|
|
16
|
+
return gl
|
|
17
|
+
})[0]
|
|
18
|
+
}
|