CX's JavaScript Diary

2015-06-21HTA で WebGL を使う方法(その4) このエントリーを含むブックマーク

lightgl.js

HTA で WebGL を使うシリーズ第4弾です。

今回は、前回のサンプルコードをライブラリを用いてダイエット(HTML のコード込みで100行→30行)させてみました。

WebGL ライブラリとしては lightgl.js を用いています。

<!DOCTYPE html>
<html>
<head>
<title>Hello, WebGL World!</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
</head>
<body>
<script src="lightgl.js"></script>
<script>
var gl = GL.create();

gl.ondraw = function() {
    gl.clear(gl.COLOR_BUFFER_BIT);
    gl.begin(gl.TRIANGLES);
    gl.color(1.0, 0.0, 0.0); gl.vertex( 0.0, 1.0, 0.0);
    gl.color(0.0, 1.0, 0.0); gl.vertex( 1.0, 0.0, 0.0);
    gl.color(0.0, 0.0, 1.0); gl.vertex(-1.0, 0.0, 0.0);
    gl.end();
};

gl.clearColor(1.0, 1.0, 1.0, 1.0);
gl.translate(0, 0, -3);
gl.fullscreen();
</script>
</body>
</html>

2015-01-20HTA で WebGL を使う方法(その3) このエントリーを含むブックマーク

cx2020150120

HTA で WebGL を使うシリーズ第三弾です。

今回は、前回のサンプルコードをダイエット(HTML のコード込みで200行→100行)させてみました。

本サンプルはライブラリを使用していない為、HTA ファイルだけで動作します。

<!DOCTYPE html>
<html>
<head>
<title>Hello, WebGL World!</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
</head>
<body>
<script id="vs" type="x-shader/x-vertex">
attribute vec3 position;
attribute vec4 color;
varying   vec4 vColor;

void main()
{
    vColor = color;
    gl_Position = vec4(position, 1.0);
}
</script>

<script id="fs" type="x-shader/x-fragment">
precision mediump float;
varying   vec4 vColor;

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

<canvas id="c" width="465" height="465"></canvas>

<script>
var c, gl;

function initWebGL() {
    c = document.getElementById("c");
    gl = c.getContext("experimental-webgl");
}

function initShaders() {
    var p = gl.createProgram();
    var vs = gl.createShader(gl.VERTEX_SHADER);
    var fs = gl.createShader(gl.FRAGMENT_SHADER);
    var v = document.getElementById("vs").text;
    var f = document.getElementById("fs").text;
    gl.shaderSource(vs, v);
    gl.shaderSource(fs, f);
    gl.compileShader(vs);
    gl.compileShader(fs);
    gl.attachShader(p, vs);
    gl.attachShader(p, fs);
    gl.linkProgram(p);
    gl.useProgram(p);
    gl.bindAttribLocation(p, 0, "position");
    gl.bindAttribLocation(p, 1, "color");
    gl.enableVertexAttribArray(0);
    gl.enableVertexAttribArray(1);
}

function draw() {
    // 頂点データ
    var data = [ 
         0.0, 1.0, 0.0,
         1.0, 0.0, 0.0,
        -1.0, 0.0, 0.0
    ];
    gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data), gl.STATIC_DRAW);
    gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);

    // 色データ
    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
    ];
    gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
    gl.vertexAttribPointer(1, 4, gl.FLOAT, false, 0, 0);
    
    // ポリゴンの描画
    gl.drawArrays(gl.TRIANGLES, 0, 3);
    gl.flush();
}

initWebGL();
initShaders();
draw();
</script>
</body>
</html>

2014-02-15HTA で WebGL を使う方法(その2) このエントリーを含むブックマーク

サンプル実行結果

前回、「HTA(HTML Application)で WebGL を使う方法」にて、 three.js を用いて、WebGL を試しました。

今回は、three.js を用いず、WebGL を試してみたいと思います。

