0

我想用opengl渲染一个有很多光源的场景。然而,在 opengl 中,最大光源为 8。我试图使用 FBO 来做到这一点。所以我会用 8 个灯渲染到 FBO1 场景,然后在 FBO2 = FBO2 + FBO1 (添加纹素组件)。所以FBO2会累积最终图像。(这就是想法)。但是我有“一些”编码问题:)这是我的代码:

渲染:

    glEnable(GL_TEXTURE_RECTANGLE_NV);
glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT); // Push our glEnable and glViewport states 
glViewport(0, 0, OPT.m_nWidth, OPT.m_nHeight);

glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear the depth and colour buffers 
glLoadIdentity();  // Reset the modelview matrix 


int iIndeks = 0, iLoopIndeks = 0, iLightsUsed = 0;
float *pM = scene3D->oCamera.SetMatrixs();
glLoadMatrixf(pM);
delete []pM;

int iAccumMult = xLightsToRender.size/MAX_OPENGL_LIGHTS;

while(iIndeks < xLightsToRender.size )
{       
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, iFrameBufferAccumulation); 

    glShadeModel(GL_SMOOTH);
    float *pM = scene3D->oCamera.SetMatrixs();
    glLoadMatrixf(pM);
    delete []pM;

    glMatrixMode(GL_MODELVIEW);

    iLightsUsed = xLightsToRender.size > (iLoopIndeks+1) * MAX_OPENGL_LIGHTS ? MAX_OPENGL_LIGHTS : (xLightsToRender.size - iLoopIndeks * MAX_OPENGL_LIGHTS);

    iIndeks+=iLightsUsed;
    glPushMatrix();
    //initilise lights
    setLights( iLoopIndeks * MAX_OPENGL_LIGHTS,  iLightsUsed, xLightsToRender );
    for (int i=0;i<scene3D->data.m_nObjectCount;i++)
    {
        //glutSolidTeapot(1.0f); // Render a teapot 
        scene3D->RenderObjectWithOpenGL(i);
    }
    if( scene3D->data.bMovingObjectIni   )
    {
        scene3D->RenderObjectWithOpenGL( -1, true);
    }       



    glPopMatrix();

    iLoopIndeks++;
    //xShader.bind();

    //xShader.unbind();
    glPopAttrib(); // Restore our glEnable and glViewport states 
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // Unbind our texture  
    //render to second buffer
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, iFrameBuffer); 
    glBindTexture(GL_TEXTURE_RECTANGLE_NV, iTextureImgAccumulation); // Bind our frame buffer texture 
    glTranslatef(0.0f, 0.0f, -2.0f); 
    glBegin(GL_QUADS);
    glTexCoord2f(0,OPT.m_nHeight);
    glVertex3f(-1,-1,0);

    glTexCoord2f(OPT.m_nWidth,OPT.m_nHeight);
    glVertex3f(1,-1,0);

    glTexCoord2f(OPT.m_nWidth,0);
    glVertex3f(1,1,0);

    glTexCoord2f(0,0);
    glVertex3f(-1,1,0);

    glEnd();
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // Unbind our texture  
}

这是 FBO 的初始化:

    void OpenGlRenderer::initFrameBufferTexture(void) 
  {  
glGenTextures(1, &iTextureImg); // Generate one texture  


glEnable(GL_TEXTURE_RECTANGLE_NV);  
glBindTexture(GL_TEXTURE_RECTANGLE_NV, iTextureImg);

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD/*GL_DECAL*/);
glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_COMPARE_MODE, GL_NONE);
glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGB16F /*GL_FLOAT_R32_NV*/, OPT.m_nWidth, OPT.m_nHeight, 0, GL_RED, GL_FLOAT, NULL);

glGenTextures(1, &iTextureImgAccumulation); // Generate one texture  
glEnable(GL_TEXTURE_RECTANGLE_NV);  
glBindTexture(GL_TEXTURE_RECTANGLE_NV, iTextureImgAccumulation);

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD/*GL_DECAL*/);
glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_COMPARE_MODE, GL_NONE);
glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGB16F /*GL_FLOAT_R32_NV*/, OPT.m_nWidth, OPT.m_nHeight, 0, GL_RED, GL_FLOAT, NULL);



// Setup the basic texture parameters  



// Unbind the texture  
glBindTexture(GL_TEXTURE_RECTANGLE_NV, 0);  
    }


    void OpenGlRenderer::initFrameBufferDepthBuffer(void) 
    {  

    glGenRenderbuffersEXT(1, &iDepthBuffer); // Generate one render buffer and store the ID in iDepthBuffer  
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, iDepthBuffer); // Bind the iDepthBuffer render buffer  

    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,  OPT.m_nWidth, OPT.m_nHeight); // Set the render buffer storage to be a depth component, with a width and height of the window  

    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, iDepthBuffer); // Set the render buffer of this buffer to the depth buffer  

    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); // Unbind the render buffer  
    }   


    void OpenGlRenderer::initFrameBuffer(void) 
    {  
   initFrameBufferDepthBuffer(); // Initialize our frame buffer depth buffer  

   initFrameBufferTexture(); // Initialize our frame buffer texture  

   glGenFramebuffersEXT(1, &iFrameBufferAccumulation); // Generate one frame buffer and store the ID in iFrameBufferAccumulation  
   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, iFrameBufferAccumulation); // Bind our frame buffer  

   glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_NV, iTextureImgAccumulation, 0); // Attach the texture fbo_texture to the color buffer in our frame buffer  

   glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, iDepthBuffer); // Attach the depth buffer iDepthBuffer to our frame buffer  

   glGenFramebuffersEXT(1, &iFrameBuffer); // Generate one frame buffer and store the ID in iFrameBufferAccumulation  
   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, iFrameBuffer); // Bind our frame buffer  

   glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_NV, iTextureImg, 0); // Attach the texture fbo_texture to the color buffer in our frame buffer  

   glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, iDepthBuffer); // Attach the depth buffer iDepthBuffer to our frame buffer  

   GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); // Check that status of our generated frame buffer  
   checkFramebufferStatus();  
   if (status != GL_FRAMEBUFFER_COMPLETE_EXT) // If the frame buffer does not report back as complete  
   {  
    std::cout << "Couldn't create frame buffer" << std::endl; // Output an error to the console  
    exit(0); // Exit the application  
   }  
  }

所以基本上我想渲染到 iFrameBufferAccumulation 然后每次使用 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD); 哪个应该有效地添加这两个帧缓冲区?(或者我需要使用着色器)

另外我想问一下我是否可以将闪电强度设置为大于 1.0(atm 它在我的程序中的工作方式与 setLights 函数一样)并且它将向 FBO 呈现正确的结果?我使用 GL_RGB16F 纹理格式。可以吗,还是我需要使用 32 位纹理?如果我需要在渲染后使用着色器来显示 FBO?

4

1 回答 1

1

另外我想问一下我是否可以将闪电强度设置为大于 1.0(atm 它在我的程序中的工作方式与 setLights 函数一样)并且它将向 FBO 呈现正确的结果?我使用 GL_RGB16F 纹理格式。可以吗,还是我需要使用 32 位纹理?如果我需要在渲染后使用着色器来显示 FBO?

一般来说,没有。几乎所有固定功能操作都被钳制,无论是在纹理提取时,还是在将它们写入帧缓冲区时,或者其他时间。

如果你想做真正的浮点运算,那么你需要放弃固定功能,转而使用着色器。

于 2012-04-24T15:20:37.597 回答