OpenGL,尽管逆时针顺序,一些法线反转
Posted
技术标签:
【中文标题】OpenGL,尽管逆时针顺序,一些法线反转【英文标题】:OpenGL, some normals reversed despite counterclockwise order 【发布时间】:2018-06-12 23:35:31 【问题描述】:在下面的代码中,我不明白为什么有些人脸的法线颠倒了。 三角形看起来是按逆时针方向排列的,但有些面仍然是黑色的。
当我使用 color = -vnormal 修改片段着色器时;两个黑色的脸被正确渲染了,但其他的显然不是。
感谢您提供的任何帮助
// minimalist but fonctional code using glew, glfw, glm
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/vec3.hpp>
#include <glm/vec4.hpp>
#include <glm/mat4x4.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "shaders.h"
GLuint myVAO;
void createCube()
// v6----- v5
// /| /|
// v1------v0|
// | | | |
// | |v7---|-|v4
// |/ |/
// v2------v3
const GLfloat cube_vertices[] =
1, 1, 1, -1, 1, 1, -1,-1, 1, // v0-v1-v2 (front)
-1,-1, 1, 1,-1, 1, 1, 1, 1, // v2-v3-v0
1, 1, 1, 1,-1, 1, 1,-1,-1, // v0-v3-v4 (right)
1,-1,-1, 1, 1,-1, 1, 1, 1, // v4-v5-v0
1, 1, 1, 1, 1,-1, -1, 1,-1, // v0-v5-v6 (top)
-1, 1,-1, -1, 1, 1, 1, 1, 1, // v6-v1-v0
-1, 1, 1, -1, 1,-1, -1,-1,-1, // v1-v6-v7 (left)
-1,-1,-1, -1,-1, 1, -1, 1, 1, // v7-v2-v1
-1,-1,-1, 1,-1,-1, 1,-1, 1, // v7-v4-v3 (bottom)
1,-1, 1, -1,-1, 1, -1,-1,-1, // v3-v2-v7
1,-1,-1, -1,-1,-1, -1, 1,-1, // v4-v7-v6 (back)
-1, 1,-1, 1, 1,-1, 1,-1,-1 ; // v6-v5-v4
// normal array
const GLfloat cube_normalsI[] =
0, 0, 1, 0, 0, 1, 0, 0, 1, // v0-v1-v2 (front)
0, 0, 1, 0, 0, 1, 0, 0, 1, // v2-v3-v0
1, 0, 0, 1, 0, 0, 1, 0, 0, // v0-v3-v4 (right)
1, 0, 0, 1, 0, 0, 1, 0, 0, // v4-v5-v0
0, 1, 0, 0, 1, 0, 0, 1, 0, // v0-v5-v6 (top)
0, 1, 0, 0, 1, 0, 0, 1, 0, // v6-v1-v0
-1, 0, 0, -1, 0, 0, -1, 0, 0, // v1-v6-v7 (left)
-1, 0, 0, -1, 0, 0, -1, 0, 0, // v7-v2-v1
0,-1, 0, 0,-1, 0, 0,-1, 0, // v7-v4-v3 (bottom)
0,-1, 0, 0,-1, 0, 0,-1, 0, // v3-v2-v7
0, 0,-1, 0, 0,-1, 0, 0,-1, // v4-v7-v6 (back)
0, 0,-1, 0, 0,-1, 0, 0,-1 ; // v6-v5-v4
// Upload per-vertex positions
GLuint positionVBO = 0;
glGenBuffers(1, &positionVBO);
glBindBuffer(GL_ARRAY_BUFFER, positionVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(cube_vertices) * sizeof(GLfloat), cube_vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// Upload per-vertex normals
GLuint normalVBO = 0;
glGenBuffers(1, &normalVBO);
glBindBuffer(GL_ARRAY_BUFFER, normalVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(cube_normalsI) * sizeof(GLfloat), cube_normalsI, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// Hook up vertex/normals buffers to a "vertex array object" (VAO)
glGenVertexArrays(1, &myVAO);
glBindVertexArray(myVAO);
// Attach position buffer as attribute 0
glBindBuffer(GL_ARRAY_BUFFER, positionVBO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// Attach normal buffer as attribute 1
glBindBuffer(GL_ARRAY_BUFFER, normalVBO);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, 0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
int main(int argc, char** argv)
glfwInit();
GLFWwindow* window = glfwCreateWindow(768, 768, "", NULL, NULL);
glfwMakeContextCurrent(window);
glewInit();
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE); // same problem with glEnable(GL_FRONT_AND_BACK);
glClearColor(0.8f, 0.7f, 0.5f, 1.0f);
unsigned int program = shaders::CreateShader("simple.vert", "simple.frag");
createCube();
while (glfwWindowShouldClose(window) == GL_FALSE)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glm::mat4 model = glm::translate(glm::mat4(1.0f), glm::vec3(0.0, 0.0, -4.0));
glm::mat4 view = glm::lookAt(glm::vec3(-2.0, -2.0, 0.0), glm::vec3(0.0, 0.0, -4.0), glm::vec3(0.0, 1.0, 0.0));
glm::mat4 projection = glm::perspective(45.0f, 1.0f, 0.1f, 10.0f);
glm::mat4 mvp = projection * view * model;
glUseProgram(program);
GLuint imvp = glGetUniformLocation(program, "mvp");
glUniformMatrix4fv(imvp, 1, false, glm::value_ptr(mvp));
glBindVertexArray(myVAO);
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);
glUseProgram(0);
glfwSwapBuffers(window);
顶点着色器:
#version 330 core
layout (location = 0) in vec3 in_position;
layout (location = 1) in vec3 in_normal;
uniform mat4 mvp;
out vec3 vnormal;
void main()
vnormal = in_normal;
gl_Position = mvp * vec4(in_position,1);
片段着色器:
#version 330 core
in vec3 vnormal;
out vec3 color;
void main()
color= vnormal;
【问题讨论】:
【参考方案1】:输出颜色被限制在 0.0-1.0 范围内。
因此,像 -1, 0, 0
这样的负法线最终会在颜色缓冲区中显示为 RGB(0,0,0)。
【讨论】:
试试:color= (vnormal+vec3(1.0f,1.0f,1.0f)*0.5f;
color= (vnormal+vec3(1.0f,1.0f,1.0f)*0.5f; 给我黑脸。谢谢帮助。
所以,正在做 vnormal= (0.5 + 0.5 * vnormal);适合我的着色计算的解决方案?
@GUNNM 不,这只是将法线视为颜色......法线必须保持原样......现在从颜色中您必须假设法线指向您脸上的方向。 .. 灰色表示法线为零 红色表示法线朝向 X+ Aqua 表示朝向 X- ...顺便说一句,我没有看到您在顶点转换法线 ...它们也应该被转换 vnormal = mvp * vec4(in_normal,0);
这会将它们变成相机本地坐标,所以你想检查 Z+/Z- 朝向所以蓝色/黄色......如果朝向相机的任何面不是蓝色(或黄色用于不同的绕组/照明设置)......
@Spektre color= (vnormal+vec3(1.0f,1.0f,1.0f)*0.5f;
缺少结束 )
以上是关于OpenGL,尽管逆时针顺序,一些法线反转的主要内容,如果未能解决你的问题,请参考以下文章