如何在OpenGL的缓冲区对象中使用new和delete?

时间:2017-03-24 20:32:13

标签: c++ opengl

我正在学习OpenGL并将其与C ++一起使用......我是初学者,如果这是一个愚蠢的问题,那就很抱歉。

我正在关注本教程(https://learnopengl.com/#!Getting-started/Hello-Triangle),我将代码拆分为create&将片段着色器和顶点着色器编译为单独的函数。显然这意味着一旦函数结束,对象就会超出范围,所以我尝试使用new并删除它们。

我试过这样做:

This is xyz
This is my home
This is my PC
This is my room
This is ubuntu PC xxxx xxxx xxxx xxxx 
xxxx xxxx xxxx xxxx xxxx xxxx xxxx 
xxxxxxxxxxxxxxxxxxxxx

但是我不知道如何将实际的缓冲区对象放入刚分配的新内存中。

我知道使用raw new / delete是不好的做法,所以我应该尝试使用智能指针吗?如果是这样,那对OpenGL的对象有什么用呢?

或者我应该创建一个包装类并将代码生成缓冲区放入类构造函数中,所以它变成这样:

GLuint * pvertexShader; //pointer to a GLuint
pvertexShader = new GLuint;

据我所知,当你为一个对象调用new时,它会在堆上构造。 如果我这样做,我是否仍然可以通过传递指针class VBO; (snip) pvertexShader = new VBO; //the class is constructed on the heap 而不是实际的顶点着色器来使用glBindBufferglAttachShader等函数?所以写pvertexShader

修改

好的,现在我发现你做的任何东西都是由OpenGL分配到GPU上的,所以你不必使用new / delete。 因为我正在做的是这样的:

glAttachShader(shaderprogram, pvertexShader)

然后,当我进入链接着色器和程序的阶段时,这些函数中的两个着色器已超出范围(根据XCode)。

如何预防/解决这个问题?

2 个答案:

答案 0 :(得分:6)

您在OpenGL中分配的缓冲区的实际内存位于GPU内。 gl_buffer *函数不会像您期望的那样返回内存数组的第一个地址,而是将ID(类型为GLuint)插入到id参数中,然后您可以将其与其他OpenGL函数一起使用以处理内存。在GPU中初始化。您不需要指向其地址的指针,OpenGL只询问内部分配给缓冲区的数字。

这是一个说明这一点的小例子。

 // unsigned int to hold the ID that OpenGL will assign to this shader
  GLuint sVertex;

  sVertex = glCreateShader(GL_VERTEX_SHADER);
  glShaderSource(sVertex, 1, &vertexSource, NULL);
  glCompileShader(sVertex);

注意这个顶点着色器是如何编译的,甚至没有移动它的地址。原因是OpenGL在GPU方面为您管理,所有您需要做的就是使用包含OpenGL用于识别着色器的数字的GLuint。

它起初反直觉,但这个系统确实有它的好处,例如你可以只使用其(GLuint)ID在正确初始化的GL资源(如纹理或着色器)上移动任何类型,示例

// texture_id contains the number that OpenGL uses to reference this particular texture in the GPU memory
void use_texture(GLuint texture_id);

答案 1 :(得分:1)

一步一步。

在存储复杂数据时,您可能只需要指针,可能在结构/类中。然后智能指针非常合适。

glXXXX调用不提供指针(glMapBuffer除外)。他们创建的任何内存(例如,通过glBufferData)是GPU内存,而不是客户端(即在CPU侧)。不要打扰它。

读取着色器代码,编译它们,链接它们,获取错误,是重复的作业,几乎没有客户端结果存储,比如标识着色器程序的整数。它们适合封装在类中。

对象VBO,VAO,顶点数据等也适用于类。同样适用于相机处理,渲染和应用的其他功能。

重点是您按任务/对象组织代码。