Search code examples
c++openglglslglm-mathlighting

opengl- vertex normal not taken in account


I was just getting into diffuse lighting, but the object always gives a black output,

The vertex and the fragment normals are defined as:

float vertices[] = {
        -0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
        0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f, 
        0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f, 
        0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f, 
        -0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f, 
        -0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f, 

        -0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,
        0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,
        0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,
        0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,
        -0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,
        -0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,

        -0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,
        -0.5f,  0.5f, -0.5f, -1.0f,  0.0f,  0.0f,
        -0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,
        -0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,
        -0.5f, -0.5f,  0.5f, -1.0f,  0.0f,  0.0f,
        -0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,

        0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,
        0.5f,  0.5f, -0.5f,  1.0f,  0.0f,  0.0f,
        0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,
        0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,
        0.5f, -0.5f,  0.5f,  1.0f,  0.0f,  0.0f,
        0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,

        -0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,
        0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,
        0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,
        0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,

        -0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,
        0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,
        0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,
        0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,
        -0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,
        -0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f
    };

The relevant VAO is defined as:

unsigned int VAO, lightVAO, VBO;
    glGenVertexArrays(1, &VAO);
    glBindVertexArray(VAO);
        glGenBuffers(1, &VBO);
        glBindBuffer(GL_ARRAY_BUFFER, VBO);
        glBufferData(GL_ARRAY_BUFFER,sizeof(vertices), vertices, GL_STATIC_DRAW);

        glVertexAttribPointer(0,3, GL_FLOAT,GL_FALSE, 6*sizeof(float),(const void*)0);
        glEnableVertexAttribArray(0);

        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(float), (const void*)3);
        glEnableVertexAttribArray(1);

The relavant uniform are set as:

mShader.use();//activate the shader, already compiled
        mShader.setMat4fv("model", model1);//model matrix
        mShader.setMat4fv("view", view1);//view matrix
        mShader.setMat4fv("projection", projection1);//projection matrix
        mShader.setVec3f("lightPosition", 1.2f, 1.0f, 2.0f);//light source position
        mShader.setVec3f("objectColor", 1.0f, 0.0f, 0.0f);//our object's base color
        mShader.setVec3f("lightColor", 1.0f, 1.0f, 1.0f);//light source color
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 36);
//glSwapBuffers is also performed, which I've double checked

The vertex shader for the object is this:

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

out vec3 mPos;
out vec3 mNormal;

uniform vec3 lightPosition;
uniform vec3 lightColor;
uniform vec3 objectColor;

out vec3 FragColor;

void main(){

    gl_Position = projection * view * model * vec4(aPos, 1.0f);

    vec3 norm = normalize(aNormal);
    vec3 Fragpos = vec3(model*vec4(aPos, 1.0f));
    vec3 lightDir = normalize(lightPosition-Fragpos);

    float diff = max(dot(norm, lightDir), 0.0f);
    vec3 diffuse = diff*lightColor;

    FragColor = diffuse;
}

The fragment shader is this:

#version 330

in vec3 FragColor;

out vec4 outFragColor;


void main(){


    outFragColor = vec4(FragColor, 1.0f);

}    

Yet the output is: enter image description here

What could be the possible cause for this. The source code is almost exactly same to the one given in learnopenGL

The full code for reference is:

#include <GL/glew.h>
#include <GLFW/glfw3.h>

#include "Libs/glm/glm.hpp" 
#include "Libs/glm/gtc/matrix_transform.hpp"
#include "Libs/glm/gtc/type_ptr.hpp"  
#include <iostream>
#include "mLibs/camera.hpp"

#ifndef STB_IMAGE_IMPLEMENTATION
    #define STB_IMAGE_IMPLEMENTATION //must define to use the library
#endif

#include "Libs/stb_image.h"

#ifdef WINDOWS
        #include <direct.h>//for windows
        #define getcwd _getcwd
    #else
        #include <unistd.h>//for unix
