2014-06-17 36 views
0

好的,所以我有一个带有深度缓冲区和4种颜色附件的FBO。我想在我握住光标的位置读取缓冲区,并从第四个颜色附件中读取值。我似乎没有管理这两者中的任何一个。 我已写下这个课程:带有FBO附件的glreadpixels

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(); 

altrough它正在屏幕上和getSignature给出错误1282(无效的操作深度是不会改变的,我觉得)与glReadBuffer一致。

主循环是:

   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); 
+0

只是想指出我注意到的一个注释掉的行:'// glReadBuffer(GL_DEPTH_ATTACHMENT)'。这是行不通的,用该命令设置的读缓冲区是一个颜色缓冲区,所以只有FRONT/BACK/LEFT/RIGHT(或这些的某些组合)和'GL_COLOR_ATTACHMENTi'是有效值。虽然有太多的缺失代码来评论其他任何东西;实际的FBO设置(例如附件所在的地方)甚至没有列出。 'GL_INVALID_OPERATION'让我相信你有错误的FBO界限,或者它实际上并没有附加到'GL_COLOR_ATTACHMENT3'的东西。 –

回答

0

看来我不得不把FBO绑定用于读取歌厅出来的数据显示,截至@Andon指出。我与GL_DRAW_FRAMEBUFFER绑定。

+0

是的,这是将'GL_FRAMEBUFFER'分离为'GL_DRAW_FRAMEBUFFER'和'GL_READ_FRAMEBUFFER'的想法。它允许您独立控制您绘制的帧缓冲区以及您读取的帧缓冲区。能够做到这一点对于读取和写入帧缓冲区的操作至关重要,最显着的是'glBlitFramebuffer()'。但它也适用于其他读操作,如'glReadPixels()'。 –