1

GLSL を使用して OpenGL でポイント ライトを実装しようとしています。必要なすべてのデータをシェーダーに送信します。簡単にするために、ここでは拡散光のみを使用します。

私の例は、単一の光源で照らしたい巨大な三角形を示しています。光源は小さな青い三角形として表示されます。

拡散光の場合、光と表面の間の角度を知る必要があります。したがって、法線と光の方向を計算します。内積は、-1 から 1 の間の数値を与えますが、0 から 1 の間のすべてが照らされます。

ただし、この例ではこの角度が正しく計算されていないため、ここで立ち往生しています。シェーダーをデバッグするのは難しいので、サーフェスの色としていくつかの出力を使用しました。三角形の色として法線を使用し、ライトがどこにあっても表面は常に緑色でした。つまり、法線は y 軸を上に向けているため、正しく計算されます。つまり、ライトの方向が間違っているに違いありません。しかし、私はそれが間違っている理由を見つけることができません。ライトの位置と頂点の位置は、ワールド空間で頂点シェーダーに渡されます。頂点シェーダーは、それらを目の空間に変換し、ライトの方向を計算して、これをフラグメント シェーダーに渡します。

頂点シェーダー:

vec4 pos = modelview_matrix * <input vertex>;
vec4 lightPos = modelview_matrix * <light position>;

vec3 lightDir = normalize(lightPos.xyz - pos.xyz);

フラグメント シェーダー:

float NdotL = max(dot(normalize(<correct normal>), normalize(lightDir)), 0.0);
gl_FragColor = vec4(1.0, NdotL, 0.0, 1.0);

補間が本当に奇妙であることを明確に示すこの例の写真をいくつか追加しました。貼り付けたコードが正しいかどうか、またはコードの詳細を知る必要があるかどうかを知りたいです。さらに、この補間動作は正常ですか、それとも私のコードのバグですか?

http://img41.imageshack.us/img41/3566/interpolation.png http://img189.imageshack.us/img189/3566/interpolation.png

特に最初の写真は、光の中心点が光の真下ではなく、三角形の中心にわずかに移動していることを示しています。

「pos」をフラグメント シェーダーに渡し (つまり、補間されます)、フラグメント シェーダーで「lightDir」を計算すると、すべて正常に動作します。

4

1 に答える 1

3

頂点シェーダーで lightDir を正規化すると、方程式から長さが取り除かれ、補間の「速度」に影響するため、ベクトルを補間するときに得られる結果に影響すると思います。

(視覚的な)説明が必要な場合は、紙に 2D で描いてみてください。最初に線 (三角形) と点 (光源) を描きます。線の両端に 2 つの線 (lightDir) を光源に追加し、それらの lightDir 線を縮小 (正規化) して、同じ長さになり、両方が光源で交わるようにします。正規化された lightDir 線の両端を接続すると、平行でない線が得られます (光源が最初の線のちょうど真ん中にない場合)。ここで、線の 1 つの真ん中を正確に通る線を引くと、もう一方の線の真ん中を通りませんが、左または右に少しぶつかることがわかります。

于 2009-06-14T18:34:18.323 に答える