Spaces:
Running
Running
clean up
Browse files- config.js +1 -1
- index.html +28 -29
config.js
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
// config.js
|
2 |
|
3 |
-
export const
|
4 |
glyphsAcrossTexture: 16,
|
5 |
glyphWidth: 32,
|
6 |
glyphHeight: 40,
|
|
|
1 |
// config.js
|
2 |
|
3 |
+
export const CONFIG = {
|
4 |
glyphsAcrossTexture: 16,
|
5 |
glyphWidth: 32,
|
6 |
glyphHeight: 40,
|
index.html
CHANGED
@@ -12,23 +12,22 @@
|
|
12 |
<script type="module">
|
13 |
import { mat4 } from 'https://webgpufundamentals.org/3rdparty/wgpu-matrix.module.js';
|
14 |
import { fetchShaderCode } from './utility.js';
|
15 |
-
import {
|
16 |
import { CANVAS, CTX, COLORS, RENDER_PASS_DESCRIPTOR } from './constants.js';
|
17 |
|
18 |
-
function generateGlyphTextureAtlas() {
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
CTX.fillStyle = config.context.fillStyle;
|
26 |
for (let c = 33, x = 0, y = 0; c < 128; ++c) {
|
27 |
-
|
28 |
-
x = (x + config.glyphWidth) %
|
29 |
if (x === 0) y += config.glyphHeight;
|
30 |
}
|
31 |
-
return
|
32 |
}
|
33 |
async function main() {
|
34 |
const adapter = await navigator.gpu?.requestAdapter();
|
@@ -52,11 +51,11 @@
|
|
52 |
code: shaderCode,
|
53 |
});
|
54 |
|
55 |
-
const glyphCanvas = generateGlyphTextureAtlas();
|
56 |
document.body.appendChild(glyphCanvas);
|
57 |
glyphCanvas.style.backgroundColor = '#222';
|
58 |
-
const vertexSize =
|
59 |
-
const vertexBufferSize =
|
60 |
const vertexBuffer = device.createBuffer({
|
61 |
label: 'vertices',
|
62 |
size: vertexBufferSize,
|
@@ -64,20 +63,20 @@
|
|
64 |
});
|
65 |
const indexBuffer = device.createBuffer({
|
66 |
label: 'indices',
|
67 |
-
size:
|
68 |
usage: GPUBufferUsage.INDEX | GPUBufferUsage.COPY_DST,
|
69 |
});
|
70 |
|
71 |
-
const indices = Array.from({ length:
|
72 |
const ndx = Math.floor(i / 6) * 4;
|
73 |
return (i % 6 < 3 ? [ndx, ndx + 1, ndx + 2] : [ndx + 2, ndx + 1, ndx + 3])[i % 3];
|
74 |
});
|
75 |
device.queue.writeBuffer(indexBuffer, 0, new Uint32Array(indices));
|
76 |
|
77 |
function generateGlyphVerticesForText(s, COLORS = [[1, 1, 1, 1]]) {
|
78 |
-
const vertexData = new Float32Array(
|
79 |
-
const glyphUVWidth =
|
80 |
-
const glyphUVHeight =
|
81 |
let offset = 0, x0 = 0, y0 = 0, x1 = 1, y1 = 1, width = 0;
|
82 |
let colorNdx = 0;
|
83 |
|
@@ -90,10 +89,10 @@
|
|
90 |
const c = s.charCodeAt(i);
|
91 |
if (c >= 33) {
|
92 |
const cIndex = c - 33;
|
93 |
-
const glyphX = cIndex %
|
94 |
-
const glyphY = Math.floor(cIndex /
|
95 |
-
const u0 = glyphX *
|
96 |
-
const v1 = glyphY *
|
97 |
const u1 = u0 + glyphUVWidth;
|
98 |
const v0 = v1 + glyphUVHeight;
|
99 |
width = Math.max(x1, width);
|
@@ -111,7 +110,7 @@
|
|
111 |
}
|
112 |
x0 += 0.55; x1 = x0 + 1;
|
113 |
}
|
114 |
-
return { vertexData, numGlyphs: offset /
|
115 |
}
|
116 |
|
117 |
const { vertexData, numGlyphs, width, height } = generateGlyphVerticesForText('Hello\nworld!\nText in\nWebGPU!', COLORS);
|
@@ -171,10 +170,10 @@
|
|
171 |
|
172 |
const uniformBuffer = device.createBuffer({
|
173 |
label: 'uniforms for quad',
|
174 |
-
size:
|
175 |
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
|
176 |
});
|
177 |
-
const uniformValues = new Float32Array(
|
178 |
const matrix = uniformValues.subarray(0, 16);
|
179 |
|
180 |
const bindGroup = device.createBindGroup({
|
@@ -187,10 +186,10 @@
|
|
187 |
});
|
188 |
|
189 |
function render(time) {
|
190 |
-
time *=
|
191 |
const fov = 60 * Math.PI / 180;
|
192 |
const aspect = canvas.clientWidth / canvas.clientHeight;
|
193 |
-
const projectionMatrix = mat4.perspective(fov, aspect,
|
194 |
const viewMatrix = mat4.lookAt([0, 0, 5], [0, 0, 0], [0, 1, 0]);
|
195 |
const viewProjectionMatrix = mat4.multiply(projectionMatrix, viewMatrix);
|
196 |
RENDER_PASS_DESCRIPTOR.colorAttachments[0].view = context.getCurrentTexture().createView();
|
|
|
12 |
<script type="module">
|
13 |
import { mat4 } from 'https://webgpufundamentals.org/3rdparty/wgpu-matrix.module.js';
|
14 |
import { fetchShaderCode } from './utility.js';
|
15 |
+
import { CONFIG } from './config.js';
|
16 |
import { CANVAS, CTX, COLORS, RENDER_PASS_DESCRIPTOR } from './constants.js';
|
17 |
|
18 |
+
function generateGlyphTextureAtlas(canvas, ctx, config) {
|
19 |
+
canvas.width = config.canvas.width;
|
20 |
+
canvas.height = config.canvas.height;
|
21 |
+
ctx.font = config.context.font
|
22 |
+
ctx.textBaseline = config.context.textBaseline;
|
23 |
+
ctx.textAlign = config.context.textAlign;
|
24 |
+
ctx.fillStyle = config.context.fillStyle;
|
|
|
25 |
for (let c = 33, x = 0, y = 0; c < 128; ++c) {
|
26 |
+
ctx.fillText(String.fromCodePoint(c), x + config.glyphWidth / 2, y + config.glyphHeight / 2);
|
27 |
+
x = (x + config.glyphWidth) % canvas.width;
|
28 |
if (x === 0) y += config.glyphHeight;
|
29 |
}
|
30 |
+
return canvas;
|
31 |
}
|
32 |
async function main() {
|
33 |
const adapter = await navigator.gpu?.requestAdapter();
|
|
|
51 |
code: shaderCode,
|
52 |
});
|
53 |
|
54 |
+
const glyphCanvas = generateGlyphTextureAtlas(CANVAS, CTX, CONFIG);
|
55 |
document.body.appendChild(glyphCanvas);
|
56 |
glyphCanvas.style.backgroundColor = '#222';
|
57 |
+
const vertexSize = CONFIG.floatsPerVertex * 4;
|
58 |
+
const vertexBufferSize = CONFIG.maxGlyphs * CONFIG.vertsPerGlyph * vertexSize;
|
59 |
const vertexBuffer = device.createBuffer({
|
60 |
label: 'vertices',
|
61 |
size: vertexBufferSize,
|
|
|
63 |
});
|
64 |
const indexBuffer = device.createBuffer({
|
65 |
label: 'indices',
|
66 |
+
size: CONFIG.maxGlyphs * CONFIG.vertsPerGlyph * 4,
|
67 |
usage: GPUBufferUsage.INDEX | GPUBufferUsage.COPY_DST,
|
68 |
});
|
69 |
|
70 |
+
const indices = Array.from({ length: CONFIG.maxGlyphs * 6 }, (_, i) => {
|
71 |
const ndx = Math.floor(i / 6) * 4;
|
72 |
return (i % 6 < 3 ? [ndx, ndx + 1, ndx + 2] : [ndx + 2, ndx + 1, ndx + 3])[i % 3];
|
73 |
});
|
74 |
device.queue.writeBuffer(indexBuffer, 0, new Uint32Array(indices));
|
75 |
|
76 |
function generateGlyphVerticesForText(s, COLORS = [[1, 1, 1, 1]]) {
|
77 |
+
const vertexData = new Float32Array(CONFIG.maxGlyphs * CONFIG.floatsPerVertex * CONFIG.vertsPerGlyph);
|
78 |
+
const glyphUVWidth = CONFIG.glyphWidth / glyphCanvas.width;
|
79 |
+
const glyphUVHeight = CONFIG.glyphHeight / glyphCanvas.height;
|
80 |
let offset = 0, x0 = 0, y0 = 0, x1 = 1, y1 = 1, width = 0;
|
81 |
let colorNdx = 0;
|
82 |
|
|
|
89 |
const c = s.charCodeAt(i);
|
90 |
if (c >= 33) {
|
91 |
const cIndex = c - 33;
|
92 |
+
const glyphX = cIndex % CONFIG.glyphsAcrossTexture;
|
93 |
+
const glyphY = Math.floor(cIndex / CONFIG.glyphsAcrossTexture);
|
94 |
+
const u0 = glyphX * CONFIG.glyphWidth / glyphCanvas.width;
|
95 |
+
const v1 = glyphY * CONFIG.glyphHeight / glyphCanvas.height;
|
96 |
const u1 = u0 + glyphUVWidth;
|
97 |
const v0 = v1 + glyphUVHeight;
|
98 |
width = Math.max(x1, width);
|
|
|
110 |
}
|
111 |
x0 += 0.55; x1 = x0 + 1;
|
112 |
}
|
113 |
+
return { vertexData, numGlyphs: offset / CONFIG.floatsPerVertex, width, height: y1 };
|
114 |
}
|
115 |
|
116 |
const { vertexData, numGlyphs, width, height } = generateGlyphVerticesForText('Hello\nworld!\nText in\nWebGPU!', COLORS);
|
|
|
170 |
|
171 |
const uniformBuffer = device.createBuffer({
|
172 |
label: 'uniforms for quad',
|
173 |
+
size: CONFIG.uniformBufferSize,
|
174 |
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
|
175 |
});
|
176 |
+
const uniformValues = new Float32Array(CONFIG.uniformBufferSize / 4);
|
177 |
const matrix = uniformValues.subarray(0, 16);
|
178 |
|
179 |
const bindGroup = device.createBindGroup({
|
|
|
186 |
});
|
187 |
|
188 |
function render(time) {
|
189 |
+
time *= CONFIG.time.phase;
|
190 |
const fov = 60 * Math.PI / 180;
|
191 |
const aspect = canvas.clientWidth / canvas.clientHeight;
|
192 |
+
const projectionMatrix = mat4.perspective(fov, aspect, CONFIG.render.zNear, CONFIG.render.zFar);
|
193 |
const viewMatrix = mat4.lookAt([0, 0, 5], [0, 0, 0], [0, 1, 0]);
|
194 |
const viewProjectionMatrix = mat4.multiply(projectionMatrix, viewMatrix);
|
195 |
RENDER_PASS_DESCRIPTOR.colorAttachments[0].view = context.getCurrentTexture().createView();
|