WebGL(TypeScript)--- 三角形描画

今回はWebGLを用いてcanvasに三角形を描画してみたいと思います。

ライブラリを用いず、一から実装してみます。

HTMLの準備

表示のため、下記htmlを用意しました。

canvas要素にWebGLで描画します。

<!DOCTYPE html>
<html>
  <body>
    <canvas id="gl_canvas" width="100" height="100"></canvas>
    <script src="script.js"></script>
  </body>
</html>


Shader作成関数

Vertex ShaderのコードとFragment Shaderのコードから、WebGLProgramを作成する関数を準備します。

function createProgram(gl : WebGLRenderingContext, vertexCode : string, fragmentCode : string) : WebGLProgram {
    // Vertex Shader コンパイル
    const vertexShader = gl.createShader(gl.VERTEX_SHADER)!;
    compileShader(gl, vertexShader, vertexCode);

    // Fragment Shader コンパイル
    const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER)!;
    compileShader(gl, fragmentShader, fragmentCode);

    // Program作成
    const program = gl.createProgram()!;
    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);
    gl.linkProgram(program);

    // エラー確認
    console.log(gl.getProgramInfoLog(program));
    if (!gl.getProgramParameter(program, gl.LINK_STATUS))
        throw new Error("program error");

    return program;
}


上記で利用しているcompileShaderは次のようになります。

function compileShader(gl : WebGLRenderingContext, shader : WebGLShader, code : string) : void {
    gl.shaderSource(shader, code);
    gl.compileShader(shader);

    // エラー確認
    console.log(gl.getShaderInfoLog(shader));
    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS))
        throw new Error("compile error");
}


VertexBuffer作成関数

頂点データの配列からWebGLBufferを作成する関数を準備します。

function createVertexBuffer(gl : WebGLRenderingContext, vertices : number[]) : WebGLBuffer {
    const buffer = gl.createBuffer()!;

    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

    return buffer;
}


main関数

三角形を描画する関数は下記の様になります。

canvasにはこのように描画されます。
f:id:any-programming:20171214011828p:plain

let gl : WebGLRenderingContext;

function main() : void {
    const canvas = <HTMLCanvasElement>document.getElementById("gl_canvas");
    gl = canvas.getContext("webgl")!;

    const vertexCode = `
        attribute vec4 position;
        void main() {
            gl_Position = position;
        }    
    `;

    const fragmentCode = `
        void main() {
            gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
        }
    `;

    const program = createProgram(gl, vertexCode, fragmentCode);

    const vertices = [
         0.0,  1.0, 0.0,
        -1.0, -1.0, 0.0,
         1.0, -1.0, 0.0,
    ];
    const vertexBuffer = createVertexBuffer(gl, vertices);

    gl.useProgram(program);
    const positionAttrib = gl.getAttribLocation(program, "position");
    gl.enableVertexAttribArray(positionAttrib);
    gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
    gl.vertexAttribPointer(positionAttrib, 3, gl.FLOAT, false, 0, 0);

    gl.clearColor(0.3, 0.3, 0.3, 1);
    gl.clear(gl.COLOR_BUFFER_BIT);
    gl.drawArrays(gl.TRIANGLES, 0, 3);
}

main();