将 FBO 复制到 VBO 时出错
Posted
技术标签:
【中文标题】将 FBO 复制到 VBO 时出错【英文标题】:Error copying FBO to VBO 【发布时间】:2012-11-26 15:54:24 【问题描述】:在 GPU 上进行一些计算后,我想将存储在 FBO 中的结果复制到 VBO 以进行渲染。
问题:当我进行复制时,似乎某些数据已损坏。我已经检查了缓冲区的格式和大小,并且还检查了存储在 FBO 中的数据是否正确。
考虑以下初始化 FBO 的代码:
unsigned int verticesTextureId = AllocateTexture(GL_TEXTURE_RECTANGLE, mVBOSize, 1, GL_RGBA32F, GL_RGBA);
CHECK_FOR_OPENGL_ERRORS();
unsigned int normalsTextureId = AllocateTexture(GL_TEXTURE_RECTANGLE, mVBOSize, 1, GL_RGBA32F, GL_RGBA);
CHECK_FOR_OPENGL_ERRORS();
SetUpViewport(mVBOSize, 1);
glBindFramebuffer(GL_FRAMEBUFFER, mFBOId);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE, verticesTextureId, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_RECTANGLE, normalsTextureId, 0);
以下代码初始化 VBO 并将数据从 FBO 复制到 VBO:
mVerticesBufferId = AllocateVBO();
CHECK_FOR_OPENGL_ERRORS();
glBindBuffer(GL_PIXEL_PACK_BUFFER, mVerticesBufferId);
glBufferData(GL_PIXEL_PACK_BUFFER, mVBOSize * 4 * sizeof(float), 0, GL_STATIC_DRAW);
mNormalsBufferId = AllocateVBO();
CHECK_FOR_OPENGL_ERRORS();
glBindBuffer(GL_PIXEL_PACK_BUFFER, mNormalsBufferId);
glBufferData(GL_PIXEL_PACK_BUFFER, mVBOSize * 4 * sizeof(float), 0, GL_STATIC_DRAW);
glReadBuffer(GL_COLOR_ATTACHMENT0);
glBindBuffer(GL_PIXEL_PACK_BUFFER, mVerticesBufferId);
glReadPixels(0, 0, mVBOSize, 1, GL_RGBA, GL_FLOAT, 0);
glReadBuffer(GL_COLOR_ATTACHMENT1);
glBindBuffer(GL_PIXEL_PACK_BUFFER, mNormalsBufferId);
glReadPixels(0, 0, mVBOSize, 1, GL_RGBA, GL_FLOAT, 0);
在这里,我将 VBO 绑定为顶点/法线属性并调用绘图:
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, mVerticesBufferId);
glVertexPointer(4, GL_FLOAT, 4 * sizeof(float), 0);
glBindBuffer(GL_ARRAY_BUFFER, mNormalsBufferId);
glNormalPointer(GL_FLOAT, 4 * sizeof(float), 0);
glDrawArrays(GL_POINTS, 0, mVBOSize);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
在此调用之后,大多数点都正确显示在屏幕上,但有些点却奇怪地显得格格不入。这似乎与信号或钳位无关,因为具有负数或大于 1 分量的顶点正在正确显示。
我附上了未正确渲染的 kosh 雪花(曲线)的图片。
1) 顶点呈现为点:
2) 使用简单的几何着色器将顶点渲染为线条:
参考图片:
【问题讨论】:
Nomencalture note:"Buffer object" 是您一直称为 VBO 的通用术语。顶点缓冲区对象是缓冲区对象的特定用途。像素缓冲区对象表示缓冲区对象的另一种使用。缓冲区对象不变;这只是你如何使用它。 "在 GPU 中进行一些计算后,我不想将存储在 FBO 中的结果复制到 VBO,以进行进一步的几何着色器操作。" 您是否考虑过变换反馈?它比渲染简单得多,然后复制到缓冲区,然后再次渲染。 哦,如果您要重新创建缓冲区的存储每一帧,那么缓冲区不是GL_STATIC_DRAW
。这是GL_STREAM_DRAW
。实际上,它是GL_STREAM_COPY
,因为您从不向它写入或从 OpenGL 读取它。
@NicolBolas 关于命名法,感谢您的提示!顺便说一句,为什么我通过调用我的“缓冲区对象”VBO 做错了?由于我使用它们来存储顶点位置和法线,我认为将它们称为 VBO 是正确的。
@NicolBolas 目前我正在片段着色器上进行 GPU 计算。如果我要使用变换反馈,我不需要在顶点或几何着色器上执行它们吗?
【参考方案1】:
使用 gDEBugger 我发现我的 VBO 上的数据也是正确的。问题是在片段着色器计算之后,我的向量的齐次分量(w)上有垃圾,这对变换产生了不必要的影响。
【讨论】:
以上是关于将 FBO 复制到 VBO 时出错的主要内容,如果未能解决你的问题,请参考以下文章