c++openglglslglfwsoil

Problem with adding texture to triangle using SOIL in OpenGL


This is an error that appears when trying to load the texture: enter image description hereThis is my working directory: enter image description here Down below is the location of my texture images enter image description hereI tried adding a texture to a triangle however something seems to go wrong. When trying to run debug there is no error and no warning however it shows an grey window with no triangle and no texture whatsoever. Here is a part of my code, what is wrong?

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#define GLEW_STATIC


#include "GL/glew.h"
#include "GLFW/glfw3.h"
#include "SOIL2/SOIL2.h"

int glWindowWidth = 640;
int glWindowHeight = 480;
int retina_width, retina_height;
GLFWwindow* glWindow = NULL;

GLfloat vertexCoordinates[] = {
    //position         //color           //texture
    0.5f,0.5f,0.0f,    1.0f,0.0f,0.0f,   1.0f ,1.0f,
    0.5f,-0.5f,0.0f,    1.0f,1.0f,1.0f,   1.0f,0.0f
    -0.5f,-0.5f,0.0f,    1.0f,0.0f,0.0f,   0.0f ,0.0f,
    -0.5f,0.5f,0.0f,    1.0f,0.0f,1.0f,   0.0f ,1.0f,
};
GLuint indices[] = 
{
0,1,2,  
1,2,3
};


GLuint verticesVBO;
GLuint triangleVAO;
GLuint EBO;




GLuint triangleVAO2;
GLuint verticesVBO2;


GLuint shaderProgram;
GLuint shaderProgram2;



void windowResizeCallback(GLFWwindow* window, int width, int height)
{
    fprintf(stdout, "window resized to width: %d , and height: %d\n", width, height);
    //TODO
}

void initObjects()
{
    //genereaza un ID unic pentru verticesVBO
    glGenBuffers(1, &verticesVBO);
    glGenBuffers(1, &EBO);
    glGenVertexArrays(1, &triangleVAO);
    glBindBuffer(GL_ARRAY_BUFFER, verticesVBO);

    glBufferData(GL_ARRAY_BUFFER, sizeof(vertexCoordinates), vertexCoordinates, GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    //genereaza un ID unic, care corespunde obiectului triangleVAO

    glBindVertexArray(triangleVAO);
    glBindBuffer(GL_ARRAY_BUFFER, verticesVBO);

    //seteaza pointer-ul atributelor de varf
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (GLvoid *)0);
    glEnableVertexAttribArray(0);
    //color attribute
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat)));
    glEnableVertexAttribArray(1);


    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
    glEnableVertexAttribArray(2);
    //de-selecteaza obiectul triangleVAO
    glBindVertexArray(0);




}

bool initOpenGLWindow()
{
    if (!glfwInit()) {
        fprintf(stderr, "ERROR: could not start GLFW3\n");
        return false;
    }

    //for Mac OS X
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_RESIZABLE,GL_FALSE);

    glWindow = glfwCreateWindow(glWindowWidth, glWindowHeight, "OpenGL Shader Example", NULL, NULL);
    if (!glWindow) {
        fprintf(stderr, "ERROR: could not open window with GLFW3\n");
        glfwTerminate();
        return false;
    }

    glfwSetWindowSizeCallback(glWindow, windowResizeCallback);
    glfwMakeContextCurrent(glWindow);

    glfwWindowHint(GLFW_SAMPLES, 4);

    // start GLEW extension handler
    glewExperimental = GL_TRUE;
    glewInit();

    // get version info
    const GLubyte* renderer = glGetString(GL_RENDERER); // get renderer string
    const GLubyte* version = glGetString(GL_VERSION); // version as a string
    printf("Renderer: %s\n", renderer);
    printf("OpenGL version supported %s\n", version);

    //for RETINA display
    glfwGetFramebufferSize(glWindow, &retina_width, &retina_height);

    return true;
}

