带有 FBO 附件的 glreadpixels
Posted
技术标签:
【中文标题】带有 FBO 附件的 glreadpixels【英文标题】:glreadpixels with FBO attachment 【发布时间】:2014-06-17 20:27:13 【问题描述】:好的,所以我有这个带有深度缓冲区和 4 个颜色附件的 FBO。我想在我持有光标的地方读取 dept 缓冲区和来自第四个颜色附件的值。我似乎没有管理任何一个。 我写了这个类:
class Picker3D
public:
bool useAtachment;
GLenum atachment;
float PickerLastSignature;
point3f PickerLastPos;
Picker3D( bool useAtachment = true , GLenum atachment = GL_COLOR_ATTACHMENT3 ) : useAtachment(useAtachment) , atachment(atachment)
void SetObjectSignature( float signature , GLSL_Prog prog )
glUniform1f( glGetUniformLocation( prog.PR , "Signature" ) , signature );
float getSignature( float x , float y , float height )
glGetError();
if( useAtachment )
glReadBuffer( atachment );
cout << " Error message1 : " << glGetError() << endl ;
float *pixels = new float[4];
glReadPixels( x , height - y , 1 , 1 , GL_RGB , GL_FLOAT , pixels );
PickerLastSignature = pixels[1];
cout << " Error message2 : " << glGetError() << endl ;
return PickerLastSignature;
point3f get3DPosition( float x , float y , float height )
//glReadBuffer( GL_DEPTH_ATTACHMENT );
double depth;
glReadPixels( x , y , 1 , 1 , GL_DEPTH_COMPONENT , GL_FLOAT , &depth );
cout << depth << endl;
int viewport[4];
float *modelview;
double projection[16];
double ModelView[16];
modelview = mat4f::GetTopMatrix().returnTransposedMatrix().returnFloatArray();
for( int i = 0 ; i < 16 ; i++ )
ModelView[i] = modelview[i];
glGetDoublev(GL_PROJECTION_MATRIX, projection);
glGetIntegerv(GL_VIEWPORT, viewport);
double x1 , y1 , z1;
gluUnProject( x , height - y , depth , ModelView , projection , viewport , &x1 , &y1 , &z1 );
PickerLastPos = point3f( x1 , y1 , z1 );
return PickerLastPos;
;
我就这样使用它
//在主循环中
BindFrameBuffer();
drawStuff();
Picker.get3DPosition( x , y , height );
Picker.getSignature( x , y , height );
UnbindBuffer();
drawSecondPass();
endDrawSecondPass();
// check Values of PickerLastPos and PickerLastSignature
SwapBuffers();
虽然它在屏幕上工作,但深度没有改变,getSignature 在与 glReadBuffer 的行给出错误 1282(我认为无效操作)。
主循环是:
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
/// deferred pass
DefFBO->drawFBO();
GeometryShader.UseNow();
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
// load the view matrix and set the camera
cam.camera_set();
cam.camera_get( GeometryShader );
// load identity for model matrix
mat4f::LoadIdentity();
/// Geometry Drawing
mat4f::PushMatrix();
mat4f::Translate( 0 , 0 , -10 );
Picker.SetObjectSignature( 1.0f , GeometryShader );
T90.obj_rend( GeometryShader );
Picker.SetObjectSignature( 2.0f , GeometryShader );
Town.obj_rend( GeometryShader );
mat4f::PopMatrix();
Picker.get3DPosition( Window.Mouse->mouse_x , Window.Mouse->mouse_y , Window.Height );
/// setting the deferred read from buffer part
// last read from framebuffer
Picker.getSignature( Window.Mouse->mouse_x , Window.Mouse->mouse_y , Window.Height );
// unbind FBO
DefFBO->readFBO();
// use fragment shader, for lights and for post processing
FragmentShader.UseNow();
// send windows width and height and bind multiple textures
DefFBO->send_to_GLSL( FragmentShader.PR );
// send view matrix to the shader
cam.camera_get( FragmentShader );
glDepthMask(GL_FALSE);
glEnable(GL_DEPTH_TEST);
glUniform3f( glGetUniformLocation( FragmentShader.PR , "CameraPosition" ) , cam.x , cam.y , cam.z );
/// final draw
DefFBO->sendGlobalLight( FragmentShader , point3f( 0 , 1 , 0 ) , point3f( 0.3 , 0.3 , 0.3 ) , point3f( 0.9 , 0.9 , 0.9 ) );
cout << Picker.PickerLastPos << endl;
DefFBO->end_read();
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
【问题讨论】:
只是想指出我在您注释掉的一行中注意到的一点://glReadBuffer( GL_DEPTH_ATTACHMENT )
。这将不起作用,使用该命令设置的读取缓冲区是颜色缓冲区,因此实际上只有 FRONT/BACK/LEFT/RIGHT(或这些的某种组合)和GL_COLOR_ATTACHMENTi
是有效值。但是,缺少太多代码无法评论其他任何内容;实际的 FBO 设置(例如,附在哪里)甚至没有列出。 GL_INVALID_OPERATION
让我相信你绑定了错误的 FBO,或者它实际上没有附加到 GL_COLOR_ATTACHMENT3
。
【参考方案1】:
正如@Andon 指出的那样,我似乎必须绑定 fbo 以从中获取数据。我正在与 GL_DRAW_FRAMEBUFFER 绑定。
【讨论】:
是的,这就是将GL_FRAMEBUFFER
分成GL_DRAW_FRAMEBUFFER
和GL_READ_FRAMEBUFFER
的想法。它允许您独立控制绘制到哪个帧缓冲区以及从哪个帧缓冲区读取。能够做到这一点对于读取和写入帧缓冲区的操作至关重要,尤其是glBlitFramebuffer()
。但它也适用于其他读取操作,例如glReadPixels()
。以上是关于带有 FBO 附件的 glreadpixels的主要内容,如果未能解决你的问题,请参考以下文章
在 AMD 上写入非零 FBO 附件时,OpenGL 会降低性能