从深度缓冲区读取深度值的有效方法

2024-02-22

对于我的算法,我需要能够访问深度缓冲区。我使用 glReadPixels 执行此操作完全没有问题,但读取 800x600 窗口的速度非常慢(从 300 fps 到 20 fps)

我读了很多关于这方面的内容,我认为将深度缓冲区转储到纹理会更快。我知道如何创建纹理,但如何获得深度?

创建 FBO 并从那里创建纹理可能会更快,目前我正在使用 FBO(但仍与 glReadPixels 结合使用)。

那么最快的方法是什么?

(我可能无法使用 GLSL,因为我对它一无所知,而且我没有太多时间来学习,截止日期!)

编辑: PBO 有效吗?正如这里所描述的:http://www.songho.ca/opengl/gl_pbo.html http://www.songho.ca/opengl/gl_pbo.html它可以快得多,但我不能像示例中那样一直更改缓冲区。

编辑2: 我该如何将深度数据放入 PBO 中?目前我这样做:

glGenBuffersARB(1, &pboId);
glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pboId);
glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, 800*600*sizeof(GLfloat),0,     GL_STREAM_READ_ARB);

在我的 readpixels 之前,我再次调用 glBindbuffer 。结果就是我什么也没读。如果我禁用 PBO,一切都会正常。

最终编辑: 我想我已经解决了,我必须使用:

glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pboId);
glReadPixels( 0, 0,Engine::fWidth, Engine::fHeight, GL_DEPTH_COMPONENT,GL_FLOAT, BUFFER_OFFSET(0));

GLuint *pixels = (GLuint*)glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);

这使我的 FPS 提高了 20。虽然没那么多,但确实是个东西。

所以,我使用了 2 个 PBO,但我仍然遇到一个问题:我的代码只执行一次。

glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pboIds[index]);  
std::cout << "Reading pixels" << std::endl;
glReadPixels( 0, 0,Engine::fWidth, Engine::fHeight, GL_DEPTH_COMPONENT,GL_FLOAT, BUFFER_OFFSET(0));
std::cout << "Getting pixels" << std::endl;
//  glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, 800*600*sizeof(GLfloat), 0, GL_STREAM_DRAW_ARB);
GLfloat *pixels = (GLfloat*)glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
int count = 0;
for(int i = 0; i != 800*600; ++i){
    std::cout << pixels[i] << std::endl;
}

最后一行执行一次,但仅执行一次,之后它继续调用该方法(这是正常的),但在调用像素时停止。


我显然忘记加载 glUnMapBuffers,这有点解决了它,尽管我的帧速率又变慢了..


我决定尝试一下 FBO,但我偶然发现了一个问题: 初始化 FBO:

glGenFramebuffersEXT(1, framebuffers);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffers[0]);
std::cout << "framebuffer generated, id: " << framebuffers[0] << std::endl;
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);

glGenRenderbuffersEXT(1,renderbuffers);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, renderbuffers[0]);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, 800, 600);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, renderbuffers[0]);
bool status = checkFramebufferStatus();
    if(!status)
        std::cout << "Could not initialise FBO" << std::endl;
    else
        std::cout << "FBO ready!" << std::endl;

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

我的绘图循环:

GLenum 错误代码; const GLubyte *errString;

if ((errCode = glGetError()) != GL_NO_ERROR) {
    errString = gluErrorString(errCode);
   fprintf (stderr, "OpenGL Error: %s\n", errString);
}

++frameCount;
// -----------  First pass to fill the depth buffer  -------------------
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffers[0]);

std::cout << "FBO bound" << std::endl;
//Enable depth testing
glEnable(GL_DEPTH_TEST);
glDisable(GL_STENCIL_TEST);
glDepthMask( GL_TRUE );
//Disable stencil test, we don't need that for this pass
glClearStencil(0);
glEnable(GL_STENCIL_TEST);

//Disable drawing to the color buffer
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);

//We clear all buffers and reset the modelview matrix
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glLoadIdentity();

//We set our viewpoint
gluLookAt(eyePoint[0],eyePoint[1], eyePoint[2], 0.0,0.0,0.0,0.0,1.0,0.0);
//std::cout << angle << std::endl;
std::cout << "Writing to FBO depth" << std::endl;
//Draw the VBO's, this does not draw anything to the screen, we are just filling the depth buffer
glDrawElements(GL_TRIANGLES, 120, GL_UNSIGNED_SHORT, BUFFER_OFFSET(0));

