not drawing anything when OpenGL buffers are declared in other classes [duplicate] - c++

#define GLEW_STATIC
#include <GL\glew.h>
#include <GLFW\glfw3.h>
#include <GL\glew.h>
#include <glm.hpp>
#include <iostream>
#include <fstream>
#include <string>
#define WIDTH 800
#define HEIGHT 600
#define TITLE "Dynamic"
GLFWwindow* window;
int vaoID;
float vertices[] = {-0.5f, 0.5f, 0, -0.5f, -0.5f, 0, 0.5f, 0.5f, 0, 0.5f, 0.5f, 0, -0.5f, -0.5f, 0, 0.5f, -0.5f, 0};
void loadToVAO(float vertices[]);
void update() {
loadToVAO(vertices);
while (!glfwWindowShouldClose(window)) {
glfwPollEvents();
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(1, 0, 0, 1);
glDrawArrays(GL_TRIANGLES, 0, 6);
glfwSwapBuffers(window);
}
}
int main() {
if (!glfwInit())
std::cout << "Couldn't initialize GLFW!" << std::endl;
window = glfwCreateWindow(WIDTH, HEIGHT, TITLE, NULL, NULL);
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
if (GLEW_OK != glewInit())
std::cout << "GLEW fucked up!" << std::endl;
std::cout << "Your GL version: " << glGetString(GL_VERSION) << std::endl;
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
update();
}
void loadShaders() {
}
void loadToVAO(float vertices[]) {
GLuint vboID;
GLuint vaoID;
glGenBuffers(1, &vboID);
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices) * 8, vertices, GL_STATIC_DRAW);
glGenVertexArrays(1, &vaoID);
glBindVertexArray(vaoID);
std::cout << vaoID << std::endl;
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
glEnableVertexAttribArray(0);
}
This is my code for creating and rendering a VAO that contains a VBO with the vertex positions. But unfortunately it doesn't work. It draws a triangle instead of a quad. But when I put the code of the loadToVAO function in the update function before the while loop, it works.

The sizeof operator always returns the size of the underlying type. When you copy the content of loadToVAO to the update function, sizeof(vertices) is basically sizeof(float[18]), which is the total size of the array.
But inside the loadToVAO, the sizeof(vertices) takes the function parameter vertices as input and not the global variable. Since array parameters of undefined size in C++ are treated as points of the same type we have here:
sizeof(vertices) == sizeof(float[]) == sizeof(float*)
which is the size of a pointer (4 or 8) and not the size of the data anymore.
To solve this, you can either pass the size of the array also to the function, which is the C way to go. The more modern way is to use std::array or std::vector to store the data in the first place.
Edit: On the second look I saw that you used sizeof(vertices) * 8 in the first place. I'm not really sure where the 8 comes from, since you neither have 8 elements nor does a float have a size of 8 bytes.

Related

c++ with openGl can't render

