WebGLその6:2D座標
2Dで制御したいい場合、WebGLそのままだと(-1,-1)-(1,1)というように2Dゲームには扱いにくい座標になっています。
これを(0,0)-(640,480)にできれば簡単に制御できます。
■index.html
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>SanoWebGLSample06.html</title> </head> <script type="text/javascript" src="webglut01.js"></script> <script id="shader-vs" type="x-shader/x-vertex"> //------------------------------------------------------------------------ // ヴァーテックスシェーダー //------------------------------------------------------------------------ attribute vec2 pos; uniform vec2 u_resolution; void main(void) { vec2 zeroToOne = pos / u_resolution; vec2 zeroToTwo = zeroToOne * 2.0; vec2 clipSpace = zeroToTwo - 1.0; gl_Position = vec4( clipSpace * vec2(1, -1), 0, 1); } </script> <script id="shader-fs" type="x-shader/x-fragment"> //------------------------------------------------------------------------ // ピクセルシェーダー //------------------------------------------------------------------------ void main(void) { gl_FragColor = vec4( 1.0, 1.0, 1.0, 1.0 ); } </script> <script> //------------------------------------------------------------------------ // //------------------------------------------------------------------------ var gl; //gl用コンテキスト var vertexModel; //頂点 var shaderProgram; //シェーダー //------------------------------------------------------------------------ // 初期化 //------------------------------------------------------------------------ function init() { // gl用コンテキストを取得 gl = Ginit( document.getElementById("c") ); // シェーダ初期化 shaderProgram = GinitShaders( "shader-vs", "shader-fs" ); shaderProgram.vertexPositionAttribute = gl.getAttribLocation( shaderProgram, "pos" ); gl.enableVertexAttribArray( shaderProgram.vertexPositionAttribute ); // var resolutionLocation = gl.getUniformLocation( shaderProgram, "u_resolution" ); gl.uniform2f( resolutionLocation, gl.viewportWidth, gl.viewportHeight ); // モデル設定 initMode(); // メインループ登録 setInterval( "MainLoop()", 33 ); } //------------------------------------------------------------------------ // メインループ //------------------------------------------------------------------------ function MainLoop() { // 画面クリア Gclear(); // 描画 drawMode(); } //------------------------------------------------------------------------ // モデル情報の初期化 //------------------------------------------------------------------------ function initMode() { // バッファに頂点をセット var vertices =[ 10, 20, 100, 40, 10, 60, ]; 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 = 3; } //------------------------------------------------------------------------ // モデル情報の描画 //------------------------------------------------------------------------ function drawMode() { gl.bindBuffer( gl.ARRAY_BUFFER, vertexModel ); gl.vertexAttribPointer( shaderProgram.vertexPositionAttribute, vertexModel.itemSize, gl.FLOAT, false, 0, 0 ); gl.drawArrays( gl.TRIANGLES, 0, vertexModel.numItems ); } </script> </head> <body onload="init();"> <canvas id="c" style="border:none" width="640" height="480"> </body> </html>
■[WebGLその3:ポリゴン表示]で使われた「webglut01.js」を使います。
http://d.hatena.ne.jp/sanoh/20120328
■これを画面に出すと
■最適化
上のプログラムでもいいのですが、最適化すると
index.html
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>SanoWebGLSample06.html</title> </head> <script type="text/javascript" src="webglut01.js"></script> <script id="shader-vs" type="x-shader/x-vertex"> //------------------------------------------------------------------------ // ヴァーテックスシェーダー //------------------------------------------------------------------------ attribute vec2 pos; uniform vec2 u_resolution; void main(void) { gl_Position = vec4( pos * u_resolution + vec2( -1, 1) , 0, 1); } </script> <script id="shader-fs" type="x-shader/x-fragment"> //------------------------------------------------------------------------ // ピクセルシェーダー //------------------------------------------------------------------------ void main(void) { gl_FragColor = vec4( 1.0, 1.0, 1.0, 1.0 ); } </script> <script> //------------------------------------------------------------------------ // //------------------------------------------------------------------------ var gl; //gl用コンテキスト var vertexModel; //頂点 var shaderProgram; //シェーダー //------------------------------------------------------------------------ // 初期化 //------------------------------------------------------------------------ function init() { // gl用コンテキストを取得 gl = Ginit( document.getElementById("c") ); // シェーダ初期化 shaderProgram = GinitShaders( "shader-vs", "shader-fs" ); shaderProgram.vertexPositionAttribute = gl.getAttribLocation( shaderProgram, "pos" ); gl.enableVertexAttribArray( shaderProgram.vertexPositionAttribute ); // var resolutionLocation = gl.getUniformLocation( shaderProgram, "u_resolution" ); gl.uniform2f( resolutionLocation, 2/gl.viewportWidth, -2/gl.viewportHeight ); // モデル設定 initMode(); // メインループ登録 setInterval( "MainLoop()", 33 ); } //------------------------------------------------------------------------ // メインループ //------------------------------------------------------------------------ function MainLoop() { // 画面クリア Gclear(); // 描画 drawMode(); } //------------------------------------------------------------------------ // モデル情報の初期化 //------------------------------------------------------------------------ function initMode() { // バッファに頂点をセット var vertices =[ 10, 20, 100, 40, 10, 60, ]; 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 = 3; } //------------------------------------------------------------------------ // モデル情報の描画 //------------------------------------------------------------------------ function drawMode() { gl.bindBuffer( gl.ARRAY_BUFFER, vertexModel ); gl.vertexAttribPointer( shaderProgram.vertexPositionAttribute, vertexModel.itemSize, gl.FLOAT, false, 0, 0 ); gl.drawArrays( gl.TRIANGLES, 0, vertexModel.numItems ); } </script> </head> <body onload="init();"> <canvas id="c" style="border:none" width="640" height="480"> </body> </html>
となします。
バーテックスシェーダーを
attribute vec2 pos; uniform vec2 u_resolution; void main(void) { gl_Position = vec4( pos * u_resolution + vec2( -1, 1) , 0, 1); }
と短くするために
gl.uniform2f( resolutionLocation, 2/gl.viewportWidth, -2/gl.viewportHeight );
事前にパラメータをある程度計算するようにしています。