多くの光源を使用して、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); を使用して毎回相対的なテクスチャを iFrameBuffer にレンダリングしたいと考えています。これら2つのフレームバッファを効果的に追加する必要があるのはどれですか? (または、シェーダーを使用する必要がありますか)
また、雷の強度を 1.0 よりも大きくすることができるかどうか (atm は私のプログラムでそのように動作します - 関数 setLights )、FBO に正しい結果をレンダリングするかどうかも尋ねたいと思いますか? GL_RGB16F テクスチャ フォーマットを使用します。それは大丈夫ですか、それとも 32 ビット テクスチャを使用する必要がありますか? そうであれば、レンダリング後にシェーダーを使用して FBO を表示する必要がありますか?