0

GLSL 3.3 を使用して Phong 反射モデルを実装しようとしています。チュートリアルに従っていますが、チュートリアルの内容に合わせてコードを変更しましたが、まだ効果を作成できません。フォンの反射ではなく、原点から光源がある場所まで、奇妙なスポットライト効果があります。頂点シェーダーは次のとおりです。

#version 330
layout(location = 0) in vec3 position;
layout(location = 1) in vec3 normal;
out vec3 Color;
out vec3 NormalCamSpace;
out vec3 EyeDir;
out vec3 PositionWorldSpace;
out vec3 LightDirCamSpace;
uniform mat4 MVP;
uniform mat4 M;
uniform mat4 V;
uniform vec3 lightPos;

void main() {
    NormalCamSpace =(V*M *vec4(normal,0.0)).xyz;
    PositionWorldSpace = (M * vec4(position,1.0)).xyz;
    vec3 PositionCamSpace = (V*M*vec4(position, 1.0)).xyz;
    EyeDir = -PositionCamSpace;
    LightDirCamSpace = (V*vec4(lightPos, 1.0)).xyz + EyeDir;
    Color = vec3(0.0, 1.0, 1.0);
    gl_Position = MVP * vec4(position, 1.0 );
}

そして、これがフラグ シェーダです。

#version 330
in vec3 Color;
in vec3 NormalCamSpace;
in vec3 PositionWorldSpace;
in vec3 EyeDir;
in vec3 LightDirCamSpace;
uniform vec3 lightPos;
uniform float ambientIntensity;

out vec3 outColor;

void main() {
    vec3 n = normalize(NormalCamSpace);
    vec3 l = normalize (LightDirCamSpace);
    float cosTheta = clamp(dot(n, l),0,1);

    vec3 E = normalize(EyeDir);
    vec3 R = reflect(-l, n);
    float cosAlpha = clamp(dot(E, R),0,1);
    cosAlpha = pow(cosAlpha, 5);
    float attenIntensity = 1.0 + 0.01*distance(lightPos, PositionWorldSpace)*distance(lightPos, PositionWorldSpace);
    outColor = Color*cosTheta /attenIntensity+
    Color* vec3(0.3, 0.3, 0.3) * cosAlpha/attenIntensity+
    vec3(0.8, 0.8, 0.8) * ambientIntensity;
}

lightPos はワールド空間にあります。

これは、関連する場合のチュートリアルです。鏡面照明以外はすべて機能します。

4

2 に答える 2

1

あなたのシェーダーは大丈夫だと思います。欠けているのは、鏡面反射項を計算するときのチェックだけですが、dot(n, l)>0実際には問題ではありません。問題は、おそらく法線が間違っていることです。

シェーダーを使用すると、次のようになります。ディフューズ カラーを赤に、スペキュラー カラーをグリーンに設定しました。これにより、スペキュラー ハイライトが黄色になります。私にはかなり大丈夫に見えます。

ここに画像の説明を入力

LightDirCamSpace = (V*vec4(lightPos, 1.0)).xyz + EyeDir;また、それが正しいことに注意したいと思います。LightDirCamSpace = (V*vec4(lightPos, 1.0)).xyz - PositionCamSpace;しかし、それをasと書くと、より明確になると思います。

ちなみに、代わりにdistance(lightPos, PositionWorldSpace)*distance(lightPos, PositionWorldSpace)使用する必要があります

vec3 lightVec = lightPos - PositionWorldSpace;
float attenIntensity = 1.0 + 0.01 * dot(lightVec, lightVec);

また、ビュー空間での照明は問題ありません。ワールド空間で行う必要はありません。

于 2013-07-14T10:52:34.550 に答える
0

ビュー空間ではなく、法線ベクトルとライト方向ベクトルのワールド空間を使用する必要があります。3D 空間で 2 つのベクトルを比較すると考えてください。どこから見ても、法線と光の方向は変わりません。

編集:別の問題

    LightDirCamSpace = (V*vec4(lightPos, 1.0)).xyz + EyeDir;

ライトの方向は、ライトの位置から頂点の位置 (頂点からライトに向かうベクトル) を差し引いたものである必要があり、これもワールド空間です。する必要があります

    LightDirCamSpace = lightPos - PositionWorldSpace;

訂正:これを無視してください。ビュー空間またはワールド空間のいずれかで照明を計算できます。誤った情報で申し訳ありません。他の回答を確認してください。

于 2013-07-12T18:35:57.470 に答える