Search code examples
openglglfwglm-math

Why did some of my surfaces disappear after I added mesh objects?


I am trying to combine 2 programs

  1. One is an empty room with a table and 2 chairs

program 1

  1. The other draws a mesh of a Taurus

I have combined both and this was the result I got Combined Program

Some of the surfaces of the table and chairs have disappeared. Can someone tell me why? I have already made an additional VBO and VAO to hold the vertice data of the meshes. However it seems to be affecting the surfaces of the cubes.

Here is my program

#define MAX_CUBES 6
#define MAX_PLANES 6

// struct for lighting properties
struct LightProperties
{
    vec4 position;
    vec4 ambient;
    vec4 diffuse;
    vec4 specular;
    float shininess;
    vec3 attenuation;
    float cutoffAngle;
    vec3 direction;
};

// struct for material properties
struct MaterialProperties
{
    vec4 ambient;
    vec4 diffuse;
    vec4 specular;
};

LightProperties g_lightProperties;
MaterialProperties g_materialProperties;

// struct for vertex attributes
struct Vertex
{
    GLfloat position[3];
    GLfloat normal[3];
};

...

Vertex g_vertices_cube[] = {
    // vertex 1
    -0.5f, 0.5f, 0.5f,  // position
    1.0f, 1.0f, 1.0f,   // normal
    // vertex 2
    -0.5f, -0.5f, 0.5f, // position
    1.0f, 1.0f, 1.0f,   // normal
    // vertex 3
    0.5f, 0.5f, 0.5f,   // position
    1.0f, 1.0f, 1.0f,   // normal
    // vertex 4
    0.5f, -0.5f, 0.5f,  // position
    1.0f, 1.0f, 1.0f,   // normal
    // vertex 5
    -0.5f, 0.5f, -0.5f, // position
    1.0f, 1.0f, 1.0f,   // normal
    // vertex 6
    -0.5f, -0.5f, -0.5f,// position
    1.0f, 1.0f, 1.0f,   // normal
    // vertex 7
    0.5f, 0.5f, -0.5f,  // position
    1.0f, 1.0f, 1.0f,   // normal
    // vertex 8
    0.5f, -0.5f, -0.5f, // position
    1.0f, 1.0f, 1.0f,   // normal
};

GLuint g_indices_cube[] = {
    0, 1, 2,    // triangle 1
    2, 1, 3,    // triangle 2
    4, 5, 0,    // triangle 3
    0, 5, 1,    // ...
    2, 3, 6,
    6, 3, 7,
    4, 0, 6,
    6, 0, 2,
    1, 5, 3,
    3, 5, 7,
    5, 4, 7,
    7, 4, 6,    // triangle 12
};

// Meshes
Vertex* g_pMeshVertices = NULL; // pointer to mesh vertices
GLint g_numberOfVertices = 0;   // number of vertices in the mesh
GLint* g_pMeshIndices = NULL;   // pointer to mesh indices
GLint g_numberOfFaces = 0;      // number of faces in the mesh

/*
    g_VBO[0] - Planes ie. walls, ceiling
    g_VBO[1] - Cubes ie. table, stools
    g_VBO[2] - Meshes (Taurus)
*/
GLuint g_IBO[2];                // index buffer object identifier
GLuint g_VBO[3];                // vertex buffer object identifier
GLuint g_VAO[3];                // vertex array object identifier
GLuint g_shaderProgramID = 0;   // shader program identifier

// locations in shader
GLuint g_MVP_Index;
GLuint g_M_Index = 0;
GLuint g_viewPointIndex = 0;
GLuint g_lightPositionIndex = 0;
GLuint g_lightAmbientIndex = 0;
GLuint g_lightDiffuseIndex = 0;
GLuint g_lightSpecularIndex = 0;
GLuint g_lightShininessIndex = 0;
GLuint g_lightAttenuationIndex = 0;
GLuint g_lightCutoffAngleIndex = 0;
GLuint g_lightDirectionIndex = 0;
GLuint g_materialAmbientIndex = 0;
GLuint g_materialDiffuseIndex = 0;
GLuint g_materialSpecularIndex = 0;

glm::mat4 g_modelMatrix_plane[MAX_PLANES];  // object's model matrix (4 walls + 1 ceiling + 1 floor)
glm::mat4 g_modelMatrix_cube[MAX_CUBES];// cube for table
glm::mat4 g_modelMatrix_mesh;       // for meshes
glm::mat4 g_viewMatrix;             // view matrix
glm::mat4 g_projectionMatrix;       // projection matrix
glm::vec3 g_viewPoint;              // view point

