Reputation: 187
First of all, I'm a beginner in c++. I'm writing my own game engine. Code is below.
Sprite.cpp
#include "Sprite.h"
Sprite::Sprite(GLfloat x, GLfloat y, GLfloat width, GLfloat height, Shader& shader, char *texturePath)
{
init(x, y, width, height, shader, texturePath, STBI_rgb_alpha);
}
Sprite::Sprite(GLfloat x, GLfloat y, GLfloat width, GLfloat height, Shader& shader, char *texturePath, int reg_comp)
{
init(x, y, width, height, shader, texturePath, reg_comp);
}
void Sprite::init(GLfloat x, GLfloat y, GLfloat width, GLfloat height, Shader& shader, char *texturePath, int reg_comp)
{
this->shader = &shader;
GLfloat vertices[] = {
width/2+x, height/2+y, 0.0f, /* Top Right */ 1.0f, 1.0f,
width/2 + x, -height / 2 + y, 0.0f, /* Bottom Right*/ 1.0f, 0.0f,
-width/2 + x, -height / 2 + y, 0.0f, /* Bottom Left*/ 0.0f, 0.0f,
-width / 2 + x, height / 2 + y, 0.0f, /* Top Left */ 0.0f, 1.0f
};
GLuint indices[] = {
0, 1, 3, // 1
1, 2, 3 // 2
};
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
//Position
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
// TexCoord
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
texture = new Texture(texturePath, reg_comp);
transformShaderLocation = glGetUniformLocation(shader.program, "transform");
glProgramUniform4fv(shader.program, transformShaderLocation, 1, transform);
}
Sprite::~Sprite()
{
delete texture;
}
void Sprite::Draw() {
glBindTexture(GL_TEXTURE_2D, texture->texture); //?
//glUniform1i(glGetUniformLocation(shader->program, "ourTexture"), 0); //?
shader->Use();
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
}
void Sprite::Transform(int x, int y) {
glProgramUniform4fv(shader->program, transformShaderLocation, 1, transform);
}
void Sprite::setTexture(Texture *texture) {
delete this->texture;
this->texture = texture;
}
Sprite.h
#pragma once
#include <GL/glew.h>
#include "Shader.h"
#include <glm/glm.hpp>
#include "Texture.h"
#include <stb_image.h>
class Sprite
{
public:
Sprite(GLfloat x, GLfloat y, GLfloat width, GLfloat height, Shader& shader, char *texturePath);
Sprite(GLfloat x, GLfloat y, GLfloat width, GLfloat height, Shader& shader, char *texturePath, int reg_comp);
~Sprite();
void Draw();
void Transform(int x, int y);
void setTexture(Texture *texture);
private:
void init(GLfloat x, GLfloat y, GLfloat width, GLfloat height, Shader& shader, char *texturePath, int reg_comp);
GLuint VBO = 0, VAO = 0, EBO = 0;
GLint transformShaderLocation;
Shader* shader;
GLfloat transform[4] = {
1.f, 1.f, 1.f, 1.f
};
Texture *texture;
};
Texture.cpp
#include "Texture.h"
Texture::Texture(char *texturePath, int reg_comp)
{
glGenTextures(1, &texture);
int _width, _height, _ImageComponents;
unsigned char *image = stbi_load(texturePath, &_width, &_height, &_ImageComponents, reg_comp);
if (image == nullptr) {
std::cout << "error loading image" << std::endl;
}
glBindTexture(GL_TEXTURE_2D, texture);
// Set our texture parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// Set texture filtering
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _width, _height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
if (_ImageComponents == 3)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, _width, _height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
else if (_ImageComponents == 4)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _width, _height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image); //RGBA8?
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
stbi_image_free(image);
}
Texture::~Texture()
{
}
Texture.h
#pragma once
#include <GL/glew.h>
#include <iostream>
#include <stb_image.h>
class Texture
{
public:
Texture(char *texturePath, int reg_comp);
~Texture();
GLuint texture = 0;
};
main.cpp
#include "main.h"
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>
int main(int argc, char* argv[]) {
Main main;
return main.init();
}
int Main::init() {
display = new Display( 800, 600, "OpenGL" );
shader = new Shader("Shaders/default.vert", "Shaders/default.frag");
sprite = new Sprite(-0.5f, -0.5f, 1.0f, 1.0f, *shader, "Textures/texture1.png");
sprite2 = new Sprite(0.5f, 0.5f, 1.0f, 1.0f, *shader, "Textures/texture2.png", STBI_rgb);
while (!display->isClosed()) {
update();
}
delete display;
delete shader;
delete sprite;
delete sprite2;
return 0;
}
void Main::update() {
draw();
display->Update();
if (debug == 0) {
texture->setTexture(new Texture("Textures/texture1.png", STBI_rgb_alpha));
debug = 1;
}
else if (debug == 1) {
texture->setTexture(new Texture("Textures/texture2.png", STBI_rgb));
debug = 0;
}
}
void Main::draw() {
glClearColor(0.0f, 0.3f, 0.5f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);;
sprite->Draw();
sprite->Draw();
}
main.h:
#pragma once
#include <iostream>
#include "Display.h"
#include "Shader.h"
#include "Triangle.h"
#include "Sprite.h"
class Main {
public:
int init();
private:
void draw();
void update();
Display *display;
Shader *shader;
Triangle *triangle, *triangle2;
Sprite *sprite, *sprite2;
int debug = 0;
};
You see, everytime a new texture is created, the last texture is deleted. However, if I open the task manager the memory usage goes up and up. Why is that so? (If I remove setTexture(new...) everything is fine, so this is the problem.
Upvotes: 0
Views: 4485
Reputation: 2004
When I am programming OpenGL stuff, i now use wrapper around all handles. If you use GLuint it is very likely to forget some setup or deletion code. Depending on your coding skills, these wrappers can be very generic or you can use the shared pointer for this purpose.
Upvotes: 1
Reputation: 162164
Where are your glDelete…
calls? (glDeleteTextures
, glDeleteBuffers
). Deallocating your class instances with the delete
operator will not magically do the proper deletion steps with OpenGL unless you do it explicitly in the destructor.
Upvotes: 6