PDA

View Full Version : Texture overwrite problem. Please Help.



flaviusxvii
09-23-2008, 10:18 AM
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?

Ilian Dinev
09-23-2008, 01:23 PM
[captain obvious]
Seeing srccode of working tutorials will show you the bug
[/captain obvious]

flaviusxvii
09-23-2008, 01:29 PM
Thankyou very little...

Zengar
09-23-2008, 02:09 PM
There must be an error in your code somewhere. A bug as huge could have never appear in production drivers.

flaviusxvii
09-23-2008, 02:24 PM
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?

dletozeun
09-23-2008, 04:14 PM
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.

flaviusxvii
09-23-2008, 08:35 PM
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... :(

#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&amp; 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, &amp;__texture_id);
__set_texture_data(data);
}

Texture::~Texture()
{
//glDeleteTextures(1, &amp;__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&amp; image)
{
Magick::Blob blob;
image.write(&amp;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 << "\n";
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&amp; 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(&amp;blob, "RGBA");
Texture::__texture_registry[key] = Texture::Ptr(new Texture(blob.data(), image.columns(), image.rows(), "RGBA", flags));
return Texture::__texture_registry[key];
}

Ilian Dinev
09-23-2008, 11:28 PM
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++.

flaviusxvii
09-24-2008, 06:12 AM
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?