Does this run properly for anyone else?

Hi everyone. This is my first OpenGL program, and I understand all of of the concepts (VAOs, VBOs, etc…) but just cannot get it to work.


//
//  main.cpp
//  opengl_rect_w_shader_header
//
//  Created by Pramod on 21/05/2017.
//  Copyright © 2017 Pramod. All rights reserved.
//

#include <iostream>
#include <SDL2/SDL.h>
#include <OpenGL/gl3.h>
#include <OpenGL/gl3ext.h>

SDL_GLContext context;
SDL_Window * window;

bool initWindow(){
    
    if (SDL_Init(SDL_INIT_VIDEO)<0){
        std::cout << "Can't make SDL" << std::endl;
    }
    
    //what version we are using
    SDL_GL_SetAttribute (SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
    //SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
    
    window = SDL_CreateWindow("Rectangle", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 512, 512, SDL_WINDOW_OPENGL);
    if (!window){
        std::cout << "No window created" << std::endl;
        //window = NULL;
        return false;
    }
    
    context = SDL_GL_CreateContext(window);
    if (!context){
        std::cout << "No context created" << std::endl;
        return false;
    }
    
    //double buffering - 24bit z buffer (might need changing for different systems)
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    
    //Makes buffer swap sync with VBLANK
    SDL_GL_SetSwapInterval(1);
    
    glViewport(0, 0, 512, 512);
    
    std:: cout << "Initialised" << std::endl;
    
    return true;
};

int main(int argc, const char * argv[]) {
    initWindow();
    /*
    const char * vshaderFile = "vertex.txt";
    const char * fshaderFile = "fragment.txt";
    long length;
    char * vertexBuf;
    
    FILE * vertexFile = fopen(vshaderFile, "r");
    
    if(!vertexFile) { std::cout << "Could not open vertex shader" << std::endl; }
    fseek(vertexFile, 0, SEEK_END);
    length = ftell(vertexFile);
    
    vertexBuf = new char [length + 1];
    fseek(vertexFile, 0, SEEK_SET);
    fread(vertexBuf, length, 1, vertexFile);
    fclose(vertexFile);
    vertexBuf[length] = 0; //makes the terminating character null
    
    //read fragment shader
    long length2;
    char * fragmentBuf;
    FILE * fragmentFile = fopen(fshaderFile, "r");
    
    if(!fragmentFile){ std::cout << "Could not open fragment shader" << std::endl; }
    fseek(fragmentFile, 0, SEEK_END);
    length2 = ftell(fragmentFile);
    
    fragmentBuf = new char [length2 + 1];
    fseek(fragmentFile, 0, SEEK_SET);
    fread(fragmentBuf, length2, 1, fragmentFile);
    fclose(fragmentFile);
    fragmentBuf[length2] = 0;
    */
    
    //makes the source pointers the buffers
    
    const char *vShaderSource = "#version 330 core
"
    "layout (location = 0) in vec3 aPos;
"
    "void main()
"
    "{
"
    "   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
"
    "}\0";
    
    const char *fShaderSource = "#version 330 core
"
    "out vec4 FragColor;
"
    "void main()
"
    "{
"
    "   FragColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);
"
    "}
\0";
    
    //compiles shaders
    
    //fragment
    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    //std::cout << glGetError() << std::endl;
    glShaderSource(fragmentShader, 1, &fShaderSource, NULL);
    glCompileShader(fragmentShader);
    int success;
    char infoLog[512];
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED
" << infoLog << std::endl;
    }
    
    //vertex
    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vShaderSource, NULL);
    glCompileShader(vertexShader);
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED
" << infoLog << std::endl;
    }
    
    
    //releases buffers
    //delete[] fragmentBuf;
    //delete[] vertexBuf;
    //fragmentBuf = NULL;
    //vertexBuf = NULL;
    
    //links program
    GLuint shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    
    glLinkProgram(shaderProgram);
    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
    if (!success) {
        glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED
" << infoLog << std::endl;
    }
    
    //deletes unneeded shaders
    glDeleteShader(fragmentShader);
    glDeleteShader(vertexShader);
    
    std:: cout << "Shaders complete" << std:: endl;
    //std::cout << vShaderSource << std::endl << std::endl << fShaderSource << std::endl;

    //=================================================================================================================
    
    
    GLfloat vertices[3][4] = {
        0.5f,  0.5f, 0.0f,  // top right
        0.5f, -0.5f, 0.0f,  // bottom right
        -0.5f, -0.5f, 0.0f,  // bottom left
        -0.5f,  0.5f, 0.0f   // top left
    };
    GLint indices[3][2] = {  // note that we start from 0!
        0, 1, 3,  // first Triangle
        1, 2, 3   // second Triangle
    };
    
    GLuint VBO, VAO, EBO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glGenBuffers(1, &EBO);
    // bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
    glBindVertexArray(VAO);
    
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, 12 * sizeof (float), vertices, GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);
    
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(int), indices, GL_STATIC_DRAW);

    glEnableVertexAttribArray(0);
    
    // note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    
    // remember: do NOT unbind the EBO while a VAO is active as the bound element buffer object IS stored in the VAO; keep the EBO bound.
    //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    
    // You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other
    // VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary.
    glBindVertexArray(0);
    
    bool loop = true;
    
    glClearColor(0.5f, 0.1f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    
    glUseProgram(shaderProgram);
    glBindVertexArray(VAO);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, (void*)0);
    //glBindVertexArray(0);
    SDL_GL_SwapWindow(window);
    std::cout << glGetError() << std::endl;
    //std::cout << glCheckError() << std::endl;

    
    while (loop) {
        SDL_Event e;
        while(SDL_PollEvent(&e)){
            if (e.type == SDL_QUIT) loop = false;
            if (e.type == SDL_KEYDOWN){
                switch(e.key.keysym.sym){
                    case SDLK_ESCAPE:
                        loop = false;
                        break;
                    case SDLK_y:
                        std::cout << glGetString(GL_VERSION) << std::endl;
                        break;
                    }
                std::cout << "Error: " << SDL_GetError() << std::endl;
                std::cout << glGetError() << std::endl;
            }
        }
        
    }
    
}


I have spent at least 3 months looking at this and wondering why it doesn’t work…

What happens when you run the program: Screen goes fuschia purple colour, but does not draw rectangle. I set the rectangle colour to white just to make sure it stood out against the background.
I made sure that I swap the buffer so that I can see the rectangle. I also checked every single function call against the prototypes and tutorials to make sure I had the right parameters.

GL version returned is 3.3, and error code is 0. SDL also returns no errors.

I can’t see what I have done wrong compared to the tutorial https://learnopengl.com/#!Getting-started/Hello-Triangle … Can someone else run this on their computer and see if the rectangle is drawn or not? (The code doesn’t have the #ifdef stuff to make it work on both Windows and Mac/Linux, sorry). Thank you.

edit: FIXED! :smiley: I changed GL_UNSIGNED_BYTE in the glDrawElements to GL_UNSIGNED_INT. Phew! Thank you everyone! My first rectangle (well, square…) at last…

Could it be that your indices array is GLint, but your calling glDrawElements with GL_UNSIGNED_BYTE? Do you need to make them GLuint?

Jeff

Yay. Awesome dude.

Glad to be of service.

Jeff