void renderScene()
{
    //initializeaza buffer-ele de culoare si adancime inainte de a rasteriza cadrul curent
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    //defineste culoarea de fundal
    glClearColor(0.8, 0.8, 0.8, 1.0);
    //specifica locatia si dimensiunea ferestrei
    glViewport(0, 0, retina_width, retina_height);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);


    if (glfwGetKey(glWindow, GLFW_KEY_D)) {
        //TODO
    }

    //activeaza program shader-ul; apeluri ulterioare de rasterizare vor utiliza acest program
    glUseProgram(shaderProgram); /**/

    //activeaza VAO
    glBindVertexArray(triangleVAO);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    glBindVertexArray(0);


    //specifica tipul primitiei, indicele de inceput si numarul de indici utilizati pentru rasterizare
    //glDrawArrays(GL_TRIANGLES, 0, 3);


    //glDrawArrays(GL_TRIANGLES, 0, 3); /**/



}

std::string readShaderFile(std::string fileName)
{
    std::ifstream shaderFile;
    std::string shaderString;

    //open shader file
    shaderFile.open(fileName);

    std::stringstream shaderStringStream;

    //read shader content into stream
    shaderStringStream << shaderFile.rdbuf();

    //close shader file
    shaderFile.close();

    //convert stream into GLchar array
    shaderString = shaderStringStream.str();
    return shaderString;
}

void shaderCompileLog(GLuint shaderId)
{
    GLint success;
    GLchar infoLog[512];

    //check compilation info
    glGetShaderiv(shaderId, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(shaderId, 512, NULL, infoLog);
        std::cout << "Shader compilation error\n" << infoLog << std::endl;
    }
}

void shaderLinkLog(GLuint shaderProgramId)
{
    GLint success;
    GLchar infoLog[512];

    //check linking info
    glGetProgramiv(shaderProgramId, GL_LINK_STATUS, &success);
    if (!success) {
        glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
        std::cout << "Shader linking error\n" << infoLog << std::endl;
    }
}

GLuint initBasicShader(std::string vertexShaderFileName, std::string fragmentShaderFileName, GLuint shaderProgram)
{
    //read, parse and compile the vertex shader
    std::string v = readShaderFile(vertexShaderFileName);
    const GLchar* vertexShaderString = v.c_str();
    GLuint vertexShader;
    vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderString, NULL);
    glCompileShader(vertexShader);
    //check compilation status
    shaderCompileLog(vertexShader);

    //read, parse and compile the vertex shader
    std::string f = readShaderFile(fragmentShaderFileName);
    const GLchar* fragmentShaderString = f.c_str();
    GLuint fragmentShader;
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderString, NULL);
    glCompileShader(fragmentShader);
    //check compilation status
    shaderCompileLog(fragmentShader);

    //attach and link the shader programs
    shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);
    //check linking info
    shaderLinkLog(shaderProgram);

    return shaderProgram;
}


int main(int argc, const char * argv[]) {

    initOpenGLWindow();

    initObjects();

    shaderProgram = initBasicShader("shaders/shader.vert", "shaders/shader.frag",shaderProgram);
    shaderProgram2 = initBasicShader("shaders/shader2.vert", "shaders/shader2.frag",shaderProgram2);
    int width, height;
    GLuint texture;

    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    unsigned char* image = SOIL_load_image("res/images/image1.jpg", &width, &height, 0, SOIL_LOAD_RGBA);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
    glGenerateMipmap(GL_TEXTURE_2D);
    SOIL_free_image_data(image);
    glBindTexture(GL_TEXTURE_2D, 0);
    while (!glfwWindowShouldClose(glWindow)) {
        glActiveTexture(GL_TEXTURE0);
        glfwPollEvents();
        renderScene();
        glBindTexture(GL_TEXTURE_2D, texture);
        glUniform1i(glGetUniformLocation(shaderProgram, "diffuseTexture"), 0);
        glBindVertexArray(triangleVAO);
        glfwSwapBuffers(glWindow);
    }

    //close GL context and any other GLFW resources
    glfwTerminate();

    return 0;
}

This is the fragment shader

#version 400
in vec3 colour;
in vec2 passTexture;
out vec4 fragmentColour;
uniform sampler2D dif;
void main() {
    fragmentColour = texture(dif, passTexture);
}

