GLSL 頂点シェーダーで頂点を正しく表示するようになってから数日後、ライティングに取り掛かりました。openGL ライティング/法線についての私の理解は、想像力を駆使してもあまりよくないので、ご容赦ください。法線を正しく表示するには、法線にどのような変換を適用する必要があるかわかりません。ライトを設定するアプリケーション コードは次のとおりです。
final float diffuseIntensity = 0.9f;
final float ambientIntensity = 0.5f;
final float position[] = { 0f, 0f, 25000f, 0f};
gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, position, 0);
final float diffuse[] = { 0, diffuseIntensity, 0, 1f};
gl.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, diffuse, 0);
final float ambient[] = { ambientIntensity, ambientIntensity, ambientIntensity, 1f};
gl.glLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT, ambient, 0);
これまでのところかなり標準的なもの。アプリケーションの要件により、(やや奇妙な) 頂点シェーダーを次に示します。
void main()
{
// P is the camera matrix, model_X_matrices are the relative translation/rotation etc of the model currently being rendered.
vec4 pos = gl_ProjectionMatrix * P * modelTranslationMatrix * modelRotationMatrix * modelScaleMatrix * gl_Vertex;
gl_Position = pos;
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_FrontColor = gl_Color;
}
gl_Normal
を世界座標に変換する必要があることは私の理解です。私のシェーダーの場合、これは次のようになると思います。
vec4 normal = modelTranslationMatrix * modelRotationMatrix * modelScaleMatrix * vec4(gl_Normal);
次に、ライトの位置を取得する必要があります (ワールド空間のアプリケーション コードで既に宣言されています)。私はこれを次のように行うと思います:
vec3 light_position = gl_LightSource[0].position.xyz;
次に、法線とライトの位置のドット積を見つけて、ライトの拡散値を見つけます。
さらに、フラグメント シェーダーでは、色にこの拡散値を乗算するだけで、すべて機能するはずです。通常の座標を正しく変換する方法が本当にわかりません。私の仮定は正しいですか、それとも私は完全にボールから外れていますか?
編集:gl_NormalMatrix
法線行列 ( ) が行列の 3x3 の逆数である
ことを読んだ後gl_ModelView
、ワールド空間で法線を計算する正しい方法は、gl_Normal
に の逆数を掛けることだとmodelTranslationMatrix * modelRotationMatrix * modelScaleMatrix
思います。P
これに行列を掛ける必要がありますか、それとも通常の計算には関係ありませんか?