openglopengl-compat

I can't repeat the texture using GL_TEXTURE_CUBE_MAP and GL_REPEAT


After two days of reading and trying, I was able to texture a cube with GL_TEXTURE_CUBE_MAP:

Textured Cube

Then I decided to make a parallelepiped from the cube, in which the corresponding texture is repeated on the long side. I get similar or worse results:

Poorly stretched texture

And I want to get such a result:

Repeated texture

Is it even possible?

Here is the essential part of the code:

void Create( void ) {
    glGenTextures( 1, &id );
    glBindTexture( GL_TEXTURE_CUBE_MAP, id );
    glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );

    const RGB bk_cols[ ] = { {207,193,0}, {133,96,169}, {0,166,81}, {0,84,166}, {158,11,15}, {137,137,137} };
    const char letters[ ] = { 'x', 'y', 'z' };
    RGB* rgb = new RGB[ 16 * 16 + 16 ];
    for( unsigned int i = 0; i < 6; i++ ) {
        glTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, 16, 16, 0, GL_RGB, GL_UNSIGNED_BYTE,
            CreateLetter16x16( rgb, {0,250,0}, bk_cols[i], {0,0,0}, letters[ i >> 1 ], (i & 1 ? false : true) ) );
    }
    delete [ ] rgb;

    glTexParameteri( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
    glTexParameteri( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
    glTexParameteri( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_REPEAT/*GL_CLAMP_TO_EDGE*/ );
    glTexParameteri( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_REPEAT/*GL_CLAMP_TO_EDGE*/ );
    glTexParameteri( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE );
}

void DrawTexturedCube( void ) {
    float v = 2.0;
    float p = 6.0;
    // All the faces that are not front-faces are discarded.
    // This is a good test of vertex sequence.
    glEnable( GL_CULL_FACE );
    // Of course a depth test is needed here.
    glEnable( GL_DEPTH_TEST );

    // Must be enabled, else textures doesn't work
    glEnable( GL_TEXTURE_CUBE_MAP );
    // If you want your image to be unaffected by the current color,
    // you must change the texture environment parameter to decal
    glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL );

    // Select texture
    glBindTexture( GL_TEXTURE_CUBE_MAP, sq_txt.id );

    glBegin( GL_QUADS );
    // Right
    glTexCoord3f( 1,-1,-1); glVertex3f( p,-v,-v);
    glTexCoord3f( 1, 1,-1); glVertex3f( p, v,-v);
    glTexCoord3f( 1, 1, 1); glVertex3f( p, v, v);
    glTexCoord3f( 1,-1, 1); glVertex3f( p,-v, v);
    // Left
    glTexCoord3f(-1,-1,-1); glVertex3f(-p,-v,-v);
    glTexCoord3f(-1,-1, 1); glVertex3f(-p,-v, v);
    glTexCoord3f(-1, 1, 1); glVertex3f(-p, v, v);
    glTexCoord3f(-1, 1,-1); glVertex3f(-p, v,-v);
    // Top
    glTexCoord3f(-1, 1, 1); glVertex3f(-p, v, v);
    glTexCoord3f( 1, 1, 1); glVertex3f( p, v, v);
    glTexCoord3f( 1, 1,-1); glVertex3f( p, v,-v);
    glTexCoord3f(-1, 1,-1); glVertex3f(-p, v,-v);
    // Bottom
    glTexCoord3f(-1,-1,-1); glVertex3f(-p,-v,-v);
    glTexCoord3f( 1,-1,-1); glVertex3f( p,-v,-v);
    glTexCoord3f( 1,-1, 1); glVertex3f( p,-v, v);
    glTexCoord3f(-1,-1, 1); glVertex3f(-p,-v, v);
    // Front
    float xn = -3.0;
    float xp =  3.0;
    float yn = -1.0;
    float yp =  1.0;
    float zz =  1.0;
    glTexCoord3f(xn,yn,zz); glVertex3f(-p,-v, v);
    glTexCoord3f(xp,yn,zz); glVertex3f( p,-v, v);
    glTexCoord3f(xp,yp,zz); glVertex3f( p, v, v);
    glTexCoord3f(xn,yp,zz); glVertex3f(-p, v, v);
    // Back
    glTexCoord3f( 1,-1,-1); glVertex3f( p,-v,-v);
    glTexCoord3f(-1,-1,-1); glVertex3f(-p,-v,-v);
    glTexCoord3f(-1, 1,-1); glVertex3f(-p, v,-v);
    glTexCoord3f( 1, 1,-1); glVertex3f( p, v,-v);

    glEnd();

    // Restore default parameters
    glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
    // Must be disabled, else colors doesn't work ( Everything will be textured ).
    glDisable( GL_TEXTURE_CUBE_MAP );


    // --------------------------------------------------------------------

    float k = v+.01f;
    // Disable fill
    glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
    // Set line width
    glLineWidth( 3 );
    glBegin( GL_QUADS );
    glColor3f( .9f, 0, 0 );
    glVertex3f( k,-k,-k); glVertex3f( k, k,-k); glVertex3f( k, k, k); glVertex3f( k,-k, k); // Right
    glVertex3f(-k,-k,-k); glVertex3f(-k,-k, k); glVertex3f(-k, k, k); glVertex3f(-k, k,-k); // Left
    glVertex3f(-k, k, k); glVertex3f( k, k, k); glVertex3f( k, k,-k); glVertex3f(-k, k,-k); // Top
    glVertex3f(-k,-k,-k); glVertex3f( k,-k,-k); glVertex3f( k,-k, k); glVertex3f(-k,-k, k); // Bottom
    glVertex3f(-k,-k, k); glVertex3f( k,-k, k); glVertex3f( k, k, k); glVertex3f(-k, k, k); // Front
    glVertex3f( k,-k,-k); glVertex3f(-k,-k,-k); glVertex3f(-k, k,-k); glVertex3f( k, k,-k); // Back
    glEnd();
    // Restore fill
    glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
    // Restore default line width
    glLineWidth( 1 );

    // Restore default state
    glDisable( GL_DEPTH_TEST );

    // Restore default state
    glDisable( GL_CULL_FACE );
}

Solution

  • Repeat filtering is a texture sampling wrap mode. And wrap modes explain how texture coordinates outside of the space of the texture work.

    But the way cubemap texture coordinates are defined (they are vectors from the center of a cube pointing to a location inside that cube), they basically never fall outside of the size of a face of the cubemap. So repeat filtering is a no-op, functionally identical to clamp-to-edge.