File size: 4,727 Bytes
6d53e86
6af9568
bc152ba
effc3a3
d13e19f
effc3a3
d998663
 
 
bc152ba
 
b27f287
6d53e86
6af9568
 
 
 
 
 
 
41fe030
6af9568
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d13e19f
6d53e86
6802c16
6af9568
 
9905bd0
 
 
538ade1
b27f287
ffea1eb
1cc5c8d
effc3a3
0391f6c
effc3a3
0391f6c
 
6af9568
effc3a3
d13e19f
 
1cc5c8d
d998663
551d60d
6d53e86
 
 
b27f287
538ade1
f15ce4c
538ade1
 
6af9568
effc3a3
d998663
ffea1eb
1614d87
 
ffea1eb
 
538ade1
9905bd0
d998663
9905bd0
538ade1
d998663
effc3a3
6802c16
1cc5c8d
9eb5291
 
1cc5c8d
538ade1
 
6af9568
d998663
 
6802c16
538ade1
6af9568
effc3a3
538ade1
9905bd0
538ade1
 
 
9905bd0
 
538ade1
9905bd0
 
 
 
 
 
 
 
538ade1
9905bd0
6d53e86
 
6af9568
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import { mat4 } from 'https://webgpufundamentals.org/3rdparty/wgpu-matrix.module.js';
import { initializeDevice } 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 { 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';

// Initialize Canvas function
async function InitializeCanvas(config) {
    // Create and configure the canvas element
    const canvas = document.createElement('canvas');
    canvas.width = config.canvas.width;
    canvas.height = config.canvas.height;
    document.body.appendChild(canvas);

    // Request WebGPU adapter and device
    const adapter = await navigator.gpu.requestAdapter();

    // Use the existing initializeDevice function
    const { device, context, presentationFormat } = await initializeDevice(navigator, adapter, canvas);

    if (!device) {
        alert('Failed to initialize WebGPU');
        return;
    }

    // Return essential components for further setup
    return { canvas, device, context, presentationFormat };
}

// Main function
const state = createState(config);

async function Main() {
    const { canvas, device, context, presentationFormat } = await InitializeCanvas(config);
    state.canvas = canvas;
    state.webgpu.device = device;
    state.webgpu.context = context;
    state.webgpu.presentationFormat = presentationFormat;

    initializeTiming(state);

    await InitializeShaders(state);
    await InitializeResources(state);

    GameLoop(state);
}

// Initialize Resources function
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);
}

// Game Loop function
function GameLoop(state) {
    function Tick(state) {
        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);
            state.timing.accumulator -= state.timing.fixedDeltaTime;
        }
        
        Render(state);

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

    Tick(state);
}

// Fixed Update function
function FixedUpdate(state) {
    state.timing.time += state.timing.fixedDeltaTime;
}

// Render function
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()]);
}

// Start the main function
Main();