2013-11-29 122 views
1

我正在嘗試在使用OpenGL和GLSL的立方體上實現凹凸貼圖。但是,當我旋轉我的立方體時,只有左側正方形和右側正方形出現(即,在負x和正x方向上),立方體的其他四個面(頂部,底部,前部,後部)是黑色的。下面是一個例子:OpenGL和GLSL中的凹凸貼圖

enter image description here

我的網格類由一個indexList和VertexList時的(頂點類包含X,Y,Z等)。我使用this simple cube.ply模型,它包含s,t紋理座標。從this example借用,我計算的切線矢量,如下所示:

void Mesh::computeTangents() { 

     for (size_t i = 0; i < m_indexList.size(); i += 3) { 

      Vertex v1 = m_vertexList[m_indexList[i]]; 
      Vertex v2 = m_vertexList[m_indexList[i+1]]; 
      Vertex v3 = m_vertexList[m_indexList[i+2]]; 

      glm::vec3 pos1 = glm::vec3(v1.getX(), v1.getY(), v1.getZ()); 
      glm::vec3 pos2 = glm::vec3(v2.getX(), v2.getY(), v2.getZ()); 
      glm::vec3 pos3 = glm::vec3(v3.getX(), v3.getY(), v3.getZ()); 
      glm::vec2 tex1 = glm::vec2(v1.getS(), v1.getT()); 
      glm::vec2 tex2 = glm::vec2(v2.getS(), v2.getT()); 
      glm::vec2 tex3 = glm::vec2(v3.getS(), v3.getT()); 

      glm::vec3 edge1 = glm::normalize(pos2 - pos1); 
      glm::vec3 edge2 = glm::normalize(pos3 - pos1); 

      glm::vec2 texEdge1 = glm::normalize(tex2 - tex1); 
      glm::vec2 texEdge2 = glm::normalize(tex3 - tex1); 

      float det = (texEdge1.x * texEdge2.y) - (texEdge1.y * texEdge2.x); 

      glm::vec3 tangent; 

      if(fabsf(det) < 1e-6f) { 
       tangent.x = 1.0; 
       tangent.y = 0.0; 
       tangent.z = 0.0; 
      } 
      else { 
       det = 1.0/det; 

       tangent.x = (texEdge2.y * edge1.x - texEdge1.y * edge2.x) * det; 
       tangent.y = (texEdge2.y * edge1.y - texEdge1.y * edge2.y) * det; 
       tangent.z = (texEdge2.y * edge1.z - texEdge1.y * edge2.z) * det; 

       glm::normalize(tangent); 
      } 

      m_vertexList[m_indexList[i]].setTanX(tangent.x); 
      m_vertexList[m_indexList[i]].setTanY(tangent.y); 
      m_vertexList[m_indexList[i]].setTanZ(tangent.z); 
      m_vertexList[m_indexList[i+1]].setTanX(tangent.x); 
      m_vertexList[m_indexList[i+1]].setTanY(tangent.y); 
      m_vertexList[m_indexList[i+1]].setTanZ(tangent.z); 
      m_vertexList[m_indexList[i+2]].setTanX(tangent.x); 
      m_vertexList[m_indexList[i+2]].setTanY(tangent.y); 
      m_vertexList[m_indexList[i+2]].setTanZ(tangent.z); 
     } 
    } 

如果我輸出用於每個三角形的切線矢量的值,我得到這些值:
1,0,0
1,0, 0
0,0,-1
0,0,-1
0,0,1
0,0,1
-1,0,0
-1,0,0,
1,0,0
1,0,0
1,0,0
1,0,0

如果這些是正確的,那麼問題可能在着色器。我的着色器如下(大部分是從一本書拍攝):

VERT:

attribute vec4 vertexPosition; 
attribute vec3 vertexNormal; 
attribute vec2 vertexTexture; 
attribute vec3 vertexTangent; 

varying vec2 texCoord; 
varying vec3 viewDirection; 
varying vec3 lightDirection; 

uniform vec3 diffuseColor; 
uniform float shininess; 
uniform vec4 lightPosition; 

uniform mat4 modelViewMatrix; 
uniform mat4 normalMatrix; 
uniform mat4 MVP; // modelview projection 

