unityController - WebGL

このセクションでは、WebGL の作成プロセスを取り扱います。

gfx_draw3D

gfx_draw3D()

gfx_draw3D は、WebGL を使用して 3D 描画処理を行います。オブジェクトとともに移動する円を描画するため、フレームごとに呼び出します。

  1. WebGL のコンテキストを取得して、古いフレームコンテンツを削除します。

  2. 描画コマンドを実行する前に、テクスチャを適切に設定します。

                // Perform the 3d draw process
                let genvidWebGL = this.genvidWebGL;
                let gl = genvidWebGL.gl;
    
                genvidWebGL.clear();
    
                let prog = this.gfx_prog;
                gl.useProgram(prog);
    
                // We prepare the program only once (good thing we have a single material).
                gl.enableVertexAttribArray(0);
                gl.enableVertexAttribArray(1);
                gl.enableVertexAttribArray(2);
                gl.activeTexture(gl.TEXTURE0);
                gl.uniform1i(gl.getUniformLocation(prog, "tex"), 0);
    
                if (this.gfx_prog_data_viewproj) {
                    gl.uniformMatrix4fv(this.gfx_prog_loc_viewproj, false, this.gfx_prog_data_viewproj);
                }
    
  3. 最後に、各オブジェクトに対してループ処理を実行し、オブジェクトの回りに輪を描画します。

            // Draw commands.
            let cmds: RenderCommand[] = [this.gfx_cmd_test, this.gfx_cmd_cubes];
            for (let cmd of cmds) {
                if (cmd.visible && cmd.vtx) {
                    gl.bindBuffer(gl.ARRAY_BUFFER, cmd.vtx[0]);
                    gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 9 * 4, 0 * 4); // Position.
                    gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 9 * 4, 3 * 4); // TexCoord.
                    gl.vertexAttribPointer(2, 4, gl.FLOAT, false, 9 * 4, 5 * 4); // Color.
                    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cmd.idx[0]);
                    gl.bindTexture(gl.TEXTURE_2D, cmd.tex);
                    genvidWebGL.checkGLError();

                    gl.drawElements(gl.TRIANGLES, cmd.idx[1], gl.UNSIGNED_SHORT, 0);
                    genvidWebGL.checkGLError();
                }
            }

gfx_initShaders

gfx_initShaders()

gfx_initShaders は、全体的な初期化プロセスにおいて、シェーダを初期化します。

        // Web GL initalization of shaders
        gfx_initShaders() {
            let genvidWebGL = this.genvidWebGL;

            let vShaderStr = [
                "uniform mat4 g_ViewProjMat;",
                "attribute vec3 g_Position;",
                "attribute vec2 g_TexCoord0;",
                "attribute vec4 g_Color0;",
                "varying vec2 texCoord;",
                "varying vec4 color;",
                "void main()",
                "{",
                "   gl_Position = g_ViewProjMat * vec4(g_Position, 1.0);",
                "   texCoord = g_TexCoord0;",
                "   color = g_Color0;",
                "}"
            ].join("\n");
            let fShaderStr = [
                "precision mediump float;",
                "uniform sampler2D tex;",
                "varying vec2 texCoord;",
                "varying vec4 color;",
                "void main()",
                "{",
                "   vec4 texColor = texture2D(tex, texCoord);",
                "   gl_FragColor = texColor * color;", // Texture with color.
                // " gl_FragColor = color;", // Just the color.
                // " gl_FragColor = texColor;", // Just the texture.
                // " gl_FragColor = vec4(texCoord, 0.0, 1.0);", // The texture coordinate.
                // " gl_FragColor = vec4(fract(texCoord), 0.0, 1.0);", // Repeating texture coordinate.
                "}"
            ].join("\n");

            let vsh = genvidWebGL.loadVertexShader(vShaderStr);
            let fsh = genvidWebGL.loadFragmentShader(fShaderStr);
            this.gfx_prog = genvidWebGL.loadProgram(vsh, fsh, ["g_Position", "g_TexCoord0"]);
            this.gfx_prog_loc_viewproj = genvidWebGL.gl.getUniformLocation(this.gfx_prog, "g_ViewProjMat");
        }

gfx_initRenderCommands

gfx_initRenderCommands()

gfx_initRenderCommands は、全体的な初期化プロセスにおいて、レンダーコマンドを初期化します。

        // Web gl initialization of render command
        gfx_initRenderCommands() {
            let genvidWebGL = this.genvidWebGL;
            let gl = genvidWebGL.gl;

            // Utility function.
            function handleTextureLoaded(image, texture, options) {
                options = options || {};
                gl.bindTexture(gl.TEXTURE_2D, texture);
                gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
                gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
                gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
                if (options.wrap) {
                    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, options.wrap);
                    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, options.wrap);
                }
                if (options.aniso) {
                    let ext = (
                        gl.getExtension("EXT_texture_filter_anisotropic") ||
                        gl.getExtension("MOZ_EXT_texture_filter_anisotropic") ||
                        gl.getExtension("WEBKIT_EXT_texture_filter_anisotropic")
                    );
                    if (ext) {
                        let max = gl.getParameter(ext.MAX_TEXTURE_MAX_ANISOTROPY_EXT);
                        // console.log("Enabling aniso filtering", max);
                        gl.texParameterf(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY_EXT, max);
                    }
                }
                gl.generateMipmap(gl.TEXTURE_2D);
                gl.bindTexture(gl.TEXTURE_2D, null);
            }

            let onload = this.gfx_draw3D.bind(this);

            {
                let vertices: number[] = [];
                this.makeCircleZ(vertices, 0, 0, 0, 0.5, genvidMath.vec4(1, 0, 0, 1));
                let num_quads = vertices.length / (4 * 9);

                let cmd = new RenderCommand();
                let options = {
                    "wrap": gl.CLAMP_TO_EDGE,
                    "aniso": true,
                };
                cmd.vtx = genvidWebGL.createBuffer(new Float32Array(vertices));
                cmd.idx = genvidWebGL.createIndexBufferForQuads(num_quads);
                cmd.tex = gl.createTexture();
                cmd.img = new Image();
                cmd.img.onload = function () { handleTextureLoaded(cmd.img, cmd.tex, options); if (onload) onload(); };
                cmd.img.src = "img/highlight_full_pa.png";
                cmd.visible = false;
                this.gfx_cmd_test = cmd;
            }

            // Cubes.
            {
                // Only prepare textures.
                let cmd = new RenderCommand();
                let options = {
                    "wrap": gl.CLAMP_TO_EDGE,
                    "aniso": true,
                };
                cmd.tex = gl.createTexture();
                cmd.img = new Image();
                cmd.img.onload = function () { handleTextureLoaded(cmd.img, cmd.tex, options); if (onload) onload(); };
                cmd.img.src = "img/highlight_full_pa.png";
                cmd.visible = true;
                this.gfx_cmd_cubes = cmd;
            }

            this.gfx_draw3D();
        }