OpenGL 및 GLSL을 사용하여 큐브에 범프 매핑을 구현하려고합니다. 그러나 큐브를 회전 시키면 왼쪽 대각선 및 오른쪽 대각선 만 나타납니다 (즉, 음수 x 및 양수 x 방향). 큐브의 다른 네면 (위, 아래, 앞, 뒤)은 검은 색입니다. 다음은 예이다 :OpenGL 및 GLSL의 범프 매핑
내 메쉬 클래스는 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));
팁 주셔서 감사합니다. 사실, 다시 보았을 때, 나는 실제로 어떤 얼굴이 실제로 보이는지 보았습니다. 나타나는 왼쪽 얼굴과 오른쪽 얼굴이 밝혀졌습니다. 또한, 제안한대로 탄젠트 값을 두 번 확인했으며 올바른 것으로 믿습니다. 각각의 삼각형에 대해 나는 수동으로 X 접선 벡터에 대해 wolfram alpha를 수동으로 검사했고, 각각의 경우에 완전한 좌표계를 만드는 적절한 비트 대각선 벡터를 제공합니다. 그래서, 나는 shader로 문제를 좁힐 수 있다고 생각하고있다. – Aaron
내 편집 3을 확인하십시오. (필자가 언급 한 버그를 포함 할 수있는) 전체 코드를 게시하는 것은 비현실적이지만 제안 사항은 접선 벡터와 관련된 모든 것을 디버깅하고 다시 확인하는 데 도움이되었습니다. 감사! – Aaron