Automatic cubemaps via PBuffers

Sage
Posts: 1,199
Joined: 2004.10
Post: #16
Well, I thought it was all sorted out. I've got mipmaps being generated correctly, and I've got rendering into cubemap faces working. The trouble is, the cubemaps aren't stitching correctly, in fact, it's all fubar.

Here's a screenshot:
[Image: Screenshots-2006-02-02-00.png]

Basically, the faces *seem* to face the right direction, but they don't stitch. And, bafflingly, negative X doesn't render correctly at all. The other five faces do, at least, "reflect" the correct imagery for that direction.

First off, I read the spec from the SGI registry. I figured out the up vectors for rendering each image from this:
Code:
major axis
direction     target                             sc     tc    ma
----------    -------------------------------    ---    ---   ---
+rx          TEXTURE_CUBE_MAP_POSITIVE_X_ARB    -rz    -ry   rx
-rx          TEXTURE_CUBE_MAP_NEGATIVE_X_ARB    +rz    -ry   rx
+ry          TEXTURE_CUBE_MAP_POSITIVE_Y_ARB    +rx    +rz   ry
-ry          TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB    +rx    -rz   ry
+rz          TEXTURE_CUBE_MAP_POSITIVE_Z_ARB    +rx    -ry   rz
-rz          TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB    -rx    -ry   rz

Next, here's my method for rendering the cubemap. Basically, it just creates a cubemap FBO, a camera with a 90 degree FOV, centers is in the world, and takes a snapshot going in each direction with the appropriate up vector:

Code:
void World::generateCubemap( void )
{
    vec2i oldSize( _glContextSize );

    using namespace PANSICore;

    if ( !_glContextAvailable )
    {
        Logger::log( LogEntry::Debug, "World::generateCubemaps",
                     "GL Context hasn't been created. Bailing for now; ( will be called later )" );
    }

    Logger::log( LogEntry::Debug, "World::generateCubemaps",
                 "Beginning..." );
    
    
    const int size = 512;
    const float padding = 500;

    Camera camera( "Cubemapper" ),
           *previousCamera = activeCamera();
    
    setActiveCamera( &camera );
    
    delete _cubemap;
    _cubemap = NULL;
    
    
    /*
        Create a cubemap FBO
    */
    
    FrameBufferObject renderTexture( size, size, GL_TEXTURE_CUBE_MAP, true,
                                     FrameBufferObject::DepthBuffer );

    camera.reshape( size, size );
    camera.setFOV( 90 );
    camera.setFarPlane( worldSize() * 0.5f );
    
    vec3 pos( 0,0,0 );

    if ( _terrain )
    {
        pos.z = _terrain->heightForPoint( pos.x, pos.y ) + padding;
    }
    
    if ( _water && pos.z < _water->level() + padding )
    {
        pos.z = _water->level() + padding;
    }

    camera.setPosition( pos );

    /*
        Now, we've gotta render into it.
        This is the order:
        
        POSX
        NEGX
        POSY
        NEGY
        POSZ
        NEGZ        
    */
    
    vec3 directions[6] = {
        vec3(  1.0f,  0.0f,  0.0f ),
        vec3( -1.0f,  0.0f,  0.0f ),
        vec3(  0.0f,  1.0f,  0.0f ),
        vec3(  0.0f, -1.0f,  0.0f ),
        vec3(  0.0f,  0.0f,  1.0f ),
        vec3(  0.0f,  0.0f, -1.0f )
    };
    
    vec3 ups[6] = {

        vec3(  0.0f, -1.0f,  0.0f ),
        vec3(  0.0f, -1.0f,  0.0f ),
        vec3(  0.0f,  0.0f,  1.0f ),
        vec3(  0.0f,  0.0f, -1.0f ),
        vec3(  0.0f, -1.0f,  0.0f ),
        vec3(  0.0f, -1.0f,  0.0f )
    };
    
    renderTexture.begin( true, _backgroundColor );

    for ( int i = 0; i < 6; i++ )
    {
        GLint face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
        camera.look( pos, pos + directions[i], ups[i] );
        
        renderTexture.beginCubemapFace( face, true, _backgroundColor );
        
        display( 0.0f );
    }
    
    renderTexture.end();
    
    /*
        We need to force mipmap generation, and then unbind cube mapping, since
        use() expects us to want to draw with it.
    */
    renderTexture.use();
    
    glBindTexture( GL_TEXTURE_CUBE_MAP, 0 );
    glDisable( GL_TEXTURE_CUBE_MAP );
    
    /*
        Now, transfer the cubemap "ownership" to a Texture and let go of FBO
    */

    TextureManager *tm = Application::instance()->textureManager();
    _cubemap = tm->takeCubemap( renderTexture.textureID(), renderTexture.width(), renderTexture.height(),
                                GL_RGB, GL_RGB );

    /*
        Finally restore the old camera, or NULL active.
    */

    if ( previousCamera )
    {
        printf( "Re-assigning active camera \"%s\"\n", previousCamera->name().c_str() );
        setActiveCamera( previousCamera );
    }
    else
    {
        setActiveCamera( NULL );
    }
    
    Logger::log( LogEntry::Debug, "World::generateCubemaps",
                 "Finished." );

}

