我目前正在从事一个项目,该项目涉及将LWJGL游戏场景渲染为视频流而不是窗口。我相信,如果将游戏场景渲染为中间格式(如 ByteBuffer),我就能实现这一目标。我正在尝试扩展LWJGL VoxelGame
演示作为概念证明。
我发现了一个类似的SO问题和一个论坛帖子,但我无法做到这一点。我是OpenGL和LWJGL的初学者,我正在努力寻找关于这方面的可理解文档。
在渲染循环(runUpdateAndRenderLoop
)的开始,调用函数glBindFramebuffer
。根据我的理解,它将FBO绑定到当前上下文,以便任何渲染都将定向到它。
我尝试过使用<code>glGetTexImage来填充字节缓冲区,但它不起作用。我在<code>glBlitFramebuffer</code>之后也尝试过,因为我想将完整的渲染图像获取到ByteBuffer。
如何将当前游戏场景渲染到ByteBuffer?有没有更好的方法将游戏场景渲染到视频流而不是中间ByteBuffer?
private void runAndUpdateRenderLoop() {
// ...
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
byte[] pixels = new byte[width * height * 4];
ByteBuffer buffer = ByteBuffer.allocateDirect(pixels.length).order(ByteOrder.nativeOrder());
glGetTexImage(GL_TEXTURE_BUFFER, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
glfwSwapBuffers(window);
}
@Blindy的答案是100%正确的,你应该接受它作为答案。
但是,如果您想要一个直接工作的解决方案的代码,那么在
glBlitFramebuffer(0, 0, 宽度, 高度, 0, 0, 宽度, 高度, GL_COLOR_BUFFER_BIT, GL_NEAREST);
但在之前
<代码>glfwSwapBuffers(窗口)
代码:
ByteBuffer bb = org.lwjgl.system.MemoryUtil.memAlloc(width * height * 4);
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, bb);
// Test with stb_image to write as jpeg:
// org.lwjgl.stb.STBImageWrite.stbi_flip_vertically_on_write(true);
// org.lwjgl.stb.STBImageWrite.stbi_write_jpg("frame.jpg", width, height, 4, bb, 50);
org.lwjgl.system.MemoryUtil.memFree(bb);
这将导致ByteBufferbb
保存当前帧的像素数据。
但是,正如@Blindy所指出的那样,这是一个严重的GPU停顿,因为您被迫等待当前帧的数据完全渲染并强制GPU-
像素路径性能警告:像素传输与3D渲染同步。
根据您的实际用例,其他方法可能更有用,例如直接从GPU内存对视频进行编码(例如使用NVENC)。
你的代码中有一大堆问题,甚至还没有看到问题的核心,因为它在<code>/…</code>部分:
>
当您尝试在无头设置中渲染时,不使用<code>glfwSwapBuffers
您不需要 glGetTexImage
和 glReadPixel
,它们都将数据从图形内存读取到系统内存。在你的例子中,你正在缓冲区
中读取纹理数据,然后用反向缓冲器数据覆盖它,这些数据应该是空的,因为你从来没有写过它。
你肯定不想要< code>glBlitFramebuffer,那是用于从视频存储器复制到视频存储器的。你真的需要停下来阅读文档,对你的视频驱动程序使用随机函数肯定会让它崩溃。
您需要启用OpenGL的调试层验证,尤其是在尝试所有这些随机函数时。与此相关的是,您需要检查您的帧缓冲区设置(glCheckFrameBufferStatusEXT
),我敢打赌您没有,但您没有显示您的代码。
您没有显示帧缓冲区绑定,因此我无法判断您是否正在执行此操作,但是您需要在读取帧缓冲区之前将其绑定为“read”(GL_READ_FRAMEBUFFER
)。我只看到“绘制”帧缓冲区绑定,而您只是随机清除它。
最后,在从视频内存读取操作时,永远不要让CPU暂停,尤其是当您有一些事情要做时,比如视频编码。以循环方式使用像素缓冲区对象来对传输进行两倍或三倍缓冲,因此不会出现停滞。
最近,我决定重温一些LWJGL渲染代码,这些代码是我根据LWJGLWiki上的教程使用索引VBOs编写的。在我的台式电脑上,一切正常,但当我切换到学校笔记本电脑时,它拒绝渲染任何内容。 我有以下渲染代码: GL20.glUseProgram(pId);System.out.println(“NO Error? ” (GL11.glGetError() == GL11.GL_NO_ERROR));
我正在使用spring boot尝试建立自己的迷你网站。 我有控制器 还有一个html文件resources/templates/index,我正试图呈现它,但我只呈现了文本“index”。如何返回html文件而不是文本?
在讲述有关list的时候,提到做游戏的事情,后来这个事情一直没有接续。不是忘记了,是在想在哪个阶段做最合适。经过一段时间学习,看官已经不是纯粹小白了,已经属于python初级者了。现在就是开始做那个游戏的时候了。 游戏内容:猜数字游戏 太简单了吧。是的,游戏难度不大,不过这个游戏中蕴含的东西可是值得玩味的。 游戏过程描述 程序运行起来,随机在某个范围内选择一个整数。 提示用户输入数字,也就是猜程序
下面的代码完整展示了通过three.js引擎创建的一个三维场景,在场景中绘制并渲染了一个立方体的效果,为了大家更好的宏观了解three.js引擎, 尽量使用了一段短小但完整的代码实现一个实际的三维效果图。 学习建议 刚一开始学习,不需要完全看懂下面的代码,能够修改增删部分代码就可以,随着时间的推移就能够很好的使用三维引擎three.js。 本课程风格和大多数课程风格不同,注意一定要结合案例代码学习
下面的LWJGL代码将在屏幕中心呈现一个蓝色正方形。相反,我得到了一个空白的白色屏幕。就像渲染根本不工作,或者我在屏幕外渲染。 我是OpenGL和LWJGL的新手,所以我力不从心。我浏览了所有内容,但似乎找不到任何可能与代码有关的问题。 OpenGLTest.scala VertexArray.scala