I try to make the code cleaner by extracting the whole main Proramm in some classes. So I have a vertex buffer, index buffer and a shader class. Only the array buffer is in the main and it worked.
Now I created a layout class and a vertex array class to put different layouts in the vertex array and the renderfunction in my main stopped to work.
Here is my code:
vertexBuffer.cpp
#include "../headerData/VertexBuffer.h"
VertexBuffer::VertexBuffer(const void* data, unsigned int size) {
glGenBuffers(1, &bufferId);
glBindBuffer(GL_ARRAY_BUFFER, bufferId);
glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);
}
VertexBuffer::~VertexBuffer() {
glDeleteBuffers(1, &bufferId);
}
void VertexBuffer::bind() const {
glBindBuffer(GL_ARRAY_BUFFER, bufferId);
}
void VertexBuffer::unbind() const {
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
vertex Index cpp:
#include "../headerData/IndexBuffer.h"
IndexBuffer::IndexBuffer(const void* data, unsigned int count) {
glGenBuffers(1, &bufferId);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferId);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, count, data, GL_STATIC_DRAW);
}
IndexBuffer::~IndexBuffer() {
glDeleteBuffers(1, &bufferId);
}
void IndexBuffer::bind() const {
glBindBuffer(GL_ARRAY_BUFFER, bufferId);
}
void IndexBuffer::unbind() const {
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
VertexLayout.h
#pragma once
#include <vector>
//Stubides Layout da vieles vorgegeben wird
struct ElementLayout {
unsigned int size; //anzahl an koordinaten die zählen
unsigned int stride; //Die größe der
};
class VertexLayout {
private:
std::vector<ElementLayout> elements;
public:
VertexLayout();
~VertexLayout();
void layoutPush(unsigned int size);
std::vector<ElementLayout> getElements() const;
};
vertexLayout.cpp:
#include"../headerData/VertexLayout.h"
VertexLayout::VertexLayout() {}
VertexLayout::~VertexLayout() {}
void VertexLayout::layoutPush(unsigned int size)
{
elements.push_back({ size, size * sizeof(float) });
}
std::vector<ElementLayout> VertexLayout::getElements() const {
return elements;
}
VertexArray.cpp
#include "../headerData/VertexArray.h"
#include <iostream>
VertexArray::VertexArray() {
glGenVertexArrays(1, &vertexArrayID);
}
VertexArray::~VertexArray() {
glDeleteVertexArrays(1, &vertexArrayID);
}
void VertexArray::bind() const {
glBindVertexArray(vertexArrayID);
}
void VertexArray::unbind() const {
glBindVertexArray(0);
}
//Vom Buffer soll auch das zugehörige Layout übergeben werden
void VertexArray::addBuffer(VertexBuffer& vb, VertexLayout& layout) {
bind();
vb.bind();
std::vector<ElementLayout> element = layout.getElements();
unsigned int offset = 0;
for (int i = 0; i < element.size(); i++) {
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, element[i].size, GL_FLOAT, GL_FALSE, element[i].stride, (void*)0);
offset += element[i].size * sizeof(float);
std::cout << GL_NO_ERROR;
}
std::cout << glGetError();
}
main.cpp:
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include "headerData/VertexBuffer.h"
#include "headerData/IndexBuffer.h"
#include "headerData/Shader.h"
#include "headerData/VertexLayout.h"
#include "headerData/VertexArray.h"
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow* window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
int main()
{
// glfw: initialize and configure
// ------------------------------
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
// glfw window creation
// --------------------
GLFWwindow* window = glfwCreateWindow(800, 800, "LearnOpenGL", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
// glad: load all OpenGL function pointers
// ---------------------------------------
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
Shader shader;
shader.bind();
// set up vertex data (and buffer(s)) and configure vertex attributes
// ------------------------------------------------------------------
float vertices[] = {
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
-1.0f, -1.0f, 0.0f //zum Testen
//dreieck
};
unsigned int indices[] = { // note that we start from 0!
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};
float vertices2[] = {
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
0.0f, 0.0f, 0.0f
};
unsigned int test;
glGenVertexArrays(1, &test);
// bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
glBindVertexArray(test);
//glBindBuffer(GL_ARRAY_BUFFER, VBO);
//glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
VertexBuffer vb(vertices, 5 * 3 * sizeof(float));
IndexBuffer ib(indices, 6 * sizeof(unsigned int));
VertexLayout layout;
layout.layoutPush(3);
VertexArray va;
//va.addBuffer(vb, layout);
//va.addBuffer(vb, layout); when this is uncomment the render function doesn't work
//Parameter
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)(0));
//glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(0);
//glEnableVertexAttribArray(1);
// uncomment this call to draw in wireframe polygons.
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
// render loop
// -----------
while (!glfwWindowShouldClose(window))
{
// input
// -----
processInput(window);
// render
// ------
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
shader.bind();
//glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, (void*)(sizeof(unsigned int) * 3));
//glDrawArrays(GL_TRIANGLES, 0, 3);
//glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, (void*)(sizeof(unsigned int) * 3));
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
// glBindVertexArray(0); // no need to unbind it every time
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
// -------------------------------------------------------------------------------
glfwSwapBuffers(window);
glfwPollEvents();
}
// optional: de-allocate all resources once they've outlived their purpose:
// ------------------------------------------------------------------------
glDeleteVertexArrays(1, &test);
// glfw: terminate, clearing all previously allocated GLFW resources.
// ------------------------------------------------------------------
glfwTerminate();
return 0;
}
With glGetError() I get the number 1281 =>invalid value but where.
The index buffer (ELEMENT_ARRAY_BUFFER) binding is stored within the Vertex Array Object. When glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferId) is called a reference to the element buffer object is stored in the currently bound Vertex Array Object. Therefore the VAO must be bound before the element buffer with glBindVertexArray(vertexArrayID):
VertexArray va;
va.bind();
IndexBuffer ib(indices, 6 * sizeof(unsigned int));