Camera g_camera;            // camera

GLuint g_windowWidth = 1600;        // window dimensions
GLuint g_windowHeight = 1000;
bool g_wireFrame = false;       // wireframe on or off

bool load_mesh(const char* fileName)
{
    // load file with assimp 
    const aiScene* pScene = aiImportFile(fileName, aiProcess_Triangulate
        | aiProcess_GenSmoothNormals | aiProcess_JoinIdenticalVertices);

    // check whether scene was loaded
    if (!pScene)
    {
        cout << "Could not load mesh." << endl;
        return false;
    }

    // get pointer to mesh 0
    const aiMesh* pMesh = pScene->mMeshes[0];

    // store number of mesh vertices
    g_numberOfVertices = pMesh->mNumVertices;

    // if mesh contains vertex coordinates
    if (pMesh->HasPositions())
    {
        // allocate memory for vertices
        g_pMeshVertices = new Vertex[pMesh->mNumVertices];

        // read vertex coordinates and store in the array
        for (int i = 0; i < pMesh->mNumVertices; i++)
        {
            const aiVector3D* pVertexPos = &(pMesh->mVertices[i]);

            g_pMeshVertices[i].position[0] = (GLfloat)pVertexPos->x;
            g_pMeshVertices[i].position[1] = (GLfloat)pVertexPos->y;
            g_pMeshVertices[i].position[2] = (GLfloat)pVertexPos->z;
        }
    }

    // if mesh contains normals
    if (pMesh->HasNormals())
    {
        // read normals and store in the array
        for (int i = 0; i < pMesh->mNumVertices; i++)
        {
            const aiVector3D* pVertexNormal = &(pMesh->mNormals[i]);

            g_pMeshVertices[i].normal[0] = (GLfloat)pVertexNormal->x;
            g_pMeshVertices[i].normal[1] = (GLfloat)pVertexNormal->y;
            g_pMeshVertices[i].normal[2] = (GLfloat)pVertexNormal->z;
        }
    }

    // if mesh contains faces
    if (pMesh->HasFaces())
    {
        // store number of mesh faces
        g_numberOfFaces = pMesh->mNumFaces;

        // allocate memory for vertices
        g_pMeshIndices = new GLint[pMesh->mNumFaces * 3];

        // read normals and store in the array
        for (int i = 0; i < pMesh->mNumFaces; i++)
        {
            const aiFace* pFace = &(pMesh->mFaces[i]);

            g_pMeshIndices[i * 3] = (GLint)pFace->mIndices[0];
            g_pMeshIndices[i * 3 + 1] = (GLint)pFace->mIndices[1];
            g_pMeshIndices[i * 3 + 2] = (GLint)pFace->mIndices[2];
        }
    }

    // release the scene
    aiReleaseImport(pScene);

    return true;
}