This is the vertex shader:

#version 400
layout(location = 0) in vec3 vertexPosition;
layout(location = 1) in vec3 vertexNormal;
layout(location = 2) in vec2 textcoord;
out vec3 colour;
out vec2 passTexture;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main() {
    colour = vertexNormal;
    passTexture = textcoord;
    gl_Position = projection * view * model * vec4(vertexPosition, 1.0);
}

Solution

  • By default all fields of the matrices in the vertex are shader are initialized by 0.0.

    To make the code run you've to skip the matrices:

    gl_Position = vec4(vertexPosition, 1.0);
    

    Or initialize them by the Identity matrix in renderScene:

    GLint model_loc = glGetUniformLocation(shaderProgram, "model");
    GLint view_loc  = glGetUniformLocation(shaderProgram, "view");
    GLint proj_loc  = glGetUniformLocation(shaderProgram, "projection");
    GLint tex_loc   = glGetUniformLocation(shaderProgram, "diffuseTexture");
    
    float identity_matrix[] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
    

    Note, uniforms have to be set, after the program is installed by glUseProgram.

    glUseProgram(shaderProgram);
    
    glUniformMatrix4fv(model_loc, 1, GL_FALSE, identity_matrix);
    glUniformMatrix4fv(view_loc,  1, GL_FALSE, identity_matrix);
    glUniformMatrix4fv(proj_loc,  1, GL_FALSE, identity_matrix);
    glUniform1i(tex_loc, 0); // unnecessary, because 0 is default.
    

    Since the Index buffers is stated in the Vertex Array Object, the VAO has to be bound, before the index buffer can be bound:

    glGenVertexArrays(1, &triangleVAO);
    glBindVertexArray(triangleVAO);
    
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
    

    Set all the necessary states, and bind the necessary objects, before you do the draw call.
    The viewport rectangle and the clear color should be set before glClear.
    The texture should be bound before the mesh is drawn.

    while (!glfwWindowShouldClose(glWindow)) {
        glfwPollEvents();        
    
        renderScene();
    
        glfwSwapBuffers(glWindow);
    }
    
    void renderScene()
    {
        glViewport(0, 0, retina_width, retina_height);
        glClearColor(0.8, 0.8, 0.8, 1.0);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
    
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, texture);
        glBindVertexArray(triangleVAO);
    
        glUseProgram(shaderProgram);
        // set the uniforms as described above
        // [...]
    
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    }
    

    Furthermore there is missing a comma (,) int the 2nd row of the array of vertex array attributes and the indices do not form a quad. Change it:

    GLfloat vertexCoordinates[] = {
        //position         //color           //texture
         0.5f, 0.5f,0.0f,    1.0f,0.0f,0.0f,  1.0f ,1.0f,
         0.5f,-0.5f,0.0f,    1.0f,1.0f,1.0f,  1.0f ,0.0f,
        -0.5f,-0.5f,0.0f,    1.0f,0.0f,0.0f,  0.0f ,0.0f,
        -0.5f, 0.5f,0.0f,    1.0f,0.0f,1.0f,  0.0f ,1.0f,
    };
    GLuint indices[] = { 0,1,2, 0,2,3 };
    

    Finally, if you want to use mipmaping, then the texture minification filter has to be one of GL_NEAREST_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR or GL_LINEAR_MIPMAP_LINEAR.


    Full code:

    #include <iostream>
    #include <fstream>
    #include <string>
    #include <sstream>
    #define GLEW_STATIC
    
    #include "GL/glew.h"
    #include "GLFW/glfw3.h"
    #include "SOIL2/SOIL2.h"
    
    int glWindowWidth = 640;
    int glWindowHeight = 480;
    int retina_width, retina_height;
    GLFWwindow* glWindow = NULL;
    
    GLfloat vertexCoordinates[] = {
        //position         //color           //texture
         0.5f, 0.5f,0.0f,    1.0f,0.0f,0.0f,  1.0f ,1.0f,
         0.5f,-0.5f,0.0f,    1.0f,1.0f,1.0f,  1.0f ,0.0f,
        -0.5f,-0.5f,0.0f,    1.0f,0.0f,0.0f,  0.0f ,0.0f,
        -0.5f, 0.5f,0.0f,    1.0f,0.0f,1.0f,  0.0f ,1.0f,
    };
    GLuint indices[] = { 0,1,2, 0,2,3 };
    
    GLuint verticesVBO;
    GLuint triangleVAO;
    GLuint EBO;
    GLuint triangleVAO2;
    GLuint verticesVBO2;
    GLuint shaderProgram;
    GLuint shaderProgram2;
    GLuint texture;
    GLint model_loc, view_loc, proj_loc, tex_loc;
    float identity_matrix[] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
    
    void windowResizeCallback(GLFWwindow* window, int width, int height)
    {
        fprintf(stdout, "window resized to width: %d , and height: %d\n", width, height);
        //TODO
    }
    
    void initObjects()
    {
        //genereaza un ID unic pentru verticesVBO
        glGenBuffers(1, &verticesVBO);
        glGenBuffers(1, &EBO);
        glGenVertexArrays(1, &triangleVAO);
        glBindVertexArray(triangleVAO);
    
        glBindBuffer(GL_ARRAY_BUFFER, verticesVBO);
        glBufferData(GL_ARRAY_BUFFER, sizeof(vertexCoordinates), vertexCoordinates, GL_STATIC_DRAW);
    
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
    
        //genereaza un ID unic, care corespunde obiectului triangleVAO
    
        glBindBuffer(GL_ARRAY_BUFFER, verticesVBO);
    
        //seteaza pointer-ul atributelor de varf
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (GLvoid *)0);
        glEnableVertexAttribArray(0);
        //color attribute
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat)));
        glEnableVertexAttribArray(1);
    
        glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
        glEnableVertexAttribArray(2);
        //de-selecteaza obiectul triangleVAO
        glBindVertexArray(0);
    }
    
    bool initOpenGLWindow()
    {
        if (!glfwInit()) {
            fprintf(stderr, "ERROR: could not start GLFW3\n");
            return false;
        }
    
        //for Mac OS X
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
        glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
        glfwWindowHint(GLFW_RESIZABLE,GL_FALSE);
    
        glWindow = glfwCreateWindow(glWindowWidth, glWindowHeight, "OpenGL Shader Example", NULL, NULL);
        if (!glWindow) {
            fprintf(stderr, "ERROR: could not open window with GLFW3\n");
            glfwTerminate();
            return false;
        }
    
        glfwSetWindowSizeCallback(glWindow, windowResizeCallback);
        glfwMakeContextCurrent(glWindow);
    
        glfwWindowHint(GLFW_SAMPLES, 4);
    
        // start GLEW extension handler
        glewExperimental = GL_TRUE;
        glewInit();
    
        // get version info
        const GLubyte* renderer = glGetString(GL_RENDERER); // get renderer string
        const GLubyte* version = glGetString(GL_VERSION); // version as a string
        printf("Renderer: %s\n", renderer);
        printf("OpenGL version supported %s\n", version);
    
        //for RETINA display
        glfwGetFramebufferSize(glWindow, &retina_width, &retina_height);
    
        return true;
    }
    
    void renderScene()
    {
        glViewport(0, 0, retina_width, retina_height);
        glClearColor(0.8, 0.8, 0.8, 1.0);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
    
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, texture);
        glBindVertexArray(triangleVAO);
    
        if (glfwGetKey(glWindow, GLFW_KEY_D)) {
            //TODO
        }
    
        glUseProgram(shaderProgram);
        glUniformMatrix4fv(model_loc, 1, GL_FALSE, identity_matrix);
        glUniformMatrix4fv(view_loc,  1, GL_FALSE, identity_matrix);
        glUniformMatrix4fv(proj_loc,  1, GL_FALSE, identity_matrix);
        glUniform1i(tex_loc, 0); // unnecessary, because 0 is default.
    
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    }
    
    std::string readShaderFile(std::string fileName)
    {
        std::ifstream shaderFile;
        std::string shaderString;
    
        //open shader file
        shaderFile.open(fileName);
    
        std::stringstream shaderStringStream;
    
        //read shader content into stream
        shaderStringStream << shaderFile.rdbuf();
    
        //close shader file
        shaderFile.close();
    
        //convert stream into GLchar array
        shaderString = shaderStringStream.str();
        return shaderString;
    }
    
    void shaderCompileLog(GLuint shaderId)
    {
        GLint success;
        GLchar infoLog[512];
    
        //check compilation info
        glGetShaderiv(shaderId, GL_COMPILE_STATUS, &success);
        if (!success)
        {
            glGetShaderInfoLog(shaderId, 512, NULL, infoLog);
            std::cout << "Shader compilation error\n" << infoLog << std::endl;
        }
    }
    
    void shaderLinkLog(GLuint shaderProgramId)
    {
        GLint success;
        GLchar infoLog[512];
    
        //check linking info
        glGetProgramiv(shaderProgramId, GL_LINK_STATUS, &success);
        if (!success) {
            glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
            std::cout << "Shader linking error\n" << infoLog << std::endl;
        }
    }
    
    GLuint initBasicShader(std::string vertexShaderFileName, std::string fragmentShaderFileName, GLuint shaderProgram)
    {
        //read, parse and compile the vertex shader
        std::string v = readShaderFile( vertexShaderFileName );
        const GLchar* vertexShaderString = v.c_str();
        GLuint vertexShader;
        vertexShader = glCreateShader(GL_VERTEX_SHADER);
        glShaderSource(vertexShader, 1, &vertexShaderString, NULL);
        glCompileShader(vertexShader);
        //check compilation status
        shaderCompileLog(vertexShader);
    
        //read, parse and compile the vertex shader
        std::string f = readShaderFile( fragmentShaderFileName );
        const GLchar* fragmentShaderString = f.c_str();
        GLuint fragmentShader;
        fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
        glShaderSource(fragmentShader, 1, &fragmentShaderString, NULL);
        glCompileShader(fragmentShader);
        //check compilation status
        shaderCompileLog(fragmentShader);
    
        //attach and link the shader programs
        shaderProgram = glCreateProgram();
        glAttachShader(shaderProgram, vertexShader);
        glAttachShader(shaderProgram, fragmentShader);
        glLinkProgram(shaderProgram);
        glDeleteShader(vertexShader);
        glDeleteShader(fragmentShader);
        //check linking info
        shaderLinkLog(shaderProgram);
    
        return shaderProgram;
    }
    
    int main(int argc, const char * argv[]) {
    
        initOpenGLWindow();
    
        initObjects();
    
        shaderProgram = initBasicShader("shaders/shader.vert", "shaders/shader.frag",shaderProgram);
    
        model_loc = glGetUniformLocation(shaderProgram, "model");
        view_loc  = glGetUniformLocation(shaderProgram, "view");
        proj_loc  = glGetUniformLocation(shaderProgram, "projection");
        tex_loc   = glGetUniformLocation(shaderProgram, "diffuseTexture");
    
        shaderProgram2 = initBasicShader("shaders/shader2.vert", "shaders/shader2.frag",shaderProgram2);
        int width, height;
    
        glGenTextures(1, &texture);
        glBindTexture(GL_TEXTURE_2D, texture);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        unsigned char* image = SOIL_load_image("SOIL2/res/images/image1.jpg", &width, &height, 0, SOIL_LOAD_RGBA);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
        glGenerateMipmap(GL_TEXTURE_2D);
        SOIL_free_image_data(image);
        glBindTexture(GL_TEXTURE_2D, 0);
        while (!glfwWindowShouldClose(glWindow)) {
            glfwPollEvents();        
    
            renderScene();
    
            glfwSwapBuffers(glWindow);
        }
    
        //close GL context and any other GLFW resources
        glfwTerminate();
    
        return 0;
    }