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\$
  • \$\begingroup\$ did you check for OpenGL errors ? \$\endgroup\$ – concept3d Nov 18 '13 at 7:22
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.

| improve this answer | |
\$\endgroup\$
  • \$\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 '13 at 10:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.