Texture overwrite problem. Please Help.

I’ve been writing OpenGL programs for many years and I’ve used texturing successfully in the past but I’ve run into a bug that I can not figure out. I’m converting a rendering engine that I wrote in python(with pyglet) to c++(GL/SDL/Magick++/Boost) and I’m having a problem with textures.
It seems that each time I create a texture it overwrites all the data of previous textures. So that no matter which texture I bind they all look like the most recently created texture. I have confirmed that I’m using different GLuints created by glGenTexture and I have confirmed that the correct texture id is bound when the texture data is attached.
Has this happened to anyone? And ideas on what I’m doing wrong?

[captain obvious]
Seeing srccode of working tutorials will show you the bug
[/captain obvious]

Thankyou very little…

There must be an error in your code somewhere. A bug as huge could have never appear in production drivers.

My question is, assuming I am dealing with multiple texture units, how could I accidentally overwrite the pixel data of one texture with the pixel data of a subsequently loaded texture?

Anyone have a clue?

Your problem is strange, a piece of code may help us. At the moment, I see only two ways to replace (not erase) a texture data, bind this one and call glTexImage*, glCopyTexImage*, glCopyTexSubImage*, drawing to texture using fbos or using pbos.

Tell us what hardware, driver version and OS you are using.

I think the following code is all the relevant stuff. The “equivalent” code works perfectly in python(with pyglet) on the same system. I’m running ubuntu(hardy) on a core2 duo with a modern nvidia card with the newest possible drivers.

Sorry for the messiness of the code… :frowning:

#include <iostream>
#include <sstream>
#include <GL/glew.h>

#include "Texture.hpp"

Texture::KeyIndexedTextures Texture::__texture_registry;

Texture::BoundMap Texture::__current_texture;
Texture::ModeMap Texture::__mode_to_glmode;

const unsigned Texture::REPEAT(1);
const unsigned Texture::NO_MIPMAP(2);

Texture::Texture():
    __width(0)
    ,__height(0)
    ,__mode("NONE")
    ,__flags(0)
    ,__dimension(GL_TEXTURE_2D)
    ,__texture_id(0)
{
    return;
}

Texture::Texture(const Texture& other):
    __width(other.__width)
    ,__height(other.__height)
    ,__mode(other.__mode)
    ,__flags(other.__flags)
    ,__dimension(other.__dimension)
    ,__texture_id(other.__texture_id)
{
    return;
}

Texture::Texture(const GLvoid* data
                 ,unsigned width
                 ,unsigned height
                 ,const std::string mode
                 ,const unsigned flags):
    __width(width)
    ,__height(height)
    ,__mode(mode)
    ,__flags(flags)
    ,__dimension(GL_TEXTURE_2D)
    //__dimension = if_then_else(len(size) == 2, GL_TEXTURE_2D, GL_TEXTURE_3D)
    ,__texture_id(0)
{
    glGenTextures(1, &__texture_id);
    __set_texture_data(data);
}

Texture::~Texture()
{
    //glDeleteTextures(1, &__texture_id);
    //if __texture_id in Texture::__texture_registry.values():
        //for n, id in Texture::__texture_registry.iteritems():
            //if id == __texture_id:
                //del Texture::__texture_registry[n]
}

/* static */
void Texture::init()
{
    Texture::__current_texture[GL_TEXTURE0] = 0;
    Texture::__current_texture[GL_TEXTURE1] = 0;
    Texture::__current_texture[GL_TEXTURE2] = 0;
    Texture::__current_texture[GL_TEXTURE3] = 0;
    Texture::__current_texture[GL_TEXTURE4] = 0;
    Texture::__current_texture[GL_TEXTURE5] = 0;
    Texture::__current_texture[GL_TEXTURE6] = 0;
    Texture::__current_texture[GL_TEXTURE7] = 0;

    Texture::__mode_to_glmode["RGB"]    = GL_RGB;
    Texture::__mode_to_glmode["RGBA"]   = GL_RGBA;
    Texture::__mode_to_glmode["L"]      = GL_LUMINANCE;
    Texture::__mode_to_glmode["LA"]     = GL_LUMINANCE_ALPHA;
}

