Glsl 球体上的切线计算会在南极留下缺失的面

Glsl 球体上的切线计算会在南极留下缺失的面,glsl,gpu,Glsl,Gpu,大家好 我正在从太空对地球进行行星模拟,还停留在正常的测绘阶段。我在互联网上浏览了一系列教程,编写了计算切线的逻辑,将其传递给顶点着色器,并计算TBN空间中的法线,然后使用法线使用phong模型计算照明。一切似乎都正常,但在地球的南极,我发现缺少三角形,因此出现了黑点: 用于计算球体几何体的代码如下所示: void Sphere::generateMesh(){ float deltaPhi = (float)PI/stacks; float deltaTheta = (2

大家好

我正在从太空对地球进行行星模拟,还停留在正常的测绘阶段。我在互联网上浏览了一系列教程,编写了计算切线的逻辑,将其传递给顶点着色器,并计算TBN空间中的法线,然后使用法线使用phong模型计算照明。一切似乎都正常,但在地球的南极,我发现缺少三角形,因此出现了黑点:

用于计算球体几何体的代码如下所示:

void Sphere::generateMesh(){

    float deltaPhi = (float)PI/stacks;
    float deltaTheta = (2 * (float)PI)/slices;

    for(float phi = 0; phi < PI ; phi += deltaPhi){
        for(float theta = 0; theta < 2*PI - 0.001; theta += deltaTheta){

            float x1 = -sinf(phi) * sinf(theta) * radius;
            float y1 = -cosf(phi) * radius;
            float z1 = -sinf(phi) * cosf(theta) * radius;

            float u1 = float( atan2(x1, z1) / (2 * PI) + 0.5 );
            float v1 = float( -asin(y1) / (float)PI + 0.5 );

            float x2 = -sinf(theta + deltaTheta) * sinf(phi) * radius;
            float y2 = -cosf(phi) * radius;
            float z2 = -sinf(phi) * cosf(theta + deltaTheta) * radius;

            float u2 = float( atan2(x2, z2) / (2 * PI) + 0.5 );
            float v2 = float( -asin(y2) / ((float)PI) + 0.5 );

            float x3 = -sinf(theta + deltaTheta) * sinf(phi + deltaPhi) * radius;
            float y3 = -cosf(phi + deltaPhi) * radius;
            float z3 = -sinf(phi + deltaPhi) * cosf(theta + deltaTheta) * radius;

            float u3 = float( atan2(x3, z3) / (2 * (float)PI) + 0.5 );
            float v3 = float( -asin(y3) / (float)PI + 0.5 );

            float x4 = -sinf(theta) * sinf(phi + deltaPhi) * radius;
            float y4 = -cosf(phi + deltaPhi) * radius;
            float z4 = -sinf(phi + deltaPhi) * cosf(theta) * radius;

            float u4 = float( atan2(x4, z4) / (2 * (float)PI) + 0.5 );
            float v4 = float( -asin(y4) / (float)PI + 0.5 );


            Vec3f p1(x1, y1, z1);
            Vec3f uv1(u1, v1, 0);
            Vec3f p2(x2, y2, z2);
            Vec3f uv2(u2, v2, 0);
            Vec3f p3(x3, y3, z3);
            Vec3f uv3(u3, v3, 0);
            Vec3f p4(x4, y4, z4);
            Vec3f uv4(u4, v4, 0);

            //addTriangle(x1, y1, z1, u1, v1,
            //  x2, y2, z2, u2, v2,
            //  x3, y3, z3, u3, v3);

            //addTriangle(x1, y1, z1, u1, v1,
            //  x3, y3, z3, u3, v3,
            //  x4, y4, z4, u4, v4); 

            addTriangle(p1, uv1, p2, uv2, p3, uv3);
            addTriangle(p1, uv1, p3, uv3, p4, uv4);
        }
    }
}
片段着色器:

#version 400 core

uniform vec4 lightColor;
uniform vec4 diffuseColor;
uniform sampler2D mySampler;
uniform sampler2D night;
uniform sampler2D clouds;
uniform sampler2D specMap;
uniform sampler2D bumpMap;

in vec3 vPos;

in vec3 lightVec;
in vec3 eyeVec;
in vec3 halfVec;

in vec2 texCoord;

out vec4 frag_color;    

void main(){

    vec3 normal = 2.0 * texture(bumpMap, texCoord).rgb - 1.0;
    //normal.z = 1 - normal.x * normal.x - normal.y * normal.y;
    normal = normalize ( normal );

    vec4 spec = vec4(1.0, 0.941, 0.898, 1.0);
    vec4 specMapColor = texture2D(specMap, texCoord);

    vec3 L = lightVec;
    vec3 N = normal;
    vec3 Emissive = normalize(-vPos);
    vec3 R = reflect(-L, N);
    float dotProd = max(dot(R, Emissive), 0.0);
    vec4 specColor = spec * pow(dotProd,6.0) * 0.6;
    float diffuse = max(dot(N, L), 0.0);

    vec2 cloud_color            =   texture2D( clouds, texCoord).rg;
    vec3 day_color              =   (texture2D( mySampler, texCoord ).rgb * diffuse + specColor.rgb * specMapColor.g) * (1 - cloud_color.r) + cloud_color.r * diffuse;
    vec3 night_color            =   texture2D( night, texCoord ).rgb * (1 - cloud_color.r) * 0.5;

    vec3 color = day_color;
    if(dot(N, L) < 0.1)
        color = mix(night_color, day_color, (diffuse + 0.1) * 5.0);
    frag_color = vec4(color, 1.0);
}
#版本400核心
均匀的vec4浅色;
均匀的vec4扩散色;
均匀取样器;
晚上穿制服;
二维均匀云;
均匀采样二维specMap;
均匀采样二维凹凸图;
在vec3 VPO中;
在vec3-lightVec中;
vec3-eyeVec;
vec3-halfVec;
在vec2 texCoord;
输出vec4 frag_颜色;
void main(){
vec3法线=2.0*纹理(凹凸贴图,texCoord).rgb-1.0;
//normal.z=1-normal.x*normal.x-normal.y*normal.y;
正常=正常化(正常);
vec4规范=vec4(1.0,0.941,0.898,1.0);
vec4 specMapColor=纹理2D(specMap,texCoord);
vec3 L=lightVec;
vec3 N=正常;
vec3发射=正常化(-vPos);
vec3 R=反射(-L,N);
float dotProd=最大值(点(R,发射),0.0);
vec4 specColor=spec*pow(dotProd,6.0)*0.6;
浮动漫反射=最大值(点(N,L),0.0);
vec2 cloud_color=texture2D(云,texCoord).rg;
vec3 day_color=(texture2D(mySampler,texCoord).rgb*漫反射+specColor.rgb*specMapColor.g)*(1-cloud_color.r)+cloud_color.r*漫反射;
vec3 night_color=texture2D(night,texCoord).rgb*(1-cloud_color.r)*0.5;
vec3颜色=天颜色;
if(点(N,L)<0.1)
颜色=混合(夜间颜色,白天颜色,(漫反射+0.1)*5.0);
frag_color=vec4(颜色,1.0);
}
如果有人能指出我在计算切线时做错了什么,我将不胜感激?如果这些信息有帮助的话,当我用顶点法线和phong着色渲染球体时,我得到了一个外观完美的行星


编辑: 以下是我仅使用纹理着色而不使用切线空间法线贴图时的屏幕截图:


如果只设置纹理着色,看起来也不错?我想是的。我可以在一段时间内发布一个屏幕截图,从相同的角度进行纹理着色。问题甚至出现在北极?不,北极的着色效果非常好。只有在南极(我刚刚更新了一张只使用纹理着色的图片。很抱歉,我花了这么长时间上传截图…如果你只设置纹理着色,看起来也不错?我想是的。我可以在一段时间内发布一张截图,从相同的角度进行纹理着色。问题甚至发生在北极?不,北极是p雷蒂的阴影很好。只有在南极。:(我刚刚更新了我的帖子,用了一张只使用纹理阴影的图片。很抱歉,我上传截图花了这么长时间。。。
void Object::calculateVertexTangents(){
    vector<Vec3f> vertexTangentList;
    //find the mean of all the tangents which are shared by the vertex,
    //and normalize and add them to the vertex tangent vector

    for (unsigned i = 0; i < points.size(); i++){
        Vec3f vt = sharedTangents.at(points.at(i));
        vt.normalize();
        vertexTangentList.push_back(vt);
    }

    outVertexTangents = new float[faces.size() * 3 * 3];
    Vec3f vt;
    int index = 0;
    for (unsigned i = 0; i < faces.size(); i++){
        for (unsigned j = 0; j < 3; j++){
            vt = vertexTangentList.at((*faces.at(i))[j]);
            outVertexTangents[index] = vt.x;
            outVertexTangents[index + 1] = vt.y;
            outVertexTangents[index + 2] = vt.z;

            index += 3;
        }
    }
}
#version 400 core

in vec3 vPosition;
in vec2 vTexCoord;
in vec3 vNormal;
in vec3 vTangent;

uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;

uniform vec4 lightPosition;

out vec2 texCoord;

out vec3 lightVec;
out vec3 eyeVec;
out vec3 halfVec;

out vec3 vPos;

void main(){

    mat4 modelView = view * model;
    mat4 normalMatrix = transpose(inverse(modelView));

    vec3 n = normalize ( ( normalMatrix * vec4( vNormal, 0.0 ) ).xyz );
    vec3 t = normalize ( ( normalMatrix * vec4( vTangent, 0.0 ) ).xyz );
    vec3 b = cross (n, t);

    vec4 vertexInEye = modelView * vec4(vPosition, 1.0);
    vPos = vertexInEye.xyz;

    vec3 lightDir = normalize( lightPosition.xyz - vertexInEye.xyz );
    vec3 temp;
    temp.x = dot (lightDir, t);
    temp.y = dot (lightDir, b);
    temp.z = dot (lightDir, n);
    lightVec = normalize(temp);

    temp.x = dot (vertexInEye.xyz, t);
    temp.y = dot (vertexInEye.xyz, b);
    temp.z = dot (vertexInEye.xyz, n);

    eyeVec = normalize(temp);

    vertexInEye = normalize(vertexInEye);
    vec3 halfVector = normalize(vertexInEye.xyz + lightDir);
    temp.x = dot (halfVector, t);
    temp.y = dot (halfVector, b);
    temp.z = dot (halfVector, n);

    halfVec = temp ; 

    texCoord = vTexCoord;

    gl_Position = projection * modelView * vec4(vPosition, 1.0);
}
#version 400 core

uniform vec4 lightColor;
uniform vec4 diffuseColor;
uniform sampler2D mySampler;
uniform sampler2D night;
uniform sampler2D clouds;
uniform sampler2D specMap;
uniform sampler2D bumpMap;

in vec3 vPos;

in vec3 lightVec;
in vec3 eyeVec;
in vec3 halfVec;

in vec2 texCoord;

out vec4 frag_color;    

void main(){

    vec3 normal = 2.0 * texture(bumpMap, texCoord).rgb - 1.0;
    //normal.z = 1 - normal.x * normal.x - normal.y * normal.y;
    normal = normalize ( normal );

    vec4 spec = vec4(1.0, 0.941, 0.898, 1.0);
    vec4 specMapColor = texture2D(specMap, texCoord);

    vec3 L = lightVec;
    vec3 N = normal;
    vec3 Emissive = normalize(-vPos);
    vec3 R = reflect(-L, N);
    float dotProd = max(dot(R, Emissive), 0.0);
    vec4 specColor = spec * pow(dotProd,6.0) * 0.6;
    float diffuse = max(dot(N, L), 0.0);

    vec2 cloud_color            =   texture2D( clouds, texCoord).rg;
    vec3 day_color              =   (texture2D( mySampler, texCoord ).rgb * diffuse + specColor.rgb * specMapColor.g) * (1 - cloud_color.r) + cloud_color.r * diffuse;
    vec3 night_color            =   texture2D( night, texCoord ).rgb * (1 - cloud_color.r) * 0.5;

    vec3 color = day_color;
    if(dot(N, L) < 0.1)
        color = mix(night_color, day_color, (diffuse + 0.1) * 5.0);
    frag_color = vec4(color, 1.0);
}