4

私は、法線マッピングに関する多くのオンライン チュートリアルに従い、ある程度機能するようになりました...

ポリゴンがビューベクトルに対して垂直でない限り、正しく機能させることができないようです。

私が言いたいことを説明するには写真だけでは不十分なので、これを説明するためにビデオを作成しました。

http://www.youtube.com/watch?v=9D4o_zy-61s

シェーダーを投稿しました:

バーテックス:

#version 400
layout (location = 0) in vec3 attribPosition;
layout (location = 1) in vec3 attribNormal;
layout (location = 2) in vec2 attribTexCoord;
layout (location = 3) in vec3 attribTangent;
layout (location = 3) in vec3 attribBinormal;

uniform mat4 mvp;
uniform mat4 mvm;
uniform mat3 nm;
uniform vec3 lightPos_World;

out vec2 vUvs;
out vec3 lightPos_Eye;
out vec3 vertexPos_Eye;
out vec3 normalDir_Eye;
out vec3 normalDir_World;
out mat3 tbnMatrix;

void main()
{
    vUvs = attribTexCoord;
    normalDir_World = attribNormal;
    normalDir_Eye = (nm * attribNormal);
    vec3 t = nm * attribTangent;
    vec3 n = nm * attribNormal;
    vec3 b = nm * cross(n,t);

    mat3 tbnMatrix = mat3(t.x, b.x, n.x,
                          t.y, b.y, n.y,
                          t.z, b.z, n.z);

    vertexPos_Eye = (mvm * vec4(attribPosition,1.0)).xyz;
    lightPos_Eye = (mvm * vec4(lightPos_World,1.0)).xyz;

    gl_Position = mvp * vec4(attribPosition,1.0);
}

断片:

#version 400
layout( location = 0 ) out vec4 frag_main;
struct PointLight{
    vec3 position;
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
    float shininess;
    float intensity;
};

uniform PointLight light[2];
uniform sampler2D colorTexture;
uniform sampler2D normalTexture;
uniform mat4 mvm;
//  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//  FLAGS - all flags start false;
//  [0][0] = colour map
//  [0][1] = normal map
//  [0][2] = unused
//  [0][3] = show normal map in colour channel
//  [1][0] = use tangent space
//  [1][1] = unused
//  [1][2] = unused
//  [1][3] = unused
//  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
uniform bvec4 flags[2];

in vec3 vertexPos_Eye;
in vec3 normalDir_World;
in vec3 normalDir_Eye;
in vec2 vUvs;
in mat3 tbnMatrix;


void main(){

    uint numLights=2;

    vec3 colorFragment;
    if(flags[0][0]){
        colorFragment = texture(colorTexture,vUvs).xyz; 
    }else{
        colorFragment = vec3(0.5);  
    }

    vec3 normalMapNormal = (texture(normalTexture,vUvs).rgb * 2) - 1;
    vec3 normalDir;
    if(flags[0][1]){
        normalDir = normalize(normalDir_Eye);
    }else{
        normalDir =  normalize(normalMapNormal.rgb);
    }

    vec4 outColor = vec4(1);
    outColor.xyz = vec3(0);

    float duller = 1/numLights;
    for(int i = 0;i< numLights;i++){
        vec3 lightPos_Eye = (mvm * vec4(light[i].position,1.0)).xyz;
        vec3 lightDir_Eye = normalize(lightPos_Eye - vertexPos_Eye);
        vec3 lightDir_Tangent = lightDir_Eye * tbnMatrix;

        vec3 vertDir_Eye = normalize(-vertexPos_Eye);
        vec3 vertDir_Tangent = vertDir_Eye * tbnMatrix;

        vec3 halfDir_Eye = normalize(vertDir_Eye + lightDir_Eye);
        vec3 halfDir_Tangent = halfDir_Eye * tbnMatrix;

        vec3 Ia = colorFragment.xyz * light[i].ambient;
        vec3 Id;
        vec3 Is;

        // tangent space
        Id = (colorFragment.xyz * light[i].diffuse ) * max(dot(lightDir_Tangent, normalDir), 0);
        Is = light[i].specular * pow(max(dot(halfDir_Eye, normalDir), 0), light[i].shininess*2);
        // eye space
        //Id = (colorFragment.xyz * light[i].diffuse ) * max(dot(lightDir_Eye, normalDir), 0);
        //Is = light[i].specular * pow(max(dot(halfDir_Eye, normalDir), 0), light[i].shininess*2);

        outColor.xyz += (Ia + Id + Is);

    }

    if(flags[0][3]){
        outColor.xyz = normalDir;
    }
    frag_main = (outColor);
}
4

1 に答える 1

0

私は次の行に気づきました:

vec3 b = nm * cross(n,t);

ただし、次のようにする必要があります。

vec3 b = cross(n,t);

とは目的のカメラ空間にあるnmため、再び掛ける必要はありません。nt

別物:

lightPos_Eye = (mvm * vec4(lightPos_World,1.0)).xyz;

(名前が示すように) はワールド空間にあるため、モデル ビューlightPos_Worldではなく *world_matrix* のようなものを掛ける必要があります。または、アプリケーション コードで計算して頂点シェーダーに送信するだけです。lightPos_Eye

これらのさまざまなベクトルをすべて管理し、それらを 1 つの適切なスペースに配置するのは非常に困難です。視覚的なバグは非常にデリケートで、見つけにくい場合があります。

于 2013-03-10T11:30:51.047 に答える