2013-11-29 2 views
1

OpenGL 및 GLSL을 사용하여 큐브에 범프 매핑을 구현하려고합니다. 그러나 큐브를 회전 시키면 왼쪽 대각선 및 오른쪽 대각선 만 나타납니다 (즉, 음수 x 및 양수 x 방향). 큐브의 다른 네면 (위, 아래, 앞, 뒤)은 검은 색입니다. 다음은 예이다 :OpenGL 및 GLSL의 범프 매핑

enter image description here

내 메쉬 클래스는 indexList 그러나 VertexList 및 구성 (정점 클래스는 X, Y, Z, 등을 포함). 난 this 단순한 cube.ply 모델을 사용하고 있는데, s, t 텍스처 좌표를 포함하고있다. 다음 this example 차용, I는 접선 벡터를 계산한다

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

I 출력 각 삼각형에 대한 접선 벡터의 값은, I는이 값을 얻을 경우
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

이 올바른 경우, 다음 문제는 쉐이더의 가능성이있다. 내 쉐이더는 다음과 같이 (주로 책에서 가져온)입니다 :

높이 요 :

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 (도트 (normalDelta, lightDirection), 0.0)의 값이이면에 대해 0을 반환한다는 것을 알았습니다. 그러나, 나는 아직도 이유를 모른다.

편집 3 : 문제는 내 Vertex 클래스에서 접선 벡터의 잘못된 인덱스를 전달한다는 것입니다. 그게 내가이 줄 대신 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를 수동으로 검사했고, 각각의 경우에 완전한 좌표계를 만드는 적절한 비트 대각선 벡터를 제공합니다. 그래서, 나는 shader로 문제를 좁힐 수 있다고 생각하고있다. – Aaron

+0

내 편집 3을 확인하십시오. (필자가 언급 한 버그를 포함 할 수있는) 전체 코드를 게시하는 것은 비현실적이지만 제안 사항은 접선 벡터와 관련된 모든 것을 디버깅하고 다시 확인하는 데 도움이되었습니다. 감사! – Aaron