GLSLの型について
C言語に似ていますが、見慣れないものもあります。
GLSL | C言語 |
---|---|
void | void |
bool | bool |
int | int |
float | float |
vec2〜vec4 | ベクトル(float[2]〜float[4]) |
mat2〜mat4 | 行列(float[2][2]〜float[4][4]) |
vec4は頂点の座標や色を表すのに使います。mat4は後述する座標変換で使います。
サイコロを描く
立方体を描くには正方形が6つ必要ですが、OpenGLでは三角形しか描けないので、12個の三角形を使います。
レンダリングした結果はこうなりました。
サイコロを動かしてみる
頂点シェーダの赤い部分を追加しました。前回追加したaPositionはattributeなので頂点ごとの値が入りますが、今回はuniformなので全ての頂点で同じ値になります。
attribute vec3 aPosition;
attribute vec3 aColor;
uniform mat4 uView;
varying lowp vec3 vColor;
void main(void) {
gl_Position = uView * vec4(aPosition, 1.0);
vColor = aColor;
}
GLSLでは、行列に対する乗算が定義されているので、乗算演算子が使えます。行列とベクトルの積は、どっちが行でどっちが列かややこしいですが、このような図を書くとわかりやすいと思います。
JavaScriptのコードを追加します。
scine.uniform = {
view: gl.getUniformLocation(scine.program, "uView"),
};
const view = new Float32Array([
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
]);
gl.uniformMatrix4fv(scine.uniform.view, false, view);
uViewは変換行列で、この値によって拡大・縮小・回転・平行移動などの変換を行います。 uViewには単位行列を設定したので、(x, y, z)は同じ値になります。
実行した結果は当然同じです。
拡大・縮小
変換行列の対角成分を1以外に変更すると、拡大・縮小変換ができます。
const view = new Float32Array([
1.5, 0, 0, 0,
0, 0.5, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
]);
実行結果はこのように、縦に潰れて横に伸ばされた形になります。
平行移動
4列目の成分を0以外に変更すると、平行移動できます。OpenGLに行列を渡すときは行優先なので、行と列が入れ替わっているように見えるので注意。
const view = new Float32Array([
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0.4, 0.5, 0, 1,
]);
回転
3軸の回転の変換行列はややこしいですが、以下の数式を頑張ってJavaScriptのコードに置き換えます。