基礎部分はできたので、実際にシェーダーにデーターを渡していこうかと思います。
サンプルとしてdrawImage関数を作ってみようかと思います。
利用するイメージ
context.fillStyle = [1, 1, 1, 1];
context.setTransform(1, 0, 0, 1, 0, 0);
context.drawImage(texture, 0, 0, width, height);
シェーダーの準備
今回は色とmatrixも使ってdrawImageを実装していきます。
頂点シェーダー
const TEXTURE_VERTEX_SHADER = "\
precision highp float;\n\
attribute vec2 a_coord;\n\
varying vec2 v_coord;\n\
uniform vec2 u_position;\n\
uniform vec2 u_size;\n\
uniform vec2 u_viewport;\n\
uniform mat3 u_transform;\n\
void main() {\n\
v_coord = a_coord;\n\
vec3 pos = u_transform * vec3(u_position + vec2(a_coord.x, 1.0 - a_coord.y) * u_size, 1.0);\n\
pos.x = (2.0 * pos.x / u_viewport.x) - 1.0;\n\
pos.y = -((2.0 * pos.y / u_viewport.y) - 1.0);\n\
gl_Position = vec4(pos.xy, 0.0, 1.0);\n\
}";
フラグメントシェーダー
const TEXTURE_FRAGMENT_SHADER = "\
precision highp float;\n\
uniform sampler2D u_texture;\n\
uniform vec4 u_color;\n\
varying vec2 v_coord;\n\
void main() {\n\
gl_FragColor = texture2D(u_texture, v_coord) * u_color;\n\
}";
drawImageを実装
/**
* @param {array} uniforms
* @return {void}
* @public
*/
updateUniforms (uniforms)
{
var length = uniforms.length;
for (let idx = 0; idx < length; idx++) {
const uniform = uniforms[idx];
var value = uniform.value;
if (Util.$isArray(value)) {
value = new Float32Array(value);
}
var info = this.uniformInfo[uniform.name];
if (!info.location) {
info.location = this.gl.getUniformLocation(this.program, uniform.name);
}
switch (info.type) {
case gl.FLOAT_MAT2:
case gl.FLOAT_MAT3:
case gl.FLOAT_MAT4:
info.method.call(this.gl, info.location, false, value);
break;
// ...他の関数も同様に値をセットしてコールする
}
}
}
/**
* @praram {WebGLTexture} texture
* @praram {number} x
* @praram {number} y
* @praram {number} width
* @praram {number} height
* @return {void}
* @public
*/
drawImage (texture, x, y, width, height)
{
// 生成したプログラムをセット
this.gl.useProgram(this.program);
// 描画したいtextureをbind
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, texture);
// 変数データを送る
this.updateUniforms ([
{ "name": "u_size", "value": [x, y] },
{ "name": "u_position", "value": [width, height] },
{ "name": "u_transform", "value": this.matrix },
{ "name": "u_color", "value": this.color },
// ...今回は他の変数は割愛
])
// buffer objectやattributeは長くなるので、今回は割愛します。
gl.drawArrays(gl.TRIANGLES, 0, 6);
}
っという感じで、一番最初はCanvas2Dで出来上がったcanvasデータをtextureに変換してWebGLで描画する事からはじめました。
次はlineToやquadraticCurveToのパス情報について書こうと思います。