C++ OpenGL 内存泄漏



首先,我是 c++ 的初学者。 我正在编写自己的游戏引擎。 代码如下。

雪碧.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;
}

雪碧.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;
};

质地.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()
{
}

纹理.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;
};

主.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();
}

主.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;
};

您会看到,每次创建新纹理时,最后一个纹理都会被删除。 但是,如果我打开任务管理器,内存使用量会越来越高。 为什么会这样? (如果我删除setTexture(new...)一切都很好,所以这就是问题所在。

你的glDelete…电话在哪里?(glDeleteTexturesglDeleteBuffers)。使用delete运算符解除分配类实例不会神奇地使用 OpenGL 执行正确的删除步骤,除非您在析构函数中显式执行此操作。

当我编写OpenGL的东西时,我现在在所有句柄周围使用包装器。如果您使用 GLuint,很可能会忘记一些设置或删除代码。根据您的编码技能,这些包装器可以非常通用,也可以为此目的使用共享指针。

最新更新