static void init(GLFWwindow* window)
{
    glEnable(GL_DEPTH_TEST);    // enable depth buffer test

    // create and compile our GLSL program from the shader files
    g_shaderProgramID = loadShaders("PerFragLightingVS.vert", "PerFragLightingFS.frag");

    // find the location of shader variables
    GLuint positionIndex = glGetAttribLocation(g_shaderProgramID, "aPosition");
    GLuint normalIndex = glGetAttribLocation(g_shaderProgramID, "aNormal");
    g_MVP_Index = glGetUniformLocation(g_shaderProgramID, "uModelViewProjectionMatrix");
    g_M_Index = glGetUniformLocation(g_shaderProgramID, "uModelMatrix");
    g_viewPointIndex = glGetUniformLocation(g_shaderProgramID, "uViewPoint");

    g_lightPositionIndex = glGetUniformLocation(g_shaderProgramID, "uLightingProperties.position");
    g_lightAmbientIndex = glGetUniformLocation(g_shaderProgramID, "uLightingProperties.ambient");
    g_lightDiffuseIndex = glGetUniformLocation(g_shaderProgramID, "uLightingProperties.diffuse");
    g_lightSpecularIndex = glGetUniformLocation(g_shaderProgramID, "uLightingProperties.specular");
    g_lightShininessIndex = glGetUniformLocation(g_shaderProgramID, "uLightingProperties.shininess");
    g_lightAttenuationIndex = glGetUniformLocation(g_shaderProgramID, "uLightingProperties.attenuation");
    g_lightCutoffAngleIndex = glGetUniformLocation(g_shaderProgramID, "uLightingProperties.cutoffAngle");
    g_lightDirectionIndex = glGetUniformLocation(g_shaderProgramID, "uLightingProperties.direction");

    g_materialAmbientIndex = glGetUniformLocation(g_shaderProgramID, "uMaterialProperties.ambient");
    g_materialDiffuseIndex = glGetUniformLocation(g_shaderProgramID, "uMaterialProperties.diffuse");
    g_materialSpecularIndex = glGetUniformLocation(g_shaderProgramID, "uMaterialProperties.specular");

    // initialise model matrix to the identity matrix
    for (int i = 0; i < MAX_PLANES; i++) { g_modelMatrix_plane[i] = glm::mat4(1.0f); }
    for (int i = 0; i < MAX_CUBES; i++) { g_modelMatrix_cube[i] = glm::mat4(1.0f); }
    g_modelMatrix_mesh = glm::mat4(1.0f);

...

// Model Matrices - Cubes
    // Table-top
    g_modelMatrix_cube[0] = glm::scale(glm::vec3(1.4f, 0.2f, 1.4f));
    // Table Leg 1
    g_modelMatrix_cube[1] = glm::translate(glm::vec3(-0.5f, -0.55f, 0.5f))
        * glm::scale(glm::vec3(0.2f, 1.2f, 0.2f));
    // Table Leg 2
    g_modelMatrix_cube[2] = glm::translate(glm::vec3(0.5f, -0.55f, 0.5f))
        * glm::scale(glm::vec3(0.2f, 1.2f, 0.2f));
    // Table Leg 3
    g_modelMatrix_cube[3] = glm::translate(glm::vec3(-0.5f, -0.55f, -0.5f))
        * glm::scale(glm::vec3(0.2f, 1.2f, 0.2f));
    // Table Leg 4
    g_modelMatrix_cube[4] = glm::translate(glm::vec3(0.5f, -0.55f, -0.5f))
        * glm::scale(glm::vec3(0.2f, 1.2f, 0.2f));
    // Chair back-rest (note: chair is a table but scaled down. And add a backrest)
    g_modelMatrix_cube[5] = glm::translate(glm::vec3(0.5f, 0.5f, 0.0f))
        * glm::scale(glm::vec3(0.2f, 1.2f, 1.35f));

// Model Matrices - Mesh
    g_modelMatrix_mesh = glm::scale(glm::vec3(0.3f, 0.3f, 0.3f));

    // set camera's view matrix
    g_camera.setViewMatrix(glm::vec3(0, 0, 3), glm::vec3(0, 0, 2), glm::vec3(0, 1, 0));

    int width, height;
    glfwGetFramebufferSize(window, &width, &height);
    float aspectRatio = static_cast<float>(width) / height;

    // set camera's projection matrix
    g_camera.setProjectionMatrix(glm::perspective(45.0f, aspectRatio, 0.1f, 100.0f));

    // load mesh
    load_mesh("models/WusonOBJ.obj");
    //load_mesh("models/suzanne.obj");

// initialise light and material properties
    g_lightProperties.position = glm::vec4(0.0f, 2.0f, 0.0f, 1.0f);
    g_lightProperties.ambient = glm::vec4(0.2f, 0.2f, 0.2f, 1.0f);
    g_lightProperties.diffuse = glm::vec4(0.0f, 0.5f, 1.0f, 1.0f);
    g_lightProperties.specular = glm::vec4(0.0f, 0.5f, 1.0f, 1.0f);
    g_lightProperties.shininess = 10.0f;
    g_lightProperties.attenuation = glm::vec3(1.0f, 0.0f, 0.0f);
    //g_lightProperties.cutoffAngle = 45.0f;
    g_lightProperties.cutoffAngle = 180.0f;
    g_lightProperties.direction = glm::vec3(0.0f, -1.0f, 0.0f);

// Material Properties - Planes
    // Floor
    g_materialProperties.ambient = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f);
    g_materialProperties.diffuse = glm::vec4(0.2f, 0.7f, 1.0f, 1.0f);
    g_materialProperties.specular = glm::vec4(0.2f, 0.7f, 1.0f, 1.0f);

