0

Orange book のセクション 16.2 には、拡散照明の実装が次のようにリストされています。

void main()
{
  vec3 N = normalize(gl_NormalMatrix * gl_Normal);
  vec4 V = gl_ModelViewMatrix * gl_vertex;
  vec3 L = normalize(lightPos - V.xyz);
  gl_FrontColor = gl_Color * vec4(max(0.0, dot(N, L));
}

ただし、これを実行すると、カメラを動かすと照明が変わります。一方、私が変わるときは

  vec3 N = normalize(gl_NormalMatrix * gl_Normal);

to vec3 N = normalize(gl_Normal);

固定パイプラインのように機能する拡散照明が得られます。

この gl_NormalMatrix とは何ですか?それを削除するとどうなりますか?...これはオレンジブックのバグですか?それとも OpenGl コードを不適切に設定していますか?

[完全を期すために、フラグメントシェーダーは色をコピーするだけです]

4

1 に答える 1

6

わかりました、半年以上経った後、あなたの質問に答えることに問題がないことを願っていますか? :)

したがって、ここで議論すべきことが 2 つあります。


a) シェーダーはどのように見えるべきか

モデルビュー マトリックスによって法線を変換する必要があります。これは当然のことです。そうしないとどうなるかを考えてみてください。モデルビュー マトリックスには、ある種の回転が含まれている可能性があります。立方体は回転しますが、法線は依然として古い方向を指しています! これは明らかに間違っています。

したがって、頂点をモデル ビュー マトリックスで変換する場合は、法線も変換する必要があります。あなたの法線はvec3ではなくvec4、変換には関心がない (法線には方向のみが含まれる) ため、法線に を掛けるだけmat3(gl_ModelViewMatrix)で、左上の 3-3 サブマトリックスになります。

次に: これはほぼ正しいですが、まだ少し間違っています - その理由はLighthouse 3D で詳しく説明されています - 読んでください. 簡単に言えば、 の代わりにmat3(gl_ModelViewMatrix)、その逆転置を掛ける必要があります。

OpenGL 2 は非常に便利で、これを として事前に計算しますgl_NormalMatrix。したがって、正しいコードは次のとおりです。

vec3 N = normalize(gl_NormalMatrix * gl_Normal);

b) しかし、固定パイプラインとは異なります。なぜですか?

最初に思いつくのは「固定パイプラインの使い方がおかしい」ということです。

私は FP (シェーダー万歳!) にはそれほど熱心ではありませんが、私が覚えている限りでは、 を介してライトを指定するとglLightParameterfv(GL_LIGHT_POSITION, something)、これはモデルビュー マトリックスの影響を受けました。(少なくとも私にとっては :)) 間違った座標系でライトの位置 (またはディレクショナル ライトのライトの方向) を指定する間違いを犯すのは簡単でした。

最近は GL3 とシェーダーを使用しているため、当時の動作を正しく覚えているかどうかはわかりませんが、試してみましょう... モデルビュー マトリックスの状態はどうでしたか? 光がオブジェクトと一緒に回転するように、目の空間ではなくオブジェクト空間で指向性ライトの方向を指定した可能性があると思います。ここで関連する場合は IDK ですが、FF を使用する場合は注意してください。これは、私がまだ GL 1.1 を使用していたときによくやっていた間違いです。

モデルビューの状態に応じて、以下でライトを指定できます。

  • アイ(カメラ)空間、
  • 世界空間、
  • オブジェクト空間。

どちらであるかを確認してください。

うーん..それでトピックがより明確になることを願っています。結論は次のとおりです。

  1. 頂点シェーダーで頂点とともに法線を常に変換します。
  2. 期待したものと異なるように見える場合は、ライトの位置を指定する方法を考えてください。(おそらく、シェーダーでもライトの位置ベクトルを乗算したいですか? ライトの位置座標系に関する注意事項は引き続き保持されます)
于 2010-11-27T13:58:50.697 に答える