WebGLその8:2Dライブラリ

せっかくなので2D関係の関数を作り、まとめてみました
■index.html

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>SanoWebGLSample08.html</title>
</head>
<script type="text/javascript" src="webglut03.js"></script>
<script>
//------------------------------------------------------------------------
//    
//------------------------------------------------------------------------
var    imageData;        //イメージデータ
//------------------------------------------------------------------------
//    初期化
//------------------------------------------------------------------------
function    init()
{
    // gl用コンテキストを取得
    Ginit( document.getElementById("c") );
    G2Dinit();
    //    テクスチャ登録
    imageData    = GsetImage( "ren01.jpg" );
    //    メインループ登録
    setInterval( "MainLoop()", 33 );
}
//------------------------------------------------------------------------
//    メインループ
//------------------------------------------------------------------------
function MainLoop()
{
    // 画面クリア
    Gclear();
    // 描画
    G2Dimage( imageData, 10, 10, 100, 100 );
    G2Dimage( imageData, 50, 50, 200, 200 );
    //ポリゴン描画
    G2DsetColor( 0.5, 0.2, 1.0, 1 );
    G2Dpolygon( 0, 0, 200, 30, 100, 100 );
    //BOX描画
    G2DsetColor( 1.0, 1.0, 1.0, 1 );
    G2Dbox( 300, 100, 200, 200 );
    //ライン描画
    G2DsetColor( 0.0, 1.0, 0.0, 1 );
    G2Dline( 10, 150, 40, 400 );
    //ラインBOX描画
    G2DsetColor( 0.0, 1.0, 1.0, 1 );
    G2DlineBox( 150, 350, 200, 50 );
}

</script>
</head>
<body onload="init();">
<canvas id="c" style="border:none" width="640" height="480">
</body>
</html>

■webglut03.js