...

// Cube
    // generate identifier for VBOs and copy data to GPU
    glGenBuffers(1, &g_VBO[1]);
    glBindBuffer(GL_ARRAY_BUFFER, g_VBO[1]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertices_cube), g_vertices_cube, GL_STATIC_DRAW);

    // generate identifier for IBO and copy data to GPU
    glGenBuffers(1, &g_IBO[0]);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_IBO[0]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(g_indices_cube), g_indices_cube, GL_STATIC_DRAW);

    // generate identifiers for VAO
    glGenVertexArrays(1, &g_VAO[1]);

    // create VAO and specify VBO data
    glBindVertexArray(g_VAO[1]);
    glBindBuffer(GL_ARRAY_BUFFER, g_VBO[1]);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_IBO[0]);
    glVertexAttribPointer(positionIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, position)));
    glVertexAttribPointer(normalIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, normal)));

    glEnableVertexAttribArray(positionIndex);   // enable vertex attributes
    glEnableVertexAttribArray(normalIndex);

// Meshes
    // generate identifier for VBOs and copy data to GPU
    glGenBuffers(1, &g_VBO[2]);
    glBindBuffer(GL_ARRAY_BUFFER, g_VBO[2]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex)*g_numberOfVertices, g_pMeshVertices, GL_STATIC_DRAW);

    // generate identifier for IBO and copy data to GPU
    glGenBuffers(1, &g_IBO[1]);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_IBO[1]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLint) * 3 * g_numberOfFaces, g_pMeshIndices, GL_STATIC_DRAW);

    // generate identifiers for VAO
    glGenVertexArrays(1, &g_VAO[2]);

    // create VAO and specify VBO data
    glBindVertexArray(g_VAO[2]);
    glBindBuffer(GL_ARRAY_BUFFER, g_VBO[2]);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_IBO[1]);
    glVertexAttribPointer(positionIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, position)));
    glVertexAttribPointer(normalIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, normal)));

    glEnableVertexAttribArray(positionIndex);   // enable vertex attributes
    glEnableVertexAttribArray(normalIndex);
}

// function used to render the scene
static void render_scene()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear colour buffer and depth buffer

    glUseProgram(g_shaderProgramID);    // use the shaders associated with the shader program

    glBindVertexArray(g_VAO[0]);        // make VAO active

// Material Properties - Planes
    glUniform4fv(g_materialAmbientIndex, 1, &g_materialProperties.ambient[0]);
    glUniform4fv(g_materialDiffuseIndex, 1, &g_materialProperties.diffuse[0]);
    glUniform4fv(g_materialSpecularIndex, 1, &g_materialProperties.specular[0]);

    glUniform4fv(g_lightPositionIndex, 1, &g_lightProperties.position[0]);
    glUniform4fv(g_lightAmbientIndex, 1, &g_lightProperties.ambient[0]);
    glUniform4fv(g_lightDiffuseIndex, 1, &g_lightProperties.diffuse[0]);
    glUniform4fv(g_lightSpecularIndex, 1, &g_lightProperties.specular[0]);
    glUniform1fv(g_lightShininessIndex, 1, &g_lightProperties.shininess);
    glUniform3fv(g_lightAttenuationIndex, 1, &g_lightProperties.attenuation[0]);
    glUniform1fv(g_lightCutoffAngleIndex, 1, &g_lightProperties.cutoffAngle);
    glUniform3fv(g_lightDirectionIndex, 1, &g_lightProperties.direction[0]);

    // set uniform shader variables
    glm::mat4 MVP = glm::mat4(1.0f);

// Draw Planes
    for (int i = 0; i < MAX_PLANES; i++)
    {
        MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix_plane[i];
        glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
        glUniformMatrix4fv(g_M_Index, 1, GL_FALSE, &g_modelMatrix_plane[i][0][0]);
        glUniform3fv(g_viewPointIndex, 1, &g_viewPoint[0]);
        glDrawArrays(GL_TRIANGLES, 0, 6);
    }

    glBindVertexArray(g_VAO[1]);        // make VAO active