之后我调用一个调用 glReadPixels() 的函数 该函数甚至没有被调用。循环在函数调用处重新开始。


显然我也解决了这个问题:我必须使用

glReadPixels( 0, 0,Engine::fWidth, Engine::fHeight, GL_DEPTH_COMPONENT,GL_UNSIGNED_SHORT, pixels);

使用 GL_UNSIGNED_SHORT 而不是 GL_FLOAT (或任何其他格式)


最快的方法是使用异步像素缓冲区对象,这里有一个很好的解释:

http://www.songho.ca/opengl/gl_pbo.html http://www.songho.ca/opengl/gl_pbo.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从深度缓冲区读取深度值的有效方法 的相关文章

  • 计算边界球体半径时遇到一些问题

    我已经设法用两种方法计算边界球体半径 但没有一种方法能够准确地满足我的要求 我不需要 像素 完美边界球 但我想要比我目前拥有的更好的东西 我正在使用 Wavefront obj 模型并计算这些模型的边界球半径 我提取当前模型尺寸 我使用 N
  • 静态链接库时出现 glew 链接器错误

    我正在尝试在 Visual Studio 2012 中构建一个 opengl 项目 我想静态包含 glew 库 因此我从源代码构建它并将生成的 glew32sd lib 复制到我的 lib 目录 我将此 lib 路径提供给 Visual S
  • OpenGL NURBS 曲面

    我正在学习 OpenGL 我想要一个中间有轻微驼峰的表面 我目前正在使用这段代码 但我不确定如何调整 ctrl 点以使其达到我想要的方式 它目前就像 我想要这样的 我不完全确定我应该使用哪些控制点 并且我对其工作原理感到困惑 include
  • 使用 Opengl 绘制立方体 3D

    我想使用 OpenGL 绘制 3D 立方体这是我的代码如何纠正错误 float ver 8 3 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
  • (定义一个宏)方便OpenGL命令调试?

    有时插入条件打印和检查需要很长时间glGetError 使用二分搜索的形式来缩小范围 其中第一个函数调用是 OpenGL 首先报告错误 我认为如果有一种方法可以构建一个宏 我可以包装所有可能失败的 GL 调用 并有条件地调用 那就太酷了gl
  • gluPerspective 与 gluOrtho2D

    我查看了 MSDN 上关于这两个函数的文档 但是 我不太明白这两个功能之间的区别 一个是用于设置 3D 相机视图 另一个是用于设置 2D 相机视图 如果能得到解答就太好了 预先感谢您的评论 正交投影基本上是没有透视的 3D 投影 本质上 这
  • 如何安装适用于 Windows C++ 的最新版本 OpenGL?

    我正在使用 Visual Studio 2010 运行 Windows 7 包含的 OpenGL 版本 include 是版本 1 1 我希望使用合理的当前版本 某种版本 3 或 4 我需要做什么才能达到该状态 OpenGL SDK 页面位
  • OpenGL 着色器不与着色器程序链接

    我正在尝试使用 GLFW GLEW 添加着色器 我收到一个错误 指出着色器已加载 但它们没有有效的对象代码 这是我用于加载着色器的代码 class SHADER public void LoadShaders const char vert
  • lwjgl 3 , glUniformMatrix4 导致 jre 崩溃

    我正在使用 lwjgl 3 并学习现代 opengl 3 我想将统一矩阵发送到顶点着色器 以便我可以应用转换 我尝试过 但程序因此错误而崩溃 A fatal error has been detected by the Java Runti
  • 阻止 OpenGL.framework 在 Cocoa 应用程序中加载

    我的应用程序链接到这些框架 Cocoa Framework AppKit Framework CoreData Framework Foundation Framework 请注意 OpenGL Framework 是NOT已链接 但是 设
  • 对齐坐标系

    Let s say I have 2 coordinate systems as it is shown in image attached 如何对齐这个坐标系 我知道我需要将第二个坐标系围绕 X 平移 180 度 然后将其平移到第一个坐标
  • OpenGL 与 Eclipse CDT + MinGW + GLEW + GLFW:未定义的参考

    Edit 与此同时 我已经弄清楚了这一点 并在下面写了详细的答案 我刚刚尝试在 Win7 上从 Express 版本的 MSVC 10 切换到 Eclipse CDT 在配置时遇到了以下简单 OpenGL 代码的问题 在 Visual St
  • glut 库中缺少 glutInitContextVersion()

    我正在练习一些 opengl 代码 但是当我想通过以下方式强制 opengl 上下文使用特定版本的 opengl 时glutInitContextVersion 它编译过程失败并给出以下消息 使用未声明的标识符 glutInitContex
  • SDL 鼠标位置调整大小后裁剪

    我在 SDL 中的鼠标位置上遇到了一些奇怪的行为 如果我将窗口大小调整得更大 则任一鼠标事件的 x y 位置似乎都限制为原始窗口的宽度和高度 如果我缺少一些函数调用来告诉 SDL 鼠标区域的大小已增加 应用程序的相关部分 void Resi
  • 如何在 GTX 560 及更高版本上使用 OpenGL 进行立体 3D?

    我正在使用在 Windows 7 上运行的开源触觉和 3D 图形库 Chai3D 我重写了该库以使用 Nvidia nvision 执行立体 3D 我将 OpenGL 与 GLUT 一起使用 并使用 glutInitDisplayMode
  • 使用 C# 截取任何外部应用程序的屏幕截图

    我们有一个 C WPF 应用程序 我们想要在其中截取我们启动的任意应用程序的屏幕截图 即 我们可以引用我们启动的进程 应用程序可能已最小化或位于其他窗口后面 但我们仍然只需要单个应用程序的图像 而不是重叠像素 我知道使用 BitBlt 或的
  • 在 GLUT 中使用鼠标滚轮

    我想在 OpenGL GLUT 程序中使用鼠标滚轮来放大和缩小场景 我怎么做 Freeglut 的 glutMouseWheelFunc 回调与版本相关 并且在 X 中不可靠 使用标准鼠标功能并测试按钮 3 和 4 OpenGlut 对 g
  • 将带有 glut 的点击坐标添加到向量链接列表中

    我想创建一个向量链接列表 并在 GLUT 库的帮助下获取点击的位置并将它们附加到链接列表中 这些是我写的结构 typedef struct vector int x int y Vector typedef struct VectorLis
  • 在 Linux 上运行我自己的程序的权限被拒绝? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我有Ubuntu 9 4 我已经构建了程序 一些基本的 OpenGL 该程序只是制作一个旋转的正方形 然后运行它并 sh blabla p
  • OpenGL缓冲区更新[重复]

    这个问题在这里已经有答案了 目前我正在编写一个模拟水的程序 以下是我所做的步骤 创建水面 平面 创建VAO 创建顶点缓冲区对象 在其中存储法线和顶点 将指针绑定到此 VBO 创建索引缓冲区对象 然后我使用 glDrawElements 渲染