Render OpenGL object in a class?

I'm trying to learn modern OpenGL and create classes for various primitive types such as cubes, spheres, etc. I have run into a problem, though, where my cube class isn't rendering anything in its Draw() function, but if I move it all into my main() function it works fine.
Here's the code for cube.cpp:
#include "cube.h"
#include <iostream>
GLuint Cube::indexArr[36] = {
0, 1, 2, // front face
2, 3, 1,
4, 5, 6,
6, 7, 4,
7, 3, 0,
0, 4, 7,
6, 2, 1,
1, 5, 6,
0, 1, 5,
5, 4, 0,
3, 2, 6,
6, 7, 3
};
bool Cube::cubeSetUp = false;
GLuint Cube::cubeVBO = 0;
GLuint Cube::cubeVAO = 0;
GLuint Cube::cubeEBO = 0;
Cube::Cube()
{
if (!cubeSetUp)
SetUpCube();
//define the 8 vertices that make up a cube
objectVerts = new GLfloat[24] {
-0.5f, -0.5f, -0.5f, // front bottom left 0
0.5f, -0.5f, -0.5f, // front bottom right 1
0.5f, 0.5f, -0.5f, // front top right 2
-0.5f, 0.5f, -0.5f, // front top left 3
-0.5f, -0.5f, 0.5f, // back bottom left 4
0.5f, -0.5f, 0.5f, // back bottom right 5
0.5f, 0.5f, 0.5f, // back top right 6
-0.5f, 0.5f, 0.5f // back top left 7
};
}
void Cube::Draw()
{
glBindVertexArray(cubeVAO);
//GLfloat modelMatrix[16];
//transform.affine.ConvertToOpenGLMatrix(modelMatrix);
//glUniformMatrix4fv(modelMatrixLoc, 1, GL_FALSE, modelMatrix);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
}
void Cube::SetUpCube()
{
cubeSetUp = true;
glGenVertexArrays(1, &cubeVAO);
glGenBuffers(1, &cubeVBO);
glGenBuffers(1, &cubeEBO);
glBindVertexArray(cubeVAO);
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(objectVerts), objectVerts, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cubeEBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexArr), indexArr, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
Code for cube.h:
#ifndef __CUBE__H_
#define __CUBE__H_
#include "scene_object.h"
class Cube : public SceneObject
{
public:
/***************
* Constructor *
***************/
Cube();
/***********************
* Overloaded Function *
***********************/
void Draw();
private:
static GLuint indexArr[36];
static bool cubeSetUp;
static GLuint cubeVBO, cubeVAO, cubeEBO;
void SetUpCube();
};
#endif
Am I doing something wrong? Does OpenGL not agree with using a static array for my index array? I tried getting rid of the element buffer object and just using glDrawArrays(...), but it also didn't work. I can provide the code for the main as well, if needed.
Also, the vertex shader isn't doing anything. It just receives the vertex information and gives it to gl_Position.
Thanks for any help.
Code for main.cpp:
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <fstream>
#include <string>
#include "shader.h"
#include "cube.h"
#include "camera.h"
using namespace std;
int main(int argc, char* argv[])
{
if (argc != 3)
{
cout << "Incorrect number of arguments!" << endl;
cout << "Usage: [executable] vertexShader fragmentShader" << endl;
return -1;
}
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
GLFWwindow* window = glfwCreateWindow(800, 600, "Scene Description Language Generator", nullptr, nullptr);
if (window == nullptr)
{
std::cout << "Failed to create the GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
{
std::cout << "Failed to initialize GLEW" << std::endl;
return -1;
}
glEnable(GL_DEPTH_TEST);
int width, height;
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
Shader shader(argv[1], argv[2]);
Cube c;
GLuint modelMat = glGetUniformLocation(shader.GetProgram(), "model");
c.SetModelMatrixLoc(modelMat);
while (!glfwWindowShouldClose(window))
{
glfwPollEvents();
glClearColor(0.2f, 0.3f, 0.3f, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
shader.Use();
c.Draw();
glfwSwapBuffers(window);
}
glfwTerminate();
return 0;
}
Edits: Added code for main.cpp and cube.h in case it is valuable to see.
At least two things going wrong.
First, as pointed out by pleluron, the cube constructor gets called before the application window and GL context has been created. On older systems this would usually crash. On modern computers there is probably a default GL context created by the windowing system, so the cube gets created for that. Then your application creates its own window and context and the cube is orphaned.
Creating OpenGL "objects" should only happen in a designated method, called only when it is safe to do so. In Qt it's the view setupGL method, in MacOS Cocoa it's prepareOpenGL, other systems it's the first window draw.
Second problem, as pointed out by BDL, is that sizeof(objectVerts) does not do what you think it does. A print statement will show you.
Third problem is that you're not calling glGetError(). OpenGL does not throw exceptions when you do something wrong, and often doesn't crash. Instead it just does nothing. Develop the habit of calling glGetError() at the end of each important function or method just to be sure everything is OK. If errors do happen, put more glGetErrors() in to narrow down the cause.

C++/OpenGL VAO Problems

#define GLEW_STATIC
#include <GL\glew.h>
#include <GLFW\glfw3.h>
#include <GL\glew.h>
#include <glm.hpp>
#include <iostream>
#include <fstream>
#include <string>
#define WIDTH 800
#define HEIGHT 600
#define TITLE "Dynamic"
GLFWwindow* window;
int vaoID;
float vertices[] = {-0.5f, 0.5f, 0, -0.5f, -0.5f, 0, 0.5f, 0.5f, 0, 0.5f, 0.5f, 0, -0.5f, -0.5f, 0, 0.5f, -0.5f, 0};
void loadToVAO(float vertices[]);
void update() {
loadToVAO(vertices);
while (!glfwWindowShouldClose(window)) {
glfwPollEvents();
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(1, 0, 0, 1);
glDrawArrays(GL_TRIANGLES, 0, 6);
glfwSwapBuffers(window);
}
}
int main() {
if (!glfwInit())
std::cout << "Couldn't initialize GLFW!" << std::endl;
window = glfwCreateWindow(WIDTH, HEIGHT, TITLE, NULL, NULL);
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
if (GLEW_OK != glewInit())
std::cout << "GLEW fucked up!" << std::endl;
std::cout << "Your GL version: " << glGetString(GL_VERSION) << std::endl;
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
update();
}
void loadShaders() {
}
void loadToVAO(float vertices[]) {
GLuint vboID;
GLuint vaoID;
glGenBuffers(1, &vboID);
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices) * 8, vertices, GL_STATIC_DRAW);
glGenVertexArrays(1, &vaoID);
glBindVertexArray(vaoID);
std::cout << vaoID << std::endl;
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
glEnableVertexAttribArray(0);
}
This is my code for creating and rendering a VAO that contains a VBO with the vertex positions. But unfortunately it doesn't work. It draws a triangle instead of a quad. But when I put the code of the loadToVAO function in the update function before the while loop, it works.
The sizeof operator always returns the size of the underlying type. When you copy the content of loadToVAO to the update function, sizeof(vertices) is basically sizeof(float[18]), which is the total size of the array.
But inside the loadToVAO, the sizeof(vertices) takes the function parameter vertices as input and not the global variable. Since array parameters of undefined size in C++ are treated as points of the same type we have here:
sizeof(vertices) == sizeof(float[]) == sizeof(float*)
which is the size of a pointer (4 or 8) and not the size of the data anymore.
To solve this, you can either pass the size of the array also to the function, which is the C way to go. The more modern way is to use std::array or std::vector to store the data in the first place.
Edit: On the second look I saw that you used sizeof(vertices) * 8 in the first place. I'm not really sure where the 8 comes from, since you neither have 8 elements nor does a float have a size of 8 bytes.

