Search code examples
c++graphicsopengl-3

Open gl sprite class not working


So first of all, i am a total beginner in open gl, and i am learning opengl from learnopengl.com. So i understood whats going on in the code in the main method.The code works in main method. But when i tried to create a class for it, it doesn't render anything!! I have absolutely no idea whats going wrong!

Sprite.h

    #pragma once

#include"Shader.h"
#include<GL\glew.h>

class Sprite {
    GLuint vao;
    GLuint vbo;

    int vertexCount;

    Shader shader;

public:

    Sprite(const GLfloat vertices[9], int noOfVertices, Shader s = Shader()) : vertexCount(noOfVertices) , shader(s)
    {

        glGenVertexArrays(1, &vao);
        glGenBuffers(1, &vbo);

        glBindVertexArray(vao);
        glBindBuffer(GL_ARRAY_BUFFER, vbo);
        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

        glVertexAttribPointer(0, this->vertexCount, GL_FLOAT, GL_FALSE, 0, nullptr);
        glEnableVertexAttribArray(0);
        glBindBuffer(GL_ARRAY_BUFFER, 0);

        glBindVertexArray(0);
    }

    void draw() {
        glBindVertexArray(this->vao);
        glDrawArrays(GL_TRIANGLES, 0, this->vertexCount);
        glBindVertexArray(0);
    }
};

Shader.h

#pragma once
#include<iostream>
#include<fstream>
#include<sstream>
#include<string>
#include<vector>

#include<GL\glew.h>

class Shader {
    GLuint programID;

    GLuint vertID;
    GLuint fragID;

public:
    Shader(std::string vertex = "Shaders/Dvert.vert", std::string fragment = "Shaders/Dfrag.frag")
    {
        this->programID = glCreateProgram();
        this->vertID = glCreateShader(GL_VERTEX_SHADER);
        this->fragID = glCreateShader(GL_FRAGMENT_SHADER);

        this->CompileShaders(vertex, fragment);
        this->LinkProgram();
    }

    GLuint getProgramId() {
        return this->programID;
    }

private:

    void CompileShaders(std::string vertexShaderPath, std::string FragShaderPath) {

        std::string vCode = GetContentsFrom(vertexShaderPath).c_str();
        const char * vertexCode = vCode.c_str();
        glShaderSource(this->vertID, 1, &vertexCode, NULL);
        glCompileShader(this->vertID);

        this->HandleShaderErrors(this->vertID);

        std::string fCode = GetContentsFrom(FragShaderPath).c_str();
        const char * fragCode = fCode.c_str();
        glShaderSource(this->fragID, 1, &fragCode, NULL);
        glCompileShader(this->fragID);

        std::cout << fragCode << std::endl;

        this->HandleShaderErrors(this->fragID);
    }

    void LinkProgram() {
        glAttachShader(this->programID, this->vertID);
        glAttachShader(this->programID, this->fragID);

        glLinkProgram(this->programID);
        this->HandleLinkErrors();
    }

    std::string GetContentsFrom(std::string path) {
        std::ifstream file(path);
        std::ostringstream stream;

        if (!file) {
            std::cout << "Specified file path is invalid" << std::endl;
            return "";
        }
        stream << file.rdbuf();

        std::cout << stream.str() << std::endl << std::endl;

        return stream.str();
    }

    void HandleLinkErrors() {
        int result;
        glGetProgramiv(this->programID, GL_LINK_STATUS, &result);

        if (result == GL_FALSE) {
            int length;
            glGetProgramiv(this->programID, GL_INFO_LOG_LENGTH, &length);

            std::vector<char> error(length);

            glGetProgramInfoLog(this->programID, length , &length, &error[0]);
            std::cout << &error[0] << std::endl;

            glDetachShader(this->programID, this->vertID);
            glDetachShader(this->programID, this->fragID);
        }
    }

    void HandleShaderErrors(GLuint shader) {
        int status;
        glGetShaderiv(shader, GL_COMPILE_STATUS, &status);

        if (status == GL_FALSE) {
            int length;
            glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);

            std::vector<char> error(length);

            glGetShaderInfoLog(shader, length, &length, &error[0]);
            std::cout << &error[0] << std::endl;

            glDeleteShader(shader);
        }
    }
};

Main.cpp

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

#include"Console.h"
#include"Headers\Shader.h"
#include"Headers\Sprite.h"

#include<iostream>

 static const GLfloat vertices[] = {
    0.5f, -0.5f ,0.0f ,
    -0.5f, -0.5f, 0.0f,
    0.0f, 0.5f, 0.0f
};

 int main() {
     if (!glfwInit()) {
         Console.Log("GLFW could not be initialised!!");
         Console.Wait();
     }

     GLFWwindow *window = glfwCreateWindow(600, 400, "Open GL", nullptr, nullptr);
     glfwMakeContextCurrent(window);

     if (glewInit() != GLEW_OK) {
         Console.Log("GLEW could not be initialised!!");
         Console.Wait();
     }

     Sprite s(vertices, 3);

     glClearColor(0, 0, 0, 1);
     glfwWindowHint(GLFW_VERSION_MAJOR, 3);
     glfwWindowHint(GLFW_VERSION_MINOR, 3);

     while (!glfwWindowShouldClose(window)) {
         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
         glfwPollEvents();
         s.draw();
         glfwSwapBuffers(window);
     }
 }

Please help me out!!

Note:- The code in the main method renders the white triangle without the shaders,so my graphics card works without shaders.

Also the Console class i have created is just to print to the console and has nothing to do with the opengl stuff. Console.Log isstd::cout<< and Console.Wait is std::cin.get();


Solution

  • There are at least two problems. The first is that your sizeof(vertices) in Sprite produces wrong result, because it gives the size of a pointer, not the size of the array. To fix it, replace it with sizeof(GLfloat) * 9.

    The second problem is that you are specifying the OpenGL context version too late, after creating the window and context. To fix it, call these methods before glfwCreateWindow, not after:

    glfwWindowHint(GLFW_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_VERSION_MINOR, 3);