1
\$\begingroup\$

I wrote my entire Texture loader by hand. I'm not using any Libraries. From what I gather the loading part is done correctly and stored in the texture class:

Texture* TGATextureLoader::create(const char *filename) {
        FILE *pFile;            // File pointer
        TGAHEADER tgaHeader;        // TGA file header
        unsigned long lImageSize;       // Size in bytes of image
        short sDepth;           // Pixel depth;
        GLbyte  *pBits = NULL;          // Pointer to bits

        // Default/Failed values
        GLint iWidth = 0;
        GLint iHeight = 0;
        GLenum eFormat = GL_BGR_EXT;
        GLint iComponents = GL_RGB8;

        // Attempt to open the fil
        pFile = fopen(filename, "rb");
        if(pFile == NULL)
            return NULL;

        // Read in header (binary)
        fread(&tgaHeader, 18/* sizeof(TGAHEADER)*/, 1, pFile);

        // Get width, height, and depth of texture
        iWidth = tgaHeader.width;
        iHeight = tgaHeader.height;
        sDepth = tgaHeader.bits / 8;

        // Put some validity checks here. Very simply, I only understand
        // or care about 8, 24, or 32 bit targa's.
        if(tgaHeader.bits != 8 && tgaHeader.bits != 24 && tgaHeader.bits != 32){
            return NULL;
        }

        // Calculate size of image buffer
        lImageSize = tgaHeader.width * tgaHeader.height * sDepth;

        // Allocate memory and check for success
        pBits = (GLbyte*)malloc(lImageSize * sizeof(GLbyte));
        if(pBits == NULL)
            return NULL;

        // Read in the bits
        // Check for read error. This should catch RLE or other 
        // weird formats that I don't want to recognize
        if(fread(pBits, lImageSize, 1, pFile) != 1)
        {
            free(pBits);
            return NULL;
        }

        // Set OpenGL format expected
        switch(sDepth)
        {
        case 3:     // Most likely case
            eFormat = GL_BGR_EXT;
            iComponents = GL_RGB8;
            break;
        case 4:
            eFormat = GL_BGRA_EXT;
            iComponents = GL_RGBA8;
            break;
        case 1:
            eFormat = GL_LUMINANCE;
            iComponents = GL_LUMINANCE8;
            break;
        };


        // Done with File
        fclose(pFile);

        Texture* texture = new Texture(pBits);
        texture->setWidth(iWidth);
        texture->setHeight(iHeight);
        texture->setComponents(iComponents);
        texture->setFormat(eFormat);

        // Return pointer to image data
        return texture;
    }

Then when Im done, I call textureName->generateTexture() Method from the texture class:

void Texture::generateTexture(){
        GLuint id;
        glGenTextures(1, &id);
        this->textureID = id;
        std::cout << "Binding Texture\n";
        glBindTexture(GL_TEXTURE_2D, this->textureID);
        glTexImage2D(GL_TEXTURE_2D, 0, 3, this->width, this->height, 0, GL_RGB, GL_UNSIGNED_BYTE, this->data);
        glBindTexture(GL_TEXTURE_2D, 0);
        std::cout << this->textureID;
    }

Then in my initialization of the resources, I call;

textureName = Engine::TGATextureLoader::create("filePath/fileName.tga");
textureName->generateTexture();

lastly in my render method, I bind the texture again before I use it:

glBindTexture(GL_TEXTURE_2D, cubeTexture->getTextureID());
glBegin(GL_TRIANGLES);                      // Drawing Using Triangles 
    glTexCoord2f(0.0f, 0.0f);
    //glColor3f(0.0f,0.0f,1.0f);
    glVertex3f( 0.0f, 1.0f, 0.0f);              // Top

    glTexCoord2f(1.0f, 0.0f);
    //glColor3f(1.0f,0.0f,0.0f);
    glVertex3f(-1.0f,-1.0f, 0.0f);              // Bottom Left

    glTexCoord2f(1.0f, 1.0f);
    //glColor3f(0.0f,1.0f,0.0f);
    glVertex3f( 1.0f,-1.0f, 0.0f);              // Bottom Right
glEnd();                            // Finished Drawing The Triangle

The texture doesn't render though. Is there something wrong with this code?

\$\endgroup\$
1
  • \$\begingroup\$ did you check for OpenGL errors ? \$\endgroup\$
    – concept3d
    Nov 18, 2013 at 7:22

1 Answer 1

1
\$\begingroup\$

You're not setting any properties in generateTexture.

Furthermore, you're setting the texture's internal format to 3, which is not valid and the type to GL_RGB, which is not correct. I recommend padding your input data with an alpha byte in order to ensure the texture's validity. Try this version instead:

void Texture::generateTexture(){
    GLuint id;
    glGenTextures(1, &id);
    this->textureID = id;
    std::cout << "Binding Texture\n";
    glBindTexture(GL_TEXTURE_2D, this->textureID);
    glTexParameterI(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterI(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterI(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterI(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexImage2D(
        GL_TEXTURE_2D, 0, GL_RGBA, 
        this->width, this->height,
        0,
        GL_BGRA, GL_UNSIGNED_BYTE, this->data
    );
    glBindTexture(GL_TEXTURE_2D, 0);
    std::cout << this->textureID;
}

If you're still not getting anything on the screen then at least your texture is valid. If the colors are wrong, try shuffling the bytes in your data.

Lastly, I highly recommend using CodeXL to debug OpenGL problems. You can use it to set a breakpoint for OpenGL errors, but also pause the program and inspect your textures and buffers.

\$\endgroup\$
1
  • \$\begingroup\$ I forgot that I grabbed the format earlier when loading the file in the TGA loader. I changed it to glTexImage2D(GL_TEXTURE_2D, 0, this->getComponents(), this->width, this->height, 0, this->getFormat(), GL_UNSIGNED_BYTE, this->data); as my texture class has 2 GLenum for internalformat(component) and format that are set in the texture when it loads. It works now! \$\endgroup\$
    – Snowdrama
    Nov 18, 2013 at 10:29

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .