glsl - Tangent calculation on a Sphere leaves missing faces at the South Pole -


howdy wonderful folks!

i doing planetary simulation of earth space , stuck @ normal mapping stage. went through bunch of tutorials on internet , wrote logic calculate tangents, pass them vertex shader , calculate normal in tbn space , use normal calculate lighting using phong model. seems work correctly @ south pole of planet, missing triangles , hence black spots:

enter image description here code calculating geometry of sphere goes along lines of:

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);         }     } } 

the addtriangle method adds triangles data structures in turn used passing vertices, normals, tangents , texture coordinates in vertex buffer objects shaders. method looks this:

void object::addtriangle(vec3f v1, vec3f u1, vec3f v2, vec3f u2, vec3f v3, vec3f u3){     //add triangle     addtriangle(v1, v2, v3);      //todo integrate uv coordinates in face     //add texture coordinates uv vector     uv.push_back(u1);     uv.push_back(u2);     uv.push_back(u3);      vec3f e1 = v2 - v1;     vec3f e2 = v3 - v1;      float deltau1 = u2.x - u1.x;     float deltav1 = u2.y - u1.y;     float deltau2 = u3.x - u1.x;     float deltav2 = u3.y - u1.y;      float f = 1.f / (deltau1 * deltav2 - deltau2 * deltav1);      vec3f tangent;     tangent = f * (deltav2 * e1 - deltav1 * e2);      auto tangentiter = find(tangents.begin(), tangents.end(), tangent);      // if tangent not in vector, add , set iter     // vector's tail.      if (tangentiter == tangents.end()){         tangents.push_back(tangent);         tangentiter = tangents.end() - 1;     }      gluint tangentindex = tangentiter - tangents.begin();      face* face = faces.back();     face->t = tangentindex;      vector<vec3f> trianglevertices;     trianglevertices.push_back(v1);     trianglevertices.push_back(v2);     trianglevertices.push_back(v3);      (unsigned = 0; < trianglevertices.size(); i++){         vec3f v = trianglevertices.at(i);         if (sharedtangents.find(v) == sharedtangents.end()){             sharedtangents.insert(pair<vec3f, vec3f>(v, tangent));         }         else{             vec3f& vt = sharedtangents.at(v);             vt += tangent;         }     }    } 

while initializing buffers, call method calculate tangents each vertex:

void object::calculatevertextangents(){     vector<vec3f> vertextangentlist;     //find mean of tangents shared vertex,     //and normalize , add them vertex tangent vector      (unsigned = 0; < 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;     (unsigned = 0; < faces.size(); i++){         (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;         }     } } 

and vertex , fragments shader code lies here: vertex shader:

#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); } 

fragment shader:

#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); } 

i appreciate if able point out i'm doing wrong in calculation of tangents? if information helps, when render sphere vertex normals , phong shading, perfect looking planet.


edit: here's screenshot when i'm using texture shading , not using tangent space normal mapping:

enter image description here


Comments

Popular posts from this blog

python - pip install -U PySide error -

arrays - C++ error: a brace-enclosed initializer is not allowed here before ‘{’ token -

cytoscape.js - How to add nodes to Dagre layout with Cytoscape -