This question already has an answer here:
这个问题已经有了答案:
- How to use GLUT/OpenGL to render to a file? 5 answers
- 如何使用过量/OpenGL来呈现文件?5个回答
My aim is to render OpenGL scene without a window, directly into a file. The scene may be larger than my screen resolution is.
我的目标是在没有窗口的情况下渲染OpenGL场景,直接进入文件。这个场景可能比我的屏幕分辨率大。
How can I do this?
我该怎么做呢?
I want to be able to choose the render area size to any size, for example 10000x10000, if possible?
我希望能够选择渲染区域大小为任意大小,例如10000x10000,如果可能的话?
5 个解决方案
#1
75
It all starts with glReadPixels
, which you will use to transfer the pixels stored in a specific buffer on the GPU to the main memory (RAM). As you will notice in the documentation, there is no argument to choose which buffer. As is usual with OpenGL, the current buffer to read from is a state, which you can set with glReadBuffer
.
这一切都始于glReadPixels,您将使用它将存储在GPU上的特定缓冲区中的像素转移到主内存(RAM)。正如您将在文档中注意到的,没有参数选择哪个缓冲区。与OpenGL一样,当前读取的缓冲区是一个状态,您可以使用glReadBuffer设置它。
So a very basic offscreen rendering method would be something like the following. I use c++ pseudo code so it will likely contain errors, but should make the general flow clear:
所以一个非常基本的离线渲染方法就像下面这样。我使用c++伪代码,这样它可能会包含错误,但应该使一般的流程清晰:
//Before swapping
std::vector<std::uint8_t> data(width*height*4);
glReadBuffer(GL_BACK);
glReadPixels(0,0,width,height,GL_BGRA,GL_UNSIGNED_BYTE,&data[0]);
This will read the current back buffer (usually the buffer you're drawing to). You should call this before swapping the buffers. Note that you can also perfectly read the back buffer with the above method, clear it and draw something totally different before swapping it. Technically you can also read the front buffer, but this is often discouraged as theoretically implementations were allowed to make some optimizations that might make your front buffer contain rubbish.
这将读取当前的返回缓冲区(通常是您正在绘制的缓冲区)。在交换缓冲区之前应该调用它。注意,您还可以使用上面的方法完美地读取后面的缓冲区,清除它并在交换之前画出完全不同的东西。从技术上讲,您也可以读取前面的缓冲区,但是这通常是不鼓励的,因为理论上实现可以进行一些优化,从而使您的前端缓冲区包含垃圾。
There are a few drawbacks with this. First of all, we don't really do offscreen rendering do we. We render to the screen buffers and read from those. We can emulate offscreen rendering by never swapping in the back buffer, but it doesn't feel right. Next to that, the front and back buffers are optimized to display pixels, not to read them back. That's where Framebuffer Objects come into play.
这有一些缺点。首先,我们并不是真的在屏幕上做渲染。我们渲染到屏幕缓冲区并从中读取。我们可以通过在后台缓冲区中不进行交换来模拟屏幕显示,但是感觉不太好。接下来,前面和后面的缓冲区被优化以显示像素,而不是读取它们。这就是Framebuffer对象发挥作用的地方。
Essentially, an FBO lets you create a non-default framebuffer (like the FRONT and BACK buffers) that allow you to draw to a memory buffer instead of the screen buffers. In practice, you can either draw to a texture or to a renderbuffer. The first is optimal when you want to re-use the pixels in OpenGL itself as a texture (e.g. a naive "security camera" in a game), the latter if you just want to render/read-back. With this the code above would become something like this, again pseudo-code, so don't kill me if mistyped or forgot some statements.
从本质上说,FBO允许您创建一个非默认的framebuffer(比如前面和后面的缓冲区),它允许您使用内存缓冲区而不是屏幕缓冲区。在实践中,您可以使用纹理或渲染缓冲。第一个是最优的,当你想要重新使用OpenGL本身的像素作为一个纹理(例如,一个简单的“安全摄像头”在游戏中),如果你只是想要渲染/读回来。上面的代码将会变成类似这样的伪代码,所以不要在键入错误或忘记一些语句时杀死我。
//Somewhere at initialization
GLuint fbo, render_buf;
glGenFramebuffers(1,&fbo);
glGenRenderbuffers(1,&render_buf);
glBindRenderbuffer(render_buf);
glRenderbufferStorage(GL_RENDERBUFFER, GL_BGRA8, width, height);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER,fbo);
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, render_buf);
//At deinit:
glDeleteFramebuffers(1,&fbo);
glDeleteRenderbuffers(1,&render_buf);
//Before drawing
glBindFramebuffer(GL_DRAW_FRAMEBUFFER,fbo);
//after drawing
std::vector<std::uint8_t> data(width*height*4);
glReadBuffer(GL_COLOR_ATTACHMENT0);
glReadPixels(0,0,width,height,GL_BGRA,GL_UNSIGNED_BYTE,&data[0]);
// Return to onscreen rendering:
glBindFramebuffer(GL_DRAW_FRAMEBUFFER,0);
This is a simple example, in reality you likely also want storage for the depth (and stencil) buffer. You also might want to render to texture, but I'll leave that as an exercise. In any case, you will now perform real offscreen rendering and it might work faster then reading the back buffer.
这是一个简单的示例,实际上您可能还需要存储深度(和模板)缓冲区。你也可能想渲染纹理,但我把它作为练习。在任何情况下,您现在都将执行真正的屏幕显示,并且它可能工作得更快,然后读取后面的缓冲区。
Finally, you can use pixel buffer objects to make read pixels asynchronous. The problem is that glReadPixels
blocks until the pixel data is completely transfered, which may stall your CPU. With PBO's the implementation may return immediately as it controls the buffer anyway. It is only when you map the buffer that the pipeline will block. However, PBO's may be optimized to buffer the data solely on RAM, so this block could take a lot less time. The read pixels code would become something like this:
最后,您可以使用像素缓存对象使读取的像素成为异步的。问题是,在像素数据完全转移之前,glReadPixels会阻塞,这可能会阻碍您的CPU。PBO的实现可能会立即返回,因为它控制了缓冲区。只有当您映射缓冲区时,管道才会阻塞。然而,PBO的优化可能只是为了缓冲内存中的数据,所以这个块可能需要更少的时间。读取的像素代码会变成这样:
//Init:
GLuint pbo;
glGenBuffers(1,&pbo);
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
glBufferData(GL_PIXEL_PACK_BUFFER, width*height*4, NULL, GL_DYNAMIC_READ);
//Deinit:
glDeleteBuffers(1,&pbo);
//Reading:
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
glReadPixels(0,0,width,height,GL_BGRA,GL_UNSIGNED_BYTE,0); // 0 instead of a pointer, it is now an offset in the buffer.
//DO SOME OTHER STUFF (otherwise this is a waste of your time)
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo); //Might not be necessary...
pixel_data = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
The part in caps is essential. If you just issue a glReadPixels
to a PBO, followed by a glMapBuffer
of that PBO, you gained nothing but a lot of code. Sure the glReadPixels
might return immediately, but now the glMapBuffer
will stall because it has to safely map the data from the read buffer to the PBO and to a block of memory in main RAM.
帽子的部分是必不可少的。如果您只向PBO发出一个glReadPixels,然后是PBO的glMapBuffer,那么您只获得了大量的代码。当然,glReadPixels可能会立即返回,但现在glMapBuffer将会停止,因为它必须安全地将数据从读取缓冲区映射到PBO,并将数据映射到主RAM中的一块内存。
Please also note that I use GL_BGRA everywhere, this is because many graphics cards internally use this as the optimal rendering format (or the GL_BGR version without alpha). It should be the fastest format for pixel transfers like this. I'll try to find the nvidia article I read about this a few monts back.
请注意,我在任何地方都使用GL_BGRA,这是因为许多图形卡在内部使用它作为最优呈现格式(或者没有alpha的GL_BGR版本)。它应该是像这样的像素传输最快的格式。我会试着找到nvidia的文章,我读过一些关于这方面的文章。
When using OpenGL ES 2.0, GL_DRAW_FRAMEBUFFER
might not be available, you should just use GL_FRAMEBUFFER
in that case.
在使用OpenGL ES 2.0时,可能无法使用GL_DRAW_FRAMEBUFFER,在这种情况下,您应该只使用GL_FRAMEBUFFER。
#2
14
I'll assume that creating a dummy window (you don't render to it; it's just there because the API requires you to make one) that you create your main context into is an acceptable implementation strategy.
我假设创建一个虚拟窗口(您不渲染它;它只是因为API需要你做一个)你创建你的主要上下文是一个可接受的实施策略。
Here are your options:
这是你的选择:
Pixel buffers
A pixel buffer, or pbuffer (which isn't a pixel buffer object), is first and foremost an OpenGL context. Basically, you create a window as normal, then pick a pixel format from wglChoosePixelFormatARB
(pbuffer formats must be gotten from here). Then, you call wglCreatePbufferARB
, giving it your window's HDC and the pixel buffer format you want to use. Oh, and a width/height; you can query the implementation's maximum width/heights.
一个像素缓冲区,即pbuffer(不是一个像素缓存对象),首先是OpenGL上下文。基本上,您创建了一个正常的窗口,然后从wglChoosePixelFormatARB中选择一个像素格式(必须从这里得到pbuffer格式)。然后,您调用wglCreatePbufferARB,给它您的窗口的HDC和您想要使用的像素缓冲格式。哦,和宽/高;您可以查询实现的最大宽度/高度。
The default framebuffer for pbuffer is not visible on the screen, and the max width/height is whatever the hardware wants to let you use. So you can render to it and use glReadPixels
to read back from it.
pbuffer的默认framebuffer在屏幕上不可见,而最大宽度/高度是硬件想让您使用的任何东西。你可以渲染它并使用glReadPixels来读取它。
You'll need to share you context with the given context if you have created objects in the window context. Otherwise, you can use the pbuffer context entirely separately. Just don't destroy the window context.
如果您在窗口上下文中创建了对象,则需要与给定上下文共享上下文。否则,您可以完全独立地使用pbuffer上下文。不要破坏窗口上下文。
The advantage here is greater implementation support (though most drivers that don't support the alternatives are also old drivers for hardware that's no longer being supported. Or is Intel hardware).
这里的优势是更大的实现支持(尽管大多数不支持替代方案的驱动程序也都是硬件的旧驱动,而这些硬件已经不再受支持了。或者是Intel硬件)。
The downsides are these. Pbuffers don't work with core OpenGL contexts. They may work for compatibility, but there is no way to give wglCreatePbufferARB
information about OpenGL versions and profiles.
这些缺点。pbuffer不使用核心OpenGL上下文。它们可以兼容,但是没有办法提供关于OpenGL版本和配置文件的wglCreatePbufferARB信息。
Framebuffer Objects
Framebuffer Objects are more "proper" offscreen rendertargets than pbuffers. FBOs are within a context, while pbuffers are about creating new contexts.
Framebuffer对象比pbuffer更“适当”的offscreen渲染目标。FBOs在一个上下文中,而pbuffer则是创建新的上下文。
FBOs are just a container for images that you render to. The maximum dimensions that the implementation allows can be queried; you can assume it to be GL_MAX_VIEWPORT_DIMS
(make sure an FBO is bound before checking this, as it changes based on whether an FBO is bound).
FBOs只是一个用于呈现图像的容器。实现允许的最大维度可以查询;您可以假设它是GL_MAX_VIEWPORT_DIMS(确保在检查这个之前,FBO是绑定的,因为它会根据FBO是否被绑定而变化)。
Since you're not sampling textures from these (you're just reading values back), you should use renderbuffers instead of textures. Their maximum size may be larger than those of textures.
由于您并不是从这些(您只是读取值)中取样纹理,所以您应该使用renderbuffer而不是纹理。它们的最大尺寸可能比材质的大。
The upside is the ease of use. Rather than have to deal with pixel formats and such, you just pick an appropriate image format for your glRenderbufferStorage
call.
好处是易于使用。您只需为glRenderbufferStorage调用选择合适的图像格式,而不必处理像素格式。
The only real downside is the narrower band of hardware that supports them. In general, anything that AMD or NVIDIA makes that they still support (right now, GeForce 6xxx or better [note the number of x's], and any Radeon HD card) will have access to ARB_framebuffer_object or OpenGL 3.0+ (where it's a core feature). Older drivers may only have EXT_framebuffer_object support (which has a few differences). Intel hardware is potluck; even if they claim 3.x or 4.x support, it may still fail due to driver bugs.
唯一真正的缺点是支持它们的更窄的硬件。一般来说,任何AMD或NVIDIA的产品都支持(现在,GeForce 6xxx或更好的(注意x的数量)和任何Radeon HD卡)都可以访问ARB_framebuffer_object或OpenGL 3.0+(它是一个核心功能)。旧的驱动程序可能只有EXT_framebuffer_object支持(它有一些差异)。Intel硬件是家常便饭;即使他们要求3。x或4。x支持,它可能仍然会因为驱动程序错误而失败。
#3
3
If you need to render something that exceeds the maximum FBO size of your GL implementation libtr
works pretty well:
如果您需要呈现超过您的GL实现的最大FBO大小的东西,libtr可以很好地工作:
The TR (Tile Rendering) library is an OpenGL utility library for doing tiled rendering. Tiled rendering is a technique for generating large images in pieces (tiles).
TR (Tile效果图)库是OpenGL实用程序库,用于进行tiled渲染。Tiled渲染是一种用块(tiles)生成大图像的技术。
TR is memory efficient; arbitrarily large image files may be generated without allocating a full-sized image buffer in main memory.
TR记忆效率;任意大的图像文件可能在主内存中不分配一个全尺寸的图像缓冲区。
#4
2
The easiest way is to use something called Frame Buffer Objects (FBO). You will still have to create a window to create an opengl context though (but this window can be hidden).
最简单的方法是使用所谓的帧缓冲对象(FBO)。您仍然需要创建一个窗口来创建opengl上下文(但是这个窗口可以被隐藏)。
#5
1
The easiest way to fulfill your goal is using FBO to do off-screen render. And you don't need to render to texture, then get the teximage. Just render to buffer and use function glReadPixels. This link will be useful. See Framebuffer Object Examples
实现目标的最简单方法是使用FBO来完成屏幕外渲染。你不需要渲染纹理,然后得到纹理。只需要渲染缓冲和使用函数glReadPixels。这个链接是有用的。看到Framebuffer对象的例子
#1
75
It all starts with glReadPixels
, which you will use to transfer the pixels stored in a specific buffer on the GPU to the main memory (RAM). As you will notice in the documentation, there is no argument to choose which buffer. As is usual with OpenGL, the current buffer to read from is a state, which you can set with glReadBuffer
.
这一切都始于glReadPixels,您将使用它将存储在GPU上的特定缓冲区中的像素转移到主内存(RAM)。正如您将在文档中注意到的,没有参数选择哪个缓冲区。与OpenGL一样,当前读取的缓冲区是一个状态,您可以使用glReadBuffer设置它。
So a very basic offscreen rendering method would be something like the following. I use c++ pseudo code so it will likely contain errors, but should make the general flow clear:
所以一个非常基本的离线渲染方法就像下面这样。我使用c++伪代码,这样它可能会包含错误,但应该使一般的流程清晰:
//Before swapping
std::vector<std::uint8_t> data(width*height*4);
glReadBuffer(GL_BACK);
glReadPixels(0,0,width,height,GL_BGRA,GL_UNSIGNED_BYTE,&data[0]);
This will read the current back buffer (usually the buffer you're drawing to). You should call this before swapping the buffers. Note that you can also perfectly read the back buffer with the above method, clear it and draw something totally different before swapping it. Technically you can also read the front buffer, but this is often discouraged as theoretically implementations were allowed to make some optimizations that might make your front buffer contain rubbish.
这将读取当前的返回缓冲区(通常是您正在绘制的缓冲区)。在交换缓冲区之前应该调用它。注意,您还可以使用上面的方法完美地读取后面的缓冲区,清除它并在交换之前画出完全不同的东西。从技术上讲,您也可以读取前面的缓冲区,但是这通常是不鼓励的,因为理论上实现可以进行一些优化,从而使您的前端缓冲区包含垃圾。
There are a few drawbacks with this. First of all, we don't really do offscreen rendering do we. We render to the screen buffers and read from those. We can emulate offscreen rendering by never swapping in the back buffer, but it doesn't feel right. Next to that, the front and back buffers are optimized to display pixels, not to read them back. That's where Framebuffer Objects come into play.
这有一些缺点。首先,我们并不是真的在屏幕上做渲染。我们渲染到屏幕缓冲区并从中读取。我们可以通过在后台缓冲区中不进行交换来模拟屏幕显示,但是感觉不太好。接下来,前面和后面的缓冲区被优化以显示像素,而不是读取它们。这就是Framebuffer对象发挥作用的地方。
Essentially, an FBO lets you create a non-default framebuffer (like the FRONT and BACK buffers) that allow you to draw to a memory buffer instead of the screen buffers. In practice, you can either draw to a texture or to a renderbuffer. The first is optimal when you want to re-use the pixels in OpenGL itself as a texture (e.g. a naive "security camera" in a game), the latter if you just want to render/read-back. With this the code above would become something like this, again pseudo-code, so don't kill me if mistyped or forgot some statements.
从本质上说,FBO允许您创建一个非默认的framebuffer(比如前面和后面的缓冲区),它允许您使用内存缓冲区而不是屏幕缓冲区。在实践中,您可以使用纹理或渲染缓冲。第一个是最优的,当你想要重新使用OpenGL本身的像素作为一个纹理(例如,一个简单的“安全摄像头”在游戏中),如果你只是想要渲染/读回来。上面的代码将会变成类似这样的伪代码,所以不要在键入错误或忘记一些语句时杀死我。
//Somewhere at initialization
GLuint fbo, render_buf;
glGenFramebuffers(1,&fbo);
glGenRenderbuffers(1,&render_buf);
glBindRenderbuffer(render_buf);
glRenderbufferStorage(GL_RENDERBUFFER, GL_BGRA8, width, height);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER,fbo);
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, render_buf);
//At deinit:
glDeleteFramebuffers(1,&fbo);
glDeleteRenderbuffers(1,&render_buf);
//Before drawing
glBindFramebuffer(GL_DRAW_FRAMEBUFFER,fbo);
//after drawing
std::vector<std::uint8_t> data(width*height*4);
glReadBuffer(GL_COLOR_ATTACHMENT0);
glReadPixels(0,0,width,height,GL_BGRA,GL_UNSIGNED_BYTE,&data[0]);
// Return to onscreen rendering:
glBindFramebuffer(GL_DRAW_FRAMEBUFFER,0);
This is a simple example, in reality you likely also want storage for the depth (and stencil) buffer. You also might want to render to texture, but I'll leave that as an exercise. In any case, you will now perform real offscreen rendering and it might work faster then reading the back buffer.
这是一个简单的示例,实际上您可能还需要存储深度(和模板)缓冲区。你也可能想渲染纹理,但我把它作为练习。在任何情况下,您现在都将执行真正的屏幕显示,并且它可能工作得更快,然后读取后面的缓冲区。
Finally, you can use pixel buffer objects to make read pixels asynchronous. The problem is that glReadPixels
blocks until the pixel data is completely transfered, which may stall your CPU. With PBO's the implementation may return immediately as it controls the buffer anyway. It is only when you map the buffer that the pipeline will block. However, PBO's may be optimized to buffer the data solely on RAM, so this block could take a lot less time. The read pixels code would become something like this:
最后,您可以使用像素缓存对象使读取的像素成为异步的。问题是,在像素数据完全转移之前,glReadPixels会阻塞,这可能会阻碍您的CPU。PBO的实现可能会立即返回,因为它控制了缓冲区。只有当您映射缓冲区时,管道才会阻塞。然而,PBO的优化可能只是为了缓冲内存中的数据,所以这个块可能需要更少的时间。读取的像素代码会变成这样:
//Init:
GLuint pbo;
glGenBuffers(1,&pbo);
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
glBufferData(GL_PIXEL_PACK_BUFFER, width*height*4, NULL, GL_DYNAMIC_READ);
//Deinit:
glDeleteBuffers(1,&pbo);
//Reading:
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
glReadPixels(0,0,width,height,GL_BGRA,GL_UNSIGNED_BYTE,0); // 0 instead of a pointer, it is now an offset in the buffer.
//DO SOME OTHER STUFF (otherwise this is a waste of your time)
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo); //Might not be necessary...
pixel_data = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
The part in caps is essential. If you just issue a glReadPixels
to a PBO, followed by a glMapBuffer
of that PBO, you gained nothing but a lot of code. Sure the glReadPixels
might return immediately, but now the glMapBuffer
will stall because it has to safely map the data from the read buffer to the PBO and to a block of memory in main RAM.
帽子的部分是必不可少的。如果您只向PBO发出一个glReadPixels,然后是PBO的glMapBuffer,那么您只获得了大量的代码。当然,glReadPixels可能会立即返回,但现在glMapBuffer将会停止,因为它必须安全地将数据从读取缓冲区映射到PBO,并将数据映射到主RAM中的一块内存。
Please also note that I use GL_BGRA everywhere, this is because many graphics cards internally use this as the optimal rendering format (or the GL_BGR version without alpha). It should be the fastest format for pixel transfers like this. I'll try to find the nvidia article I read about this a few monts back.
请注意,我在任何地方都使用GL_BGRA,这是因为许多图形卡在内部使用它作为最优呈现格式(或者没有alpha的GL_BGR版本)。它应该是像这样的像素传输最快的格式。我会试着找到nvidia的文章,我读过一些关于这方面的文章。
When using OpenGL ES 2.0, GL_DRAW_FRAMEBUFFER
might not be available, you should just use GL_FRAMEBUFFER
in that case.
在使用OpenGL ES 2.0时,可能无法使用GL_DRAW_FRAMEBUFFER,在这种情况下,您应该只使用GL_FRAMEBUFFER。
#2
14
I'll assume that creating a dummy window (you don't render to it; it's just there because the API requires you to make one) that you create your main context into is an acceptable implementation strategy.
我假设创建一个虚拟窗口(您不渲染它;它只是因为API需要你做一个)你创建你的主要上下文是一个可接受的实施策略。
Here are your options:
这是你的选择:
Pixel buffers
A pixel buffer, or pbuffer (which isn't a pixel buffer object), is first and foremost an OpenGL context. Basically, you create a window as normal, then pick a pixel format from wglChoosePixelFormatARB
(pbuffer formats must be gotten from here). Then, you call wglCreatePbufferARB
, giving it your window's HDC and the pixel buffer format you want to use. Oh, and a width/height; you can query the implementation's maximum width/heights.
一个像素缓冲区,即pbuffer(不是一个像素缓存对象),首先是OpenGL上下文。基本上,您创建了一个正常的窗口,然后从wglChoosePixelFormatARB中选择一个像素格式(必须从这里得到pbuffer格式)。然后,您调用wglCreatePbufferARB,给它您的窗口的HDC和您想要使用的像素缓冲格式。哦,和宽/高;您可以查询实现的最大宽度/高度。
The default framebuffer for pbuffer is not visible on the screen, and the max width/height is whatever the hardware wants to let you use. So you can render to it and use glReadPixels
to read back from it.
pbuffer的默认framebuffer在屏幕上不可见,而最大宽度/高度是硬件想让您使用的任何东西。你可以渲染它并使用glReadPixels来读取它。
You'll need to share you context with the given context if you have created objects in the window context. Otherwise, you can use the pbuffer context entirely separately. Just don't destroy the window context.
如果您在窗口上下文中创建了对象,则需要与给定上下文共享上下文。否则,您可以完全独立地使用pbuffer上下文。不要破坏窗口上下文。
The advantage here is greater implementation support (though most drivers that don't support the alternatives are also old drivers for hardware that's no longer being supported. Or is Intel hardware).
这里的优势是更大的实现支持(尽管大多数不支持替代方案的驱动程序也都是硬件的旧驱动,而这些硬件已经不再受支持了。或者是Intel硬件)。
The downsides are these. Pbuffers don't work with core OpenGL contexts. They may work for compatibility, but there is no way to give wglCreatePbufferARB
information about OpenGL versions and profiles.
这些缺点。pbuffer不使用核心OpenGL上下文。它们可以兼容,但是没有办法提供关于OpenGL版本和配置文件的wglCreatePbufferARB信息。
Framebuffer Objects
Framebuffer Objects are more "proper" offscreen rendertargets than pbuffers. FBOs are within a context, while pbuffers are about creating new contexts.
Framebuffer对象比pbuffer更“适当”的offscreen渲染目标。FBOs在一个上下文中,而pbuffer则是创建新的上下文。
FBOs are just a container for images that you render to. The maximum dimensions that the implementation allows can be queried; you can assume it to be GL_MAX_VIEWPORT_DIMS
(make sure an FBO is bound before checking this, as it changes based on whether an FBO is bound).
FBOs只是一个用于呈现图像的容器。实现允许的最大维度可以查询;您可以假设它是GL_MAX_VIEWPORT_DIMS(确保在检查这个之前,FBO是绑定的,因为它会根据FBO是否被绑定而变化)。
Since you're not sampling textures from these (you're just reading values back), you should use renderbuffers instead of textures. Their maximum size may be larger than those of textures.
由于您并不是从这些(您只是读取值)中取样纹理,所以您应该使用renderbuffer而不是纹理。它们的最大尺寸可能比材质的大。
The upside is the ease of use. Rather than have to deal with pixel formats and such, you just pick an appropriate image format for your glRenderbufferStorage
call.
好处是易于使用。您只需为glRenderbufferStorage调用选择合适的图像格式,而不必处理像素格式。
The only real downside is the narrower band of hardware that supports them. In general, anything that AMD or NVIDIA makes that they still support (right now, GeForce 6xxx or better [note the number of x's], and any Radeon HD card) will have access to ARB_framebuffer_object or OpenGL 3.0+ (where it's a core feature). Older drivers may only have EXT_framebuffer_object support (which has a few differences). Intel hardware is potluck; even if they claim 3.x or 4.x support, it may still fail due to driver bugs.
唯一真正的缺点是支持它们的更窄的硬件。一般来说,任何AMD或NVIDIA的产品都支持(现在,GeForce 6xxx或更好的(注意x的数量)和任何Radeon HD卡)都可以访问ARB_framebuffer_object或OpenGL 3.0+(它是一个核心功能)。旧的驱动程序可能只有EXT_framebuffer_object支持(它有一些差异)。Intel硬件是家常便饭;即使他们要求3。x或4。x支持,它可能仍然会因为驱动程序错误而失败。
#3
3
If you need to render something that exceeds the maximum FBO size of your GL implementation libtr
works pretty well:
如果您需要呈现超过您的GL实现的最大FBO大小的东西,libtr可以很好地工作:
The TR (Tile Rendering) library is an OpenGL utility library for doing tiled rendering. Tiled rendering is a technique for generating large images in pieces (tiles).
TR (Tile效果图)库是OpenGL实用程序库,用于进行tiled渲染。Tiled渲染是一种用块(tiles)生成大图像的技术。
TR is memory efficient; arbitrarily large image files may be generated without allocating a full-sized image buffer in main memory.
TR记忆效率;任意大的图像文件可能在主内存中不分配一个全尺寸的图像缓冲区。
#4
2
The easiest way is to use something called Frame Buffer Objects (FBO). You will still have to create a window to create an opengl context though (but this window can be hidden).
最简单的方法是使用所谓的帧缓冲对象(FBO)。您仍然需要创建一个窗口来创建opengl上下文(但是这个窗口可以被隐藏)。
#5
1
The easiest way to fulfill your goal is using FBO to do off-screen render. And you don't need to render to texture, then get the teximage. Just render to buffer and use function glReadPixels. This link will be useful. See Framebuffer Object Examples
实现目标的最简单方法是使用FBO来完成屏幕外渲染。你不需要渲染纹理,然后得到纹理。只需要渲染缓冲和使用函数glReadPixels。这个链接是有用的。看到Framebuffer对象的例子