使用OpenGL .obj法线时遇到麻烦

时间:2017-08-07 00:54:00

标签: c++ opengl

我尝试使用Blender的exported.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);

顶点着色器

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

Fragment Shader:

#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

2 个答案:

答案 0 :(得分:1)

法线数组只有6个值,因为立方体有6个面并且您创建了一个模型,其中每个面在指向相同方向的角上有4个法线(即相同) - 这解释了照明不看你怎么样期望的。

obj文件使用索引,因此它可以为这8个顶点中的每一个分配这6个唯一值中的一个

答案 1 :(得分:1)

您必须扩展OBJ文件中的数据。 OpenGL期望为每个顶点单独指定法线。在OBJ文件中,顶点和法线分开处理。你要做的是找到唯一的顶点+正常组合,将其存储并索引到新的顶点+正常数组中,而不是使用单独的索引。

使用现代OpenGL,通过使用顶点着色器纹理提取,在纹理中存储顶点数据,可以为每个顶点属性使用不同的索引。但这会带来性能损失。