0

In the code below, I don't understand why some faces have their normals reversed. The triangles looks ordered in the anti-clockwise direction, but some faces remain black.

When I modify the fragment shader with color = -vnormal; the two black faces are rendered correctly, but not the others, obviously.

Thanks for any help given

// 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);
  }
}

The vertex shader:

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

The fragment shader:

#version 330 core

in vec3 vnormal;

out vec3 color;

void main() {
  color= vnormal;
}
genpfault
  • 51,148
  • 11
  • 85
  • 139
Leon
  • 554
  • 4
  • 18

1 Answers1

2

Output colors get clamped to the 0.0-1.0 range.

So your negative normals like -1, 0, 0 end up as RGB(0,0,0) in the color buffer.

genpfault
  • 51,148
  • 11
  • 85
  • 139
  • try: `color= (vnormal+vec3(1.0f,1.0f,1.0f)*0.5f;` instead – Spektre Jun 13 '18 at 06:51
  • color= (vnormal+vec3(1.0f,1.0f,1.0f)*0.5f; gives me black faces. Thx for help. – Leon Jun 13 '18 at 06:58
  • So, is doing vnormal= (0.5 + 0.5 * vnormal); the right solution for my shading calculations? – Leon Jun 13 '18 at 07:06
  • @GUNNM NO that is just to see the normals as colors ... the normals must stay as they are ... now from the colors you have to assume which way the normals point on your faces ... gray means normal is zero red means normal is facing X+ Aqua means facing X- ... btw I do not see you transforming the normal in vertex ... they should be transformed too `vnormal = mvp * vec4(in_normal,0);` this will turn them into camera local coordinates so you want to inspect Z+/Z- facing so Blue/Yellow ... if any face turned towards camera is not blue (or yellow for different winding/lighting setup) ... – Spektre Jun 14 '18 at 06:30
  • @GUNNM btw you should add `@nick` to your comments and site will notify the user `nick` automatically (not needed for author of the thread where you are posting). It is weird that `color= (vnormal+vec3(1.0f,1.0f,1.0f)*0.5f;` do not work and `color= (0.5 + 0.5 * vnormal);` does as they do the same must be a driver/implementation thing ... or some bug in somewhere did you check GLSL logs [complete GL+GLSL+VAO/VBO C++ example](https://stackoverflow.com/a/31913542/2521214) with `glGetShaderInfoLog` and `glGetProgramInfoLog` what did they say? btw cube there should be with correct winding/normals – Spektre Jun 14 '18 at 06:40
  • 1
    @Spektre `color= (vnormal+vec3(1.0f,1.0f,1.0f)*0.5f;` is missing a closing `)` – Alex - GlassEditor.com Jun 15 '18 at 01:08
  • @Alex that's it :) didn't see it – Spektre Jun 15 '18 at 05:59