File size: 4,068 Bytes
6d53e86
46ec188
bc152ba
effc3a3
d13e19f
effc3a3
1cc5c8d
9905bd0
 
bc152ba
 
b27f287
6d53e86
e8a6c79
d13e19f
6d53e86
6802c16
cf65f18
9905bd0
cf65f18
 
9905bd0
 
 
538ade1
ffea1eb
b27f287
ffea1eb
1cc5c8d
 
effc3a3
0391f6c
 
effc3a3
0391f6c
 
effc3a3
d13e19f
 
1cc5c8d
9905bd0
551d60d
6d53e86
 
 
b27f287
538ade1
f15ce4c
538ade1
 
effc3a3
6802c16
ffea1eb
1614d87
 
6802c16
ffea1eb
 
538ade1
9905bd0
effc3a3
9905bd0
538ade1
 
effc3a3
6802c16
1cc5c8d
9eb5291
 
1cc5c8d
538ade1
 
effc3a3
9905bd0
6802c16
538ade1
effc3a3
538ade1
9905bd0
538ade1
 
 
9905bd0
538ade1
9905bd0
538ade1
9905bd0
 
 
 
 
 
 
 
538ade1
9905bd0
6d53e86
 
6802c16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import { mat4 } from 'https://webgpufundamentals.org/3rdparty/wgpu-matrix.module.js';
import { initializeWebGPU } from './wgpu-device.js';
import { createState } from './wgpu-state.js';
import { initializeTiming } from './wgpu-timing.js';
import { createPipeline } from './wgpu-pipeline.js';
import { generateGlyphTextureAtlas, createTextureFromSource } from './wgpu-utility.js';
import { fetchShaderCode, InitializeShaders } from './wgpu-shader.js';
import { GenerateVertexDataAndTexture } from './wgpu-texture.js'; 
import { generateGlyphVerticesForText } from './wgpu-text.js'; 
import { config } from './wgpu-config.js';
import { CANVAS, CTX, COLORS, RENDER_PASS_DESCRIPTOR } from './wgpu-constants.js';
import { CreateBuffers } from './wgpu-buffer.js';

// State initialization
const state = createState(config);

async function Main() {
    const adapter = await navigator.gpu?.requestAdapter();
    const { device, context, presentationFormat } = await initializeWebGPU(navigator, adapter, state.canvas);
    if (!device) return;

    state.webgpu.device = device;
    state.webgpu.context = context;
    state.webgpu.presentationFormat = presentationFormat;

    // Initialize timing properties
    initializeTiming(state);

    // Initialize Shaders and Resources
    await InitializeShaders(state);
    await InitializeResources(state);

    // Start the game loop
    GameLoop(state);
}

async function InitializeResources(state) {
    const vertexSize = config.floatsPerVertex * 4;

    state.webgpu.pipeline = await createPipeline(state.webgpu.device, state.webgpu.presentationFormat, vertexSize, state.webgpu.shaderCode);
    
    const glyphCanvas = generateGlyphTextureAtlas(CANVAS, CTX, config);
    document.body.appendChild(glyphCanvas);
    glyphCanvas.style.backgroundColor = '#222';

    CreateBuffers(state, config);

    GenerateVertexDataAndTexture(state, glyphCanvas, generateGlyphVerticesForText, COLORS, config, createTextureFromSource);
}

function GameLoop(state) {
    function Tick() {
        state.timing.currentTime = performance.now();
        state.timing.frameTime = (state.timing.currentTime - state.timing.lastTime) / 1000;
        state.timing.lastTime = state.timing.currentTime;

        state.timing.deltaTime = Math.min(state.timing.frameTime, state.timing.maxFrameTime);
        state.timing.accumulator += state.timing.deltaTime;

        while (state.timing.accumulator >= state.timing.fixedDeltaTime) {
            FixedUpdate(state.timing.fixedDeltaTime, state);
            state.timing.accumulator -= state.timing.fixedDeltaTime;
        }

        Render(state);

        setTimeout(() => Tick(state), state.timing.frameDuration);
    }

    Tick(state);
}

function FixedUpdate(deltaTime, state) {
    state.timing.time += deltaTime;
}

function Render(state) {
    const fov = 60 * Math.PI / 180;
    const aspect = state.canvas.clientWidth / state.canvas.clientHeight;
    const projectionMatrix = mat4.perspective(fov, aspect, config.render.zNear, config.render.zFar);
    const viewMatrix = mat4.lookAt([0, 0, 5], [0, 0, 0], [0, 1, 0]);
    const viewProjectionMatrix = mat4.multiply(projectionMatrix, viewMatrix);
    RENDER_PASS_DESCRIPTOR.colorAttachments[0].view = state.webgpu.context.getCurrentTexture().createView();

    const encoder = state.webgpu.device.createCommandEncoder();
    const pass = encoder.beginRenderPass(RENDER_PASS_DESCRIPTOR);
    pass.setPipeline(state.webgpu.pipeline);
    mat4.rotateY(viewProjectionMatrix, state.timing.time, state.matrices.matrix);
    mat4.translate(state.matrices.matrix, [-state.glyphs.width / 2, -state.glyphs.height / 2, 0], state.matrices.matrix);
    state.webgpu.device.queue.writeBuffer(state.webgpu.uniformBuffer, 0, state.matrices.uniformValues);
    pass.setBindGroup(0, state.webgpu.bindGroup);
    pass.setVertexBuffer(0, state.webgpu.vertexBuffer);
    pass.setIndexBuffer(state.webgpu.indexBuffer, 'uint32');
    pass.drawIndexed(state.glyphs.numGlyphs * 6);
    pass.end();
    state.webgpu.device.queue.submit([encoder.finish()]);
}

Main();