Jump to content
  • Advertisement
Sign in to follow this  
Trapper Zoid

OpenGL Trouble loading an OpenGL texture from a PNG

This topic is 4175 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm currently having problems with loading textures from PNG to an OpenGL texture; instead of getting a rendered test sprite in a quad, all I'm getting is a solid white quad instead. Part of my frustration is that I'm not entirely sure exactly where it is that I've made the mistake; there's a lot of code that could be at fault. I'm currently building a 2D sprite based game library in C++ using SDL with OpenGL, and I'm up to basic sprite rendering. In my previous system I loaded in PNG textures using SDL_image. For this new system I have integrated in PhysicsFS to deal with the file system, so since I'm using a different file read method and already have zlib statically compiled in I thought it might be time to use libpng to load in the textures. However none of my tests have seemed to work so far. I have had libpng compile and output something to memory structure, but OpenGL didn't render it. After reworking it a few times I've switched to using the glpng code (after rewriting it to take PhysicsFS file handles), but it also doesn't seem to work. Part of my frustration is that I'm not sure if the PNG loading code is to blame; it's entirely possible I've done something boneheaded in importing the SDL and OpenGL code from my previous system. I'm not an expert an diagnosing OpenGL problems, so can anyone give me some tips as to how I can fix this?
Here's some relevant code to what I'm doing. I can't include it all as there's a lot of resource management going on behind the scenes. It's a bit hackish at the moment; I'll clean it up once everything is working. Sorry if the underlying architecture isn't clear and that there are functions I haven't included: DrawSprites function - draws all sprites in the internal list
// draw all the sprites to the screen
void DrawSprites()
{
    internal::GraphicsData &gData = internal::GraphicsData::ref();
    spriteList_t::iterator spriteHook = gData.activeSpriteList.begin();
    spriteList_t::iterator end = gData.activeSpriteList.end();

    while (spriteHook != end)
    {
            // draw that sprite!
            // currently just debugging code
        file::LogDebug("Drawing sprite of type %d at (%f,%f,%f)...",
            (*spriteHook)->my_spriteType, (*spriteHook)->my_x, (*spriteHook)->my_y, (*spriteHook)->my_angle);

            // load in the sprite (won't do much if its already loaded...)
        if (!gData.resourceManager.LoadSprite((*spriteHook)->my_spriteType))
        {
                // cannot draw this sprites!
            file::LogError("Cannot draw sprite of type %d!", (*spriteHook)->my_spriteType);
            ++spriteHook;
            continue;
        }

            // now draw that sprite!
        glEnable(GL_TEXTURE_2D);
        glPushMatrix();

        glTranslatef((*spriteHook)->my_x, (*spriteHook)->my_y, 0.0f);
        glRotatef((*spriteHook)->my_angle, 0.0f, 0.0f, 1.0f);

        GLuint texID;
        GLfloat x1, y1, x2, y2, width, height;

            // get the appropriate texture code and dimensions
        if (!gData.resourceManager.GetSpriteInfo((*spriteHook)->my_spriteType, &texID, &x1, &y1, &x2, &y2, &width, &height))
            return;     // an error! Can't draw the sprite!
        width = width / 2.0;
        height = height / 2.0;

        if (height < 0)
            glFrontFace(GL_CW);

            // draw the sprite to the screen
        glBindTexture(GL_TEXTURE_2D, texID);
        glBegin(GL_QUADS);
            glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
            glTexCoord2f(x1,y1);  glVertex2f(-width, height);
            glTexCoord2f(x1,y2);  glVertex2f(-width, -height);
            glTexCoord2f(x2,y2);  glVertex2f(width, -height);
            glTexCoord2f(x2,y1);  glVertex2f(width, height);
        glEnd();

        file::LogDebug("......(%d)(%f, %f)(%f, %f), (%f, %f)",texID,x1,y1,x2,y2,width,height);

        if (height < 0)
            glFrontFace(GL_CCW);

        glPopMatrix();
        glDisable(GL_TEXTURE_2D);


        ++spriteHook;
    }
}
Code that loads in an image - currently using glpng
// helper function to load in images given a filename
// adapted from "Pierre and the Fish"
bool GraphicsResourceManager::LoadImage(unsigned int imageNum)
{
    using namespace file;
    boost::shared_ptr<ImageInfo> image = imageInfoList[imageNum];

        // first see if we need to actually *do* this...
    if (image->isTexIDAllocated)
        return true;        // if it's already loaded, we can just return

    Log("Loading image texture for [%s]...", image->filename.c_str());

        // load up the image texture to OpenGL using glpng

        // need a new texture for this
    //glGenTextures(1, &image->texID);
        // need to bind to this texture
    //glBindTexture(GL_TEXTURE_2D, image->texID);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);

    FileHandle handle = OpenRead(image->filename.c_str());
    if (!handle)
    {
        LogError("Error opening [%s], %s", image->filename.c_str(), ErrorString());
        return false;
    }
    const int MIPMAP = 0;
    const int TRANSPARENCY = PNG_SOLID;
    const int MIPMAP_FILTER = GL_NEAREST; // GL_LINEAR_MIPMAP_NEAREST
    image->texID = pngBindF(handle, MIPMAP, TRANSPARENCY, 0, GL_CLAMP,
        MIPMAP_FILTER, MIPMAP_FILTER);
    if (!image->texID)
    {
        LogError("Error loading in PNG file [%s] to OpenGL texture!", image->filename.c_str());
        return false;
    }
    if (!Close(handle))
    {
        LogError("Error closing [%s], %s", image->filename.c_str(), ErrorString());
        return false;
    }

    LogDebug("...The OpenGL ID number for this texture is [%d]", image->texID);
        // finally, set the loaded flag to true
    image->isTexIDAllocated = true;

    return true;
}

Share this post


Link to post
Share on other sites
Advertisement
Further tests by hacking in some simple SDL code to load bitmaps from my previous project suggests the problem is indeed something boneheaded I've done with either SDL or OpenGL's basic texture rendering system, rather than with PhysicsFS or glpng. I'm just currently too close to the code and too inexperienced with OpenGL to see it.

Share this post


Link to post
Share on other sites
Gah - I'm a total idiot! It turns out the problem was with my graphics resource manager; it was returning the position of the sprite in terms of image pixels rather than as a fraction from 0 to 1. Several hours debugging the wrong section of code; well at least it's working now [grin].

Share this post


Link to post
Share on other sites
...eh, well not quite. While I can see my sample sprite, I'm having a lot of difficulty getting OpenGL to recognise the alpha transparency, despite my logging functions stating that alpha is set to 8 bits for the texture and glEnable(GL_ALPHA_TEST) is set. I must still be doing something wrong.

Share this post


Link to post
Share on other sites
Ah, it's fixed now; I should have remembered that turning on mipmapping wasn't a good idea for sprites, but unfortunately I'd set a texture enviroment flag in my earlier debugging attempts that gave the same effect so my strategy of toggling everything one by one didn't work.

And with my problem solved and a record five posts by me in a row, I think my work here is done. Time to cue the closing credits and ride off into the sunset.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!