プリミティブの描画の前に、この環境での文字表示を作るのを忘れていたので、作ることにした。 VRAMプレーンで行ったことを応用すればできるはずだ。
文字表示は以下の仕様となっている。
- 文字は8x8ピクセルのサイズ、40桁×30行。
- キャラクタVRAMおよびアトリビュートVRAMをそれぞれ1枚ずつテクスチャで持つ(64x32ピクセルのgl.LUMINANCEとして)。
- アトリビュートVRAMの仕様はMZ-700とほぼ同じ。
- キャラクタVRAM/アトリビュートVRAMに文字コード/アトリビュートコードを書きこむと文字が表示される。
文字データはMZ-700のエミュレータ(MZ700WIN)に入っていたフォントデータ(mz700fon.txt)を使わせていただいた。
シェーダーコードはちょっと複雑になってきた。
// パレットエミュレートシェーダー
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 textureB;
uniform sampler2D textureG;
uniform sampler2D textureR;
uniform sampler2D pallet_color;
uniform sampler2D textureFont;
uniform sampler2D textureCharCode;
uniform sampler2D textureCharAttr;
uniform float time;
varying vec2 vtexture_coord;
// グラフィック表示
vec4 graphicPlane(void)
{
//テクスチャ座標よりビット位置を求め、そのビットが立った2進数値を得る。
float t = exp2(floor(mod(vtexture_coord.x * 512.0,8.0)));
// RGB各プレーンの現在座標のバイトデータを読み込む
vec4 rt = texture2D(textureR, vtexture_coord);
vec4 gt = texture2D(textureG, vtexture_coord);
vec4 bt = texture2D(textureB, vtexture_coord);
// バイトデータの中でビットが立っているかどうかを調べる
// Rプレーン
float r = floor(mod(min(rt.x * 256.0,255.0) / t,2.0)) * 4.0;
// Gプレーン
float g = floor(mod(min(gt.x * 256.0,255.0) / t,2.0)) * 2.0;
// Bプレーン
float b = floor(mod(min(bt.x * 256.0,255.0) / t,2.0));
// 各色の値を足して正規化を行い、パレットインデックスから実際の色を得る
vec4 p = texture2D(pallet_color,vec2((r + g + b) / 8.0 ,0.5));
float i = min(p.x * 256.0,255.0);
float ar = floor(mod(i * 0.5,2.0)); // bit3
float ag = floor(mod(i * 0.25,2.0)); // bit2
float ab = floor(mod(i,2.0)); // bit1
return vec4(ar,ag,ab,1.0);
}
// 文字表示
vec4 textPlane(void){
// キャラクタコードを読み出し
vec4 cct = texture2D(textureCharCode, vtexture_coord);
float cc = min(cct.x * 256.0,255.0);// キャラクターコード
// アトリビュートを読み出し
vec4 attrt = texture2D(textureCharAttr, vtexture_coord);
// 表示対象の文字のビット位置を求める
float x = exp2(floor(mod(vtexture_coord.x * 512.0,8.0)));
// 表示対象の文字のY位置を求める
float y = floor(mod(vtexture_coord.y * 256.0,8.0));
// アトリビュートの評価
float i = min(attrt.x * 256.0,255.0);// アトリビュートデータ
// キャラクタセット(0.0 .. セット0, 1.0 .. セット1 )
float att = floor(mod(i / 128.0,2.0)) * 8.0;// bit 7
// 文字色
float ccg = floor(mod(i / 64.0,2.0));// bit 6
float ccr = floor(mod(i / 32.0,2.0));// bit 5
float ccb = floor(mod(i / 16.0,2.0));// bit 4
// 背景色
float bgg = floor(mod(i / 4.0,2.0));// bit 2
float bgr = floor(mod(i / 2.0,2.0));// bit 1
float bgb = floor(mod(i ,2.0));// bit 0
// フォント読み出し位置
vec2 fontpos = vec2(cc / 256.0,(y + att) / 16.0);
// フォントデータの読み出し
vec4 pixByte = texture2D(textureFont,fontpos);
// 指定位置のビットが立っているかチェック
float pixBit = floor(mod(min(pixByte.x * 256.0,255.0) / x,2.0));
if(pixBit == 1.0){
// ビットが立っているときは、文字色を設定
return vec4(ccr,ccg,ccb,1.0);
}
// ビットが立っていないときは背景色を設定
return vec4(bgr,bgb,bgg,1.0);
}
void main(void){
vec4 textColor = textPlane();
if((textColor.r + textColor.g + textColor.b) > 0.0){
gl_FragColor = textColor;
} else {
vec4 color = graphicPlane();
gl_FragColor = color;
}
}
`;
そういうことで懐かしのキャラクターがWebGLで表示できた。。
文字コードを見たらMZ-700が家に届いたときの興奮が蘇ってきた。急いでテレビにつないで、ベーマガのゲームを慣れないキーボードと格闘しながら入力したのを思い出したよ。最初は打ち込みミスでバグってちゃんと動かなかったんだよね。ゲーム向きなキャラクタも含まれていて、投稿作品によく使われていたな。
MZ-700の文字コードはASCIIやJIS8ではないんだよね。ディスプレイコードとかいうらしい。JSから打ち込んだ文字を表示させるには変換が必要だ。それはまあなんとかなるかな。
動作サンプル
ソースコード・リソース
/dev/graphics/devver/20160410/css/sfstyle.css
/dev/graphics/devver/20160410/index.html