If it helps somebody, here is my working code for RTT + multisample resolve + compression + storage in texture array slot. Compression is done by glCopyTexSubImage3D() for free if the format is a compressed one, but this is rather slow.
I have 3 fonctions, one for initialization, one called just before RTT, and one just after.
void Texture::initRTT( int width, int internalFormat, bool zbuf )
{
int num_samples = 4;
rttReady = true;
// AA frame buffer to render into
glGenFramebuffers(1, &fboAA);
glBindFramebuffer(GL_FRAMEBUFFER, fboAA);
glGenTextures(1, &textureAA);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textureAA);
glTexImage2DMultisample( GL_TEXTURE_2D_MULTISAMPLE, num_samples, internalFormat, width, width, false );
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, textureAA, 0);
GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0}; // Set the list of draw buffers.
glDrawBuffers(1, DrawBuffers); // "1" is the size of DrawBuffers
if( zbuf )
{
hasZbuf = true;
glGenTextures(1, &textureDepth);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textureDepth);
glTexImage2DMultisample( GL_TEXTURE_2D_MULTISAMPLE, num_samples, GL_DEPTH_COMPONENT24, width, width, false );
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE, textureDepth, 0 );
}
if( glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE ) sys.abort( "rtt fboAA not ok");
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); // Give an empty image to OpenGL ( the last "0" )
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
if( glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE ) sys.abort( "rtt fbo not ok");
}
void Texture::beginRTT( int numSlot, bool zbuf )
{
if( rttReady == false ) initRTT( dx_, internalFormat_, zbuf );
gl.viewport( 0,0,dx_, dx_ );
glBindFramebuffer(GL_FRAMEBUFFER, fboAA); // rebind the rtt fb
gl.clearRTT( zbuf );
}
void Texture::endRTT( int numSlot, bool zbuf )
{
glBindFramebuffer(GL_READ_FRAMEBUFFER, fboAA); // resolve MSAA from fboAA to fbo with a blit
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
glBlitFramebuffer( 0,0, dx_-1, dx_-1, 0, 0, dx_-1, dx_-1, GL_COLOR_BUFFER_BIT, GL_LINEAR );
glBindTexture(GL_TEXTURE_2D_ARRAY, idBind_ );
// glBindFramebuffer(GL_FRAMEBUFFER, fbo); // not necessary?
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); // store resolved fbo in texture slot
//glReadBuffer(GL_COLOR_ATTACHMENT0); // not necessary?
glCopyTexSubImage3D( GL_TEXTURE_2D_ARRAY, 0, 0, 0, numSlot, 0, 0, dx_, dx_ ); // addapts to texture format (compressed or not)
glBindFramebuffer(GL_FRAMEBUFFER, 0); // rebind the main fb
gl.viewport( 0,0, sys.getScreenWidth(), sys.getScreenHeight() ); // restore viewport
}
void GL::clearRTT( bool zbuf )
{
glClearColor( clearColorRTT.r, clearColorRTT.g, clearColorRTT.b, 1.f);
int flag = GL_COLOR_BUFFER_BIT;
if( zbuf ) flag += GL_DEPTH_BUFFER_BIT;
if( !(state_ & GN_ZWRITE) ) glDepthMask( GL_TRUE ); // renable zwrite
glClear( flag ); // clear
if( !(state_ & GN_ZWRITE) ) glDepthMask( GL_FALSE );// put back as it was
}