// Draw Cubes
    // Table top + 4 Table legs
    for (int i = 0; i < (MAX_CUBES - 1); i++)
    {
        MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix_cube[i];
        glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
        glUniformMatrix4fv(g_M_Index, 1, GL_FALSE, &g_modelMatrix_cube[i][0][0]);
        glUniform3fv(g_viewPointIndex, 1, &g_viewPoint[0]);
        glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);   // display the vertices based on their indices and primitive type
    }

    // Chair (Right)
    for (int i = 0; i < MAX_CUBES; i++)
    {
        MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() 
            * glm::translate(glm::vec3(1.5f, -0.2f, 0.0f)) * glm::scale(glm::vec3(0.7f, 0.7f, 0.7f)) * g_modelMatrix_cube[i];
        glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
        glUniformMatrix4fv(g_M_Index, 1, GL_FALSE, &g_modelMatrix_cube[i][0][0]);
        glUniform3fv(g_viewPointIndex, 1, &g_viewPoint[0]);
        glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);   // display the vertices based on their indices and primitive type
    }
    // Chair (Left)
    for (int i = 0; i < MAX_CUBES; i++)
    {
        MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix()
            * glm::rotate(glm::radians(180.0f), glm::vec3(0.0f, 1.0f, 0.0f))
            * glm::translate(glm::vec3(1.5f, -0.2f, 0.0f)) * glm::scale(glm::vec3(0.7f, 0.7f, 0.7f)) * g_modelMatrix_cube[i];
        glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
        glUniformMatrix4fv(g_M_Index, 1, GL_FALSE, &g_modelMatrix_cube[i][0][0]);
        glUniform3fv(g_viewPointIndex, 1, &g_viewPoint[0]);
        glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);   // display the vertices based on their indices and primitive type
    }

    glBindVertexArray(g_VAO[2]);        // make VAO active

// Draw Meshes
    // Taurus
    MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix_mesh;
    glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
    glUniformMatrix4fv(g_M_Index, 1, GL_FALSE, &g_modelMatrix_mesh[0][0]);
    glUniform3fv(g_viewPointIndex, 1, &g_viewPoint[0]);
    glDrawElements(GL_TRIANGLES, g_numberOfFaces * 3, GL_UNSIGNED_INT, 0);  // display the vertices based on their indices and primitive type

    glFlush();  // flush the pipeline
}

...

int main(void)
{
    GLFWwindow* window = NULL;  // pointer to a GLFW window handle
    TwBar *TweakBar;            // pointer to a tweak bar

    glfwSetErrorCallback(error_callback);   // set error callback function

    // initialise GLFW
    if (!glfwInit())
    {
        // if failed to initialise GLFW
        exit(EXIT_FAILURE);
    }

    // minimum OpenGL version 3.3
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);

    // create a window and its OpenGL context
    window = glfwCreateWindow(g_windowWidth, g_windowHeight, "Tutorial", NULL, NULL);

    // if failed to create window
    if (window == NULL)
    {
        glfwTerminate();
        exit(EXIT_FAILURE);
    }

    glfwMakeContextCurrent(window); // set window context as the current context
    glfwSwapInterval(1);            // swap buffer interval

    // initialise GLEW
    if (glewInit() != GLEW_OK)
    {
        // if failed to initialise GLEW
        cerr << "GLEW initialisation failed" << endl;
        exit(EXIT_FAILURE);
    }

    // set key callback function
    glfwSetKeyCallback(window, key_callback);
    glfwSetCursorPosCallback(window, cursor_position_callback);
    glfwSetMouseButtonCallback(window, mouse_button_callback);

    // use sticky mode to avoid missing state changes from polling
    glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);

    // use mouse to move camera, hence use disable cursor mode
    glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);

    // initialise AntTweakBar
    TwInit(TW_OPENGL_CORE, NULL);

    // give tweak bar the size of graphics window
    TwWindowSize(g_windowWidth, g_windowHeight);
    TwDefine(" TW_HELP visible=false ");    // disable help menu
    TwDefine(" GLOBAL fontsize=3 ");        // set large font size

    // create a tweak bar
    TweakBar = TwNewBar("Main");
    TwDefine(" Main label='Controls' refresh=0.02 text=light size='220 200' ");

    // create display entries
    TwAddVarRW(TweakBar, "Wireframe", TW_TYPE_BOOLCPP, &g_wireFrame, " group='Display' ");

    // display a separator
    TwAddSeparator(TweakBar, NULL, NULL);

    // create spotlight entries
    TwAddVarRW(TweakBar, "Cutoff", TW_TYPE_FLOAT, &g_lightProperties.cutoffAngle, " group='Spotlight' min=-180.0 max=180.0 step=1.0 ");
    TwAddVarRW(TweakBar, "Direction: x", TW_TYPE_FLOAT, &g_lightProperties.direction[0], " group='Spotlight' min=-1.0 max=1.0 step=0.1");
    TwAddVarRW(TweakBar, "Direction: y", TW_TYPE_FLOAT, &g_lightProperties.direction[1], " group='Spotlight' min=-1.0 max=1.0 step=0.1");
    TwAddVarRW(TweakBar, "Direction: z", TW_TYPE_FLOAT, &g_lightProperties.direction[2], " group='Spotlight' min=-1.0 max=1.0 step=0.1");

    // initialise rendering states
    init(window);

    // the rendering loop
    while (!glfwWindowShouldClose(window))
    {
        g_camera.update(window);    // update camera

        if (g_wireFrame)
            glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

        render_scene();     // render the scene

        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

        TwDraw();           // draw tweak bar(s)

        glfwSwapBuffers(window);    // swap buffers
        glfwPollEvents();           // poll for events
    }

    // clean up
    if (g_pMeshVertices)
        delete[] g_pMeshVertices;
    if (g_pMeshIndices)
        delete[] g_pMeshIndices;
    glDeleteProgram(g_shaderProgramID);
    glDeleteBuffers(1, &g_VBO[0]);
    glDeleteVertexArrays(1, &g_VAO[0]);

    // uninitialise tweak bar
    TwTerminate();

    // close the window and terminate GLFW
    glfwDestroyWindow(window);
    glfwTerminate();

    exit(EXIT_SUCCESS);
}