void main() { 
    vec4 eyePosition = modelViewMatrix * vertexPosition; 
    vec3 N = normalize(vec3(normalMatrix * vec4(vertexNormal, 1.0))); 
    vec3 T = normalize(vec3(normalMatrix * vec4(vertexTangent, 1.0))); 
    vec3 B = normalize(cross(N, T)); 

    vec3 v; 
    v.x = dot(lightPosition.xyz, T); 
    v.y = dot(lightPosition.xyz, B); 
    v.z = dot(lightPosition.xyz, N); 
    lightDirection = normalize(v); 

    v.x = dot(eyePosition.xyz, T); 
    v.y = dot(eyePosition.xyz, B); 
    v.z = dot(eyePosition.xyz, N); 
    viewDirection = normalize(v); 

    texCoord = vertexTexture; 
    gl_Position = MVP * vertexPosition; 
} 

破片:

varying vec2 texCoord; 
varying vec3 viewDirection; 
varying vec3 lightDirection; 

uniform vec3 diffuseColor; 
uniform float shininess; 

void main() { 

    float bumpDensity = 16.0; 
    float bumpSize = 0.15; 

    vec2 c = bumpDensity * texCoord; 
    vec2 p = fract(c) - vec2(0.5); 

    float d, f; 
    d = dot(p, p); 
    f = 1.0/sqrt(d + 1.0); 

    if (d >= bumpSize) { 
     p = vec2(0.0); 
     f = 1.0; 
    } 

    vec3 normalDelta = vec3(p.x, p.y, 1.0) * f; 
    vec3 litColor = diffuseColor * max(dot(normalDelta, lightDirection), 0.0); 
    vec3 reflectDir = reflect(lightDirection, normalDelta); 
    float spec = max(dot(viewDirection, reflectDir), 0.0); 
    spec *= shininess; 
    litColor = min(litColor + spec, vec3(1.0)); 
    gl_FragColor = vec4(litColor, 1.0); 
} 

編輯:改變背景更清楚地看到黑色的面孔。另外,我錯誤地注意到哪些面孔實際上出現過。

編輯2:我發現片段着色器中的max(dot(normalDelta,lightDirection),0.0)值對這些面返回0。但是,我仍然不知道爲什麼。

編輯3:嗯,問題原來是因爲我在我的頂點類中傳遞了切線向量的錯誤索引。也就是說,我在這一行,而不是9例10:

glVertexAttribPointer(v3, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(sizeof(float) * 9)); 

回答

1

好了,問題是,面對任何一個正常的在XZ平面不能正常呈現,即那些正確渲染的是沿着y軸的法線(頂部和底部面)。

而且你的切線的列表:

1, 0, 0 
1, 0, 0 
0, 0, -1 
0, 0, -1 
0, 0, 1 
0, 0, 1 
-1, 0, 0 
-1, 0, 0 
1, 0, 0 
1, 0, 0 
1, 0, 0 
1, 0, 0 

是否所有要麼沿X或Z軸。那麼我猜可能發生的是,你的法線和切線指向了同一個(或相反)的方向,在這種情況下,這條線在你的頂點着色器:

vec3 B = normalize(cross(N, T)); 

會導致vec3(0.0,0.0,0。0),這不能被標準化。

我的建議是嘗試手動給出x和z面沿y軸的切線,看看是否有所作爲。如果有幫助,那麼你知道問題在於你對切線的計算。

如果沒有幫助,則可以通過將片段着色器中的值作爲屏幕上的顏色輸出來進行故障排除。嘗試顯示viewDirection,lightDirection,normalDelta,reflectDir和其他所有可以想到的內容,以查看哪個變量導致黑度。

獎勵:將glClear顏色切換爲黑色以外的顏色?因此它看起來不像是在太空中飄浮的臉。

+0

感謝您的提示。其實,再看一遍之後,我錯誤地看到了實際出現的面。原來它是出現的左臉和右臉。另外,我按照你的建議仔細檢查了切線值,我相信它們是正確的。對於每個三角形,我手動檢查了常規X切向量的wolfram alpha,並且在每種情況下都給出了一個合適的雙切線向量,它構成了一個完整的座標系。所以,我猜測(並希望)我可以將問題縮小到着色器中。 – Aaron

+0

檢查我的編輯3.儘管發佈我的整個代碼(可能包含如我注意到的這些錯誤)是不切實際的,但您的建議幫助我調試並仔細檢查了與切線向量相關的所有內容。謝謝! – Aaron