Modern (SDL2) OpenGl 3.3 Not Drawing

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Xillez
    New Member
    • Jul 2013
    • 93

    Modern (SDL2) OpenGl 3.3 Not Drawing

    Hey I'm new to the modern world of OpenGL but have done quite a lot of older OpenGl stuff.

    I had this program displaying stuff via loading in textures and a vertices array, but I changed it so I could append vertices (with their respective color) one by one and "initMesh() " later. For some reason this doesn't work and I can't see why it won't. Would be very appreciated if anyone could help :-). Here's all the files:

    main.cpp:
    Code:
    #include <SDL2\SDL.h>
    #include <GL\glew.h>
    #include <glm\glm.hpp>
    #include "Window.h"
    #include "Shader.h"
    #include "Mesh.h"
    
    
    
    int main(int argc, char *args[])
    {
        Window window(600, 600, "Vector Field Editor");
        Shader shader/*("")*/;
    
        Vertex vertices[] = { Vertex(glm::vec3(-0.5, -0.5, 1.0), glm::vec4(1.0f, 0.0f, 0.0f, 1.0f)),
            Vertex(glm::vec3(0,    0.5, 1.0), glm::vec4(1.0f, 0.0f, 0.0f, 1.0f)),
            Vertex(glm::vec3(0.5, -0.5, 1.0), glm::vec4(1.0f, 0.0f, 0.0f, 1.0f)) };
    
        Mesh mesh(GL_TRIANGLES);
    
        mesh.appendVertex(vertices[0]);
        mesh.appendVertex(vertices[1]);
        mesh.appendVertex(vertices[2]);
        mesh.initMesh();
        while (window.isOpen())
        {
            // Clear window
            window.clear(0.0f, 0.0f, 0.0f, 0.0f);
            shader.bind();
            mesh.draw();
            // Update window
            window.update();
            // Handle events
            window.handleEvents();
        }
        return 0;
    }
    Window.h + Window.cpp
    Code:
    Header:
    #pragma once
    #include <string>
    #include <SDL2\SDL.h>
    #include <GL\glew.h>
    #include <glm\glm.hpp>
    #include <iostream>
    
    class Window
    {
    public:
        Window(int width, int height, const std::string& title);
        virtual ~Window();
    
        void update();
        void handleEvents();
        bool isOpen();
        void clear(float r, float g, float b, float a);
    
    protected:
        //
    private:
        // The Window
        SDL_Window* window;
        // Windows context
        SDL_GLContext glContext;
        // If the window is closed or not
        bool isWOpen = true;
        // Glew initialization status
        GLenum m_status;
    };
    
    CPP:
    #include "Window.h"
    
    Window::Window(int width, int height, const std::string& title)
    {
        // Initialize SDL
        SDL_Init(SDL_INIT_EVERYTHING);
        // Sets SDL OpenGL Attributes
        SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
        SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
        SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
        SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
        SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32);
        SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
        SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
    
        // Makes the window pointer
        window = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_OPENGL);
    
        // If window creation failed
        if (window == NULL)
        {
            std::cerr << "SDL Error(couldn't create window): " << SDL_GetError() << std::endl;
        }
    
        // Sets the context for the given window
        glContext = SDL_GL_CreateContext(window);
    
        // If window context creation failed
        if (glContext == NULL)
        {
            std::cerr << "SDL Error(something about glcontext): " << SDL_GetError() << std::endl;
        }
    
        // Using an experimental version of OpenGl
        glewExperimental = GL_TRUE;
        // Initialize Glew
        GLenum status = glewInit();
        // Glew failed to initialize
        if (status = !GLEW_OK)
        {
            std::cerr << "GLEW Error(something about the initilazation): " << glewGetErrorString(status) << " | OpenGL Version: " << glGetString(GL_VERSION) << std::endl;
        }
    
        /*if (GLEW_VERSION_4_5)
        {
            std::cout << "We support version 4.5.0!" << std::endl;
        }*/
    
        glEnable(GL_DEPTH_TEST);
    
        glEnable(GL_CULL_FACE);
        glCullFace(GL_BACK);
    }
    
    Window::~Window()
    {
        // Delete Window Context
        SDL_GL_DeleteContext(glContext);
        // Destroy window
        SDL_DestroyWindow(window);
        // SDL Should quit
        SDL_Quit();
    }
    
    void Window::update()
    {
        // Swap buffers
        SDL_GL_SwapWindow(window);
    }
    
    void Window::handleEvents()
    {
        // Get all events
        SDL_Event e;
        // Extract all events
        while (SDL_PollEvent(&e))
        {
            // If SDL_QUIT event, then window should close
            if (e.type == SDL_QUIT)
                isWOpen = false;
        }
    }
    
    bool Window::isOpen()
    {
        return isWOpen;
    }
    
    void Window::clear(float r, float g, float b, float a)
    {
        glClearColor(r, g, b, a);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    }
    Shader.h + Shader.cpp
    Code:
    Header:
    #pragma once
    #include <string>
    #include <GL\glew.h>
    #include <iostream>
    #include <vector>
    #include <fstream>
    #include <algorithm>
    
    #define VERTEX_SHADER 0
    #define FRAGMENT_SHADER 1
    #define NUM_SHADERS 2
    
    class Shader
    {
    public:
        Shader();
        virtual ~Shader();
    
        void bind();
        //void update(const Transform& trans, const Camera& camera);
    protected:
        //
    private:
        //enum { TRANSFORM_U, NUM_UNIFORMS };
    
        GLuint program;
        GLuint shaders[NUM_SHADERS];
        //GLuint uniforms[NUM_UNIFORMS];
    };
    
    CPP:
    
    #include "Shader.h"
    
    static std::string LoadShader(const std::string & fileName);
    static void CheckShaderError(GLuint shader, GLuint flag, bool isProgram, const std::string & errorMessage);
    static GLuint CreateShader(const std::string& text, GLenum shaderType);
    
    Shader::Shader(/*const std::string& fileName*/)
    {
        // Make a program for shaders
        program = glCreateProgram();
        // Make vertex shader
        shaders[VERTEX_SHADER] = CreateShader(LoadShader(/*fileName + ".vs"*/"./shaders/vertexShader.glsl"), GL_VERTEX_SHADER);
        // Make fragment shader
        shaders[FRAGMENT_SHADER] = CreateShader(LoadShader(/*fileName + ".fs"*/"./shaders/fragmentShader.glsl"), GL_FRAGMENT_SHADER);
    
        // Attach all indevidual shaders to the program
        for (unsigned int i = 0; i < NUM_SHADERS; i++)
            glAttachShader(program, shaders[i]);
    
        // Bind the word "position" in the shader as "0"
        glBindAttribLocation(program, 0, "position");
        //
        glBindAttribLocation(program, 1, "color");
    
        // Link shader program
        glLinkProgram(program);
        // Check shader program for linking errors
        CheckShaderError(program, GL_LINK_STATUS, true, "Error: Program linking failed: ");
    
        // Validate shader program
        glValidateProgram(program);
        // Check shader program for validation status
        CheckShaderError(program, GL_VALIDATE_STATUS, true, "Error: Program is invalid: ");
    
        /*uniforms[TRANSFORM_U] = glGetUniformLocation(program, "transform");*/
    }
    
    Shader::~Shader()
    {
        // Deleting all shaders
        for (unsigned int i = 0; i < NUM_SHADERS; i++)
        {
            glDetachShader(program, shaders[i]);
            glDeleteShader(shaders[i]);
        }
        // Delete shader program
        glDeleteProgram(program);
    }
    
    void Shader::bind()
    {
        // Binds the program to window
        glUseProgram(program);
    }
    
    /*void Shader::update(const Transform& transform, const Camera& camera)
    {
        glm::mat4 model = camera.getViewProjection() * transform.getModel();
    
        glUniformMatrix4fv(uniforms[TRANSFORM_U], 1, GL_FALSE, &model[0][0]);
    }*/
    
    std::string LoadShader(const std::string& fileName)
    {
        std::ifstream file((fileName).c_str());
    
        std::string output;
        std::string line;
    
        if (file.is_open())
        {
            while (file.good())
            {
                getline(file, line);
                output.append(line + "\n");
            }
        }
        else
        {
            std::cerr << "Unable to load shader: " << fileName << std::endl;
        }
    
        return output;
    }
    
    void CheckShaderError(GLuint shader, GLuint flag, bool isProgram, const std::string& errorMessage)
    {
        GLint success = 0;
        GLchar error[1024] = { 0 };
    
        if (isProgram)
            glGetProgramiv(shader, flag, &success);
        else
            glGetShaderiv(shader, flag, &success);
    
        if (success == GL_FALSE)
        {
            if (isProgram)
                glGetProgramInfoLog(shader, sizeof(error), NULL, error);
            else
                glGetShaderInfoLog(shader, sizeof(error), NULL, error);
    
            std::cerr << errorMessage << ": '" << error << "'" << std::endl;
        }
    }
    
    GLuint CreateShader(const std::string& text, GLenum shaderType)
    {
        GLuint shader = glCreateShader(shaderType);
    
        if (shader == 0)
            std::cerr << "Error: Shader creation failed!" << std::endl;
    
        const GLchar* shaderSourceStrings[1];
        shaderSourceStrings[0] = text.c_str();
        GLint shaderSourceStringLengths[1];
        shaderSourceStringLengths[0] = text.length();
    
        glShaderSource(shader, 1, shaderSourceStrings, shaderSourceStringLengths);
        glCompileShader(shader);
    
        CheckShaderError(shader, GL_COMPILE_STATUS, false, "Error: Shader compilation failed: ");
    
        return shader;
    }
    Vertex.h (inline):
    Code:
    #pragma once
    class Vertex
    {
    public:
        Vertex(const glm::vec3& pos, glm::vec4& color = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f))
        {
            this->pos = pos;
            this->color = color;
        }
    
        virtual ~Vertex() {}
    
        inline glm::vec3 getPos() { return pos; }
        inline void setPos(glm::vec3 pos) { this->pos = pos; }
        inline glm::vec4 getColor() { return color; }
        inline void setColor(glm::vec4 pos) { this->color = color; }
    
        bool operator==(Vertex& other) const
        {
            return (pos == other.getPos() && color == other.getColor());
        }
    
    protected:
        //
    private:
        glm::vec3 pos;
        glm::vec4 color;
    };
    Mesh.h + Mesh.cpp
    Code:
    Header:
    #pragma once
    #include <glm/glm.hpp>
    #include <gl/glew.h>
    #include <vector>
    #include <string>
    #include <cassert>
    #include <iostream>
    #include "Vertex.h"
    #include "stb_image.h"
    
    class Mesh
    {
    public:
        Mesh(GLenum drawType/*, unsigned int* indecies, unsigned int numIndecies*/);
        virtual ~Mesh();
    
        void appendVertex(Vertex vertex);
        void draw();
        void initMesh();
    protected:
        //
    private:
        enum {POSITION_VB, COLOR_VB, /*INDEX_VB,*/ NUM_BUFFERS};
    
        std::vector<Vertex> vertices;
    
        GLuint vertexArrayObject;
        GLuint vertexArrayBuffers[NUM_BUFFERS];
        //unsigned int nrVertices;
        //bool textureAvaliable;
        GLenum drawType;
    };
    
    CPP:
    
    #include "Mesh.h"
    
    Mesh::Mesh(GLenum drawType/*, unsigned int* indecies, unsigned int numIndecies*/)
    {
        // Set the drawType
        this->drawType = drawType;
    }
    
    Mesh::~Mesh()
    {
        // Delete vertex array
        glDeleteVertexArrays(1, &vertexArrayObject);
        glDeleteBuffers(NUM_BUFFERS, vertexArrayBuffers);
    }
    
    void Mesh::appendVertex(Vertex vertex)
    {
        vertices.push_back(vertex);
        //nrVertices++;
    }
    
    void Mesh::draw()
    {
        // Bind the vertex array object
        glBindVertexArray(vertexArrayObject);
        // Draw array
        glDrawArrays(/*drawType*/ GL_TRIANGLES, 0, /*nrVertices*/vertices.size());
        // Clear binding of vertex array
        glBindVertexArray(0);
    }
    
    void Mesh::initMesh()
    {
        // Generate vertex array object
        glGenVertexArrays(1, &vertexArrayObject);
    
        // Bind the vertex array object
        glBindVertexArray(vertexArrayObject);
    
        std::vector<glm::vec3> positions;
        std::vector<glm::vec4> colors;
    
    
        // Prereserve enough memory
        positions.reserve(/*nrVertices*/vertices.size());
        colors.reserve(/*nrVertices*/vertices.size());
    
        // Move all positions and texCoords over
        for (unsigned int i = 0; i < /*nrVertices*/vertices.size(); i++)
        {
            positions.push_back(vertices[i].getPos());
            colors.push_back(vertices[i].getColor());
        }
    
        for (unsigned int i = 0; i < /*nrVertices*/vertices.size(); i++)
        {
            std::cout << "\n\nPosition: (" << positions[i].x <<
                                      ", " << positions[i].y <<
                                      ", " << positions[i].z << ")\n Color: (" << colors[i].x <<
                                                                          ", " << colors[i].y <<
                                                                          ", " << colors[i].z <<
                                                                          ", " << colors[i].w << ")";
        }
    
        // Generate buffer
        glGenBuffers(NUM_BUFFERS, vertexArrayBuffers);
    
        // !!!! Make a buffer for VERTEX POSITIONS !!!!
        // Bind the buffer
        glBindBuffer(GL_ARRAY_BUFFER, vertexArrayBuffers[POSITION_VB]);
    
        // Put the given data in buffer
        glBufferData(GL_ARRAY_BUFFER, /*nrVertices*/vertices.size() * sizeof(positions[0]), &positions[0], GL_STATIC_DRAW);
    
        // Enable vertex attribute array POSITION_VB
        glEnableVertexAttribArray(POSITION_VB);
    
        // Gett OpenGl how to use the vertex attribute array
        glVertexAttribPointer(POSITION_VB, 3, GL_FLOAT, GL_FALSE, 0, 0);
    
        // !!!! Make a buffer for the COLORS !!!!
        // Bind the buffer
        glBindBuffer(GL_ARRAY_BUFFER, vertexArrayBuffers[COLOR_VB]);
    
        // Put the given data in buffer
        glBufferData(GL_ARRAY_BUFFER, /*nrVertices*/vertices.size() * sizeof(colors[0]), &colors[0], GL_STATIC_DRAW);
    
        // // Enable vertex attribute array COLOR_VB
        glEnableVertexAttribArray(COLOR_VB);
    
        // Gett OpenGl how to use the vertex attribute array
        glVertexAttribPointer(COLOR_VB, 4, GL_FLOAT, GL_FALSE, 0, 0);
    
        // Bind vertex array
        glBindVertexArray(0);
    }
    Vertex.glsl + Fragment.glsl
    Code:
    Vertex:
    #version 330
    
    attribute vec3 position;
    attribute vec4 color;
    
    varying vec4 color0;
    
    //uniform mat4 transform;
    
    void main()
    {
        //gl_Position = /*transform * */vec4(position, 1.0);
        gl_Position = vec4(position, 1.0);
        color0 = color;
    }
    
    Fragment:
    #version 330
    
    varying vec4 color0;
    
    void main()
    {
        gl_FragColor = color0;
    }
  • weaknessforcats
    Recognized Expert Expert
    • Mar 2007
    • 9214

    #2
    I am not an OpenGL person but I did have a question. In main() a mesh object s created, a constructor called, various other mesh member functions are called, and then initMesh member function is called.

    Shouldn't initMesh be part of the constructor? It just looks odd that a mesh object is created, modified, and then initialized.

    Comment

    • Xillez
      New Member
      • Jul 2013
      • 93

      #3
      No, the reason is that I can add a unknown number of vertices in a mesh and once the mesh initializes, OpenGL takes all those vertices at once and dumps them in a buffer for drawing. That's why it's Create, Modify and then Init :-) (I do understand that it looks a little weird) Plus it cuts down on the amount of array's of vertices I would need to have everywhere and it makes the code a little more cleaner I think :-)

      Comment

      • weaknessforcats
        Recognized Expert Expert
        • Mar 2007
        • 9214

        #4
        The next step is to put a breakpoint at the beginning of each function and start the code using your debugger. Each time a function is called, execution breaks to the debugger. You can see where the call came from and verify all the variables in the code are in the correct state.

        When you are sure a function is correct, remove its breakpoint.

        Obviously, the debugger should run to breakpoint rather than stepping a line at a time.

        When there are no breakpoints left, the code should be working.

        Let me know what happened.

        Comment

        • Xillez
          New Member
          • Jul 2013
          • 93

          #5
          I kind of fixed it. It was the "Depth_Buff er", "Depth_Test " and "GL_Cull_Fa ce" that messed it up. OpenGL is testing each pixels z-value in the depth buffer, but I haven't assigned a depth buffer to be used other than saying OpenGl will get 16+ bits to store depth information per pixel, so OpenGl doesn't draw. Plus that I reverted "Mesh.h + Mesh.cpp" to take everything it needs and initializes immediately, instead of waiting for vertices and then initializing. But at least I can draw now :-)

          Comment

          Working...