glDrawPixels vs textures在OpenGL中绘制2d缓冲区

glDrawPixels vs textures在OpenGL中绘制2d缓冲区,opengl,Opengl,我有一个二维图形库,我想在OpenGL中使用,能够混合二维和三维图形。最简单的方法似乎是使用glDrawPixels,但许多最近的教程和论坛建议使用命令glTexSubImage2D使用纹理,然后使用这种纹理绘制正方形 我的问题是:为什么?优势在哪里?它只增加了一个步骤(内存缓冲区->纹理->视频缓冲区,而不是内存缓冲区->视频缓冲区)。由于OpenGL使用视频内存,使用简单的“绘制像素”必须非常慢,因为每次绘制都要进行大量GPU/CPU同步 当您使用glTexSubImage2D时,您可以确保

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


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

由于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);
如果不想使用直接状态访问,请不要忘记绑定


但是,如果仍要执行像素绘制(例如程序渲染),则必须尽可能快地编写自己的片段着色器。主要原因有两个:

  • glDrawPixels()
    已弃用,在OpenGL核心配置文件或OpenGL ES中不可用
  • 在多次绘制图像时,通过将图像数据存储在纹理中可以节省大量重复工作
你很少只需要画一次图像。更常见的是,每次重画时都会重复绘制。使用
glDrawPixels()
每次都必须将图像数据传递到OpenGL中。如果将其存储在纹理中,则可以重复绘制,OpenGL每次都可以重用相同的数据


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

glDrawPixels已知非常慢。比glTexSubImage2D慢吗?这两个命令的作用是相同的:从系统内存复制到视频内存。2D纹理在3D图形中是交错的还是什么?如果它总是在顶部或底部,您可以直接使用窗口系统将其blit到backbuffer。我的想法是使用2d在顶部,带有alpha通道,来绘制分数,或使用HUD,或简单的GUI。我想在windows中使用wgl,在linux中使用glx来创建上下文。使用它们来blit 2d图像的最佳方式是什么?我在考虑使用覆盖层。。。但看起来大多数图形卡都不支持它们,但即使是glTexSubImage2D也会将数据传输到视频存储器中,如果在每一帧使用它,也会进行大量的同步。如果图片是静态的,我可以只使用它一次在视频内存中留下一个副本,但它不是静态的(而且2d图像不是由Opengl渲染的,所以不能使用FBO)。如果纹理不是静态的,我想有几种方法可以实现这一点。第一种方法是加载所有可能的图像(一个gif由多个图像组成),第二种方法是使用一个PBO的持久映射,例如,纹理是由CPU动态生成的,因此无法预加载(它是2d库的输出)。两者都不能直接在GPU上生成(2d库在常规内存缓冲区上工作),所以您尝试过使用PBO吗?我没有尝试过。。。它们是否在较旧的OpenGl版本上受支持,如1.4(如果可能,我希望我的代码可以在任何地方运行)它可能会被弃用。。。但是用四边形替换它不会有帮助,因为绘制四边形的命令(glOrtho、glLoadIdentity等)也被弃用,并且在GLES2上不可用,因此我仍然需要不同的渲染器(在版本1上不起作用…许多计算机仍然只支持版本1)。此外,我不想在每次重画时使用相同的数据,因为缓冲区可能已经更改,屏幕需要更新,所以我仍然需要将数据发送到视频卡。