Sign in to follow this  
Tac-Tics

OpenGL Troubles loading textures

Recommended Posts

I'm porting a game I wrote in Python using PyOpenGL and PyGame to SDL in C++. I am having troubles with my textures, and I have a suspicion that I'm not loading them correctly.
void LoadTexture(string textname)
{
	GLuint textureNumber;
	string filename = DATA_DIR + textname + string(".png");
	SDL_Surface* surface = IMG_Load(filename.c_str());

	glGenTextures(1, &textureNumber);
	textures[textname] = textureNumber; // textures is a global map.
	glBindTexture(GL_TEXTURE_2D, textureNumber);
	GLvoid* data = surface->pixels;
	cout << textname << "'s format is... " << endl;
	cout << "Bits per pixel: " << (int)surface->format->BitsPerPixel << endl;
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, surface->w, surface->h, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
	SDL_FreeSurface(surface);
}

Here is my original source which works just fine:
def LoadImage(filename):
    global textures
    image = Image.open("data\\%s.png" % filename)
    data = image.tostring("raw", "RGB", 0, -1)
    textures[filename] = glGenTextures(1)
    glBindTexture(GL_TEXTURE_2D, textures[filename])
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.size[0], image.size[1], 0, GL_RGB, GL_UNSIGNED_BYTE, data)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)

Any ideas of what I might be doing wrong? What can I do to further troubleshoot texture errors? OpenGL will just let them pass silently and there's so much that can go wrong (is GL_TEXTURE_2D enabled? Are my coordinates correct?, etc), it's often hard to pinpoint where the error is.

Share this post


Link to post
Share on other sites
Compare the two pieces of code more closely. There are two things (of which one is an important) you're doing in the Python code but not in the C++ code. OpenGL is not saying anything because the difference in itself is not an error, but it leads to an error later.

Share this post


Link to post
Share on other sites
I know I'm not doing the format conversion. I'm not quite sure how I do that and the documentation isn't cooperating with me. Honestly, I didn't understand how the conversion worked in PIL either (the last two parameters were not documented, I just lifted it from a tutorial online).

I read somewhere about creating an SDL surface with the correct format and then blitting the image onto that surface, but that adds more steps and more places to mess up, and I still can't quite get it to work.

Here's what I currently have.


void LoadTexture(string textname)
{
GLuint textureNumber;
string filename = DATA_DIR + textname + string(".png");
SDL_Surface* surface = IMG_Load(filename.c_str());
SDL_Rect zero;
zero.h = surface->h;
zero.w = surface->w;
zero.x = 0;
zero.y = 0;

#if SDL_BYTEORDER == SDL_BIG_ENDIAN
int rmask = 0xff000000;
int gmask = 0x00ff0000;
int bmask = 0x0000ff00;
int amask = 0x000000ff;
#else
int rmask = 0x000000ff;
int gmask = 0x0000ff00;
int bmask = 0x00ff0000;
int amask = 0xff000000;
#endif

SDL_Surface* converted_surface = SDL_CreateRGBSurface(SDL_SWSURFACE, surface->w, surface->h, 24,
rmask, gmask, bmask, amask);

SDL_BlitSurface(surface, &zero, converted_surface, &zero);

glGenTextures(1, &textureNumber);
textures[textname] = textureNumber;
glBindTexture(GL_TEXTURE_2D, textureNumber);
GLvoid* data = converted_surface->pixels;
cout << textname << "'s format is... " << endl;
cout << "Bits per pixel: " << (int)converted_surface->format->BitsPerPixel << endl;
cout << endl;
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, surface->w, surface->h, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
SDL_FreeSurface(surface);
SDL_FreeSurface(converted_surface);
}



Also, I don't understand the difference between the 3rd and 3rd-from-last parameters in glTexImage2D. What is the difference between "Format" and "Internal Format"? And does "GL_RGB" mean the same as "3" for the internal format.

EDIT:
Durr. I also forgot
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
. I'm not sure 100% what this line actually does either X-(

Share this post


Link to post
Share on other sites
Quote:
Original post by Tac-Tics
Also, I don't understand the difference between the 3rd and 3rd-from-last parameters in glTexImage2D. What is the difference between "Format" and "Internal Format"? And does "GL_RGB" mean the same as "3" for the internal format.

Third-from-last parameter (together with second-from-last) tells OpenGL what the source format is. You cannot just give OpenGL a pointer and expect it to correctly parse any arbitrary image data. You must tell it what the pointed to data really is.

For example: an RGB image where each component is a byte (GL_RGB and GL_UNSIGNED_BYTE), a greyscale image where each pixel is represented by an integer (GL_LUMINANCE and GL_INT), or an BGRA (watch the component order aswell) image with floatingpoint components (GL_BGRA with GL_FLOAT). Without this information, you cannot say how the image is really stored.

The third parameter tells OpenGL in what format the texture should be stored internally. GL_RGB says you want the image stored as a three-component RGB texture. GL_LUMINANCE means a single component grayscale image. Conversions are done as needed by OpenGL.

For example: you pass an RGB image and say the internal format is RGBA, the alpha channel is automatically added. If you pass an RGBA image and say the internal format is GL_ALPHA, the RGB channels are dropped and only the alpha channel is used.

And yes, 3 and GL_RGB means the same thing when used to specify internal format. But don't use numbers, use the explicit constants instead.

Quote:
Original post by Tac-Tics
EDIT:
Durr. I also forgot
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
. I'm not sure 100% what this line actually does either X-(

Default minification filter is GL_LINEAR_MIPMAP_NEAREST. This minification filter requires a full set of mipmap levels to be a complete texture object. Since you didn't change the default and only uploaded the base level, the texture object is incomplete. An incomplete texture object, when used in rendering, will disable texturing as long as the texture object is bound and incomplete.

Changing the filtering to GL_LINEAR, mipmaps are no longer required, and the texture object requires only the base level. Since you have uploaded that, the texture object is now complete, and will work as expected.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this