故障使用OpenGL的obj法线时
问题描述:
我试图渲染使用搅拌机的exported.obj文件的立方体但照明看起来是错误的。故障使用OpenGL的obj法线时
我想这是因为我的顶点数组包含8个值,但法线数组只有6
我无法理解的OpenGL是如何使用这个指数的数组。这对我来说有点魔力。
任何人都可以帮助我吗?
这是文件:
v -1.000000 -1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 1.000000 0.999999
v -0.999999 1.000000 -1.000001
v 1.000000 1.000000 -1.000000
v 1.000000 1.000000 1.000000
vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 -0.0000
vn -1.0000 -0.0000 0.0000
vn 0.0000 -0.0000 -1.0000
vn 1.0000 -0.0000 0.0000
vn -0.0000 0.0000 1.0000
f 2//1 4//1 1//1
f 8//2 6//2 5//2
f 5//3 2//3 1//3
f 6//4 3//4 2//4
f 3//5 8//5 4//5
f 1//6 8//6 5//6
f 2//1 3//1 4//1
f 8//2 7//2 6//2
f 5//3 6//3 2//3
f 6//4 7//4 3//4
f 3//5 7//5 8//5
f 1//6 4//6 8//6
这是我的代码:
GLuint cubeVAO, cubeVerticesVBO, cubeColorsVBO, cubeNormalsVBO, cubeIndicesVBO;
glGenVertexArrays(1, &cubeVAO);
glBindVertexArray(cubeVAO);
glGenBuffers(1, &cubeVerticesVBO);
glBindBuffer(GL_ARRAY_BUFFER, cubeVerticesVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(cube_vertices), cube_vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), BUFFER_OFFSET(0));
glEnableVertexAttribArray(0);
glGenBuffers(1, &cubeColorsVBO);
glBindBuffer(GL_ARRAY_BUFFER, cubeColorsVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(cube_colors), cube_colors, GL_STATIC_DRAW);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), BUFFER_OFFSET(0));
glEnableVertexAttribArray(1);
glGenBuffers(1, &cubeNormalsVBO);
glBindBuffer(GL_ARRAY_BUFFER, cubeNormalsVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(cube_normals), cube_normals, GL_STATIC_DRAW);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), BUFFER_OFFSET(0));
glEnableVertexAttribArray(2);
glGenBuffers(1, &cubeIndicesVBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cubeIndicesVBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(cube_indices), cube_indices, GL_STATIC_DRAW);
glBindVertexArray(cubeVAO);
cubeShader.use();
glm::mat4 model;
cubeShader.setMat4("model", model);
cubeShader.setMat4("view", view);
cubeShader.setMat4("projection", projection);
cubeShader.setVec3("lampColor", lampColor);
cubeShader.setVec3("lampPos", lampPos);
cubeShader.setVec3("viewPos", viewPos);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);
的Vertex Shader
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 color;
layout (location = 2) in vec3 normal;
out vec3 Color;
out vec3 Normal;
out vec3 FragPos;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
vec4 posv4 = vec4(position, 1.0f);
Color = color;
FragPos = vec3(model * posv4);
Normal = normal;
gl_Position = projection*view*model*posv4;
}
片段着色器:
#version 330 core
in vec3 Color;
in vec3 Normal;
in vec3 FragPos;
out vec4 FragColor;
uniform vec3 lampColor;
uniform vec3 lampPos;
uniform vec3 viewPos;
void main()
{
// ambient
float ambientStrength = 0.1;
vec3 ambient = ambientStrength * lampColor;
// diffuse
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(lampPos - FragPos);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = diff * lampColor;
// specular
float specularStrength = 0.5;
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);
vec3 specular = specularStrength * spec * lampColor;
vec3 result = (ambient + diffuse + specular) * Color;
FragColor = vec4(result, 1.0);
}
怎么了? , - ,
示范视频: https://vid.me/vy17h
答
你必须扩大在OBJ文件中的数据。 OpenGL的预计为每个顶点中指定一个正常的,个别地。在OBJ文件中,顶点和法线分开处理。你需要做的是找到独特的顶点+正常组合,将它和索引存储到新的顶点+正常数组中,而不是使用单独的索引。
使用现代OpenGL,通过使用顶点着色器纹理获取,将顶点数据存储在纹理中,可以对每个顶点属性使用不同的索引。但是这带来了性能问题。
答
法线阵列仅具有6个值,因为立方体具有6个面和已创建,其中每个面具有在相同的方向上指向的角部4点的法线(一个模型即相同) - 这解释了照明不是你期待的。
OBJ文件使用索引以便它可以分配这些6个独特的价值观之一,每个8个顶点