WebController - WebGL

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

gfxDraw3D

gfxDraw3D()

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

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

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

        // Performs the 3d draw process
        const gl = this.genvidWebGL.gl;
    
        this.genvidWebGL.clear();
    
        gl.useProgram(this.gfxProg);
    
        // 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(this.gfxProg, "tex"), 0);
    
        if (this.gfxProgDataViewproj) {
          gl.uniformMatrix4fv(
            this.gfxProgLocViewproj,
            false,
            this.gfxProgDataViewproj
          );
        }
    
  3. 最後に円を描画します。

    // Draws commands.
    if (this.gfxCmdCubes.visible && this.gfxCmdCubes.vtx) {
      gl.bindBuffer(gl.ARRAY_BUFFER, this.gfxCmdCubes.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, this.gfxCmdCubes.idx[0]);
      gl.bindTexture(gl.TEXTURE_2D, this.gfxCmdCubes.tex);
      this.genvidWebGL.checkGLError();

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

gfxInitShaders

gfxInitShaders()

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

  // Web GL initalization of shaders
  gfxInitShaders() {
    const 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");
    const 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.
      "}",
    ].join("\n");

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

gfxInitRenderCommands

gfxInitRenderCommands()

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

  // Web gl initialization of render command
  gfxInitRenderCommands() {
    let gl = this.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);
          gl.texParameterf(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY_EXT, max);
        }
      }
      gl.generateMipmap(gl.TEXTURE_2D);
      gl.bindTexture(gl.TEXTURE_2D, null);
    }

    // Cubes.
    {
      // Only prepares textures.
      this.gfxCmdCubes = {
        tex: gl.createTexture(),
        img: new Image(),
        visible: true,
      };
      this.gfxCmdCubes.img.onload = () => {
        handleTextureLoaded(this.gfxCmdCubes.img, this.gfxCmdCubes.tex, {
          wrap: gl.CLAMP_TO_EDGE,
          aniso: true,
        });
        if (this.gfxDraw3D) this.gfxDraw3D();
      };
      this.gfxCmdCubes.img.src = "img/highlight_full_pa.png";
    }

    this.gfxDraw3D();
  }