随机推荐

  • 在 Android 上检测 4K UHD 屏幕

    我正在尝试检测设备何时能够以 4K UHD 3840x2160 分辨率输出 nVidia Shield TV 和 Sony Xperia Z5 Premium 等许多设备即使支持 UHD 也会报告以 1080p 运行 因为它们默认为非视频布
  • Windows 7 左键单击时钟弹出窗口

    当在 Windows 7 也可能是 Vista 上单击任务栏中的时钟时 会打开一个弹出窗口 显示日历和时钟 因此不是日期和时间调整窗口 我如何自己打开这个窗口 在 C 中首选 我希望timedate cpl会调用它 但这会打开日期和时间调整
  • 如何在 Tkinter 中获得带有滚动条的框架?

    我想要一个Frame 用户可以根据应用程序的需要添加任意数量的文本字段 该应用程序以一个文本字段和该文本字段下方的一个按钮开始 当用户按下按钮时 新的文本条目将添加到第一个文本条目下方 这可能会重复无数次 在窗口的中间 会有一个Text小部
  • docker 中的特权模式以集群形式组成

    我在用docker compose yml在具有树莓派集群的 docker swarm 中部署服务 我的服务需要访问树莓派 GPIO 并且需要特权模式 我使用 docker 版本 18 02 和 docker compose 版本 3 6
  • 返回流而不是列表[重复]

    这个问题在这里已经有答案了 在 Java 8 中我越来越多地替换Collection返回值与Stream 所以我曾经拥有过 public List
  • 我可以使用 Google Chrome 扩展程序阻止alert()吗

    我可以创建一个 Google Chrome 扩展来阻止该页面执行alert 正如 MrGlass 所说 目前 Chrome 扩展程序在单独的环境中运行 限制了对实际应用程序的访问 window对象并提供仅对扩展有效的副本 为了解决这个问题
  • Django - 区分不同类型的 IntegrityError

    我正在使用 django MySQL 有时 我将重复的数据插入数据库 这会导致 django 引发错误IntegrityErrror 问题是 django python 对几个不同的版本使用相同的错误MySQL 错误 http dev my
  • write_some 与 write - boost asio

    为什么有人想使用write some什么时候它可能无法将所有数据传输给对等方 从升压write some文档 write some 操作可能不会将所有数据传输到对等方 如果需要确保所有数据都被写入 请考虑使用 write 函数 在阻塞操作完
  • is_numeric、intval、ctype__digit..您可以信赖它们吗?

    is numeric intval ctype digit 您可以信赖它们吗 或者我必须使用正则表达式 function isNum str return preg match 0 9 str 你们有什么感想 我是傻子吗 之间的一个重要区别
  • 如何使用 OpenSSL 提取公钥?

    以下命令生成一个包含公钥和私钥的文件 openssl genrsa des3 out privkey pem 2048 Source here http www openssl org docs HOWTO keys txt 使用OpenS
  • make:安装:找不到命令

    当我尝试安装时git从它的源头开始qnx 我收到以下错误 请注意 pound 是 sudo 的提示qnx configure without iconv with perl usr pkg bin perl with python usr
  • 在哪里可以找到使用 boto3 编写自定义 AWS 凭证提供程序的文档?

    我希望创建一个 python 进程来在运行时刷新临时 AWS 凭证 有效期为 30 分钟 以确保我的代码可以连续运行超过 30 分钟 什么是 RefreshableCredentials 以及如何使用它 经过大量研究后 我终于得出结论 bo
  • 使用jest 模拟react-router-dom 钩子不起作用

    我正在使用 Enzyme 的浅层方法来测试使用useParams钩子从 URL 参数中获取 ID 我试图嘲笑useParams挂钩 这样它就不会调用实际的方法 但它不起作用 我还在得到TypeError Cannot read proper
  • 从 Windows 进行 Linux 开发的最佳设置? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 从 Windows 工作站开发 Linux 应用程序的最佳设置是什么 现在 我通过 SSH 连接到我们的 Linux 开发服务器 并使用 Ecl
  • 结构图 - 构造函数中依赖项的集合

    我的注册表中有以下代码 Scan x gt x Assembly Assembly GetExecutingAssembly x AddAllTypesOf
  • 如何使用构建中注入的密码作为 Active Choices 参数中的环境变量

    我在标题为 将密码作为环境变量注入到构建中 的构建配置部分中定义了密码 我想在我的 Active Choices 中使用 MYVAR 未加密值 不幸的是 它不起作用 对 MYVAR 的引用失败 在下面的示例中 为了测试 我只是尝试显示 MY
  • 通过参数推导多参数模板中的第一个模板参数

    首先是我的问题 然后解释我正在尝试做什么 因为我可能会错误地处理问题 是否可以在指定其他参数的同时从参数中推导出多参数模板中的第一个模板参数 例子 template
  • 在自定义模块中使用时,Import-Pssession 不会导入 cmdlet

    我有一个 PowerShell 脚本 函数 当我在 PowerShell 配置文件中使用它或在 PowerShell 窗口中手动复制 粘贴该函数时 效果非常好 我正在尝试使该功能作为模块可供团队的其他成员访问 我希望将模块存储在一个中心位置
  • 对 C# 中 UDP 协议的套接字感到困惑

    我刚刚开始通过各种 Google 搜索学习套接字 但在弄清楚如何在 C 中正确使用套接字时遇到一些问题 我需要一些帮助 我有一个测试应用程序 Windows 窗体 和一个不同的类 实际上在它自己的 dll 中 但这无关紧要 我有我的套接字代
  • 从深度缓冲区读取深度值的有效方法

    对于我的算法 我需要能够访问深度缓冲区 我使用 glReadPixels 执行此操作完全没有问题 但读取 800x600 窗口的速度非常慢 从 300 fps 到 20 fps 我读了很多关于这方面的内容 我认为将深度缓冲区转储到纹理会更快