aboutsummaryrefslogtreecommitdiff
path: root/web/pw-visualizer/src/webgl/texture.ts
blob: faafe76a7f0b0ac37e8589ab679faf01159a0fc3 (plain)
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
import type { Renderer } from "./renderer";

export class Texture {
    texture: WebGLTexture;
    width: number;
    height: number;
    loaded: boolean;
    name: string;

    static fromImage(
        gl: WebGLRenderingContext,
        path: string,
        name: string,
    ): Promise<Texture> {
        return new Promise((resolve, reject) => {
            const out = new Texture(gl, name);

            const image = new Image();
            image.onload = () => {
                out.setImage(gl, image);
                resolve(out);
            }
            image.onerror = reject;
            image.src = path;
        })
    }

    static fromRenderer(
        gl: WebGLRenderingContext,
        name: string,
        width: number,
        height: number,
        renderer: Renderer
    ): Texture {
        const out = new Texture(gl, name);
        out.width = width;
        out.height = height;

        gl.texImage2D(
            gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0,
            gl.RGBA, gl.UNSIGNED_BYTE, null);

        const fb = gl.createFramebuffer();
        gl.bindFramebuffer(gl.FRAMEBUFFER, fb);

        const attachmentPoint = gl.COLOR_ATTACHMENT0;
        gl.framebufferTexture2D(gl.FRAMEBUFFER, attachmentPoint, gl.TEXTURE_2D, out.texture, 0);

        renderer.render(gl, fb, width, height);

        out.loaded = true;

        return out;
    }

    constructor(
        gl: WebGLRenderingContext,
        name: string,
    ) {
        this.loaded = false;
        this.name = name;

        this.texture = gl.createTexture();
        this.bind(gl);

        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);

        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA,
            gl.UNSIGNED_BYTE, new Uint8Array([255, 0, 0, 255]));
    }

    setImage(gl: WebGLRenderingContext, image: HTMLImageElement) {
        this.bind(gl);
        this.width = image.width;
        this.height = image.height;

        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);

        this.unbind(gl);

        this.loaded = true;
    }

    bind(gl: WebGLRenderingContext, location=0) {
        gl.activeTexture(gl.TEXTURE0 + location);
        gl.bindTexture(gl.TEXTURE_2D, this.texture);
    }

    unbind(gl: WebGLRenderingContext) {
        gl.bindTexture(gl.TEXTURE_2D, null);
    }


    getWidth(): number {
        return this.width;
    }

    getHeight(): number {
        return this.height;
    }
}