OpenGL Attrib Pointer Not Working Inside Class Method

Hi all. Recently I had started learning opengl. I decided that it would be easier for me in the long run if I could wrap some code I had written of the opengl function calls within classes. At the moment I have been trying to get a texture to show up on a rectangle. However the code runs with either a completely black or no rectangle at all. I had messed around with the code and found out it may be related to calling glVertexAttribPointer(…) and glEnableVertexAttribArray(…). If i leave these outside the function the code works fine, however I would really like to put these into a method. Relative code is posted below (If you need me to provide additional files please let me know).

I would also like to add that if you have any tips for me, please feel free to say so. Thanks.

Problematic code located halfway in window.cpp

Window.cpp


#include "Window.h"
#include "Error.h"

#include "VertexArray.h"
#include "Buffer.h"
#include "Program.h"
#include "Texture.h"

#include <GL\glew.h>
#include <iostream>

Window::Window(unsigned int windowWidth, unsigned int windowHeight) : _windowWidth(windowWidth), _windowHeight(windowHeight){ ... }

Window::~Window() { ... }

void Window::run(void)
{
	SDL_Event e;
	SDL_Event e;
	_running = true;

	/*----------------------*/
	VertexArray VAO;

	const float vertices[] =
	{
		// Positions       //Colors			  //Texture Coordinates
		0.5f,  0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,  // top right
		0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,  // bottom right
		-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,  // bottom left
		-0.5f,  0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f   //top left
	};

	const unsigned int indicies[] =
	{
		0, 1, 3,	//First Triangle (Vert 0, Vert 1, Vert 3)
		1, 2, 3
	};

	//Generate Texture
	Texture texture(GL_TEXTURE_2D);
	texture.bind();
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	texture.unbind();
	texture.loadImage("wall.jpg");


	Buffer EBO(GL_ELEMENT_ARRAY_BUFFER);
	EBO.loadData(indicies, 6, GL_STATIC_DRAW);
	VAO.bindBuffer(EBO);

	Buffer VBO(GL_ARRAY_BUFFER);
	VBO.loadData(vertices, 32, GL_STATIC_DRAW);
	Program PGRM("VertexShader.vert", "FragmentShader.frag");

	{
		//HERE BE ERRORS???
		//VAO.bindAttribute(VBO, 0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
		//VAO.bindAttribute(VBO, 1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
		//VAO.bindAttribute(VBO, 2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));

		/* CODE HERE WORKS FINE*/
		VAO.bind();
		VBO.bind();
		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
		glEnableVertexAttribArray(0);

		glVertexAttribPointer(
			1,							//Attribute location 1
			3,							//Color values have size3
			GL_FLOAT,					//color values are of float value
			GL_FALSE,					//Do not normalize (translte into normalized screen coor)
			8 * sizeof(float),			//Stride value
			(void*)(3 * sizeof(float))	//3 floats to the right is the offset to our color data
		);
		glEnableVertexAttribArray(1);

		glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
		glEnableVertexAttribArray(2);	//Remember now its 8 elements per vertex

										//Remember to unbind vbo and attr pointer when done with vao
		VBO.unbind();
		VAO.unbind();
		EBO.unbind();
	}

	while (_running)
	{
		handleEvent(e);

		glClear(GL_COLOR_BUFFER_BIT);

		texture.bind();
		PGRM.useProgram();

		VAO.bind();
		glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
		glBindVertexArray(0);

		PGRM.unuseProgram();

		SDL_GL_SwapWindow(_window);
	}
}

void Window::handleEvent(SDL_Event &e) { ... }

VertexArray.h


#pragma once

#include "Buffer.h"
#include "GLobject.h"
#include <iostream>

#include <GL\glew.h>

class VertexArray : public GLobject
{
public:
	VertexArray() : GLobject()
	{
		glGenVertexArrays(1, &_objectId);
	}
	~VertexArray()
	{
		glDeleteVertexArrays(1, &_objectId);
	}

	//Bind/Unbind
	void bind(void) const override { glBindVertexArray(_objectId); }
	void unbind(void) const override { glBindVertexArray(0); }

