WebGLその7:2Dイメージ

■index.html

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>SanoWebGLSample07.html</title>
</head>
<script type="text/javascript" src="webglut02.js"></script>
<script id="shader-vs" type="x-shader/x-vertex">
//------------------------------------------------------------------------
//    ヴァーテックスシェーダー
//------------------------------------------------------------------------
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;
}
</script>
<script id="shader-fs" type="x-shader/x-fragment">
//------------------------------------------------------------------------
//    ピクセルシェーダー
//------------------------------------------------------------------------
#ifdef GL_ES
precision highp float;
#endif

uniform sampler2D sampler2d;
varying vec2 texCoord;
void main(void)
{
    gl_FragColor = texture2D(sampler2d, texCoord);
}
</script>
<script>
//------------------------------------------------------------------------
//    
//------------------------------------------------------------------------
var    gl;                //gl用コンテキスト
var    vertexModel;    //頂点
var    uvModel;        //UV
var    imageData;        //イメージデータ
var    shaderProgram;    //シェーダー
//------------------------------------------------------------------------
//    初期化
//------------------------------------------------------------------------
function    init()
{
    // gl用コンテキストを取得
    gl    = Ginit( document.getElementById("c") );
    shaderProgram    = GinitImage();
    //    モデル設定
    initMode();
    //    メインループ登録
    setInterval( "MainLoop()", 33 );
}
//------------------------------------------------------------------------
//    メインループ
//------------------------------------------------------------------------
function MainLoop()
{
    // 画面クリア
    Gclear();
    // 描画
    drawMode();
}
//------------------------------------------------------------------------
//    モデル情報の初期化
//------------------------------------------------------------------------
function    initMode()
{
    // バッファに頂点をセット
    var    vertices    =[
        10, 10,
        100, 10,
        10, 100,
        100, 100
    ];
    vertexModel    = gl.createBuffer();
    gl.bindBuffer( gl.ARRAY_BUFFER, vertexModel );
    gl.bufferData( gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW );

    vertexModel.itemSize = 2;
    vertexModel.numItems = 4;
    //    UV情報の設定
    var uvData = [
        0.0, 0.0,
        1.0, 0.0,
        0.0, 1.0,
        1.0, 1.0
    ];
    uvModel = gl.createBuffer();
    gl.bindBuffer( gl.ARRAY_BUFFER, uvModel );
    gl.bufferData( gl.ARRAY_BUFFER, new Float32Array(uvData), gl.STATIC_DRAW );        
    uvModel.itemSize = 2;
    uvModel.numItems = 4;
    //    イメージ情報の設定
    imageData    = GsetImage( "ren01.jpg" );
}
//------------------------------------------------------------------------
//    モデル情報の描画
//------------------------------------------------------------------------
function    drawMode()
{
    gl.bindBuffer( gl.ARRAY_BUFFER, vertexModel );
    gl.vertexAttribPointer( shaderProgram.vertexPositionAttribute, vertexModel.itemSize, gl.FLOAT, false, 0, 0 );

    gl.bindBuffer( gl.ARRAY_BUFFER, uvModel );
    gl.vertexAttribPointer( shaderProgram.textureCoordAttribute, uvModel.itemSize, gl.FLOAT, false, 0, 0);

    gl.bindTexture( gl.TEXTURE_2D, imageData );

    gl.drawArrays( gl.TRIANGLE_STRIP, 0, vertexModel.numItems );
}

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

■webglut02.js

(function(np){
    var gl = null;
    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.GinitImage = function()
    {
        var    shaderVs1=
            "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    shaderFs1=
            "precision highp float;"+
            "uniform sampler2D sampler2d;"+
            "varying vec2 texCoord;"+
            "void main(void)"+
            "{"+
            "    gl_FragColor = texture2D(sampler2d, texCoord);"+
            "}";
        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    shaderProgram  = gl.createProgram();

        var vertex_shader   = ggetShader( gl, shaderVs1, gl.VERTEX_SHADER );
        var fragment_shader = ggetShader( gl, shaderFs1, 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 );

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

        return    shaderProgram;
    }
    //--------------------------------------------------------------
    //
    //--------------------------------------------------------------
    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;
    }
})(this);

■2Dでイメージをスプライトみたいに表示するとこんな感じです