(function(np){
    var gl = null;
    var    spriteShaderI = null;
    var    spriteShaderP = null;
    var    spriteVertex = null;
    var    spriteUV = null;
    var    colorLocation;
    np.Ginit = function( canvas )
    {
        try {
            gl = canvas.getContext( "experimental-webgl" );
            gl.viewportWidth = canvas.width;
            gl.viewportHeight= canvas.height;
        }
        catch (e) {}

        if (!gl) {
            alert( "WebGL に対応してないです" );
            return;
        }
        gl.clearColor( 0.0, 0.0, 0.0, 1.0 );
        gl.clearDepth( 1.0 );
        gl.enable( gl.DEPTH_TEST );
        gl.depthFunc( gl.LEQUAL );
        return gl;
    };
    //--------------------------------------------------------------
    //
    //--------------------------------------------------------------
    np.G2Dinit = function()
    {
        gl.enable( gl.DEPTH_TEST );
        gl.enable( gl.BLEND );
        gl.blendFunc( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA ); 
        gl.enable( gl.TEXTURE_2D );
        //----------------------------------------------------------------------
        var    shaderVsI    =
            "attribute vec2 pos;"+
            "attribute vec2 uv;"+
            "uniform vec2 u_resolution;"+
            "varying vec2 texCoord;"+
            "void main(void)"+
            "{"+
            "    gl_Position = vec4( pos * u_resolution + vec2( -1, 1) , 0, 1);"+
            "    texCoord = uv;"+
            "}";
        var    shaderFsI    =
            "precision highp float;"+
            "uniform sampler2D sampler2d;"+
            "varying vec2 texCoord;"+
            "void main(void)"+
            "{"+
            "    gl_FragColor = texture2D(sampler2d, texCoord);"+
            "}";
        spriteShaderI  = gl.createProgram();

        gl.attachShader( spriteShaderI, ggetShader( gl, shaderVsI, gl.VERTEX_SHADER ) );
        gl.attachShader( spriteShaderI, ggetShader( gl, shaderFsI, gl.FRAGMENT_SHADER ) );
        
        gl.linkProgram( spriteShaderI );
        if (!gl.getProgramParameter( spriteShaderI, gl.LINK_STATUS ) )
        {
            alert( "initShaders" );
        }
        gl.useProgram( spriteShaderI );

        spriteShaderI.vertexPositionAttribute = gl.getAttribLocation( spriteShaderI, "pos" );
        gl.enableVertexAttribArray( spriteShaderI.vertexPositionAttribute );
        spriteShaderI.textureCoordAttribute = gl.getAttribLocation( spriteShaderI, "uv" );
        gl.enableVertexAttribArray( spriteShaderI.textureCoordAttribute );
        //
        var resolutionLocation = gl.getUniformLocation( spriteShaderI, "u_resolution" );
        gl.uniform2f( resolutionLocation, 2/gl.viewportWidth, -2/gl.viewportHeight );

        //----------------------------------------------------------------------
        var    shaderVsP    =
            "attribute vec2 pos;"+
            "uniform vec2 u_resolution;"+
            "void main(void)"+
            "{"+
            "    gl_Position = vec4( pos * u_resolution + vec2( -1, 1) , 0, 1);"+
            "}";
        var    shaderFsP    =
            "precision highp float;"+
            "uniform vec4 u_color;"+
            "void main(void)"+
            "{"+
            "    gl_FragColor = u_color;"+
            "}";
        spriteShaderP  = gl.createProgram();

        gl.attachShader( spriteShaderP, ggetShader( gl, shaderVsP, gl.VERTEX_SHADER ) );
        gl.attachShader( spriteShaderP, ggetShader( gl, shaderFsP, gl.FRAGMENT_SHADER ) );

        gl.linkProgram( spriteShaderP );
        if (!gl.getProgramParameter( spriteShaderP, gl.LINK_STATUS ) )
        {
            alert( "initShaders" );
        }
        gl.useProgram( spriteShaderP );

        spriteShaderP.vertexPositionAttribute = gl.getAttribLocation( spriteShaderP, "pos" );
        gl.enableVertexAttribArray( spriteShaderP.vertexPositionAttribute );
        colorLocation = gl.getUniformLocation( spriteShaderP, "u_color");
        gl.uniform4f( colorLocation, 1, 0, 1, 1 );
        var    resolutionLocation2 = gl.getUniformLocation( spriteShaderP, "u_resolution" );
        gl.uniform2f( resolutionLocation2, 2/gl.viewportWidth, -2/gl.viewportHeight );
        //----------------------------------------------------------------------
        // バッファに頂点をセット
        spriteVertex    = gl.createBuffer();
        //    UV情報の設定
        var uvData = [
            0.0, 0.0,
            1.0, 0.0,
            0.0, 1.0,
            1.0, 1.0
        ];
        spriteUV = gl.createBuffer();
        gl.bindBuffer( gl.ARRAY_BUFFER, spriteUV );
        gl.bufferData( gl.ARRAY_BUFFER, new Float32Array(uvData), gl.STATIC_DRAW );        
        return    spriteShaderI;
    }
    //--------------------------------------------------------------
    //
    //--------------------------------------------------------------
    np.Gclear = function()
    {
        gl.viewport( 0, 0, gl.viewportWidth, gl.viewportHeight );
        gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT );
    }

    //--------------------------------------------------------------
    //
    //--------------------------------------------------------------
    var ggetShader = function( gl, str, type )
    {
        var shader;

        shader = gl.createShader( type )
        gl.shaderSource( shader, str );
        gl.compileShader( shader );
        if (!gl.getShaderParameter( shader, gl.COMPILE_STATUS ) ) {
            alert( gl.getShaderInfoLog( shader ) );
            return null;
        }
        return shader;
    };

    //--------------------------------------------------------------
    //
    //--------------------------------------------------------------
    np.GinitShaders = function( vsName, fsName )
    {
        var    vsStr    = document.getElementById( vsName ).innerText;
        var    fsStr    = document.getElementById( fsName ).innerText;
        var    shaderProgram;
        shaderProgram  = gl.createProgram();

        var vertex_shader   = ggetShader( gl, vsStr, gl.VERTEX_SHADER );
        var fragment_shader = ggetShader( gl, fsStr, gl.FRAGMENT_SHADER );
        
        gl.attachShader( shaderProgram, vertex_shader );
        gl.attachShader( shaderProgram, fragment_shader );
        
        gl.linkProgram( shaderProgram );
        if (!gl.getProgramParameter( shaderProgram, gl.LINK_STATUS ) )
        {
            alert( "initShaders" );
        }
        gl.useProgram( shaderProgram );

        return    shaderProgram;
    };
    //--------------------------------------------------------------
    //
    //--------------------------------------------------------------
    np.GsetImage = function( imageName )
    {
        var    imageData = gl.createTexture();
        imageData.image = new Image();
        imageData.image.onload = function() { 
            gl.bindTexture( gl.TEXTURE_2D, imageData );
            gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, imageData.image );    
            gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR );
            gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR );
            gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE );
            gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE );
            gl.bindTexture( gl.TEXTURE_2D, null );
        }
        imageData.image.src = imageName;
        return    imageData;
    }
    //--------------------------------------------------------------
    //
    //--------------------------------------------------------------
    np.G2Dimage = function( iMag, wx, wy, wwidth, wheight )
    {
        gl.useProgram( spriteShaderI );
        var    vertices    =[
            wx, wy,
            wx+wwidth, wy,
            wx, wy+wheight,
            wx+wwidth, wy+wheight
        ];
        gl.bindBuffer( gl.ARRAY_BUFFER, spriteVertex );
        gl.bufferData( gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW );
        gl.vertexAttribPointer( spriteShaderI.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0 );

        gl.bindBuffer( gl.ARRAY_BUFFER, spriteUV );
        gl.vertexAttribPointer( spriteShaderI.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0);

        gl.bindTexture( gl.TEXTURE_2D, iMag );
        gl.drawArrays( gl.TRIANGLE_STRIP, 0, 4 );
    }
    //--------------------------------------------------------------
    //
    //--------------------------------------------------------------
    np.G2DsetColor = function( ir, ig, ib, ia )
    {
        gl.useProgram( spriteShaderP );
        gl.uniform4f( colorLocation, ir, ig, ib, ia );
    }
    //--------------------------------------------------------------
    //
    //--------------------------------------------------------------
    np.G2Dpolygon = function( ix0, iy0, ix1, iy1, ix2, iy2 )
    {
        gl.useProgram( spriteShaderP );
        var    vertices    =[
            ix0, iy0,
            ix1, iy1,
            ix2, iy2
        ];
        gl.bindBuffer( gl.ARRAY_BUFFER, spriteVertex );
        gl.bufferData( gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW );
        gl.vertexAttribPointer( spriteShaderP.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0 );

        gl.drawArrays( gl.TRIANGLES, 0, 3 );
    }
    //--------------------------------------------------------------
    //
    //--------------------------------------------------------------
    np.G2Dbox = function( wx, wy, wwidth, wheight )
    {
        gl.useProgram( spriteShaderP );
        var    vertices    =[
            wx, wy,
            wx+wwidth, wy,
            wx, wy+wheight,
            wx+wwidth, wy+wheight
        ];
        gl.bindBuffer( gl.ARRAY_BUFFER, spriteVertex );
        gl.bufferData( gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW );
        gl.vertexAttribPointer( spriteShaderP.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0 );

        gl.drawArrays( gl.TRIANGLE_STRIP, 0, 4 );
    }
    //--------------------------------------------------------------
    //
    //--------------------------------------------------------------
    np.G2Dline = function( ix0, iy0, ix1, iy1 )
    {
        gl.useProgram( spriteShaderP );
        var    vertices    =[
            ix0, iy0,
            ix1, iy1
        ];
        gl.bindBuffer( gl.ARRAY_BUFFER, spriteVertex );
        gl.bufferData( gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW );
        gl.vertexAttribPointer( spriteShaderP.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0 );

        gl.drawArrays( gl.LINES, 0, 2 );
    }
    //--------------------------------------------------------------
    //
    //--------------------------------------------------------------
    np.G2DlineBox = function( wx, wy, wwidth, wheight )
    {
        gl.useProgram( spriteShaderP );
        var    vertices    =[
            wx, wy,
            wx+wwidth, wy,
            wx+wwidth, wy+wheight,
            wx, wy+wheight,
            wx, wy
        ];
        gl.bindBuffer( gl.ARRAY_BUFFER, spriteVertex );
        gl.bufferData( gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW );
        gl.vertexAttribPointer( spriteShaderP.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0 );

        gl.drawArrays( gl.LINE_STRIP, 0, 5 );
    }
})(this);

■これを実行すれば、2D関係、簡単に表示できます