故障使用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个顶点