PBO 缓冲区内容是什么意思?

What does the PBO buffer content mean?

我试图通过使用 PBO(使用 OpenGL 的像素缓冲对象)来实现颜色选择系统,当我完成时,我意识到映射时从 PBO 出来的数字没有任何意义全部。我让我的应用程序渲染不同颜色的大方块,结果 DID 在这些不同颜色之间变化,但即使在分析了数字之后,我也无法理解它。

例如,点击纯红色给了我字节数 (-1,0,0),虽然纯蓝色给出 (0,0,-1),但与所有逻辑相反,纯绿色给出 (-1,0,-1),青色也给出 (-1,0,0 ), 黄色给出 (76,-1,0).

显然这些数字是错误的,因为两种不同的颜色可能导致相同的字节构成。完全红色不应该是 (127,0,0) 吗?

这是我用于初始化的代码,大小为 3,因为我只读取一个像素。

pboid = glGenBuffersARB(); //Initialize buffer for pbo
glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, pboid); //bind buffer
glBufferDataARB(GL_PIXEL_PACK_BUFFER_EXT, 3,GL_DYNAMIC_READ); //create a pbo with 3 slots
glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, 0); //unbind buffer

这是我用来读取像素的代码

glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, pboid); //Bind the pbo
glReadPixels((int)lastMousePosition.x,(int)lastMousePosition.y,1,1, GL_RGB, GL_UNSIGNED_BYTE, 0); //Read 1 pixel
ByteBuffer colorBuffer = glMapBufferARB(GL_PIXEL_PACK_BUFFER_EXT, GL_READ_ONLY_ARB); //Map the buffer so we can read it
for(int x = 0; x < colorBuffer.limit(); x++)
{
    System.out.println("color byte: " + colorBuffer.get(x)); //Print out the color byte
}
glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_EXT); //Unmap the buffer so it can be used again
glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, 0); //Unbind the pbo

如果我所做的任何假设有误,请纠正我。我可能计划使用这个系统来判断哪个 gui 元素被点击,方法是将每个元素渲染到具有独特颜色的 fbo 并测试点击了哪个像素颜色。在此先感谢任何可以提供帮助的人!

有几种可能性,但我没有设置我的 openGL 系统来测试 - 但无论如何你都可以尝试这些。我也不太了解 Java(C、C++ 等是我的领域)

编辑

1) 您已从 glReadPixels() 请求 GL_UNSIGNED_BYTE 数据,但您正在以签名格式打印。 GL_UNSIGNED_BYTE 的值为 0-256,因此不可能有负值!尝试为 UNSIGNED_BYTE 格式化您的打印​​输出并查看结果。 (从你的代码中我可以看到现在已经修复了)。

2) 正如 derhass 在他的评论中指出的那样,您不应该使用 ARB(体系结构审查委员会)扩展版本的 OpenGL 缓冲函数,因为它们在很长一段时间内都是 OpenGL 核心的一部分。有关版本历史,请参阅 https://www.khronos.org/opengl/wiki/History_of_OpenGL。从这里我可以看到 glBindBufferARB(例如)在 2003 年被弃用。它可能会或不会影响您的特定问题,但请将 glXXXXXARB() 替换为 glXXXXX() thorughout,并确保您的 OpenGL 库是最新的(v4 或更高版本)。

3) 同时感谢 derhass,并阅读你的 GitHub 代码,你的 getMousePosition() 通过 glfwGetCursorPos returns 屏幕坐标(0,0 是你的 window 的左上角) 所以你需要转换为视口坐标(0,0 是左下角)来读取帧缓冲区。您在 GitHub 的代码似乎没有进行转换。

4) 也归功于 derhass,您根本不需要使用 PBO 来进行基本的颜色选择。 glReadPixels() 默认目标是帧缓冲区,因此您可以安全地放弃 VBO 并直接从帧缓冲区获取颜色、深度和模板数据。 (您需要启用深度和模板缓冲区)。

5) 如果您在 3D 场景上进行选择,您还需要将视口坐标和深度转换(取消投影)回世界坐标,以便能够识别您单击的对象。有关选择的一些想法,请参阅 https://en.wikibooks.org/wiki/OpenGL_Programming/Object_selection

我希望所有这些都能有所帮助,尽管这对我们俩来说都是一种学习经历。

终于找到问题了!

首先,使用Byte.toUnsignedInt(byte),你可以把pbo给你的颜色变成你传统的0-255范围的rgb数字。

其次,这是主要问题,当 OpenGL 要求像素坐标填充 pbo 时,它是相对于右下角的。我的问题是我使用的是 GLFW,它给出了相对于右上角的坐标,这意味着屏幕垂直中间的颜色选择是准确的,但它得到了我在其他地方选择颜色时正在寻找的屏幕的反面部分。要解决此问题,只需从 window 高度中减去鼠标点击的 y 坐标即可。

感谢您的帮助和想法!