File size: 3,557 Bytes
352fb85
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import type { Scene } from "../core/Scene";
import { FadeInPass } from "./webgl/passes/FadeInPass";
import { Camera } from "../cameras/Camera";
import { Color32 } from "../math/Color32";
import { ShaderProgram } from "./webgl/programs/ShaderProgram";
import { RenderProgram } from "./webgl/programs/RenderProgram";
import { ShaderPass } from "./webgl/passes/ShaderPass";

export class WebGLRenderer {
    private _canvas: HTMLCanvasElement;
    private _gl: WebGL2RenderingContext;
    private _backgroundColor: Color32 = new Color32();
    private _renderProgram: RenderProgram;

    addProgram: (program: ShaderProgram) => void;
    removeProgram: (program: ShaderProgram) => void;
    resize: () => void;
    setSize: (width: number, height: number) => void;
    render: (scene: Scene, camera: Camera) => void;
    dispose: () => void;

    constructor(optionalCanvas: HTMLCanvasElement | null = null, optionalRenderPasses: ShaderPass[] | null = null) {
        const canvas: HTMLCanvasElement = optionalCanvas || document.createElement("canvas");
        if (!optionalCanvas) {
            canvas.style.display = "block";
            canvas.style.boxSizing = "border-box";
            canvas.style.width = "100%";
            canvas.style.height = "100%";
            canvas.style.margin = "0";
            canvas.style.padding = "0";
            document.body.appendChild(canvas);
        }
        canvas.style.background = this._backgroundColor.toHexString();
        this._canvas = canvas;

        this._gl = canvas.getContext("webgl2", { antialias: false }) as WebGL2RenderingContext;

        const renderPasses = optionalRenderPasses || [];
        if (!optionalRenderPasses) {
            renderPasses.push(new FadeInPass());
        }

        this._renderProgram = new RenderProgram(this, renderPasses);
        const programs = [this._renderProgram] as ShaderProgram[];

        this.resize = () => {
            const width = canvas.clientWidth;
            const height = canvas.clientHeight;
            if (canvas.width !== width || canvas.height !== height) {
                this.setSize(width, height);
            }
        };

        this.setSize = (width: number, height: number) => {
            canvas.width = width;
            canvas.height = height;
            this._gl.viewport(0, 0, canvas.width, canvas.height);
            for (const program of programs) {
                program.resize();
            }
        };

        this.render = (scene: Scene, camera: Camera) => {
            for (const program of programs) {
                program.render(scene, camera);
            }
        };

        this.dispose = () => {
            for (const program of programs) {
                program.dispose();
            }
        };

        this.addProgram = (program: ShaderProgram) => {
            programs.push(program);
        };

        this.removeProgram = (program: ShaderProgram) => {
            const index = programs.indexOf(program);
            if (index < 0) {
                throw new Error("Program not found");
            }
            programs.splice(index, 1);
        };

        this.resize();
    }

    get canvas() {
        return this._canvas;
    }

    get gl() {
        return this._gl;
    }

    get renderProgram() {
        return this._renderProgram;
    }

    get backgroundColor() {
        return this._backgroundColor;
    }

    set backgroundColor(value: Color32) {
        this._backgroundColor = value;
        this._canvas.style.background = value.toHexString();
    }
}