のぐそんブログ

暗いおじさんがシコシコ書くブログです。

WebGLでライトを実装する為に最低限理解しておく必要基礎知識

今回はWebGLでライトを実装する為に最低限理解しておく必要があることについてまとめました。

法線

法線とは向きを表すベクトルです。法線ベクトルと呼ぶ場合のあります。

法線の扱い方

法線は頂点属性としてVBOとしてシェーダーに渡します。 その為GLSL側では、座標データや、頂点色と同じでattribute変数として受け取ります。 ベクトルなのでX,Y,Zの値を設定します。ストライドは3です。

<script id="vs" type="x-shader/x-vertex">

//法線データはnormalを表記することが多い
attribute vec3 normal;
・・・

法線ベクトルとライトベクトル

ライトベクトルとは、光がどうのような向きで頂点に当たるかを表します。 光は、反射の向きで強さが変わります。

光の影響力

こちらでは平行光源で考えます。

また、法線ベクトルもライトベクトルも正規化して使用します。 なぜ正規化するかというと、平行光源での陰影の表示には法線とライトの角度重要になる為、 距離を均一に扱う必要があるからです。

GLSLでライトベクトルを正規化
normalize(vec3(1.0, 1.0, 1.0));
jsで法線ベクトルを正規化
V = [x,y,z];
Vの大きさ = Math.sqrt(x * x + y * y + z * z); //sqrtは平方根
Vの単位ベクトル = [x / 大きさ, y / 大きさ, z / 大きさ];

光の影響は、法線ベクトルとライトベクトルの内積で求めることができます。

ベクトルの内積

ベクトルの内積とは言葉にすると、それぞれのベクトルの要素を順番に掛け合わせて、全部足したものです。

ベクトルの内積の戻り値は、ベクトルではなく数値となります。 正規化したベクトル同士の内積はベクトルの向きのシンクロ率と考えることができます。

まず内積の計算方法です。 LとNの2つのベクトルがあったとします。

//正規化されたベクトルaとb
L = [x1,y1,z1];
N = [x2,y2,z2];

//内積は「L・N」のようにドットつなぎで表記します
L・N === (x1 * x2) + (y1 * y2) + (z1 * z2);

GLSLではdotというベクトルの内積を計算できる関数が用意されています。

a・b = dot(a,b);

内積の計算例

実際にライトベクトルと法線の内積を求めてみたいと思います。 それぞれの値は正規化して使用します。

ここで注意が必要なのが、現実世界の光源と物の関係と、3Dプログラミングの世界を一緒に考えないことです。

下記の例では、平行光源のベクトルと、法線が同じ向きのほうが値が大きくなります。 現実世界のイメージですと、向きが逆のほうが光の影響が大きくなるようなイメージですが、 3Dプログラミングでは、向きが同じほど影響が大きくなると考えるのが一般的なようです。

まとめ

WebGLでライトを実装する為には、法線とライトベクトルの関係を理解する必要があります。 現実世界のライト(光源)をイメージしてしまうのが、難しくしている1つの要因かもしれません。