Texture Unable To Render Within Method

I am confusion:confused:. Textures will render in main loop, but not when called by render function. If i try to pass program by value into the render method, the screen turns white (glGetError = 0 then 1281) and if I pass by reference the object remains solid black (glGetError = 0). If I take the object and render within the main loop without terrain class, the code runs correctly. I know for sure both vertex/frag shader are working along with everything else, but if you want to look at them just ask.

DOES NOT WORK


#include "Game.h"
#include "Viewport.h"
#include "Program.h"
#include "Terrain.h"
#include "Texture.h"

#include <glm.hpp>
#include <gtc\matrix_transform.hpp>
#include <iostream>
#include <vector>

void Game::run(void)
{
	std::vector<Terrain> terrains;

	glm::mat4 modelMatrix = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, 0.0f));
	modelMatrix = glm::rotate(modelMatrix, glm::radians(-90.0f), glm::vec3(1.0f, 0.0f, 0.0f));
	glm::mat4 projMatrix  = glm::perspective(glm::radians(45.0f), (GLfloat)Viewport::getWidth() / (GLfloat)Viewport::getHeight(), 0.1f, 100.0f);

	terrains.push_back(Terrain(0, -1, "grass.jpg"));

	while (_isActive)
	{
		while (SDL_PollEvent(&e))
		{
			handleEvent(e);
		}

		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		
		for (Terrain t : terrains)
			t.render(sample, modelMatrix, camera.getViewMatrix(), projMatrix);

		Viewport::update();
	}

	Viewport::close();
}

Terrain.h


#ifndef TERRAIN_H
#define TERRAIN_H

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

#include "Texture.h"
#include "Program.h"

class Terrain
{
	GLuint _vao;	//mesh data (We dont want to keep remaking the same vao)
	GLuint _size;	//vert count
	Texture _texture;

public:
	Terrain(GLint gridX, GLint gridZ, const char * texture) : _texture(GL_TEXTURE_2D, texture)
	{
		this->testSquare();
	}

	void testSquare(void)
	{
		GLfloat t[] =
		{
			-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
			-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
			1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
			1.0f, 1.0f, 0.0f, 1.0f, 1.0f
		};
		GLuint i[] =
		{
			0, 1, 2,
			2, 3, 0
		};

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

		glBindVertexArray(vao);
		glBindBuffer(GL_ARRAY_BUFFER, vbo);
		glBufferData(GL_ARRAY_BUFFER, sizeof(t), t, GL_STATIC_DRAW);
		glEnableVertexAttribArray(0);
		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)0);
		glEnableVertexAttribArray(2);
		glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat)));
		glBindBuffer(GL_ARRAY_BUFFER, 0);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
		glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(i), i, GL_STATIC_DRAW);
		glBindVertexArray(0);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

		_size = 6;
		_vao = vao;
	}

	void render(Program program, glm::mat4 model, glm::mat4 view, glm::mat4 proj) //White Screen Or Passing program by reference draws solid black object instead...
	{
		glUseProgram(program.getId());
		glUniformMatrix4fv(glGetUniformLocation(program.getId(), "model"), 1, GL_FALSE, &model[0][0]);
		glUniformMatrix4fv(glGetUniformLocation(program.getId(), "view"), 1, GL_FALSE, &view[0][0]);
		glUniformMatrix4fv(glGetUniformLocation(program.getId(), "proj"), 1, GL_FALSE, &proj[0][0]);
		glUniform1i(glGetUniformLocation(program.getId(), "texture1"), 0);
		
		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_2D, _texture.getId());

		glBindVertexArray(_vao);
		glDrawElements(GL_TRIANGLES, _size, GL_UNSIGNED_INT, 0);
		glBindVertexArray(0);

		glUseProgram(0);
	}
};

#endif // !TERRAIN_H

EDIT:
Well :doh:. I partially solve the issue. I replaced the for each loop with a regular for loop and passed the program in as a reference. Not sure why I needed to do this. Can anyone clarify the reasoning for this issue? If I had to guess it has to do something with open gl and copy constructors?

My first suspicion would be that the Texture class has a copy constructor which merely copies the handle but a destructor which deletes the underlying OpenGL texture object. So creating then destroying a copy deletes the underlying texture and renders the original Texture instance invalid.

If that’s the case, using a range-for loop with a reference type should avoid the problem, i.e.:


for (Terrain& t : terrains)

More generally, attempts to force OOP onto OpenGL rarely end well, particularly with regard to copying and destruction.

[QUOTE=GClements;1291285]My first suspicion would be that the Texture class has a copy constructor which merely copies the handle but a destructor which deletes the underlying OpenGL texture object. So creating then destroying a copy deletes the underlying texture and renders the original Texture instance invalid.

If that’s the case, using a range-for loop with a reference type should avoid the problem, i.e.:


for (Terrain& t : terrains)

More generally, attempts to force OOP onto OpenGL rarely end well, particularly with regard to copying and destruction.[/QUOTE]

You are absolutely correct :). After I had read your post I checked my class code for both my texture and program which contain destructors that call glDelete* on the opengl objects. I cant believe I this never crossed my mind. Ill probably do as you say and move away from the gl object wrappers to prevent issues like this from happening again. Thanks for the help.

You could just =delete the copy constructors and make the types move-only. This really isn’t a problem in a post-C++11 world.