HTA としてのポイントは、互換モード(X-UA-Compatible)を明示的に「IE=edge」(最新)を指定する点になります。なお、WebGLIE11 以上で利用可能です。

<meta http-equiv="X-UA-Compatible" content="IE=edge">

以下は、「WebGL 開発支援サイト wgld.org」さんの「WebGL: ポリゴンに色を塗る(頂点色の指定) 」のサンプルを HTA の形式に変換したものになります。

<!DOCTYPE HTML>
<html>
<head>
<title>Hello, WebGL World!</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<script type="text/javascript" src="minMatrix.js"></script>
<script id="vs" type="x-shader/x-vertex">
    attribute vec3 position;
    attribute vec4 color;
    uniform   mat4 mvpMatrix;
    varying   vec4 vColor;

    void main(void){
        vColor = color;
        gl_Position = mvpMatrix * vec4(position, 1.0);
    }
</script>

<script id="fs" type="x-shader/x-fragment">
    precision mediump float;

    varying vec4 vColor;

    void main() {
        gl_FragColor = vColor;
    }
</script>
</head>
<body>
<canvas id="canvas"></canvas>
<script type="text/javascript">
var X_MAX = 640;
var Y_MAX = 480;

window.resizeTo(X_MAX+40, Y_MAX+60);

