Почему у меня есть фрагменты моей текстуры со светом, а другие темные? - PullRequest
0 голосов
/ 09 января 2019

Я пытался реализовать Normal Mapping с использованием OpenGL. Я реализовал самую базовую версию этого, но перешел к попытке реализовать REAL Normal Mapping, который включает в себя вычисление би-тангенсов и тангетов для каждой вершины. Я начал с реализации Fragment и Vertex Shaders, как вы можете видеть ниже:

Вершинный шейдер:

#version 330 core

in vec4 in_Position;
in vec2 in_Coordinates;
in vec3 in_Normal;
in vec3 tangent;
in vec3 bitangent;

out vec2 ex_textCoord;

out VS_OUT{
    vec3 FragPos;
    vec3 Normal;
    vec4 LightVec;
    vec4 ViewVec;
} vs_out;

uniform mat4 ModelMatrix;
uniform vec4 VertColor;
uniform SharedMatrices
{
    mat4 ViewMatrix;
    mat4 ProjectionMatrix;
};

uniform vec4 plane;

uniform vec3 lightPos;
uniform vec3 viewPos;

void main(void)
{

    vec4 worldPosition = ModelMatrix * in_Position;
    gl_Position = ProjectionMatrix * ViewMatrix * worldPosition;
    vs_out.FragPos = vec3(ModelMatrix * in_Position);
    ex_textCoord = in_Coordinates;

    mat3 normalMatrix = transpose(inverse(mat3(ModelMatrix)));
    vs_out.Normal = normalMatrix * in_Normal;

    vec3 T = normalize(vec3(ModelMatrix * vec4(tangent, 0.0)));
    vec3 N = normalize(vec3(ModelMatrix * vec4(in_Normal, 0.0)));

    T = normalize(T - dot(T, N) * N);

    vec3 B = cross(T, N);

    mat4 TBN4 = mat4(
        vec4(T, 0.0),
        vec4(B, 0.0),
        vec4(N, 0.0),
        worldPosition 
    );

    mat4 invTBN4 = inverse(TBN4);

    vs_out.LightVec = invTBN4 * vec4(normalize(lightPos - worldPosition.xyz), 0.0);
    vs_out.ViewVec  = invTBN4 * vec4(normalize(viewPos - worldPosition.xyz), 0.0);
    //vs_out.TangentFragPos = TBN * vec3(worldPosition);
    gl_ClipDistance[0] = dot(worldPosition, plane);

}

Фрагмент шейдера:

#version 330 core

out vec4 color;

in vec2 ex_textCoord;

in VS_OUT{
    vec3 FragPos;
    vec3 Normal;
    vec4 LightVec;
    vec4 ViewVec;
} fs_in;

uniform sampler2D screenTexture; //Diffuse Texture
uniform sampler2D normalTexture; //Normal Mapping Texture

uniform bool normalMapping; //Enable or Disable Normal Mapping  

uniform vec3 lightPosition;
uniform vec3 lightColour;

void main()
{
    vec3 normal = texture(normalTexture, ex_textCoord).rgb;
    normal = normalize(normal * 2.0 - 1.0);

    vec3 Normalcolor = texture(screenTexture, ex_textCoord).rgb;

    //Ambient Light
    vec3 ambient = 0.1 * Normalcolor;

    //Diffuse Light
    vec4 lightDir = normalize(fs_in.LightVec);
    float diff = max(dot(vec3(lightDir), normal), 0.0);
    vec3 diffuse = diff * Normalcolor;

    //Specular Light
    vec4 viewDir = normalize(fs_in.ViewVec);
    vec3 reflectDir = reflect(vec3(-lightDir), normal);
    vec4 halfwayDir = normalize(lightDir + viewDir);
    float spec = pow(max(dot(normal, vec3(halfwayDir)), 0.0), 32.0);
    vec3 specular = vec3(0.2) * spec;

    color = vec4(ambient + diffuse + specular, 1.0f);
}

Теперь шейдеры кажутся мне вполне честными, я видел примеры фрагментов кода, и мои шейдеры кажутся 1: 1 с ними. Теперь проблема либо в освещении (я в этом сомневаюсь, но это возможно), либо в способе вычисления тангенса и би-тангенса, который я делаю при загрузке сетки, как вы можете видеть ниже:

Vec3 pos1, pos2, pos3, pos4, tangent1, bitangent1, edge1, edge2, normal;
    Vec2 uv1, uv2, uv3, uv4, deltaUV1, deltaUV2;

    for (int i = 0; i <= TempMeshRef->vertexIdx.size() - 3; i += 1) {

        pos1 = TempMeshRef->vertexData[TempMeshRef->vertexIdx[i]-1];
        pos2 = TempMeshRef->vertexData[TempMeshRef->vertexIdx[i+1]-1];
        pos3 = TempMeshRef->vertexData[TempMeshRef->vertexIdx[i+2]-1];
        //pos4 = TempMeshRef->vertexData[TempMeshRef->vertexIdx[i+3]-1];

        uv1 = TempMeshRef->texcoordData[TempMeshRef->texcoordIdx[i]-1];
        uv2 = TempMeshRef->texcoordData[TempMeshRef->texcoordIdx[i+1]-1];
        uv3 = TempMeshRef->texcoordData[TempMeshRef->texcoordIdx[i+2]-1];
        //uv4 = TempMeshRef->texcoordData[TempMeshRef->texcoordIdx[i+3]-1];

        normal = TempMeshRef->normalData[TempMeshRef->normalIdx[i]-1];

        //Triangle 1

        edge1 = pos2 - pos1;
        edge2 = pos3 - pos1;
        deltaUV1 = uv2 - uv1;
        deltaUV2 = uv3 - uv1;

        GLfloat f = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV2.x * deltaUV1.y);

        tangent1.x = f * (deltaUV2.y * edge1.x - deltaUV1.y * edge2.x);
        tangent1.y = f * (deltaUV2.y * edge1.y - deltaUV1.y * edge2.y);
        tangent1.z = f * (deltaUV2.y * edge1.z - deltaUV1.y * edge2.z);
        tangent1 = Normalized(tangent1);

        TempMeshRef->tangentData.push_back(tangent1);

        bitangent1.x = f * (-deltaUV2.x * edge1.x + deltaUV1.x * edge2.x);
        bitangent1.y = f * (-deltaUV2.x * edge1.y + deltaUV1.x * edge2.y);
        bitangent1.z = f * (-deltaUV2.x * edge1.z + deltaUV1.x * edge2.z);
        bitangent1 = Normalized(bitangent1);

        TempMeshRef->biTangentData.push_back(bitangent1);

Теперь если я прикажу вам увидеть результаты, которые я получаю, это следующая ошибка:

Bug

Причина, по которой я думаю, что это не связано с источниками света, заключается в том, что в зависимости от способа вычисления моих Касательных и Битангенсов более или менее фрагменты «подсвечиваются»

...