2

照明用に次の GLSL コードがあります。

uniform vec3 lightDir; // Parallel light
uniform float ambient;
uniform vec3 lightColour;

void main()
{
     gl_Position = ftransform();

     vec3 eyeNormal = normalize(gl_NormalMatrix * gl_Normal);
     float intensity = max(ambient, dot(eyeNormal, normalize(-lightDir));

     gl_FrontColor = gl_Color * vec4(lightColour, 1.0) * intensity;
}

ライト ベクトルはワールド空間で指定されます。を使用してカメラの向きと位置を設定しgluLookAtます。OpenGL はライト ベクトルがカメラ空間にあると想定するため、ライトは固定方向にとどまるのではなく、カメラと共に移動します。

を呼び出す前と後に、シェーダーをアクティブにしてライト ベクトルを設定してみましたgluLookAtが、同じ効果が得られます。光ベクトルを適切に変換するには、正確に何をしなければなりませんか?

4

5 に答える 5

3

オンラインの GLSL チュートリアルでよく見られる、一般的な問題があります。ユニフォームを介して照明値を渡しています。glLight固定関数のレンダリングのように呼び出しを使用して、から値を取得しないのはなぜですかgl_LightSource[n]。違いは、openGL がビュー スペース内のすべてを自動的に変換することです。

void main()
{
    // remember: directional lights are GL_POSITION with w = 0
    vec3 lightDir = vec3(gl_LightSource[0].position); 
    float ambient = gl_LightSource[0].ambient;
    vec3 lightColour = vec3(gl_LightSource[0].diffuse);


    gl_Position = ftransform();

    vec3 eyeNormal = normalize(gl_NormalMatrix * gl_Normal);
    float intensity = max(ambient, dot(eyeNormal, normalize(-lightDir));

    gl_FrontColor = gl_Color * vec4(lightColour, 1.0) * intensity;
}

このテーマに関する常に優れたリソース: http://www.lighthouse3d.com/opengl/glsl/index.php?lights

そして常に役に立つのが GLSL チート チートです: http://www.cs.brown.edu/courses/cs123/resources/glslQuickRef.pdf

于 2010-03-05T16:31:18.313 に答える
2

どのスペースで照明を行うかを決める必要があります。「標準」のOpenGLに従う場合は、ビュースペースです。次に、シェーダーに渡す前に、ビューマトリックスの回転部分によって光ベクトルを回転させる必要があります(最も単純なソリューション)。

他のスペース(接線、オブジェクト、ワールド、さらにはスクリーンスペース-異なるシェーディングの場合)にライトを適用することもできますが、それは別のトピックです。また、高度な使用のためには、OpenGLを忘れて、独自のマトリックスとシェーダー(デフォルトのライティング/トランスフォーメーションのものはありません)を使用してすべてを行う必要があることに注意してください。

于 2010-03-01T12:34:25.570 に答える
-1

シェーダーの問題は、目の空間の法線とワールド空間のライトがあることです。
よくわかりませんが、光ベクトルを法線行列で変換すると問題が解決するはずです。

または、より効率的にするために、ライト vec をオブジェクト空間 (プログラム コード内) で変換できます。その後、各法線の変換は必要ありません。

于 2009-12-11T09:01:48.437 に答える
-1

問題の一部は次の場所にあると思われます: float intensity = max(ambient, dot(eyeNormal, normalize(-lightDir));.

アンビエント項は、ランバート ベースのシェーダーでは、内積によってスケーリングされます。ここでは、内積よりも大きくなる可能性が高いため、周囲の項が頻繁に主張されます。gl_NormalMatrix の使用も問題です。これは、上でコメントしたように、lightDir がオブジェクト空間にあり、法線ベクトルがオブジェクト空間から目の座標に変換されることを意味するためです。

試す:

vec3 n=normalize(normal);
float ndotl=max(0.0, dot(n, normalize(lightDir)));

vec3 diffuse=ambient * ndotl; 
于 2011-08-11T10:24:49.290 に答える
-2

シェーダーのコードは、ライトの位置によって変化しない指向性ライトを計算するため、spotLightまたはpointLight関数を使用する必要があります。

これらの光源のシェーダーを見つけてください。見つからない場合は教えてください。お送りします。

于 2009-12-17T16:00:52.140 に答える