ホーム < ゲームつくろー! < IKD備忘録

WebGL
板ポリ一枚をブラウザの世界に投下:サンプルプログラム


 この章で説明した板ポリゴンを1枚canvasに描画するHTMLプログラムです。以下のプログラムをHTMLファイルとしてコピペし、ベクトルと行列を扱うライブラリ(oxglmath.js)をこちらからダウンロードして、HTML5のcanvasをサポートしているブラウザ(Chromeを推奨)で起動すると三角ポリゴンが表示されます:

<html>
<head>
<meta charset="UTF-8">
    <script src="oxglmath.js"></script>
    <script id="vtxshader" type="x-shader/x-vertex">
        // ここに頂点シェーダを書くのです
        attribute vec3 aPos;
        attribute vec4 aColor;
        uniform mat4 uWVP;

        varying vec4 vColor;

        void main( void ) {
            vColor = aColor;
            vec4 outPos = vec4( aPos, 1.0 ) * uWVP;
            gl_Position = outPos / outPos.w;
        }
    </script>

    <script id="frgshader" type="x-shader/x-fragment">
        // ここにフラグメントシェーダを書くのです
        precision mediump float;

        varying vec4 vColor;

        void main( void ) {
            gl_FragColor = vColor;
        }
    </script>

    <script>
        window.onload = function() {
            // canvasからコンテキストを取得する
            var canvas = document.getElementById("canvas");
            var glc = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");

            // 頂点シェーダを読み込んでコンパイル
            var vshader = glc.createShader( glc.VERTEX_SHADER );
            var shaderSrc = document.getElementById("vtxshader").text;
            glc.shaderSource( vshader, shaderSrc );
            glc.compileShader( vshader );
            if ( !glc.getShaderParameter( vshader, glc.COMPILE_STATUS ) ) {
                var str = glc.getShaderInfoLog( vshader );
                window.alert( "頂点シェーダエラー:\n" + str );
                return false;
            }

            // フラグメントシェーダを読み込んでコンパイル
            var fshader = glc.createShader( glc.FRAGMENT_SHADER );
            shaderSrc = document.getElementById("frgshader").text;
            glc.shaderSource( fshader, shaderSrc );
            glc.compileShader( fshader );
            if ( !glc.getShaderParameter( fshader, glc.COMPILE_STATUS ) ) {
                var str = glc.getShaderInfoLog( fshader );
                window.alert( "フラグメントシェーダエラー:\n" + str );
                return false;
            }

            // シェーダプログラムを作る
            var program = glc.createProgram();
            glc.attachShader( program, vshader );
            glc.attachShader( program, fshader );
            glc.linkProgram( program );

            // 頂点座標バッファ作成
            var coords = [
                -1.0, 0.0, 0.0,
                0.0, 1.0, 0.0,
                1.0, 0.0, 0.0,
            ];
            var coordBuf = glc.createBuffer();
            glc.bindBuffer( glc.ARRAY_BUFFER, coordBuf ); // バッファをセットして
            glc.bufferData( glc.ARRAY_BUFFER, new Float32Array(coords), glc.STATIC_DRAW ); // 配列を流し込んでいる

            // 頂点カラーバッファ作成
            var colors = [
                1.0, 0.0, 0.0, 1.0,
                0.0, 1.0, 0.0, 1.0,
                0.0, 0.0, 1.0, 1.0
            ];
            var colorBuf = glc.createBuffer();
            glc.bindBuffer( glc.ARRAY_BUFFER, colorBuf );
            glc.bufferData( glc.ARRAY_BUFFER, new Float32Array( colors ), glc.STATIC_DRAW );


            // ゲームループ
            function update() {
                // 変換行列作成
                var world = new OXMath.Mat4x4();
                var view = OXMath.lookAtLH(
                    new OXMath.Vec3( 0.0, 0.0, -5.0 ),
                    new OXMath.Vec3( 0.0, 0.0, 0.0 ),
                    new OXMath.Vec3( 0.0, 1.0, 0.0 )
                );
                var proj = OXMath.perspLH( OXMath.toRad(30.0), 1.0, 0.01, 100.0 );
                var wvp = world.mul(view).mul(proj);

                // 作ったシェーダプログラムをコンテキストに設定
                glc.useProgram( program );

                // シェーダ入力引数であるAttributeとUniformを取得
                var aPos = glc.getAttribLocation( program, "aPos" );
                var aColor = glc.getAttribLocation( program, "aColor" );
                var uWVP = glc.getUniformLocation( program, "uWVP" );

                // 各バッファとシェーダ引数を繋ぐ
                // 座標
                glc.bindBuffer( glc.ARRAY_BUFFER, coordBuf );
                glc.vertexAttribPointer( aPos, 3, glc.FLOAT, false, 0, 0 );
                // カラー
                glc.bindBuffer( glc.ARRAY_BUFFER, colorBuf );
                glc.vertexAttribPointer( aColor, 4, glc.FLOAT, false, 0, 0 );
                // 行列
                glc.uniformMatrix4fv( uWVP, false, wvp.ary() );

                // 使用するAttributeを指定
                glc.enableVertexAttribArray( aPos );
                glc.enableVertexAttribArray( aColor );

                // 描画
                glc.drawArrays( glc.TRIANGLES, 0, 3 );

            }
            setInterval( update, 33 );
        }

    </script>

</head>

<body>
    <canvas id="canvas" width=480 height=480></canvas>
</body>
</html>