概要
GLSLのuintは、bit列を2進数表示した数値で表されます。これを利用して、16進数で指定した値でお絵描きをします。
なお、GLSLのビット演算はES 3.0
以降で利用できます。
https://nemutas.github.io/webgl-sketch/20240208/
進数計算
10進数,16進数,2進数は、それぞれ下表で対応付けされます。
一般に、n進数を10進数に直す場合、数をnのべき乗の和に直すことによって表現されます。
例えば、2進数から10進数の場合、
1101_2 = 1 * 2^3 + 1 * 2^2 + 0 * 2^1 + 1 * 2^0 = 8 + 4 + 0 + 1 = 13
となり、16進数では対応表により、D
となります。
👾
space invader👾を描画する場合。
例えば、下列の4bitでは、
■☐☐☐
であるので、
1000_2 = 1 * 2^3 + 0 * 2^2 + 0 * 2^1 + 0 * 2^0 = 8 + 0 + 0 + 0 = 8_{10} = 8_{16}
となります。
次の4bitは、
■■☐■
なので、
1101_2 = 1 * 2^3 + 1 * 2^2 + 0 * 2^1 + 1 * 2^0 = 8 + 4 + 0 + 1 = 13_{10} = D_{16}
となります。
この調子で計算すると、下列は16進数で、
0x0d8u
となり、全体のbitmapは次のようになります。
uint[8] rows = uint[](
0x0d8u,
0x505u,
0x5fdu,
0x7ffu,
0x376u,
0x1fcu,
0x088u,
0x104u
);
表示
vec2 iuv = floor(uv * 32.0);
uint[8] rows = uint[](
...
);
if (int(iuv.y) < rows.length()) {
uint b = rows[int(iuv.y)];
b = (b << uint(iuv.x)) >> 31;
float c = float(b);
}
uintは32bitの2進数bit列なので、uvを32倍してfloor()
をとることで、0~31の整数に変換します。
iuv.y
で対象のbit列b
を取得して、iuv.x
分を左シフトします。
その後に、31bit分右シフトすると対象のセルに対するbit値を取得できます。
例えば、0x0d8u
の場合、bit列は、
0000 0000 0000 0000 0000 0000 1101 1000
なので、8bit目の1
を取得する場合、
b = 0000 0000 0000 0000 0000 0000 1101 1000
b << 23 // 31 - 8
b = 1101 1000 0000 0000 0000 0000 0000 0000
b >> 31
b = 0000 0000 0000 0000 0000 0000 0000 0001
となります。
bitシフトは、左シフトした場合は、あふれた分が下位bitに表示されます。
b = 1000 0000 0000 0000 0000 0000 0000 0001
b << 1
b = 0000 0000 0000 0000 0000 0000 0000 0011
右シフトした場合は、あふれた分が削除され上位bitは0
で埋められます。
b = 1000 0000 0000 0000 0000 0000 0000 0001
b >> 1
b = 0100 0000 0000 0000 0000 0000 0000 0000
作品
画面右下のsource
からコードを参照できます。
作品はすべてローカル環境で作成していますが、twigl
でも再現できます。(おそらく)
https://twigl.app/
twiglを使用する場合は、Regulationをclassic(300es)
にします。