onload = function(){
   // canvasエレメントを取得
    var c = document.getElementById('canvas');
    c.width = X_MAX;
    c.height = Y_MAX;

    // webglコンテキストを取得
    var gl = c.getContext('webgl') || c.getContext('experimental-webgl');
    
    // canvasを初期化する色を設定する
    gl.clearColor(0.0, 0.0, 0.0, 1.0);
    
    // canvasを初期化する際の深度を設定する
    gl.clearDepth(1.0);
    
    // canvasを初期化
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    
    // 頂点シェーダとフラグメントシェーダの生成
    var v_shader = create_shader('vs');
    var f_shader = create_shader('fs');
    
    // プログラムオブジェクトの生成とリンク
    var prg = create_program(v_shader, f_shader);
    
    // attributeLocationを配列に取得
    var attLocation = new Array(2);
    attLocation[0] = gl.getAttribLocation(prg, 'position');
    attLocation[1] = gl.getAttribLocation(prg, 'color');
    
    // attributeの要素数を配列に格納
    var attStride = new Array(2);
    attStride[0] = 3;
    attStride[1] = 4;
    
    // 頂点の位置情報を格納する配列
    var vertex_position = [
         0.0, 1.0, 0.0,
         1.0, 0.0, 0.0,
        -1.0, 0.0, 0.0
    ];
    
    // 頂点の色情報を格納する配列
    var vertex_color = [
        1.0, 0.0, 0.0, 1.0,
        0.0, 1.0, 0.0, 1.0,
        0.0, 0.0, 1.0, 1.0
    ];
    
    // VBOの生成
    var position_vbo = create_vbo(vertex_position);
    var color_vbo = create_vbo(vertex_color);
    
    // VBOをバインドし登録する(位置情報)
    gl.bindBuffer(gl.ARRAY_BUFFER, position_vbo);
    gl.enableVertexAttribArray(attLocation[0]);
    gl.vertexAttribPointer(attLocation[0], attStride[0], gl.FLOAT, false, 0, 0);
    
    // VBOをバインドし登録する(色情報)
    gl.bindBuffer(gl.ARRAY_BUFFER, color_vbo);
    gl.enableVertexAttribArray(attLocation[1]);
    gl.vertexAttribPointer(attLocation[1], attStride[1], gl.FLOAT, false, 0, 0);
    
    // minMatrix.js を用いた行列関連処理
    // matIVオブジェクトを生成
    var m = new matIV();
    
    // 各種行列の生成と初期化
    var mMatrix = m.identity(m.create());
    var vMatrix = m.identity(m.create());
    var pMatrix = m.identity(m.create());
    var mvpMatrix = m.identity(m.create());
    
    // ビュー座標変換行列
    m.lookAt([0.0, 1.0, 3.0], [0, 0, 0], [0, 1, 0], vMatrix);
    
    // プロジェクション座標変換行列
    m.perspective(90, c.width / c.height, 0.1, 100, pMatrix);
    
    // 各行列を掛け合わせ座標変換行列を完成させる
    m.multiply(pMatrix, vMatrix, mvpMatrix);
    m.multiply(mvpMatrix, mMatrix, mvpMatrix);
    
    // uniformLocationの取得
    var uniLocation = gl.getUniformLocation(prg, 'mvpMatrix');
    
    // uniformLocationへ座標変換行列を登録
    gl.uniformMatrix4fv(uniLocation, false, mvpMatrix);
    
    // モデルの描画
    gl.drawArrays(gl.TRIANGLES, 0, 3);
    
    // コンテキストの再描画
    gl.flush();
    
    // シェーダを生成する関数
    function create_shader(id){
        // シェーダを格納する変数
        var shader;
        
        // HTMLからscriptタグへの参照を取得
        var scriptElement = document.getElementById(id);
        
        // scriptタグが存在しない場合は抜ける
        if(!scriptElement){return;}
        
        // scriptタグのtype属性をチェック
        switch(scriptElement.type){
            
            // 頂点シェーダの場合
            case 'x-shader/x-vertex':
                shader = gl.createShader(gl.VERTEX_SHADER);
                break;
                
            // フラグメントシェーダの場合
            case 'x-shader/x-fragment':
                shader = gl.createShader(gl.FRAGMENT_SHADER);
                break;
            default :
                return;
        }
        
        // 生成されたシェーダにソースを割り当てる
        gl.shaderSource(shader, scriptElement.text);
        
        // シェーダをコンパイルする
        gl.compileShader(shader);
        
        // シェーダが正しくコンパイルされたかチェック
        if(gl.getShaderParameter(shader, gl.COMPILE_STATUS)){
            
            // 成功していたらシェーダを返して終了
            return shader;
        }else{
            
            // 失敗していたらエラーログをアラートする
            alert(gl.getShaderInfoLog(shader));
        }
    }
    
    // プログラムオブジェクトを生成しシェーダをリンクする関数
    function create_program(vs, fs){
        // プログラムオブジェクトの生成
        var program = gl.createProgram();
        
        // プログラムオブジェクトにシェーダを割り当てる
        gl.attachShader(program, vs);
        gl.attachShader(program, fs);
        
        // シェーダをリンク
        gl.linkProgram(program);
        
        // シェーダのリンクが正しく行なわれたかチェック
        if(gl.getProgramParameter(program, gl.LINK_STATUS)){
        
            // 成功していたらプログラムオブジェクトを有効にする
            gl.useProgram(program);
            
            // プログラムオブジェクトを返して終了
            return program;
        }else{
            
            // 失敗していたらエラーログをアラートする
            alert(gl.getProgramInfoLog(program));
        }
    }
    
    // VBOを生成する関数
    function create_vbo(data){
        // バッファオブジェクトの生成
        var vbo = gl.createBuffer();
        
        // バッファをバインドする
        gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
        
        // バッファにデータをセット
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data), gl.STATIC_DRAW);
        
        // バッファのバインドを無効化
        gl.bindBuffer(gl.ARRAY_BUFFER, null);
        
        // 生成した VBO を返して終了
        return vbo;
    }

};
</script>
</body>
</html>

2013-06-27HTA(HTML Application)で WebGL を使う方法 このエントリーを含むブックマーク

cx2020130627

IE11 から WebGL の機能が追加されたようです。せっかくなので、HTA から使ってみました。

使用方法は、前回の HTA で Canvas を使用する方法と同じで、互換モード(X-UA-Compatible)を明示的に「IE=edge」(最新)と指定することで、WebGL が使えるようになります。

