glre 0.24.0 → 0.25.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.d.ts +39 -9
- package/dist/index.js +17 -23
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +17 -23
- package/dist/index.mjs.map +1 -1
- package/dist/native.d.ts +1 -1
- package/dist/native.js +17 -23
- package/dist/native.js.map +1 -1
- package/dist/native.mjs +17 -23
- package/dist/native.mjs.map +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.js +17 -23
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +17 -23
- package/dist/react.mjs.map +1 -1
- package/dist/solid.d.ts +1 -1
- package/dist/solid.js +17 -23
- package/dist/solid.js.map +1 -1
- package/dist/solid.mjs +17 -23
- package/dist/solid.mjs.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +6 -3
- package/src/types.ts +6 -0
- package/src/utils/pipeline.ts +56 -68
- package/src/utils/program.ts +23 -17
- package/src/webgl.ts +34 -57
- package/src/webgpu.ts +70 -80
package/src/utils/pipeline.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { wgsl } from '../code/wgsl'
|
|
2
|
+
import { X } from '../node'
|
|
3
|
+
import { is } from './helpers'
|
|
4
|
+
import type { GPUContext, GPUDevice, GPUPipeline } from '../types'
|
|
2
5
|
|
|
3
6
|
const defaultVertexWGSL = `
|
|
4
7
|
@vertex
|
|
@@ -10,13 +13,7 @@ fn main(@builtin(vertex_index) vertex_index: u32) -> @builtin(position) vec4f {
|
|
|
10
13
|
`
|
|
11
14
|
|
|
12
15
|
const defaultFragmentWGSL = `
|
|
13
|
-
|
|
14
|
-
iResolution: vec2f,
|
|
15
|
-
iMouse: vec2f,
|
|
16
|
-
iTime: f32,
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
@group(0) @binding(0) var<uniform> u: Uniforms;
|
|
16
|
+
@group(0) @binding(0) var<uniform> iResolution: vec2f;
|
|
20
17
|
|
|
21
18
|
@fragment
|
|
22
19
|
fn main(@builtin(position) position: vec4f) -> @location(0) vec4f {
|
|
@@ -24,13 +21,26 @@ fn main(@builtin(position) position: vec4f) -> @location(0) vec4f {
|
|
|
24
21
|
}
|
|
25
22
|
`
|
|
26
23
|
|
|
24
|
+
export const createDevive = async (c: GPUContext) => {
|
|
25
|
+
const gpu = (navigator as any).gpu
|
|
26
|
+
const format = gpu.getPreferredCanvasFormat()
|
|
27
|
+
const adapter = await gpu.requestAdapter()
|
|
28
|
+
const device = await adapter.requestDevice()
|
|
29
|
+
c.configure({ device, format, alphaMode: 'opaque' })
|
|
30
|
+
return { device, format }
|
|
31
|
+
}
|
|
32
|
+
|
|
27
33
|
export const createPipeline = (
|
|
28
34
|
device: GPUDevice,
|
|
29
35
|
format: string,
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
36
|
+
buffers: any[],
|
|
37
|
+
layouts: any[],
|
|
38
|
+
vs: string | X = defaultVertexWGSL,
|
|
39
|
+
fs: string | X = defaultFragmentWGSL
|
|
33
40
|
) => {
|
|
41
|
+
if (is.obj(fs)) fs = wgsl(fs)
|
|
42
|
+
if (is.obj(vs)) vs = wgsl(vs)
|
|
43
|
+
const layout = device.createPipelineLayout({ bindGroupLayouts: layouts })
|
|
34
44
|
return device.createRenderPipeline({
|
|
35
45
|
vertex: {
|
|
36
46
|
module: device.createShaderModule({ code: vs.trim() }),
|
|
@@ -42,11 +52,30 @@ export const createPipeline = (
|
|
|
42
52
|
entryPoint: 'main',
|
|
43
53
|
targets: [{ format }],
|
|
44
54
|
},
|
|
45
|
-
layout
|
|
55
|
+
layout,
|
|
46
56
|
primitive: { topology: 'triangle-list' },
|
|
47
57
|
}) as GPUPipeline
|
|
48
58
|
}
|
|
49
59
|
|
|
60
|
+
export const createBindGroup = (device: GPUDevice, resources: any[]) => {
|
|
61
|
+
const entries0 = [] as any[]
|
|
62
|
+
const entries1 = [] as any[]
|
|
63
|
+
resources.forEach((resource, binding) => {
|
|
64
|
+
if (!resource) return
|
|
65
|
+
const isUniform = 'buffer' in resource // @ts-ignore
|
|
66
|
+
const isTexture = resource instanceof GPUTextureView // @ts-ignore
|
|
67
|
+
const isSampler = resource instanceof GPUSampler // @ts-ignore
|
|
68
|
+
if (isUniform) entries0.push({ binding, visibility: 3, buffer: { type: 'uniform' } })
|
|
69
|
+
else if (isTexture) entries0.push({ binding, visibility: 2, texture: {} })
|
|
70
|
+
else if (isSampler) entries0.push({ binding, visibility: 2, sampler: {} })
|
|
71
|
+
else return
|
|
72
|
+
entries1.push({ binding, resource })
|
|
73
|
+
})
|
|
74
|
+
const layout = device.createBindGroupLayout({ entries: entries0 })
|
|
75
|
+
const bindGroup = device.createBindGroup({ layout, entries: entries1 })
|
|
76
|
+
return [layout, bindGroup]
|
|
77
|
+
}
|
|
78
|
+
|
|
50
79
|
export const createDescriptor = (c: GPUContext) => {
|
|
51
80
|
return {
|
|
52
81
|
colorAttachments: [
|
|
@@ -60,65 +89,24 @@ export const createDescriptor = (c: GPUContext) => {
|
|
|
60
89
|
}
|
|
61
90
|
}
|
|
62
91
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
//
|
|
92
|
+
export const alignTo256 = (size: number) => Math.ceil(size / 256) * 256
|
|
93
|
+
|
|
94
|
+
export const createUniformBuffer = (device: GPUDevice, value: number[]) => {
|
|
95
|
+
const array = new Float32Array(value)
|
|
96
|
+
const size = alignTo256(array.byteLength)
|
|
97
|
+
const buffer = device.createBuffer({ size, usage: 72 }) as Buffer // 72 === GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
|
|
98
|
+
return { array, buffer }
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export const createTextureSampler = (device: GPUDevice, width = 1280, height = 800) => {
|
|
102
|
+
const texture = device.createTexture({ size: [width, height], format: 'rgba8unorm', usage: 22 })
|
|
103
|
+
const sampler = device.createSampler({ magFilter: 'linear', minFilter: 'linear' })
|
|
104
|
+
return [texture, sampler] as const
|
|
105
|
+
}
|
|
106
|
+
|
|
69
107
|
// export const createVertexBuffer = (device: GPUDevice, value: number[]) => {
|
|
70
108
|
// const array = new Float32Array(value)
|
|
71
109
|
// const buffer = device.createBuffer({ size: array.byteLength, usage: 0x20 | 0x4 })
|
|
72
110
|
// device.queue.writeBuffer(buffer, 0, array)
|
|
73
111
|
// return buffer as Buffer
|
|
74
112
|
// }
|
|
75
|
-
//
|
|
76
|
-
// export const createBindGroup = (device: GPUDevice, pipeline: GPUPipeline, entries: any[]) => {
|
|
77
|
-
// const layout = pipeline.getBindGroupLayout(0)
|
|
78
|
-
// return device.createBindGroup({ layout, entries })
|
|
79
|
-
// }
|
|
80
|
-
//
|
|
81
|
-
// export const updateBindGroup = (
|
|
82
|
-
// device: GPUDevice,
|
|
83
|
-
// pipeline: GPUPipeline,
|
|
84
|
-
// uniformBuffer: Buffer,
|
|
85
|
-
// textures: any = {},
|
|
86
|
-
// sampler: any = null
|
|
87
|
-
// ) => {
|
|
88
|
-
// const entries = [{ binding: 0, resource: { buffer: uniformBuffer } }]
|
|
89
|
-
// let binding = 1
|
|
90
|
-
// Object.values(textures).forEach((texture: any) => {
|
|
91
|
-
// entries.push({ binding: binding++, resource: texture.createView() })
|
|
92
|
-
// })
|
|
93
|
-
// if (sampler && Object.keys(textures).length > 0) entries.push({ binding: binding++, resource: sampler })
|
|
94
|
-
// return createBindGroup(device, pipeline, entries)
|
|
95
|
-
// }
|
|
96
|
-
//
|
|
97
|
-
// export const createUniform = (device: GPUDevice, buffer: any, data: Float32Array, offset = 0) => {
|
|
98
|
-
// device.queue.writeBuffer(buffer, offset, data)
|
|
99
|
-
// }
|
|
100
|
-
//
|
|
101
|
-
// export const createDeviceTexture = (device: GPUDevice, image: HTMLImageElement) => {
|
|
102
|
-
// const texture = device.createTexture({
|
|
103
|
-
// size: { width: image.width, height: image.height },
|
|
104
|
-
// format: 'rgba8unorm',
|
|
105
|
-
// usage: 0x4 | 0x2,
|
|
106
|
-
// })
|
|
107
|
-
// device.queue.copyExternalImageToTexture(
|
|
108
|
-
// { source: image },
|
|
109
|
-
// { texture },
|
|
110
|
-
// { width: image.width, height: image.height }
|
|
111
|
-
// )
|
|
112
|
-
// return texture
|
|
113
|
-
// }
|
|
114
|
-
//
|
|
115
|
-
// export const createSampler = (device: GPUDevice) => {
|
|
116
|
-
// return device.createSampler({
|
|
117
|
-
// magFilter: 'linear',
|
|
118
|
-
// minFilter: 'linear',
|
|
119
|
-
// addressModeU: 'clamp-to-edge',
|
|
120
|
-
// addressModeV: 'clamp-to-edge',
|
|
121
|
-
// })
|
|
122
|
-
// }
|
|
123
|
-
//
|
|
124
|
-
// export const getDefaultVertices = () => new Float32Array([-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1])
|
package/src/utils/program.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import { glsl } from '../code/glsl'
|
|
2
|
+
import { X } from '../node'
|
|
3
|
+
import { is } from './helpers'
|
|
4
|
+
|
|
1
5
|
export const defaultVertexGLSL = /* cpp */ `
|
|
2
6
|
#version 300 es
|
|
3
7
|
void main() {
|
|
@@ -17,7 +21,7 @@ void main() {
|
|
|
17
21
|
}
|
|
18
22
|
`
|
|
19
23
|
|
|
20
|
-
|
|
24
|
+
const createShader = (c: WebGLRenderingContext, source: string, type: number) => {
|
|
21
25
|
const shader = c.createShader(type)
|
|
22
26
|
if (!shader) throw new Error('Failed to create shader')
|
|
23
27
|
c.shaderSource(shader, source.trim())
|
|
@@ -28,7 +32,13 @@ export const createShader = (c: WebGLRenderingContext, source: string, type: num
|
|
|
28
32
|
throw new Error(`Could not compile shader: ${error}`)
|
|
29
33
|
}
|
|
30
34
|
|
|
31
|
-
export const createProgram = (
|
|
35
|
+
export const createProgram = (
|
|
36
|
+
c: WebGLRenderingContext,
|
|
37
|
+
vs: string | X = defaultVertexGLSL,
|
|
38
|
+
fs: string | X = defaultFragmentGLSL
|
|
39
|
+
) => {
|
|
40
|
+
if (is.obj(fs)) fs = glsl(fs as X)
|
|
41
|
+
if (is.obj(vs)) vs = glsl(vs as X)
|
|
32
42
|
const pg = c.createProgram()
|
|
33
43
|
c.attachShader(pg, createShader(c, vs, c.VERTEX_SHADER))
|
|
34
44
|
c.attachShader(pg, createShader(c, fs, c.FRAGMENT_SHADER))
|
|
@@ -55,20 +65,26 @@ export const createIbo = (c: WebGLRenderingContext, data: number[]) => {
|
|
|
55
65
|
return buffer
|
|
56
66
|
}
|
|
57
67
|
|
|
68
|
+
export const getStride = (count: number, value: number[], iboValue?: number[]) => {
|
|
69
|
+
if (iboValue) count = Math.max(...iboValue) + 1
|
|
70
|
+
const stride = value.length / count
|
|
71
|
+
return Math.floor(stride)
|
|
72
|
+
}
|
|
73
|
+
|
|
58
74
|
export const createAttrib = (
|
|
59
75
|
c: WebGLRenderingContext,
|
|
60
76
|
stride: number,
|
|
61
|
-
|
|
77
|
+
loc: any,
|
|
62
78
|
vbo: WebGLBuffer,
|
|
63
79
|
ibo?: WebGLBuffer
|
|
64
80
|
) => {
|
|
65
81
|
c.bindBuffer(c.ARRAY_BUFFER, vbo)
|
|
66
|
-
c.enableVertexAttribArray(
|
|
67
|
-
c.vertexAttribPointer(
|
|
82
|
+
c.enableVertexAttribArray(loc)
|
|
83
|
+
c.vertexAttribPointer(loc, stride, c.FLOAT, false, 0, 0)
|
|
68
84
|
if (ibo) c.bindBuffer(c.ELEMENT_ARRAY_BUFFER, ibo)
|
|
69
85
|
}
|
|
70
86
|
|
|
71
|
-
export const createTexture = (c: WebGLRenderingContext, img: HTMLImageElement) => {
|
|
87
|
+
export const createTexture = (c: WebGLRenderingContext, img: HTMLImageElement, loc: any, unit: number) => {
|
|
72
88
|
const texture = c.createTexture()
|
|
73
89
|
c.bindTexture(c.TEXTURE_2D, texture)
|
|
74
90
|
c.texImage2D(c.TEXTURE_2D, 0, c.RGBA, c.RGBA, c.UNSIGNED_BYTE, img)
|
|
@@ -78,17 +94,7 @@ export const createTexture = (c: WebGLRenderingContext, img: HTMLImageElement) =
|
|
|
78
94
|
c.texParameteri(c.TEXTURE_2D, c.TEXTURE_WRAP_S, c.CLAMP_TO_EDGE)
|
|
79
95
|
c.texParameteri(c.TEXTURE_2D, c.TEXTURE_WRAP_T, c.CLAMP_TO_EDGE)
|
|
80
96
|
c.bindTexture(c.TEXTURE_2D, null)
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export const activeTexture = (
|
|
85
|
-
c: WebGLRenderingContext,
|
|
86
|
-
location: WebGLUniformLocation | null,
|
|
87
|
-
unit: number,
|
|
88
|
-
texture: WebGLTexture
|
|
89
|
-
) => {
|
|
90
|
-
if (!location) return
|
|
91
|
-
c.uniform1i(location, unit)
|
|
97
|
+
c.uniform1i(loc, unit)
|
|
92
98
|
c.activeTexture(c.TEXTURE0 + unit)
|
|
93
99
|
c.bindTexture(c.TEXTURE_2D, texture)
|
|
94
100
|
}
|
package/src/webgl.ts
CHANGED
|
@@ -1,77 +1,54 @@
|
|
|
1
|
-
import { nested } from 'reev'
|
|
2
|
-
import { glsl } from './code/glsl'
|
|
1
|
+
import { nested as cached } from 'reev'
|
|
3
2
|
import { is } from './utils/helpers'
|
|
4
|
-
import
|
|
5
|
-
import type { GL } from './types'
|
|
6
|
-
import { activeTexture, createAttrib, createIbo, createProgram, createTexture, createVbo } from './utils/program'
|
|
3
|
+
import { createAttrib, createIbo, createProgram, createTexture, createVbo, getStride } from './utils/program'
|
|
4
|
+
import type { GL, WebGLState } from './types'
|
|
7
5
|
|
|
8
|
-
export const webgl = async (gl: GL) => {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const c = gl.el.getContext('webgl2')!
|
|
14
|
-
const pg = createProgram(c, vs, fs)
|
|
6
|
+
export const webgl = async (gl: Partial<GL>) => {
|
|
7
|
+
const c = gl.el!.getContext('webgl2')!
|
|
8
|
+
const pg = createProgram(c, gl.vs, gl.fs)
|
|
9
|
+
const state = { context: c, program: pg } as WebGLState
|
|
10
|
+
c.useProgram(pg)
|
|
15
11
|
|
|
16
12
|
let _activeUnit = 0
|
|
17
|
-
const activeUnits =
|
|
13
|
+
const activeUnits = cached(() => _activeUnit++)
|
|
18
14
|
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
return c.getUniformLocation(pg, key) as WebGLUniformLocation
|
|
22
|
-
})
|
|
15
|
+
const uniformLocations = cached((key) => c.getUniformLocation(pg, key))
|
|
16
|
+
const attribLocations = cached((key) => c.getAttribLocation(pg, key))
|
|
23
17
|
|
|
24
|
-
const
|
|
25
|
-
if (iboValue) count = Math.max(...iboValue) + 1
|
|
26
|
-
const stride = value.length / count
|
|
27
|
-
if (stride !== Math.floor(stride)) console.warn(`Vertex Stride Error: count ${count} is mismatch`)
|
|
28
|
-
return Math.floor(stride)
|
|
29
|
-
})
|
|
18
|
+
const clean = () => c.deleteProgram(pg)
|
|
30
19
|
|
|
31
|
-
const
|
|
32
|
-
const loc = locations(key)
|
|
33
|
-
if (is.num(value)) return (value: any) => c.uniform1f(loc, value)
|
|
34
|
-
let l = value.length as 3
|
|
35
|
-
if (l <= 4) return (value: any) => c[`uniform${l}fv`](loc, value)
|
|
36
|
-
l = (Math.sqrt(l) << 0) as 3
|
|
37
|
-
return (value: any) => c[`uniformMatrix${l}fv`](loc, false, value)
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
gl('clean', () => c.deleteProgram(pg))
|
|
41
|
-
|
|
42
|
-
gl('render', () => {
|
|
43
|
-
c.useProgram(pg)
|
|
20
|
+
const render = () => {
|
|
44
21
|
c.clear(c.COLOR_BUFFER_BIT)
|
|
45
|
-
c.viewport(0, 0, ...gl.size)
|
|
22
|
+
c.viewport(0, 0, ...gl.size!)
|
|
46
23
|
c.drawArrays(c.TRIANGLES, 0, 3)
|
|
47
|
-
}
|
|
24
|
+
}
|
|
48
25
|
|
|
49
|
-
|
|
50
|
-
const loc =
|
|
26
|
+
const _attribute = (key = '', value: number[], iboValue: number[]) => {
|
|
27
|
+
const loc = attribLocations(key, true)
|
|
51
28
|
const vbo = createVbo(c, value)
|
|
52
29
|
const ibo = createIbo(c, iboValue)
|
|
53
|
-
const str =
|
|
30
|
+
const str = getStride(gl.count!, value, iboValue)
|
|
54
31
|
createAttrib(c, str, loc, vbo, ibo)
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
gl('_uniform', (key: string, value: number | number[]) => {
|
|
58
|
-
uniforms(key, value)(value)
|
|
59
|
-
})
|
|
32
|
+
}
|
|
60
33
|
|
|
61
|
-
const
|
|
62
|
-
const loc =
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
34
|
+
const _uniform = (key: string, value: number | number[]) => {
|
|
35
|
+
const loc = uniformLocations(key)
|
|
36
|
+
if (is.num(value)) return c.uniform1f(loc, value)
|
|
37
|
+
let l = value.length
|
|
38
|
+
if (l <= 4) return c[`uniform${l as 2}fv`](loc, value)
|
|
39
|
+
l = Math.sqrt(l) << 0
|
|
40
|
+
c[`uniformMatrix${l as 2}fv`](loc, false, value)
|
|
66
41
|
}
|
|
67
42
|
|
|
68
|
-
|
|
43
|
+
const _texture = (alt: string, src: string) => {
|
|
69
44
|
const image = new Image()
|
|
70
|
-
image.addEventListener('load', _loadFn.bind(null, image), false)
|
|
71
45
|
Object.assign(image, { src, alt, crossOrigin: 'anonymous' })
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
46
|
+
image.decode().then(() => {
|
|
47
|
+
const loc = uniformLocations(image.alt)
|
|
48
|
+
const unit = activeUnits(image.alt)
|
|
49
|
+
createTexture(c, image, loc, unit)
|
|
50
|
+
})
|
|
51
|
+
}
|
|
75
52
|
|
|
76
|
-
return
|
|
53
|
+
return { webgl: state, render, clean, _attribute, _uniform, _texture }
|
|
77
54
|
}
|
package/src/webgpu.ts
CHANGED
|
@@ -1,102 +1,92 @@
|
|
|
1
|
-
import { wgsl } from './code/wgsl'
|
|
2
1
|
import { is } from './utils/helpers'
|
|
3
2
|
import {
|
|
3
|
+
createDevive,
|
|
4
4
|
createPipeline,
|
|
5
5
|
createDescriptor,
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
// createUniform,
|
|
10
|
-
// createDeviceTexture,
|
|
11
|
-
// createSampler,
|
|
6
|
+
createUniformBuffer,
|
|
7
|
+
createBindGroup,
|
|
8
|
+
createTextureSampler,
|
|
12
9
|
} from './utils/pipeline'
|
|
13
|
-
import type {
|
|
14
|
-
import type { GL, GPUBindGroup, GPUPipeline } from './types'
|
|
15
|
-
import { nested } from 'reev'
|
|
10
|
+
import type { GL, WebGPUState } from './types'
|
|
16
11
|
|
|
17
|
-
const
|
|
12
|
+
export const webgpu = async (gl: Partial<GL>) => {
|
|
13
|
+
const c = gl.el!.getContext('webgpu') as any
|
|
14
|
+
const { device, format } = await createDevive(c)
|
|
15
|
+
const state = {
|
|
16
|
+
device,
|
|
17
|
+
context: c,
|
|
18
|
+
uniforms: {},
|
|
19
|
+
textures: {},
|
|
20
|
+
resources: [[], []],
|
|
21
|
+
loadingImg: 0,
|
|
22
|
+
needsUpdate: true,
|
|
23
|
+
} as WebGPUState
|
|
18
24
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const gpu = (navigator as any).gpu
|
|
26
|
-
const adapter = await gpu.requestAdapter()
|
|
27
|
-
const device = await adapter.requestDevice()
|
|
28
|
-
const format = gpu.getPreferredCanvasFormat()
|
|
29
|
-
c.configure({ device, format, alphaMode: 'opaque' })
|
|
25
|
+
const initUniform = (value: number[]) => {
|
|
26
|
+
const { array, buffer } = createUniformBuffer(device, value)
|
|
27
|
+
state.resources[0].push({ buffer })
|
|
28
|
+
state.needsUpdate = true
|
|
29
|
+
return { array, buffer }
|
|
30
|
+
}
|
|
30
31
|
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
const initTexutre = (source: HTMLImageElement) => {
|
|
33
|
+
const { width, height } = source
|
|
34
|
+
const [texture, sampler] = createTextureSampler(device, width, height)
|
|
35
|
+
state.resources[1].push(sampler, texture.createView())
|
|
36
|
+
state.needsUpdate = true
|
|
37
|
+
return { texture, width, height }
|
|
38
|
+
}
|
|
33
39
|
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
let uniformData = new Float32Array(0)
|
|
46
|
-
|
|
47
|
-
gl('render', () => {
|
|
48
|
-
if (!pipeline) {
|
|
49
|
-
pipeline = createPipeline(device, format, vs, fs, [])
|
|
50
|
-
bindGroup = device.createBindGroup({
|
|
51
|
-
layout: pipeline.getBindGroupLayout(0),
|
|
52
|
-
entries: [
|
|
53
|
-
{
|
|
54
|
-
binding: 0,
|
|
55
|
-
resource: { buffer },
|
|
56
|
-
},
|
|
57
|
-
],
|
|
58
|
-
})
|
|
59
|
-
}
|
|
40
|
+
const update = () => {
|
|
41
|
+
const layouts = [] as any
|
|
42
|
+
state.groups = []
|
|
43
|
+
state.resources.forEach((resource) => {
|
|
44
|
+
if (!resource.length) return
|
|
45
|
+
const [layout, group] = createBindGroup(device, resource)
|
|
46
|
+
layouts.push(layout)
|
|
47
|
+
state.groups.push(group)
|
|
48
|
+
})
|
|
49
|
+
state.pipeline = createPipeline(device, format, [], layouts, gl.vs, gl.fs)
|
|
50
|
+
}
|
|
60
51
|
|
|
52
|
+
const render = () => {
|
|
53
|
+
if (state.loadingImg) return // ignore if loading img
|
|
54
|
+
if (state.needsUpdate) update() // first rendering
|
|
55
|
+
state.needsUpdate = false
|
|
61
56
|
const encoder = device.createCommandEncoder()
|
|
62
57
|
const pass = encoder.beginRenderPass(createDescriptor(c))
|
|
63
|
-
pass.setPipeline(pipeline)
|
|
64
|
-
pass.setBindGroup(
|
|
65
|
-
pass.draw(
|
|
58
|
+
pass.setPipeline(state.pipeline)
|
|
59
|
+
state.groups.forEach((v, i) => pass.setBindGroup(i, v))
|
|
60
|
+
pass.draw(gl.count, 1, 0, 0)
|
|
66
61
|
pass.end()
|
|
67
62
|
device.queue.submit([encoder.finish()])
|
|
68
|
-
|
|
69
|
-
})
|
|
63
|
+
}
|
|
70
64
|
|
|
71
|
-
|
|
65
|
+
const clean = () => {}
|
|
66
|
+
|
|
67
|
+
const _attribute = (key = '', value: number[]) => {
|
|
72
68
|
// @TODO FIX
|
|
73
69
|
// vertexBuffers(key, value)
|
|
74
|
-
}
|
|
70
|
+
}
|
|
75
71
|
|
|
76
|
-
|
|
72
|
+
const _uniform = (key: string, value: number | number[]) => {
|
|
77
73
|
if (is.num(value)) value = [value]
|
|
78
|
-
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
uniformData = array
|
|
84
|
-
}
|
|
85
|
-
for (let i = 0; i < size; i++) uniformData[unit - size + i] = value[i]
|
|
86
|
-
device.queue.writeBuffer(buffer, 0, uniformData)
|
|
87
|
-
})
|
|
88
|
-
|
|
89
|
-
// const _loadFun = (image: HTMLImageElement, gl: GL) => {
|
|
90
|
-
// const texture = createDeviceTexture(device, image)
|
|
91
|
-
// // bindGroup = updateBindGroup(device, pipeline, buffer, textures, sampler)
|
|
92
|
-
// }
|
|
74
|
+
if (!state.uniforms[key]) state.uniforms[key] = initUniform(value)
|
|
75
|
+
const { array, buffer } = state.uniforms[key]
|
|
76
|
+
array.set(value)
|
|
77
|
+
device.queue.writeBuffer(buffer, 0, array)
|
|
78
|
+
}
|
|
93
79
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
80
|
+
const _texture = (key: string, src: string) => {
|
|
81
|
+
state.loadingImg++
|
|
82
|
+
const source = Object.assign(new Image(), { src, crossOrigin: 'anonymous' })
|
|
83
|
+
source.decode().then(() => {
|
|
84
|
+
if (!state.textures[key]) state.textures[key] = initTexutre(source)
|
|
85
|
+
const { texture, width, height } = state.textures[key]
|
|
86
|
+
device.queue.copyExternalImageToTexture({ source }, { texture }, { width, height })
|
|
87
|
+
state.loadingImg--
|
|
88
|
+
})
|
|
89
|
+
}
|
|
100
90
|
|
|
101
|
-
return
|
|
91
|
+
return { webgpu: state, render, clean, _attribute, _uniform, _texture }
|
|
102
92
|
}
|