	void bindAttribute(Buffer vertexBuffer, GLuint index, GLint size,  GLenum type, GLboolean normalized, GLsizei stride, const void * pointer)
	{
		glBindVertexArray(_objectId);
		glBindBuffer(vertexBuffer.getTarget(), vertexBuffer.getId());	//Bind vert buffer before pointing (we need to know which buffer has the pointer)
		glVertexAttribPointer(index, size, type, GL_FALSE, stride, pointer);
		glEnableVertexAttribArray(index);
		glBindBuffer(vertexBuffer.getTarget(), 0);	//No need to keep vertex buffer
		glBindVertexArray(0);
	}

	//Bind/Unbind Buffer
	void bindBuffer(const Buffer buffer)
	{
		glBindVertexArray(_objectId);
		glBindBuffer(buffer.getTarget(), buffer.getId());
		glBindVertexArray(0);
		glBindBuffer(buffer.getTarget(), 0);
	}
};

After looking a little more into the problem, it seems that including all glVertexAttribPointers together in a single function call works. Is it necessary to assign and enable all the stuff together in one go?


	void bindAttribute(Buffer vertexBuffer, GLuint index, GLint size,  GLenum type, GLboolean normalized, GLsizei stride, const void * pointer)
	{
		glBindVertexArray(_objectId);
		glBindBuffer(vertexBuffer.getTarget(), vertexBuffer.getId());	//Bind vert buffer before pointing (we need to know which buffer has the pointer)
		//glVertexAttribPointer(index, size, type, GL_FALSE, stride, pointer);
		//glEnableVertexAttribArray(index);

		glVertexAttribPointer(index, size, type, normalized, stride, pointer);
		glEnableVertexAttribArray(index);

		glVertexAttribPointer(
			1,							//Attribute location 1
			3,							//Color values have size3
			GL_FLOAT,					//color values are of float value
			GL_FALSE,					//Do not normalize (translte into normalized screen coor)
			8 * sizeof(float),			//Stride value (each color attribute is start of each item, since we have 6 flaots per vertex)
			(void*)(3 * sizeof(float))	//3 flaots to the right is the offset to our color data
		);
		glEnableVertexAttribArray(1);

		glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
		glEnableVertexAttribArray(2);

		glBindBuffer(vertexBuffer.getTarget(), 0);	//No need to keep vertex buffer
		glBindVertexArray(0);
	}

No.

If you’re trying to wrap OpenGL objects inside classes, you need to take some care. In particular, you should make the objects non-copyable (either delete the default copy constructor or add your own copy constructor and make it private). Also, you need to ensure that the correct context is bound before calling any methods which use the underlying object (this includes destructors). Making “clean” OOP wrappers is easier if you can use the direct state access (DSA) functions from OpenGL 4.5 or the ARB_direct_state_access extension.

If you’re using the bind-to-target approach, you need to take care that you don’t accidentally change a binding as a side-effect of calling a method (e.g. calling your bindAttribute() and bindBuffer() methods will unbind any VAO). IMHO, this sort of thing tends to make OOP wrappers counter-productive.

[QUOTE=GClements;1290855]No.

If you’re trying to wrap OpenGL objects inside classes, you need to take some care. In particular, you should make the objects non-copyable (either delete the default copy constructor or add your own copy constructor and make it private). Also, you need to ensure that the correct context is bound before calling any methods which use the underlying object (this includes destructors). Making “clean” OOP wrappers is easier if you can use the direct state access (DSA) functions from OpenGL 4.5 or the ARB_direct_state_access extension.

If you’re using the bind-to-target approach, you need to take care that you don’t accidentally change a binding as a side-effect of calling a method (e.g. calling your bindAttribute() and bindBuffer() methods will unbind any VAO). IMHO, this sort of thing tends to make OOP wrappers counter-productive.[/QUOTE]

The tutorials I have been looking at have been using the binding approach. Which I would have to say is pretty tedious, especially for someone as clueless as me. However, now that you mentioned the direct state access functions Ill probably use those more since I didn’t know that I can avoid some binding. Will using the direct state access functions completely remove the need for bind or will I still need to use that for certain parts? Thanks for the help.

DSA functions eliminate the need to use their non-DSA counterparts. Typically, binding objects is only required to set the state used by draw calls, not to specify the target for other state-setting operations.

So you don’t need to use e.g. glBindVertexArray() in order to change the state contained within a VAO; you can just use e.g. glVertexArrayAttribFormat() instead of glBindVertexArray()+glVertexAttribFormat(). You still need to bind the VAO prior to glDrawElements() etc. Similarly, glNamedFramebufferTexture() replaces glBindFramebuffer()+glFramebufferTexture() but you still need to bind the appropriate FBO in order to render to it.