mitesh mitesh - 1 year ago 67
C++ Question

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();

Answer Source

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);
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download