FBO and multitexture combiners

Hi, trying to use a combination of FBO and texture combiners. Basic principle is:

create FBO
create textures, attach to FBO
loop: first glCopyTexImage2D to get pre-RGBA data into a texture, clear buffers, render to FBO, glCopyTexImage2D to get post-RGBA data into a texture, then use a texture combiner to interpolate a result.

Here’s the code:

init:

    if(m_hFrameBuffer != 0)
        glDeleteFramebuffersEXT(1, &m_hFrameBuffer);
    glGenFramebuffersEXT(1, &m_hFrameBuffer);
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_hFrameBuffer);

    //  before the volume is rendered
    glActiveTexture(GL_TEXTURE0);
    glEnable(GL_TEXTURE_2D);
    if(m_uiBeforeTexture == 0)
        glGenTextures(1, &m_uiBeforeTexture);
    glBindTexture(GL_TEXTURE_2D, m_uiBeforeTexture);
    glTexImage2D(  GL_TEXTURE_2D,
                   0,
                   GL_RGBA8,
                   glReadWidth,
                   glReadHeight,
                   0,
                   GL_RGBA,
                   GL_UNSIGNED_BYTE,
                   0 );
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );

	glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_uiBeforeTexture, 0 );

    //  after the volume is rendered
    glActiveTexture(GL_TEXTURE1);
    glEnable(GL_TEXTURE_2D);
    if(m_uiAfterTexture == 0)
        glGenTextures(1, &m_uiAfterTexture);
    glBindTexture(GL_TEXTURE_2D, m_uiAfterTexture);
    glTexImage2D(  GL_TEXTURE_2D,
                   0,
                   GL_RGBA8,
                   glReadWidth,
                   glReadHeight,
                   0,
                   GL_RGBA,
                   GL_UNSIGNED_BYTE,
                   0 );
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );

	glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, m_uiAfterTexture, 0 );

    //  check that the frame buffer was correctly initialized
	GLenum status = glCheckFramebufferStatusEXT( GL_FRAMEBUFFER_EXT );

	switch( status )
	{
		case GL_FRAMEBUFFER_COMPLETE_EXT:
			Log("Attached frame buffer!");
			break;
		case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
			Log("Frame buffers are unsupported!");
			break;
        case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
            Log("Frame buffer missing attachment!");
            break;
		default:
			Log("Failed to attach frame buffer! Error = " + IntToStr(status));
            break;
	}

    //  go back to the default frame buffer
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

loop:

                    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_hFrameBuffer);

                    glActiveTexture(GL_TEXTURE0);
                    glEnable(GL_TEXTURE_2D);
                    glBindTexture(GL_TEXTURE_2D, m_uiBeforeTexture);

                    if(i == 0)
                    {
                        unsigned char * beforeBuffer = new unsigned char[glReadWidth * glReadHeight * 4];
                        memset(beforeBuffer, 0x0, 4 * glReadWidth * glReadHeight);
                        glTexImage2D(  GL_TEXTURE_2D,
                                       0,
                                       GL_RGBA8,
                                       glReadWidth,
                                       glReadHeight,
                                       0,
                                       GL_RGBA,
                                       GL_UNSIGNED_BYTE,
                                       beforeBuffer );
                        delete [] beforeBuffer;
                    }
                    else
                    {
                        glCopyTexImage2D( GL_TEXTURE_2D,
                                          0,
                                          GL_RGBA8,
                                          0,
                                          0,
                                          glReadWidth,
                                          glReadHeight,
                                          0);
                    }
                	glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_uiBeforeTexture, 0 );

                    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
                    RenderVolume(start, end, multiRenderFlag);

                    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		...<render planes of volumetric data>...

                    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_hFrameBuffer);
                    //==========================================================
                    glActiveTexture(GL_TEXTURE1);
                    glEnable(GL_TEXTURE_2D);
                    glBindTexture(GL_TEXTURE_2D, m_uiAfterTexture);
                    glCopyTexImage2D(   GL_TEXTURE_2D,  //  target
                                        0,              //  texture
                                        GL_RGBA8,       //  internal format
                                        0,              //  x
                                        0,              //  y
                                        glReadWidth,    //  width
                                        glReadHeight,   //  height
                                        0 );            //  border
                	glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, m_uiAfterTexture, 0 );

                    GLfloat constAlpha[] = {1.0f, 0.0f, 0.0f, (20.0f - (GLfloat)i) / 19.0f};

                    glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constAlpha);

                    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);

                    glTexEnvf(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE0);
                    glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);

                    glTexEnvf(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE1);
                    glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);

                    glTexEnvf(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_CONSTANT);
                    glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);

                    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

                    glEnable(GL_TEXTURE_2D);
                    glBindTexture(GL_TEXTURE_2D, m_uiAfterTexture);

                    glColor4f(1.0f, 1.0f, 1.0f, 1.0f);

                    glBegin(GL_QUADS);
                        glNormal3f(0.0f, 0.0f, 1.0f);

                        glTexCoord2f(-1.0f, -1.0f);
                        glVertex3f(0.0f, 0.0f, 0.0f);

                        glTexCoord2f( 1.0f, -1.0f);
                        glVertex3f(2.0f, 0.0f, 0.0f);

                        glTexCoord2f( 1.0f,  1.0f);
                        glVertex3f(2.0f, 1.5f, 0.0f);

                        glTexCoord2f(-1.0f,  1.0f);
                        glVertex3f(0.0f, 1.5f, 0.0f);
                    glEnd();

                    glDisable(GL_TEXTURE_2D);

                    float lineWidth;
                    glGetFloatv(GL_LINE_WIDTH, &lineWidth);

                    glLineWidth(6.0f);
                    glBegin(GL_LINE_LOOP);
                        glNormal3f(0.0f, 0.0f, 1.0f);
                        glVertex3f(0.0f, 0.0f, 0.0f);
                        glVertex3f(2.0f, 0.0f, 0.0f);
                        glVertex3f(2.0f, 1.5f, 0.0f);
                        glVertex3f(0.0f, 1.5f, 0.0f);
                    glEnd();

                    glLineWidth(lineWidth);

                    glEnable(GL_TEXTURE_2D);

                    glFlush();
                    SwapBuffers(hdc);

As you can see, right there at the end I’m mapping what should be the end result of the texture combiner onto a
quad so I can see what’s going on. So far, nothing but black. Blech!

Anybody have any nuggets of wisdom to share? I’m flying by the seat of my pants, so I’m sure I must be doing something
wrong.

Thanks,
Matt