少しずつ試してみる

ousttrue2008-02-16

最小限のシェーダ

vertex shader
void main(){
  gl_Position = ftransform();
  gl_FrontColor = gl_Color;
}

頂点シェーダではgl_Position(スクリーン座標に変換された頂点座標。vec4)を出力するのは必須。
gl_FrontColorはフラグメントシェーダのgl_Colorに渡される(表側の場合)。
gl_ColorはglVertexのときglColorで指定していた色。
transform()は、

gl_ModelViewProjectionMatrix * gl_vertex

とするのと同じ

fragment shader
void main(){
  gl_FragColor = gl_Color;
}

フラグメントシェーダでgl_FragColorとして出力したものが最終的な色になる。
これは入力の色をそのまま出力するだけ。
gl_Colorは頂点シェーダでgl_FrontColorとして出力した色。

Lambertシェーダ

vertex shader
void main{
  vec3 position = vec3(gl_ModelViewMatrix * gl_Vertex);
  vec3 normal = normalize(gl_NormalMatrix * gl_Normal);
  vec3 light = normalize(gl_LightSource[0].position.xyz - position);
  float diffuse = dot(light, normal);
  gl_FrontColor = gl_LightSource[0].diffuse * diffuse * gl_Color;

  gl_Position = ftransform();
}

頂点から光源へのベクトルと法線ベクトルの内積から反射率を求めて頂点色に乗算する。
gl_NormalMatrixがいちばんの謎だったが赤本によるとモデルビュー行列の左上3x3の逆転置行列と書いてある。
3x3にするのは法線に移動は関係ないから回転だけにするためだと察しがついたが
回転行列は転置したら逆行列と同じなるから意味無いんじゃないかと思った。
逆転置行列で調べてみるとゲーム方面で法線の回転に使われる様子。
C++DirectX初心者質問スレ Part4【C++】で

・回転のみ(直交行列)なら、逆転置は用意せず、正規化もしない。
・回転と一様スケーリングのみ(直交行列の定数倍)なら、逆転置は用意せず、正規化のみ行う。
・非一様スケーリングやせん断変形を含む一般の行列なら、逆転置を用意して、さらに正規化も行う。

という説明を発見。たぶん回転だけを取り出すってこと。腑に落ちた。
DirectXOpenGLを同時に進めていくと理解は深まりそうだなぁ。
急がば回れかも。