9

接線空間の法線マッピング シェーダーからかなりおかしな結果が得られます :)。ここに示したシーンでは、ティーポットと市松模様の壁が通常の Phong-Blinn シェーダでシェーディングされています (明らかに、ティーポットのバックフェース カリングにより、少し儚いルック アンド フィールが得られます :-) )。サイケデリックな結果で、球に法線マッピングを追加しようとしました:

球体の法線マッピングが正しくない

光は右側から来ています (ほぼ黒い塊として見えます)。球体で使用している法線マップは次のようになります。

法線マップ

入力モデルの処理に AssImp を使用しているため、各頂点の接線と従法線が自動的に計算されます。

ピクセル シェーダーと頂点シェーダーは次のとおりです。何が問題なのかよくわかりませんが、接線基底行列が何らかの形で間違っていても驚かないでしょう。物事を目の空間に計算してから、目と光のベクトルを接線空間に変換する必要があり、これが正しい方法であると思います。ライトの位置は、既にビュー スペースにあるシェーダーに入ることに注意してください。

// Vertex Shader
#version 420

// Uniform Buffer Structures

// Camera.
layout (std140) uniform Camera
{
    mat4 Camera_Projection; 
    mat4 Camera_View;
};

// Matrices per model.
layout (std140) uniform Model
{
    mat4 Model_ViewModelSpace;
    mat4 Model_ViewModelSpaceInverseTranspose;
};

// Spotlight.
layout (std140) uniform OmniLight
{
    float Light_Intensity;

    vec3 Light_Position;            // Already in view space.
    vec4 Light_Ambient_Colour;
    vec4 Light_Diffuse_Colour;
    vec4 Light_Specular_Colour;
};

// Streams (per vertex)
layout(location = 0) in vec3 attrib_Position;
layout(location = 1) in vec3 attrib_Normal;
layout(location = 2) in vec3 attrib_Tangent;
layout(location = 3) in vec3 attrib_BiNormal;
layout(location = 4) in vec2 attrib_Texture;

// Output streams (per vertex)
out vec3 attrib_Fragment_Normal;
out vec4 attrib_Fragment_Position;
out vec3 attrib_Fragment_Light;
out vec3 attrib_Fragment_Eye;

// Shared.
out vec2 varying_TextureCoord;

// Main
void main()
{
    // Compute normal.
    attrib_Fragment_Normal = (Model_ViewModelSpaceInverseTranspose * vec4(attrib_Normal, 0.0)).xyz;

    // Compute position.
    vec4 position = Model_ViewModelSpace * vec4(attrib_Position, 1.0);

    // Generate matrix for tangent basis.
    mat3 tangentBasis = mat3(   attrib_Tangent, 
                                attrib_BiNormal, 
                                attrib_Normal);

    // Light vector.
    attrib_Fragment_Light = tangentBasis * normalize(Light_Position - position.xyz);

    // Eye vector.
    attrib_Fragment_Eye = tangentBasis * normalize(-position.xyz);

    // Return position.
    gl_Position = Camera_Projection * position;
}

...そして、ピクセル シェーダーは次のようになります。

// Pixel Shader
#version 420

// Samplers
uniform sampler2D Map_Normal;

// Global Uniforms

// Material.
layout (std140) uniform Material
{
    vec4  Material_Ambient_Colour;
    vec4  Material_Diffuse_Colour;
    vec4  Material_Specular_Colour;
    vec4  Material_Emissive_Colour;

    float Material_Shininess;
    float Material_Strength;
};

// Spotlight.
layout (std140) uniform OmniLight
{
    float Light_Intensity;

    vec3 Light_Position;    
    vec4 Light_Ambient_Colour;
    vec4 Light_Diffuse_Colour;
    vec4 Light_Specular_Colour;
};

// Input streams (per vertex)
in vec3 attrib_Fragment_Normal;
in vec3 attrib_Fragment_Position;
in vec3 attrib_Fragment_Light;
in vec3 attrib_Fragment_Eye;

// Shared.
in vec2 varying_TextureCoord;

// Result
out vec4 Out_Colour;

// Main
void main(void)
{
    // Compute normals.
    vec3 N = normalize(texture(Map_Normal, varying_TextureCoord).xyz * 2.0 - 1.0);  
    vec3 L = normalize(attrib_Fragment_Light);
    vec3 V = normalize(attrib_Fragment_Eye);
    vec3 R = normalize(-reflect(L, N));

    // Compute products.
    float NdotL = max(0.0, dot(N, L));
    float RdotV = max(0.0, dot(R, V));

    // Compute final colours.
    vec4 ambient  = Light_Ambient_Colour * Material_Ambient_Colour;
    vec4 diffuse  = Light_Diffuse_Colour * Material_Diffuse_Colour * NdotL;
    vec4 specular = Light_Specular_Colour * Material_Specular_Colour * (pow(RdotV, Material_Shininess) * Material_Strength);

    // Final colour.
    Out_Colour = ambient + diffuse + specular;      
}

編集: シーンの 3D Studio レンダリング (UV が球体で問題ないことを示すため):

ここに画像の説明を入力

4

1 に答える 1

3

シェーダーは問題ないと思いますが、球体のテクスチャ座標が完全にずれています。経度に沿って極に向かって歪んでいるかのようです。

于 2012-04-05T16:29:44.713 に答える