#endif

#include "mLibs/window.hpp"
#include "mLibs/shaderClass.hpp"

void mouse_callback(GLFWwindow* window, double xpos, double ypos);
void scroll_callback(GLFWwindow* window, double xOffset, double yOffset);
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow *window);

Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));

float deltaTime = 0.0f;
float lastFrame = 0.0f;
// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;


bool firstMouse = true;
float lastX = SCR_WIDTH/2.0f;
float lastY = SCR_HEIGHT/2.0f;

std::string objVShader = "objVShader.vs";
std::string objFShader = "objFShader.fs";

std::string lightVShader = "lightVShader.vs";
std::string lightFShader = "lightFShader.fs";

void framebuffer_size_callback(GLFWwindow* window, int width, int height){
    glViewport(0, 0, width, height);
}

int main(){

    GLFWwindow* mainWindow = static_cast<GLFWwindow*>(window::getWindow());
    if(glewInit() != GLEW_OK){
        util::LogUtil::Log("GLEW: ", "GlewInitialization failed");
        window::DestroyAndTerminate(mainWindow);
    }


    glfwSetFramebufferSizeCallback(mainWindow, framebuffer_size_callback);
    glfwSetFramebufferSizeCallback(mainWindow, framebuffer_size_callback);
    glfwSetCursorPosCallback(mainWindow, mouse_callback);
    glfwSetScrollCallback(mainWindow, scroll_callback);

    glEnable(GL_DEPTH_TEST);

    float vertices[] = {
        -0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
        0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f, 
        0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f, 
        0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f, 
        -0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f, 
        -0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f, 

        -0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,
        0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,
        0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,
        0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,
        -0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,
        -0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,

        -0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,
        -0.5f,  0.5f, -0.5f, -1.0f,  0.0f,  0.0f,
        -0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,
        -0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,
        -0.5f, -0.5f,  0.5f, -1.0f,  0.0f,  0.0f,
        -0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,

        0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,
        0.5f,  0.5f, -0.5f,  1.0f,  0.0f,  0.0f,
        0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,
        0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,
        0.5f, -0.5f,  0.5f,  1.0f,  0.0f,  0.0f,
        0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,

        -0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,
        0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,
        0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,
        0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,

        -0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,
        0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,
        0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,
        0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,
        -0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,
        -0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f
    };



    unsigned int VAO, lightVAO, VBO;
    glGenVertexArrays(1, &VAO);
    glBindVertexArray(VAO);
        glGenBuffers(1, &VBO);
        glBindBuffer(GL_ARRAY_BUFFER, VBO);
        glBufferData(GL_ARRAY_BUFFER,sizeof(vertices), vertices, GL_STATIC_DRAW);

        glVertexAttribPointer(0,3, GL_FLOAT,GL_FALSE, 6*sizeof(float),(const void*)0);
        glEnableVertexAttribArray(0);

        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(float), (const void*)3);
        glEnableVertexAttribArray(1);

    glGenVertexArrays(1, &lightVAO);
    glBindVertexArray(lightVAO);
        //select lightVAO and bind the same VBO to this VAO
        glBindBuffer(GL_ARRAY_BUFFER, VBO);
        glVertexAttribPointer(0,3, GL_FLOAT,GL_FALSE,6*sizeof(float),(const void*)0);
        glEnableVertexAttribArray(0);

    glm::mat4 model1 = glm::mat4(1.0f);
    glm::mat4 view1 = glm::mat4(1.0f);
    glm::mat4 projection1 = glm::mat4(1.0f);

    glm::mat4 model2 = glm::mat4(1.0f);
    glm::mat4 view2 = glm::mat4(1.0f);
    glm::mat4 projection2 = glm::mat4(1.0f);

    Shader mShader(objVShader.c_str(), objFShader.c_str());
    Shader lightCubeShader(lightVShader.c_str(), lightFShader.c_str());

    mShader.CompileShaders();
    lightCubeShader.CompileShaders();

    model2 = glm::translate(model2, glm::vec3(.3f, .4f, .5f));

    projection1 = glm::perspective(camera.Zoom, static_cast<float>(SCR_WIDTH/SCR_HEIGHT), 0.1f, 100.0f);

    float currentFrame;
    while(!window::WindowShouldClose(mainWindow)){

        glfwPollEvents();

        currentFrame = glfwGetTime();
        deltaTime = currentFrame - lastFrame;
        lastFrame = currentFrame;

        processInput(mainWindow);

        view1 = camera.GetViewMatrix();
        glClearColor(1, 0, 1, 1);
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);


        mShader.use();
        mShader.setMat4fv("model", model1);
        mShader.setMat4fv("view", view1);
        mShader.setMat4fv("projection", projection1);
        mShader.setVec3f("lightPosition", 1.2f, 1.0f, 2.0f);
        mShader.setVec3f("objectColor", 1.0f, 0.0f, 0.0f);
        mShader.setVec3f("lightColor", 1.0f, 1.0f, 1.0f);


        glBindVertexArray(VAO);
        glDrawArrays(GL_TRIANGLES,0, 36);

        lightCubeShader.use();
        model2 = glm::mat4(1.0f);
        model2 = glm::translate(model2, glm::vec3(1, 1, 1));
        model2 = glm::scale(model2, glm::vec3(0.5f, 0.5f, 0.5f));
        lightCubeShader.setMat4fv("model", model2);
        lightCubeShader.setMat4fv("view", view1);
        lightCubeShader.setMat4fv("projection", projection1);
        glBindVertexArray(lightVAO);
        glDrawArrays(GL_TRIANGLES,0, 36);

        glfwSwapBuffers(mainWindow);
    }

    glDeleteVertexArrays(1,&VAO);
    glDeleteVertexArrays(1,&lightVAO);
    glDeleteBuffers(1, &VBO);

    return 0;
}



