如何在应用程序中使用多个 openGL 状态?
Posted
技术标签:
【中文标题】如何在应用程序中使用多个 openGL 状态?【英文标题】:How to use more than one openGL state in an application? 【发布时间】:2020-08-06 22:36:13 【问题描述】:我知道 openGL 是一个状态机,我不知道状态是如何存储的。
我有一个项目,我必须在 c++ dll/动态库中将屏幕外的东西渲染到内存中,并将最终图像传递给 c# 应用程序,该应用程序也使用 openGL 状态来做任何可以想象的事情(渲染任何应用程序想要以任何方式)。这显然使得无法区分用于在屏幕外(在 dll/动态库中)绘制的 openGL 状态和用于在应用程序中绘制的 openGL 状态。
我将如何在 C++ 中为我的屏幕外渲染器创建/使用单独的 openGL 状态? c++ std::threads 在其中使用 openGL 时会使用/创建单独的 openGL 状态吗?
最后(我不需要回答最后一部分,但要完整),有没有办法在一个应用程序中处理多个 openGL 状态(并在这些状态之间交替)而不使用多个线程?
【问题讨论】:
我认为您将 state 的两种不同含义混为一谈。 @AluanHaddad 我问如果我想在两个单独的实例中使用openGL,是否必须使用线程。我相信对于 openGL,实际术语是“上下文”,而不是我猜你是对的状态。 我只是在评论“openGL 是一个状态机”的说法。任何程序都是状态机。但图书馆本身可能没有这样描述。 【参考方案1】:如果您想将最终的渲染图像传递给另一个应用程序,您可以使用 PBO 传递它,并使用 glMapBuffer 传递指向像素数据的指针。
这是我将像素数据传递给其他应用程序的代码。
glReadBuffer(GL_COLOR_ATTACHMENT0);
writeIndex = (writeIndex + 1) % 2;
readIndex = (readIndex + 1) % 2;
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo[writeIndex]);
// copy from framebuffer to PBO asynchronously. it will be ready in the NEXT frame
glReadPixels(0, 0, SCR_WIDTH, SCR_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
// now read other PBO which should be already in CPU memory
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo[readIndex]);
unsigned char* downsampleData = (unsigned char *)glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
float Time1 = bm.GetTime();
blueOut.RenderOut(downsampleData, FieldNumber); // Pass it to the other application
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
您必须为 c# 应用程序编写驱动程序,它将数据指针实时传递给应用程序。
【讨论】:
我目前正在将图像传递给 ram,然后将其复制到另一个图像,最后将其传递回 gpu;这有多慢?如果它是唯一的瓶颈,它会相对较快地工作吗?这种方法是否相同/相似? @MatiasChara 通常 DMA 是此类传输的首选,我正在做一个非常快的 DMA。【参考方案2】:这很像 CPU 进行线程调度的上下文切换。
假设你在一个线程中有两个管道 M 和 N 并且 M 先运行,当你想切换到 N 时,你可以先保存 M 的上下文,然后启动 N 的管道,在 N 运行的某个时刻你可以保存N 的上下文并恢复 M 的上下文。所以问题是如何显式保存OpenGL的上下文。
实际上 OpenGL 提供了很多查询/获取方法(或几个方法但很多参数),如glGetIntegerv
、glGetVertexAttribiv
和glGetVertexAttribPointerv
(glGet),您可以查询并将结果保存到某个地方并恢复它们在某个时候。
这是一个简单的包装类示例:
class GLStateSaver
GLuint framebuffer;
GLint activeTexture;
GLint boundedTextures[MAX_USED_TEXTURES];
// ... add more fields if you need, like programID, memory object id etc.
public:
void Save()
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &framebuffer);
glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTexture);
// ...
void Restore()
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glActiveTexture(activeTexture);
// ...
【讨论】:
以上是关于如何在应用程序中使用多个 openGL 状态?的主要内容,如果未能解决你的问题,请参考以下文章
OpenGL - 如何使用弹出菜单绘制多个不同的 2D 形状?
Metal:在一个渲染过程中使用多个 MTLRenderCommandEncoder