<meta http-equiv="X-UA-Compatible" content="IE=edge">

以下は HTA より three.js ライブラリを使用した WebGL のサンプルになります。

<!DOCTYPE HTML>
<html>
<head>
<title>Hello, WebGL World!</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<script src="three.js"></script>
</head>
<body>
<script type="text/javascript">
var X_MAX = 640;
var Y_MAX = 480;
var R = 100;          // 半径
var X_SEGMENTS = 12;  // 経度分割数
var Y_SEGMENTS = 12;  // 緯度分割数
window.resizeTo(X_MAX+40, Y_MAX+60);

// レンダラー準備
var renderer = new THREE.WebGLRenderer();
renderer.setSize(X_MAX, Y_MAX);
document.body.appendChild(renderer.domElement);

// カメラ準備
var camera = new THREE.PerspectiveCamera(45, X_MAX / Y_MAX, 1, 1000);
camera.position.z = 300;

// シーン(空間)準備
var scene = new THREE.Scene();

// オブジェクトの形状設定
var geometry = new THREE.SphereGeometry(R, X_SEGMENTS, Y_SEGMENTS);
var material = new THREE.MeshNormalMaterial();
var sphere = new THREE.Mesh(geometry, material);
sphere.overdraw = true;

// シーン(空間)にオブジェクトを追加
scene.add(sphere);

// レンダラーにシーンとカメラを設定しオブジェクトを描画
renderer.render(scene, camera);
</script>
</body>
</html>

2013-02-27HTA(HTML Application)で Canvas を使う方法 このエントリーを含むブックマーク

cx2020130227

IE9/10 環境であっても、HTA のドキュメント互換モードがレガシーな設定となっている為、既定では HTML5Canvas 機能が使用できないようです。

ただし、互換モード(X-UA-Compatible)を明示的に「IE=edge」(最新)と指定することで、Canvas が使えるようになります。

(2013.04.28 追記:IE10 モードにすると HTA:Application オプションが効かなくなるとのこと。)

<meta http-equiv="X-UA-Compatible" content="IE=edge">

■ Tech babble | HTA with HTML5 elements

http://blog.roth-russell.com/post/HTA-with-HTML5-elements.aspx

以下、サンプルです。

<html>
<title>Hello, Canvas World!</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<script type="text/javascript">
var X_MAX = 640;
var Y_MAX = 480;
var R = 240;
window.resizeTo(X_MAX + 40, Y_MAX + 60);

function draw() {
    var canvas = document.getElementById("Canvas");
    var ctx = canvas.getContext("2d");
    drawScreen( ctx );
    drawGraph( ctx );
    drawSin( ctx );
}

function drawScreen( ctx ) {
    ctx.fillStyle = "rgb( 0, 0, 0 )";
    ctx.fillRect( 0, 0, X_MAX, Y_MAX );
}

function drawGraph( ctx ) {
    ctx.strokeStyle = "rgb( 0, 127, 0 )";
    ctx.beginPath();
    var x, y;
    for (x = 0; x <= X_MAX; x += 20) {
        ctx.moveTo(x, 0);
        ctx.lineTo(x, Y_MAX);
    }
    for (y = 0; y <= Y_MAX; y += 20) {
        ctx.moveTo(0, y);
        ctx.lineTo(X_MAX, y);
    }
    ctx.stroke();
}

function drawSin( ctx ) {
    ctx.strokeStyle = "rgb( 0, 255, 0 )";
    ctx.beginPath();
    ctx.moveTo(0, R);
    var x, y;
    for (x = 0; x <= X_MAX; x += 20) {
        y = R - R * Math.sin( 2 * Math.PI * ( x / X_MAX ) )
        ctx.lineTo(x, y);
    }
    ctx.stroke();
}
</script>
<body onload="draw()">
<canvas id="Canvas" width="640" height="480"></canvas>
</body>
</html>