Fragment shader

#version 330 core

// interpolated values from the vertex shaders
in vec3 vNormal;
in vec3 vPosition;

// uniform input data
struct LightProperties
{
    vec4 position;
    vec4 ambient;
    vec4 diffuse;
    vec4 specular;
    float shininess;
    vec3 attenuation;
    float cutoffAngle;
    vec3 direction;
};

struct MaterialProperties
{
    vec4 ambient;
    vec4 diffuse;
    vec4 specular;
};

uniform LightProperties uLightingProperties;
uniform MaterialProperties uMaterialProperties;
uniform vec3 uViewPoint;

// output data
out vec3 fColor;

void main()
{
    // calculate vectors for lighting
    vec3 N = normalize(vNormal);
    vec3 L;
    float attenuation = 1.0f;

    // calculate the attenuation based on distance
    L = (uLightingProperties.position).xyz - vPosition;
    float distance = length(L);
    L = normalize(L);
    attenuation = 1/(uLightingProperties.attenuation.x 
        + uLightingProperties.attenuation.y * distance 
        + uLightingProperties.attenuation.z * distance * distance);

    vec3 V = normalize(uViewPoint - vPosition);
    vec3 R = reflect(-L, N);

    // the direction of the spotlight
    vec3 direction = normalize(uLightingProperties.direction);
    // the angle between the vector from the light to the fragment’s position and the spotlight’s direction
    float angle = degrees(acos(dot(-L, direction)));

    vec3 colour = vec3(0.0f, 0.0f, 0.0f);

    // only compute if angle is less than the cutoff angle
    if(angle <= uLightingProperties.cutoffAngle)
    {
        // calculate Phong lighting
        vec4 ambient  = uLightingProperties.ambient * uMaterialProperties.ambient;
        vec4 diffuse  = uLightingProperties.diffuse * uMaterialProperties.diffuse * max(dot(L, N), 0.0);
        vec4 specular = vec4(0.0f, 0.0f, 0.0f, 1.0f);

        if(dot(L, N) > 0.0f)
        {
            specular = uLightingProperties.specular * uMaterialProperties.specular 
                * pow(max(dot(V, R), 0.0), uLightingProperties.shininess);
        }

        colour = (attenuation * (diffuse + specular)).rgb + ambient.rgb;
        // fade the spotlight's intensity linearly with angle
        colour *= 1.0f - angle/uLightingProperties.cutoffAngle;
    }

    // set output color
    fColor = colour;    
}

Solution

  • You are overriding the index buffer of g_VAO[1]. Since you don't unbind the VAO after it its initialization has finished, glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_IBO[1]); will modify it.

    To solve your problem: Unbind VAOs before binding any buffers that are not related to them.