Opengl 在渲染和等待结果时切换帧缓冲区
我的问题是,我希望在渲染时切换帧缓冲区,并在切换回帧缓冲区时立即使用帧缓冲区。实际上,这会导致一个空的帧缓冲区,这并不是您可以想象的预期结果 在我发现要显示的帧缓冲区在开始渲染另一个帧缓冲区的帧缓冲区之前进行渲染是可行的之前,我已经使用了帧缓冲区 渲染路径不工作Opengl 在渲染和等待结果时切换帧缓冲区,opengl,Opengl,我的问题是,我希望在渲染时切换帧缓冲区,并在切换回帧缓冲区时立即使用帧缓冲区。实际上,这会导致一个空的帧缓冲区,这并不是您可以想象的预期结果 在我发现要显示的帧缓冲区在开始渲染另一个帧缓冲区的帧缓冲区之前进行渲染是可行的之前,我已经使用了帧缓冲区 渲染路径不工作 渲染到FBO0 开始渲染到FBO1 切换回FBO0 将FBO1渲染为FB0 工作路径 渲染成FBO1 渲染为FBO0 将FBO1渲染为FBO0 因为它看起来像一个同步问题,我想知道如何防止这种情况?是否有任何命令可确保已完成对上
- 渲染到FBO0
- 开始渲染到FBO1
- 切换回FBO0
- 将FBO1渲染为FB0
- 渲染成FBO1
- 渲染为FBO0
- 将FBO1渲染为FBO0
GLFramebuffer.BindFramebuffer(FramebufferTarget.FRAMEBUFFER, _FramebufferHandle);
#if DEBUG
FramebufferStatus status = GLFramebuffer.CheckFramebufferStatus(FramebufferTarget.FRAMEBUFFER);
if (status != FramebufferStatus.FRAMEBUFFER_COMPLETE)
{
GLFramebuffer.BindFramebuffer(FramebufferTarget.FRAMEBUFFER, FramebufferHandle.Default);
throw new OpenGLException(GLFramebuffer.GetStatusString(status));
}
#endif
RenderStack.Push(Tuple.Create(this, attachments));
GL.Viewport(0, 0, Width, Height);
Tuple<Framebuffer, FramebufferAttachement[]> peeked;
if (RenderStack.Count == 0 || (peeked = RenderStack.Peek()).Item1 != this)
{
if (RenderStack.Any(p => p.Item1 == this))
{
throw new InvalidOperationException("Framebuffer is not the top framebuffer, you must call 'StopRendering()' on all previous used buffers");
}
else throw new InvalidOperationException("Framebuffer is not in the rendering stack, please use 'StartRendering(...)' to use the current framebuffer");
}
AssertDisposed();
RenderStack.Pop();
if (RenderStack.Count == 0)
{
GLFramebuffer.BindFramebuffer(FramebufferTarget.FRAMEBUFFER, FramebufferHandle.Default);
}
else
{
Rebind(peeked);
}
以及停止渲染的代码:
GLFramebuffer.BindFramebuffer(FramebufferTarget.FRAMEBUFFER, _FramebufferHandle);
#if DEBUG
FramebufferStatus status = GLFramebuffer.CheckFramebufferStatus(FramebufferTarget.FRAMEBUFFER);
if (status != FramebufferStatus.FRAMEBUFFER_COMPLETE)
{
GLFramebuffer.BindFramebuffer(FramebufferTarget.FRAMEBUFFER, FramebufferHandle.Default);
throw new OpenGLException(GLFramebuffer.GetStatusString(status));
}
#endif
RenderStack.Push(Tuple.Create(this, attachments));
GL.Viewport(0, 0, Width, Height);
Tuple<Framebuffer, FramebufferAttachement[]> peeked;
if (RenderStack.Count == 0 || (peeked = RenderStack.Peek()).Item1 != this)
{
if (RenderStack.Any(p => p.Item1 == this))
{
throw new InvalidOperationException("Framebuffer is not the top framebuffer, you must call 'StopRendering()' on all previous used buffers");
}
else throw new InvalidOperationException("Framebuffer is not in the rendering stack, please use 'StartRendering(...)' to use the current framebuffer");
}
AssertDisposed();
RenderStack.Pop();
if (RenderStack.Count == 0)
{
GLFramebuffer.BindFramebuffer(FramebufferTarget.FRAMEBUFFER, FramebufferHandle.Default);
}
else
{
Rebind(peeked);
}
这些方法只是包装好的,因此GLFramebuffer.DrawBuffers
等于glDrawBuffers
不工作的渲染路径
- 渲染到FBO0
- 开始渲染到FBO1
- 切换回FBO0
- 将FBO1渲染为FBO0
- 渲染到FBO0
- 开始渲染到FBO1
- 切换回FBO0
- 将FBO1渲染为FBO0
- 渲染到FBO0
- 开始渲染到FBO1
- 切换回FBO0
- 将FBO1渲染为FBO0
- 渲染到FBO0
- 开始渲染到FBO1
- 切换回FBO0
- 将FBO1渲染为FBO0
要么您使用的OpenGL实现有一个bug,要么您做错了什么。我们需要看一些代码。关于“内存模型”的OpenGL Wiki建议您使用
glMemoryBarrier
来“在一个渲染命令和一些后续OpenGL操作之间建立可见性”,但我敢说这是胡说八道。使用FBO渲染到纹理在任何人想到像glMemoryBarrier
这样的东西之前已经工作了几十年。您确定没有通过将“渲染到纹理”意外绑定到两个FBO来调用UB,并且确定没有使用错误的目标或其他东西吗?通常情况下,这必须正常工作,OpenGL会自动同步。“内存模型”上的OpenGL Wiki建议您使用glMemoryBarrier
来“在一个渲染命令和后来的OpenGL操作之间建立可见性”,但我敢说这是胡说八道。使用FBO渲染到纹理在任何人想到像glMemoryBarrier
这样的东西之前已经工作了几十年。您确定没有通过将“渲染到纹理”意外绑定到两个FBO来调用UB,并且确定没有使用错误的目标或其他东西吗?通常情况下,这必须正常工作,OpenGL会自动同步。“内存模型”上的OpenGL Wiki建议您使用glMemoryBarrier
来“在一个渲染命令和后来的OpenGL操作之间建立可见性”,但我敢说这是胡说八道。使用FBO渲染到纹理在任何人想到像glMemoryBarrier
这样的东西之前已经工作了几十年。您确定没有通过将“渲染到纹理”意外绑定到两个FBO来调用UB,并且确定没有使用错误的目标或其他东西吗?通常情况下,这必须正常工作,OpenGL会自动同步。“内存模型”上的OpenGL Wiki建议您使用glMemoryBarrier
来“在一个渲染命令和后来的OpenGL操作之间建立可见性”,但我敢说这是胡说八道。使用FBO渲染到纹理在任何人想到像glMemoryBarrier
这样的东西之前已经工作了几十年。您确定没有通过将“渲染到纹理”意外绑定到两个FBO来调用UB,并且确定没有使用错误的目标或其他东西吗?正常情况下,这必须正常工作,OpenGL会自动同步。@FelixK。您没有包括RenderStack::Push
方法。但我的直觉告诉我,在将帧缓冲区推送和弹出到自定义渲染堆栈之间的某个地方