谁能告诉我如何使用硬件内存在 OpenGL 中创建纹理?目前我在窗口模式下运行我的游戏,我是否需要切换到全屏才能使用硬件?
如果我可以在硬件中创建纹理,纹理数量(硬件内存除外)是否有限制?然后如何将我的纹理缓存到硬件中?谢谢。
几乎所有的 OpenGL 纹理教程都应该涵盖这一点。例如这里、这里和这里。
对于每个纹理,您首先需要一个纹理名称。纹理名称就像单个纹理的唯一索引。每个名称都指向一个纹理对象,它可以有自己的参数、数据等。glGenTextures用于获取新名称。我不知道除了 uint 范围(2^32)之外是否有任何限制。如果有,那么您可能会为所有新纹理名称得到 0(和 gl 错误)。
下一步是绑定你的纹理(参见glBindTexture)。之后,所有使用或影响纹理的操作都将使用您用作 glBindTexture 参数的纹理名称指定的纹理。您现在可以设置纹理参数 ( glTexParameter ) 并使用glTexImage2D上传纹理数据(用于 2D 纹理)。调用 glTexImage 后,您还可以使用纹理数据释放系统内存。
对于静态纹理,所有这些都只需要完成一次。如果要使用纹理,只需再次绑定并启用纹理 (glEnable(GL_TEXTURE_2D))。
单个纹理的大小(宽度/高度)受 GL_MAX_TEXTURE_SIZE 限制。这通常是 4096、8192 或 16384。它还受到可用图形内存的限制,因为它必须与帧缓冲区或顶点缓冲区等其他一些资源一起适应它。所有纹理加在一起可以大于可用内存,但随后它们将被交换。
在大多数情况下,图形驱动程序应该决定哪些纹理存储在系统内存中,哪些存储在图形内存中。但是,您可以使用glPrioritizeTextures或 glTexParameter 为某些纹理赋予更高的优先级。
编辑: 我不会太担心纹理的存储位置,因为驱动程序通常做得很好。经常使用的纹理也更有可能存储在图形内存中。如果您设置了一个优先级,这只是对驱动程序的“提示”,即纹理保留在显卡上的重要性。也有可能完全忽略优先级。您还可以使用glAreTexturesResident检查纹理当前的位置。
要在 GPU 上创建纹理,请查看“渲染到纹理”教程。有两种常用方法:将 PBuffer 上下文绑定为纹理,或使用帧缓冲区对象。PBuffer 渲染到纹理是较旧的方法,并且具有更广泛的支持。帧缓冲区对象更易于使用。
此外,您不必切换到“全屏”模式来让 OpenGL 进行硬件加速。事实上,OpenGL 根本不知道窗口。全屏 OpenGL 窗口就是这样:在所有其他窗口之上的顶层窗口,没有任何装饰并且输入焦点被抓住。一些驱动程序绕过窗口屏蔽和剪辑代码,如果具有活动 OpenGL 上下文的窗口覆盖整个屏幕,则采用更简单、更快的缓冲区交换方法,从而获得一点性能,但与当前的硬件和软件相比,效果非常小到其他影响。
通常,当您谈论在GPU上生成纹理时,您实际上并不是在创建纹理图像并像普通纹理一样应用它们。更简单和更常见的方法是使用片段着色器从头开始实时程序计算每个像素的颜色。
典型的例子是在一个物体(比如茶壶)的表面上生成 Mandelbrot 图案。茶壶由应用程序使用其多边形和纹理坐标进行渲染。在渲染管道的某个阶段,茶壶的每个像素都通过片段着色器,片段着色器是应用程序发送到 GPU 的小程序。片段着色器读取 2D 纹理坐标并计算 2D 坐标的 Mandelbrot 集颜色并将其应用于像素。
全屏模式与它无关。即使您处于窗口模式,也可以使用着色器并生成纹理。正如我所提到的,您创建的纹理实际上从未占用纹理内存中的空间,它们是动态创建的。人们可能会想到一种方法来捕获和缓存生成的纹理,但这可能有点复杂并且需要多次渲染。
如果您在 google 中查找“GLSL”(OpenGL 着色语言),您可以了解更多信息。
这个有点过时的教程展示了如何创建一个简单的片段着色器来绘制 Mandelbrot 集(第 4 页)。
如果您可以阅读“OpenGL Shading Language, 2nd Edition”一书,您会发现它包含许多简单的示例,这些示例通过应用程序的外部 3D Perlin 噪声纹理生成天空、火和木材纹理.