openGL Unhandled exception on glDrawArrays(GL_TRIANGLES, 0, model.indicesCount); call

So I'm trying to write a simple 3D rendering engine using GLFW and GLEW in C++. However the program crashes on glDrawArrays(GL_TRIANGLES, 0, model.indicesCount); call. I'm pretty sure I'm doing something wrong but I can't figure out where or what needs to be changed/altered. I'm actually rewriting a perfectly working engine from Java.
My code:
common.h:
#ifndef _COMMON
#define _COMMON
// standard stuff
#include <iostream>
#include <list>
// openGL stuff
#include "GL\glew.h"
#include "GLFW\glfw3.h"
// my stuff
#include "DisplayManager.h"
#include "RawModel.h"
#include "Loader.h"
#include "Renderer.h"
#endif
DisplayManager.h:
#pragma once
#include "common.h"
class DisplayManager{
private:
GLFWwindow* window;
public:
void create(int width = 1280, int height = 720, std::string title = "Untitled"){
if(!glfwInit()){
std::cerr << "GLFW init failed\n";
system("pause");
exit(EXIT_FAILURE);
}
glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
window = glfwCreateWindow(width, height, title.c_str(), NULL, NULL);
glfwMakeContextCurrent(window);
if(!window){
std::cerr << "Failed to create a window\n";
system("pause");
exit(EXIT_FAILURE);
}
glewExperimental = GL_TRUE;
if(glewInit() != GLEW_OK){
std::cerr << "GLEW init failed\n";
system("pause");
glfwTerminate();
exit(EXIT_FAILURE);
}
}
void update(){
glfwSwapBuffers(window);
glfwPollEvents();
}
int isCloseRequested(){
return glfwWindowShouldClose(window);
}
void close(){
glfwDestroyWindow(window);
glfwTerminate();
}
};
RawModel.h:
#pragma once
struct RawModel{
public:
GLuint vaoID;
GLuint indicesCount;
RawModel(GLuint vaoID, GLuint indicesCount){
this->vaoID = vaoID;
this->indicesCount = indicesCount;
}
};
Loader.h:
#pragma once
#include "common.h"
#define VERTEX_ATTRIB_INDEX 0
#define VERTEX_SIZE 3
class Loader{
public:
// functions
RawModel loadModel(const GLfloat vertices[], GLuint verticesCount){
GLuint vaoID = createAndBindVao();
storeFloatDataInVAO(VERTEX_ATTRIB_INDEX, vertices, verticesCount, VERTEX_SIZE);
unbindVAO();
return RawModel(vaoID, verticesCount);
}
void cleanUp(){
std::list<GLuint>::iterator vao_it = vaos.begin();
for(; vao_it != vaos.end(); ++vao_it){
const GLuint vao = *vao_it;
glDeleteVertexArrays(1, &vao);
}
std::list<GLuint>::iterator vbo_it = vbos.begin();
for(; vbo_it != vbos.end(); ++vbo_it){
const GLuint vbo = *vbo_it;
glDeleteBuffers(1, &vbo);
}
}
private:
// variables
std::list<GLuint> vaos;
std::list<GLuint> vbos;
// functions
GLuint createAndBindVao(){
GLuint vaoID;
glGenVertexArrays(1, &vaoID);
vaos.push_back(vaoID);
glBindVertexArray(vaoID);
return vaoID;
}
void storeFloatDataInVAO(const GLuint attributeIndex, const GLfloat data[], const GLuint dataLength, const GLuint chunkSize){
GLuint vboID;
glGenBuffers(1, &vboID);
vbos.push_back(vboID);
glBindBuffer(GL_VERTEX_ARRAY, vboID);
glBufferData(GL_VERTEX_ARRAY, sizeof(GLfloat) * dataLength * chunkSize, data, GL_STATIC_DRAW);
glVertexAttribPointer(attributeIndex, chunkSize, GL_FLOAT, GL_FALSE, 0, (void*)0);
glBindBuffer(GL_VERTEX_ARRAY, 0);
}
void unbindVAO(){
glBindVertexArray(0);
}
};
Renderer.h:
#pragma once
#include "common.h"
#define BLACK 0.0f, 0.0f, 0.0f, 1.0f
#define WHITE 1.0f, 1.0f, 1.0f, 1.0f
#define RED 1.0f, 0.0f, 0.0f, 1.0f
#define GREEN 0.0f, 1.0f, 0.0f, 1.0f
#define BLUE 0.0f, 0.0f, 1.0f, 1.0f
#define YELLOW 1.0f, 1.0f, 0.0f, 1.0f
class Renderer{
public:
void prepare(){
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(YELLOW);
};
void render(RawModel model){
glBindVertexArray(model.vaoID);
glEnableVertexAttribArray(VERTEX_ATTRIB_INDEX);
glDrawArrays(GL_TRIANGLES, 0, model.indicesCount);
glDisableVertexAttribArray(VERTEX_ATTRIB_INDEX);
glBindVertexArray(0);
}
};
and the Source.cpp with the main function:
#include "common.h"
static const GLfloat VERTICES[] = {
// X Y Z
-0.5f, 0.5f, 0,
-0.5f, -0.5f, 0,
0.5f, 0.5f, 0
};
int main(){
DisplayManager display;
display.create();
Loader loader;
RawModel model = loader.loadModel(VERTICES, 3);
Renderer renderer;
// main loop
while(!display.isCloseRequested()){
renderer.prepare();
renderer.render(model);
display.update();
}
loader.cleanUp();
display.close();
return EXIT_SUCCESS;
}
If I comment out the glDrawArrays(GL_TRIANGLES, 0, model.indicesCount); it seams to be working and I get a green window.
The error is here:
glBindBuffer(GL_VERTEX_ARRAY, vboID);
glBufferData(GL_VERTEX_ARRAY, sizeof(GLfloat) * dataLength * chunkSize, data, GL_STATIC_DRAW);
glVertexAttribPointer(attributeIndex, chunkSize, GL_FLOAT, GL_FALSE, 0, (void*)0);
glBindBuffer(GL_VERTEX_ARRAY, 0);
GL_VERTEX_ARRAY is not a valid buffer target in OpenGL, the correct one is GL_ARRAY_BUFFER. As a consequence, these commands all should generate a GL error. The attrib pointer function will should generate GL_INVALID_OPERATION, since no GL_ARRAY_BUFFER is bound at the time of the call, the others should just generate GL_INVALID_ENUM. Now you have basically an uninitialized vertex attribute pointer, you later enable that attribute array and try to draw from it, resulting in the crash.
Another thing: I don't see any shaders in your code. Shaders are mandatory in the core profile, which you use. Now glDrawElements() actually should fail, although some implementors ignore that and use some trivial shaders in that scenario.