void Texture::__set_texture_data(const GLvoid* data)
{
    bind();
    //glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    //if(__dimension == GL_TEXTURE_2D) {
        glTexImage2D(GL_TEXTURE_2D
                     ,0
                     ,__mode.length()
                     ,__width
                     ,__height
                     ,0
                     ,__mode_to_glmode[__mode]
                     ,GL_UNSIGNED_BYTE
                     ,data);
    //} else if(__dimension == GL_TEXTURE_3D) {
        //std::cout << "Building 3D texture..." << __size << std::endl;
        //for i, d, size in data:
            //glTexImage3D(GL_TEXTURE_3D, i, len(__mode), \
                            size[0], size[1], size[2], 0, \
                            __mode_to_glmode[__mode], GL_UNSIGNED_BYTE, d)
    //} else {
        //std::cerr << "ERROR: Invalid texture dimension!" <<  __dimension << std::endl;
    //}

    glTexParameterf(__dimension, GL_TEXTURE_WRAP_S, __flags & Texture::REPEAT ? GL_REPEAT : GL_CLAMP);
    glTexParameterf(__dimension, GL_TEXTURE_WRAP_T, __flags & Texture::REPEAT ? GL_REPEAT : GL_CLAMP);

    //if 'no mipmap' not in __flags and __dimension == GL_TEXTURE_2D:
    glTexParameterf(__dimension, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterf(__dimension, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    //glTexParameterf(__dimension, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
    //gluBuild2DMipmaps(GL_TEXTURE_2D, __mode_to_glmode[__mode],
                             //__width, __height, __mode_to_glmode[__mode],
                             //GL_UNSIGNED_BYTE, data );
    //else:
        //glTexParameterf(__dimension, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

    done();
}
void Texture::reset_image(Magick::Image& image)
{
    Magick::Blob blob;
    image.write(&blob, "RGBA");
    __set_texture_data(blob.data());
}

void Texture::bind(unsigned number)
{
    if(Texture::__current_texture[number] == __texture_id) {
        return; //# The texture is already bound
    }

    glActiveTexture(number);
    glEnable( __dimension );
    glBindTexture(__dimension, __texture_id);
    Texture::__current_texture[number] = __texture_id;
}

void Texture::done(unsigned number)
{
    //std::cout << "Done texture " << number << " " << __dimension << " " << __texture_id << "
";
    glActiveTexture(number);
    glDisable(__dimension );
    Texture::__current_texture[number] = 0;
}

/* static */
void Texture::reset()
{
    glActiveTexture(GL_TEXTURE0);
    glEnable(GL_TEXTURE_2D );
}

/* static */
void Texture::disable()
{
    glActiveTexture(GL_TEXTURE0);
    glDisable( GL_TEXTURE_2D );
    glDisable( GL_TEXTURE_3D );
}

/* static */
std::string Texture::__make_key(std::string pref, unsigned flags)
{
    std::stringstream ss;
    ss << pref << flags;
    return ss.str();
}

/* static */
Texture::Ptr Texture::from_file(std::string file,
                        unsigned flags,
                        boost::filesystem::path prefix)
{
    std::string key = Texture::__make_key(file, flags);
    if(Texture::__texture_registry.find(key) != Texture::__texture_registry.end()) {
        return Texture::__texture_registry[key];
    }
    Magick::Image image((prefix /= file).string().c_str());
    return Texture::from_image(image, file, flags);
}

/* static */
Texture::Ptr Texture::from_image(Magick::Image& image,
                            std::string prekey,
                            unsigned flags)
{
    std::string key(Texture::__make_key(prekey, flags));
    if(Texture::__texture_registry.find(key) != Texture::__texture_registry.end()) {
        return Texture::__texture_registry[key];
    }

    Magick::Blob blob;
    image.write(&blob, "RGBA");
    Texture::__texture_registry[key] = Texture::Ptr(new Texture(blob.data(), image.columns(), image.rows(), "RGBA", flags));
    return Texture::__texture_registry[key];
}

From opengl.h:
#define GL_TEXTURE0 0x84C0

From your code:
Texture::__current_texture[GL_TEXTURE0] = 0;
void Texture::bind(unsigned number){…} // here, what is the default value? Is it a number between 0…7 or is it GL_TEXTURE0?

I’d say the culprit is somewhere in your code, where you call Texture::bind(int WrongValue).
Btw, very scripty code… Maybe access to some of those maps (instead of arrays) got incorrectly ported to C++.

void Texture::bind(unsigned number){…} // here, what is the default value? Is it a number between 0…7 or is it GL_TEXTURE0?

It’s GL_TEXTURE0.

The __current_texture map keeps track of which textures are bound for each unit, so I don’t rebind them if they’re already bound.

Yeah the code is scripty. I wanted to complete the python -> c++ port before starting to optimize and refactor. So yeah. This all worked perfectly in python… So strange.

Any more suggestions?