3

現在、古き良きフォンシェーディングを実装しています。全体的にはかなり正しいように見えますが、法線の出現には説明できないパターンがあります。

よく見なくても、スタンフォードバニーはかなり正しいように見えます。 ここに画像の説明を入力

しかし、たとえば耳には奇妙なパターンがあります。 ここに画像の説明を入力

この写真では、法線を視覚化し、彩度を上げて問題をより見やすくしています。 ここに画像の説明を入力

これは私の頂点シェーダーです:

#version 330 core

layout (location = 0) in vec4 vPosition;
layout (location = 1) in vec3 vNormal;

out vec4 fWorldPosition;
smooth out vec3 fWorldNormalSmooth;

...    

void main() {
    fWorldNormalSmooth = normalize(NormalMatrix*vNormal);
    fWorldPosition = WorldMatrix*vPosition;
    gl_Position = ProjectionMatrix*ViewMatrix*WorldMatrix*vPosition;
}

これは私のフラグメントシェーダーです:

#version 330 core

smooth in vec3 fWorldNormalSmooth;
in vec4 fWorldPosition;

out vec4 color;

...    

vec4 shadePointLight(Material material, PointLight pointLight, vec3 worldPosition, vec3 worldNormal) {
    vec3 cameraPosition = wdiv(inverse(ViewMatrix)*vec4(0, 0, 0, 1));
    vec3 cameraDirection = normalize(cameraPosition - worldPosition);
    vec3 lightDirection = normalize(pointLight.position - worldPosition);
    vec3 reflectionDirection = reflect(-lightDirection, worldNormal);

    vec4 i_amb  = material.ambientReflection*pointLight.ambientColor;
    vec4 i_diff = max(0, dot(worldNormal, lightDirection))*material.diffuseReflection*pointLight.diffuseColor;
    vec4 i_spec = pow(max(0, dot(reflectionDirection, cameraDirection)), material.shininess)*material.specularReflection*pointLight.specularColor;

    float distance = length(pointLight.position - worldPosition);
    float d  = 1.0 / (pointLight.falloff.constant + pointLight.falloff.linear*distance + pointLight.falloff.quadratic*distance*distance);

    return i_amb + d*(i_diff + i_spec);
}

void main() {
    ...

    color = shadePointLight(material, pointLight, wdiv(fWorldPosition), normalize(fWorldNormalSmooth));
}

誰かがこの動作を説明できますか?

4

1 に答える 1

5

頂点とフラグメント ステージ間で発生するように、同じ長さの 2 つのベクトル間で線形補間を行う場合、結果のベクトルの長さはその間で短くなります。2 つの法線間を補間する数学的に正しい方法は、球面線形補間(SLERP) を実行することですが、角度の小さな変化については、補間された法線ベクトルをフラグメントシェーダーで単純に正規化することで回避できます (これはsin(x) ≈ x、小x)。編集:適切な SLERP 補間による大きな角度の場合は、必要です。

于 2016-06-28T08:58:30.900 に答える