My code for binding and displaying the cubemap looks like this:
Code:
glActiveTextureARB( GL_TEXTURE0_ARB + texName );
glEnable(GL_TEXTURE_CUBE_MAP);

glBindTexture(GL_TEXTURE_CUBE_MAP, _environmentMapTexture->textureID() );

GLint mode = GL_REFLECTION_MAP;
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, mode );
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, mode );
glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, mode );

glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );

glEnable (GL_TEXTURE_GEN_S);
glEnable (GL_TEXTURE_GEN_T);
glEnable (GL_TEXTURE_GEN_R);

glMatrixMode( GL_TEXTURE );
glLoadMatrixf( WORLD()->activeCamera()->modelview().rotation().inverse().mat );
glMatrixMode( GL_MODELVIEW );

Now, all this being said, I *think* the trouble is not in the generation of the cubemap but rather somewhere when its rendered. The reason I say this is this -- I downloaded an ancient demo from NVIDIA of cubemaps ( '99 ) which included 6 pre-rendered tga images which are applied to a teapot, a torus, etc. They stitched correctly and look great.

When I use those *exact* same six images ( instead of rendering my own ) I get the same baffling weirdness. See screenshot:

[Image: Screenshots-2006-02-02-08.png]

So, I have to assume something's ass backwards in the way I map the cubemap. Does anybody have any suggestions?
Quote this message in a reply
Moderator
Posts: 771
Joined: 2003.04
Post: #17
(Judging from the second screenshot)

* The bottom should be rotated 90 degrees counter-clockwise
* Two of the side textures are upside-down
Quote this message in a reply
Sage
Posts: 1,199
Joined: 2004.10
Post: #18
That's not the point. The point is that those textures -- those exact and unmodified textures -- work fine in a demo cubemap app.

I want to know what I'm doing wrong.
Quote this message in a reply
Sage
Posts: 1,232
Joined: 2002.10
Post: #19
I'd guess it is what you're loading into the texture matrix.
Quote this message in a reply
Sage
Posts: 1,199
Joined: 2004.10
Post: #20
arekkusu Wrote:I'd guess it is what you're loading into the texture matrix.

That's what seemed odd to me as well, but when I commented that bit out entirely, it *still* stitched incorrectly.
Quote this message in a reply
Sage
Posts: 1,199
Joined: 2004.10
Post: #21
FIXED!

It turned out that I was using incorrect glViewport information later in the rendering process.... a stupid mistake. I took a week or so to clear my head, working on my FBO effect system, as well as migrating my vertex array code to VBOs with mapped buffers; This morning on coming back to the cubemap issues, I found the bug immediately.

[Image: Screenshots-2006-02-15-03.png]

Woo!
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Best strategy for rendering into cubemaps? TomorrowPlusX 7 4,824 Dec 6, 2009 11:53 AM
Last Post: TomorrowPlusX
  PBuffers and setTextureImageToPBuffer:colorBuffer: Marjock 4 2,773 Jul 16, 2006 01:19 AM
Last Post: Marjock
  cubemaps with shaders akb825 3 3,162 Apr 5, 2006 06:24 PM
Last Post: akb825
  Displaying my cubemaps in world space, rather than eye TomorrowPlusX 1 2,806 Jan 26, 2006 04:29 AM
Last Post: TomorrowPlusX
  Seams showing on my cubemaps TomorrowPlusX 4 4,021 Dec 14, 2005 12:56 PM
Last Post: TomorrowPlusX