「リアルタイムグラフィックスの数学」勉強ログ - 第2章疑似乱数

はじめに
「リアルタイムグラフィックスの数学」の第 2 章の疑似乱数についての勉強ログです。
レガシー乱数
GLSL ES 1.0 ではビット演算が使えないため、ハッシュ関数ではなくサイン関数を使用した乱数生成が行われていました。The Book of Shaders ではサイン関数を使用した乱数生成の方法が紹介されています。

サイン関数自体には乱数性はないですが、サイン関数の値に大きい値をかけて桁を上げ、fract
で小数部分を取り出すことで乱数のように見えることができます。
レガシー乱数の 1 変数と 2 変数のコードは次のようになります。
// 1変数のレガシー乱数
float fractSin11(float x) {
return fract(1000.0 * sin(x));
}
// 2変数のレガシー乱数
float fractSin21(vec2 xy) {
return fract(sin(dot(xy, vec2(12.9898, 78.233))) * 43758.5453123);
}
結果は下図のようになります。
2 変数のレガシー乱数で使用しているマジックナンバーは、GLSL で伝統的によく使用されている値になります。
符号なし整数の可視化
サンプルコード 2.2 のコードを説明します。このサンプルでは 32 ビットの 2 進数を白黒で可視化しています。ここで 「特定のビットを取り出し」0 か 1 かを判定しているコードは次のようになってます。
b = (b << uint(pos.x)) >> 31;
分かりやすく考えるために、10 進数で 9 の場合を例としてみましょう。
10 進数で 9 を 32 ビットで表現すると次のようになります。
b = 0000 0000 0000 0000 0000 0000 0000 1001
4 ビット目の 1 を取得する場合を考えてみましょう。まずなので 27 ビット分を左シフトします。
b = 0000 0000 0000 0000 0000 0000 0000 1001
b << 27 // 31 - 4
b = 1001 0000 0000 0000 0000 0000 0000 0000
これを 31 ビット分を右シフトすることで 4 ビット目の 1 が取得できます。
b = 1001 0000 0000 0000 0000 0000 0000 0000
b >> 31
b = 0000 0000 0000 0000 0000 0000 0000 0001
サンプルコードではフラグメント範囲の x 座標を 32 に拡大しているので、uint(pos.x)
を取ることで 32 ビットの 2 進数を白黒で可視化することができています。
浮動小数点数のビット列
符号なし整数(uint, unsigned integer)はビット列をそのまま 2 進数変換することで得られます。ですが、負の数や小数部分を含む浮動小数点の場合は、ビット列から数値への変換は自明ではないです。32 ビット浮動小数点は IEEE754 と呼ばれる標準規格があり、highp 精度ではこれに準拠して変換されます。
IEEE754 では、32 ビットの情報をの 2 進数で表したとき、符号部、指数部、仮数部のように分けて、としたときに次のように計算します。
書籍の例として 11.5625 の浮動小数点を符号なし整数に変換してみましょう。
整数部分の 11 を 2 進数に変換すると 1011 になります。小数部分の 0.5625 を 2 進数に変換すると 0.1001 になります。これを計算式に合うように整数部分に 1 が来るようにかけて右にずらします。
このが仮数部になります。符号部に関しては、正の数なのでは になります。
最後に指数部に関しては、なのでになり、を 2 進数で表すとになるのでこの値が指数部になります。
結果として、11.5625 の符号なし整数は下記になります。
0 10000010 0111001...0
GLSL ではビット列としての浮動小数点を符号なし整数に変換する関数として、floatBitsToUint
関数が組み込まれています。
ハッシュ関数
ハッシュ関数による乱数生成法については、難しかったので機会があれば調べる予定。
書籍で紹介されていた、Jarzynski-Olano の約 30 ものハッシュ関数についてのコストパフォマンスについての論文Hash Functions for GPU Rendering - Jarzynski-Olano
Shadertoy での実装についてはこちら
後で詳しく調べるものリスト
-
ハッシュ関数のアルゴリズム
ハッシュ関数ハッシュ関数 あるいは要約関数とは、任意のデータから、別の(多くの場合は短い固定長の)値を得るための操作、または、その様な値を得るための関数のこと。ハッシュ関数から得られた値のことを要約値やハッシュ値または単にハッシュという。
Wikipedia -
Xorshift による乱数生成法
XorshiftXorshiftは疑似乱数列生成法の1つである。George Marsaglia が2003年に提案した。演算が排他的論理和とビットシフトのみであるため高速である などの特徴がある。
Wikipedia -
bit 演算お絵描き
参考
【GLSL】bit 演算お絵描き