2016-04-10 48 views
3

我有一个2D图形库,我想在OpenGL中使用,以便能够混合2D和3D图形。最简单的方法似乎是使用glDrawPixels,但许多最近的教程和论坛建议使用glTexSubImage2D命令使用纹理,然后用这种纹理绘制正方形。glDrawPixels vs纹理在OpenGL中绘制2D缓冲区

我的问题是:为什么?优势在哪里?它只是增加了一个步骤(内存缓冲区 - >纹理 - >视频缓冲区,而不是内存缓冲区 - >视频缓冲区)。

+0

glDrawPixels被称为非常慢。 –

+0

比glTexSubImage2D慢?两个命令都执行相同的操作:从系统内存复制到视频内存。 – angros47

+0

3D图形中的2D纹理交错或其他内容?如果它始终位于顶部或底部,则可以直接使用窗口系统将其缓冲到后缓冲区。 – Andreas

回答

1

由于OpenGL使用视频内存,因此使用简单的“绘制像素”必须非常慢,因为您将为每个绘制执行大量的GPU/CPU同步。

当您使用glTexSubImage2D时,确保图像将始终驻留在快速的视频内存中(始终)。加载内部显存纹理

的一种方法是:

glCreateTextures(GL_TEXTURE_2D, 1, &texture->mId); 

glTextureParameteri(mId, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 
glTextureParameteri(mId, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 

GLsizei numMipmaps = ((GLsizei)log2(std::max(surface->w, surface->h)) + 1); 
glTextureStorage2D(*texture, numMipmaps, internalFormat, surface->w, surface->h); 
glTextureSubImage2D(*texture, 0, 0, 0, surface->w, surface->h, 
        format, GL_UNSIGNED_BYTE, surface->pixels); 

glGenerateTextureMipmap(*texture); 

不要忘记绑定,如果你不想使用直接访问状态。

但是,如果你仍然要执行像素平局(例如,用于程序渲染),你必须编写自己的片段着色器要尽可能快

+0

但即使glTexSubImage2D将数据传输到视频内存,如果它在每帧使用应该做很多同步。如果图片是静态的,我可以只使用它一次在视频内存中留下副本,但它不是静态的(并且2d图像不是由Opengl渲染的,所以不能使用FBO) – angros47

+0

如果纹理不是静态,我想有几种方法可以实现这一点。第一个是加载所有可能的图像(一个gif与几个图像组合),第二个是使用一个PBO的持久映射,例如? –

+0

纹理由CPU即时生成,因此无法预加载(这是2d库的输出)。两者都不能直接在GPU上生成(2d库在常规内存缓冲区中工作) – angros47

2

主要有两个原因:

  • glDrawPixels()已弃用,并且在OpenGL核心配置文件或OpenGL ES中不可用。
  • 多次绘制图像时,通过将图像数据存储在纹理中可以节省大量重复的工作。

这是非常罕见的,你将不得不画一次图像。更为常见的是,您可以在每次重绘时重复绘制它。使用glDrawPixels(),您必须每次将图像数据传递到OpenGL。如果将其存储在纹理中,则可以重复绘制它,并且OpenGL可以每次重复使用相同的数据。

要绘制纹理的内容,您不一定需要设置着色器,绘制四边形等。您可以使用glBlitFramebuffer()将纹理内容复制到显示器。

+0

它可能不推荐使用,但用四元组替换它并不会起作用,因为绘制四元组(glOrtho,glLoadIdentity等)的命令是也不赞成使用GLES2,所以我仍然需要一个不同的渲染器(这不适用于版本1 ......并且许多计算机仍然只支持版本1) – angros47

+0

另外,我不想使用相同的数据在每次重绘时,因为缓冲区可能已被更改并且屏幕需要更新,所以我仍然需要将数据发送到视频卡。 – angros47

相关问题