A little confusion about glTexSubImage + GL_TEXTURE_RECTANGLE_ARB

Okay I’ll confess. I’m sure I’m doing something wrong (as usual), but from what I’ve read, this should work…

According to the OpenGL spec for glTexSubImage, GL_TEXTURE_RECTANGLE_ARB isn’t a valid target, but according to the GL_TEXTURE_RECTANGLE_ARB page, it is, so long as level is 0, and GL_TEXTURE_RECTANGLE_ARB should be appended to the list of valid targets. I’ve been experimenting with this and getting kind of odd results. No errors generated, but when I try to replace a 4x16 patch of a 64x64 texture, nothing is being replaced. When I change the target back to GL_TEXTURE_2D, everything works as expected.

The code is a bit large so I’ll try to post as small chunk as I can…

#define TEXWIDTH  64
#define TEXHEIGHT 64

TextureHandler::TextureHandler() {

    m_InternalFormat = GL_RGBA;
    m_Format = GL_RGBA;
    m_Type = GL_FLOAT;
    m_Height = TEXHEIGHT;
    m_Width  = TEXWIDTH;


void TextureHandler::Initialize() {

    // prepare all m_Data cells as blue, full alpha
    for ( int i = 0; i < m_Width; i++ ) {
        for ( int j = 0; j < m_Height; j++ ) {

            m_Data[i][j][0] = 0.0;
            m_Data[i][j][1] = 0.0;
            m_Data[i][j][2] = 1.0;
            m_Data[i][j][3] = 1.0;


void TextureHandler::GenAndBindTexture() {

    glGenTextures( 1, &m_id );  // generate a texture
    // glActiveTexture(GL_TEXTURE0 + m_id); // for the shader later
	glBindTexture( m_Target, m_id );  // bind it to the target type


	glTexImage2D( m_Target, 0, m_InternalFormat,
                  m_Width, m_Height, 0,
                  m_Format, m_Type, m_Data );


void TextureHandler::EditTexture( ) {

    glBindTexture( m_Target, m_id );

    float l_Data[4][15][4];

    // prepare a purple rectangle.
    for ( int i = 0; i < 4; i++ ) {
        for ( int j = 0; j < 15; j++ ) {

            l_Data[i][j][0] = 1.;
            l_Data[i][j][1] = 0.;
            l_Data[i][j][2] = 1.;
            l_Data[i][j][3] = 1.;


    // make the change...
    glTexSubImage2D( m_Target, 0, 1, 1,  //target, level, offsets
                     15, 4, m_Format, m_Type, l_Data );


void static Redraw() {

    // render implemented as singleton
    Render* l_Render = Render::GetInstance();

    // swap to model view and clear everything
    glMatrixMode( GL_MODELVIEW );

    // set Color to red so we know if the texture doesn't
    // even show up, then back up 3.6
    glColor3f( 1.0, 0.0, 0.0 );
    glTranslatef( 0.0, 0.0, -3.6 );

    // enable textures in decal mode
    // with target specified by m_Texture.m_Target
    glEnable( l_Render->m_Texture.m_Target );

    // bind the texture we want to use
    glBindTexture( l_Render->m_Texture.m_Target,
                   l_Render->m_Texture.m_id );

    // move back and draw
        glTexCoord2f(0.0, 0.0); glVertex3f(-2.0, -1.0, 0.0);
        glTexCoord2f(0.0, 1.0); glVertex3f(-2.0,  1.0, 0.0);
        glTexCoord2f(1.0, 1.0); glVertex3f( 0.0,  1.0, 0.0);
        glTexCoord2f(1.0, 0.0); glVertex3f( 0.0, -1.0, 0.0);

    glDisable( l_Render->m_Texture.m_Target );


I know that’s a large chunk (and it’s by far not the full app), but I wanted to provide context… Like I said, if I change it to TEXTURE_2D (and then change the TexParameteri calls, then it displays fine… but with GL_TEXTURE_RECTANGLE_ARB, it doesn’t work… so I don’t know what to think…

(Also… as an aside, I’m curious as to why if I make a glActiveTexture call, I can’t see any texture changes, even with GL_TEXTURE_2D as the target…)

I see you are using normalized texture coordinates [0.0,1.0]. This is not the way it works with rectangular textures. Texture coordinates go from 0 to width-1 and 0 to height-1.

Ahah! Okay, yes, that was it apparently. Thanks for that! :slight_smile: Does that apply to inside the shader as well then as well?

Also, I’m still kind of curious why if I make that glActiveTexture call, it makes any changes I make not appear… whether target is GL_TEXTURE_2D or GL_TEXTURE_RECTANGLE_ARB… anyone know?

yes, this is true inside a shader too. BTW, re-reading the spec of this extension, I made a mistake, it is no from 0 to width-1 but from 0 to width, etc.

THAT explains it then… the reason I was mapping this texture onto the surface is to get a view of what was happening in the shader, no matter where I sampled, I was getting the changed value… but I was always sampling texture location (0,0) essentially because I was dividing the (x,y) location I was trying to reference by the texture width,height. Makes sense now…