PDA

View Full Version : rtt + multisample resolution + dxt1 compression



lamigo
08-29-2014, 01:46 AM
My OpenGL 3.3 render to texture needs to be resolved for multisampling and then compressed to DXT1 on the fly. My understanding is that I have to :
- create a multisample frame buffer
- render into it
- blit to a single sample uncompressed texture (glBlitFrameBuffer() ?)
- copy to a compressed texture with glCopyTexImage2D()

Is it the way to go? I need the whole thing to happen within less than 10ms for a 256x256 texture.
I only see GL_COMPRESSED_RGB for the internal flags of glCopyTexImage2D. How can I ask DXT1 to be used, if supported of course, and not another compression method?
Would there be an all in one example (shader?) out there for this relatively basic need?

Osbios
08-29-2014, 04:51 AM
http://www.opengl.org/registry/specs/EXT/texture_compression_s3tc.txt


This extension introduces new tokens:

COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3

In OpenGL 1.2.1 these tokens are accepted by the <internalformat> parameter
of TexImage2D, CopyTexImage2D, and CompressedTexImage2D and the <format>
parameter of CompressedTexSubImage2D.
I just remembered that from making a list of texture formats. I actually never used compressed formats and can't tell you anything about the timing.

lamigo
10-04-2014, 06:23 AM
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
}