OpenGL: program organization

I am starting to learn OpenGL. So far I am doing alright, the only problem is that I don't know exactly which is the "best" way to organize the program. For example, a lot of tutorials construct all of the code sequentially on the main() function, which I don't think is very nice. Others will build functions like render(), init(), and call them on the main() function.
Right now I am trying to mix things, I built a class to wrap GLFW and GLEW libraries, and I call them on the main(). Also I have init() and render() functions. The problem I am getting into is that I have to declare (GLuint program) as a global variable, which is not advisable. This is the only way I can get the render function to use also the variable.
Here is the code:
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "GLWrapper.h"
#include "GLShader.h"
#include <iostream>
#include <ctime>
using namespace std;
GLuint program;
void renderer() {
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
float time = float(clock()) / float(CLOCKS_PER_SEC);
GLint uniColor = glGetUniformLocation(program, "triangleColor");
glUniform3f(uniColor, (sin(time * 4.0f) + 1.0f) / 2.0f, cos(time*2), 0.0f);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
void init() {
float vertices[] = {
0.0f, 0.5f, // Vertex 1 (X, Y)
0.5f, -0.5f, // Vertex 2 (X, Y)
-0.5f, -0.5f // Vertex 3 (X, Y)
};
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
GLuint vbo;
glGenBuffers(1, &vbo); // Generate 1 buffer
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
program = LoadShader("Shader.vert", "Shader.frag");
glUseProgram(program);
}
int main() {
GLWrapper *glw = new GLWrapper(800, 600, "Ola Mundo!");
glw->setRenderer(renderer);
init();
GLint posAttrib = glGetAttribLocation(program, "position");
glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(posAttrib);
glw->glMainLoop();
delete(glw);
return 0;
}
So, I want to know If there is a better way of organizing this code (building a class perhaps?), because since I will be building bigger and bigger codes, I want them to be as organized as possible.
Hope I made myself clear.