いろいろなサイトを参考にしながらようやく完成した。runをクリックすると、8色の縞模様がスクロールしているように見えるはずだ。
このようなデモを昔よく見かけたものだ。というか私が店頭でPCをいじっているときにBASICでよくこんな縞模様を書いて、パレットを変えてアニメーションさせたものである。
これを作るにあたっては以下のサイトを参考にさせていただいた。
http://jsdo.it/sapphire_al2o3/1vJc
https://wgld.org/d/webgl/w026.html
WebGLの初期化コードはほとんどそのまま上記のものを使わせていただいた。おかげでWebGLの初期化方法を学ぶことができた。
この画面は以下の仕様になっている。
- 320x240ピクセル。
- ピクセル単位に8色が指定できる。
- カラーパレットは32ビットカラーのうち8つの色が設定できる。
仕組みとしては、
- バックバッファとして、512x256ピクセルの2Dテクスチャを
gl.LUMINANCE
で作る。バックバッファが320x240でないのは、テクスチャは2のべき乗のサイズでないと作れないからである。表示する際にはテクスチャ座標を調節して、バックバッファのうち320x240の部分だけを表示するようにする。gl.LUMINANCE
にしているのは、1ピクセルに1バイトを割り当て、パレットインデックスとして使用するためである。 - カラーパレット用として、8x1ピクセルの2Dテクスチャを
gl.RGBA
で作る。 - 表示用のcanvasを作る。実画面サイズによって640x480もしくは320x240に切り替える。
- 画面一杯に表示する矩形ポリゴンを1枚作る。
- フラグメントシェーダーでバックバッファのテクスチャを読み出し、その値をインデックスとしてカラーパレット用のテクスチャを読み出し、ピクセルの色とする。
- 描画時はバックバッファにパレットインデックスを書き込む。それを
requestAnimationFrame
の周期で、毎回バックバッファとカラーパレットの情報をテクスチャに転送して、矩形ポリゴンを表示用のcanvasに描画する。
である。シェーダー部分のコードは以下のとおりである。
// パレットエミュレートシェーダー
// バーテックスシェーダー
var vshaderPSrc =
`precision mediump float;
attribute vec2 position;
attribute vec2 texture_coord;
varying vec2 vtexture_coord;
void main(void) {
gl_Position = vec4(position,0.0,1.0);
vtexture_coord = texture_coord;
}
`;
// フラグメントシェーダー
var fshaderPSrc =
`precision mediump float;
uniform sampler2D tex;
uniform sampler2D pallet_color;
varying vec2 vtexture_coord;
void main(void){
vec4 sampcolor = texture2D(tex, vtexture_coord);
vec4 color = texture2D(pallet_color,vec2(sampcolor.x * 32.0,0.5));
gl_FragColor = color;
}
`;
私のコードはほとんどコピペレベルであるけれども、それでもシェーダーコードを書くのは楽しいなと思う。
動作サンプル
ソースコード・リソース
/dev/graphics/devver/20160406/css/sfstyle.css
/dev/graphics/devver/20160406/index.html