void mouse_callback(GLFWwindow* window, double xpos, double ypos){
    if(firstMouse){
        lastX = xpos;
        lastY = ypos;
        firstMouse = false;
    }

    float xOffset = xpos-lastX;
    float yOffset = lastY - ypos;
    lastX = xpos;
    lastY = ypos;
    camera.ProcessMouseMovement(xOffset, yOffset);
}

void scroll_callback(GLFWwindow* window, double xOffset, double yOffset){
    camera.ProcessMouseScroll(yOffset);
}


void processInput(GLFWwindow *window)
{
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);

    if(glfwGetKey(window, GLFW_KEY_W)==GLFW_PRESS)
        camera.ProcessKeyboard(FORWARD, deltaTime);
    if(glfwGetKey(window, GLFW_KEY_S)==GLFW_PRESS)
        camera.ProcessKeyboard(BACKWARD, deltaTime);
    if(glfwGetKey(window, GLFW_KEY_A)==GLFW_PRESS)
        camera.ProcessKeyboard(LEFT, deltaTime);
    if(glfwGetKey(window, GLFW_KEY_D)==GLFW_PRESS)
        camera.ProcessKeyboard(RIGHT, deltaTime);
    if(glfwGetKey(window, GLFW_KEY_Q)==GLFW_PRESS)
        camera.ProcessKeyboard(UP, deltaTime);
    if(glfwGetKey(window, GLFW_KEY_E)==GLFW_PRESS)
        camera.ProcessKeyboard(DOWN, deltaTime);

}

Solution

  • If a named buffer object is bound, then the last parameter of glVertexAttribPointer is treated as a byte offset into the buffer object's data store. The offset of the normal vector attribute are 3*4 bytes, thus (const void*)3 has to be (const void*)(3*sizeof(float)):

    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(float), (const void*)3);

    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(float), 
        (const void*)(3*sizeof(float));