TGA Resource Texture Problem

Started by
5 comments, last by lc_overlord 19 years, 7 months ago
I recently spent some time writing a TGA loader, and then trying to write a resource TGA loader. I accomplished this by creating a class that could accept either a string representing the TGA file location or an unsigned integer representing the resource ID. However, I have run into some problems with it. I can load the resource texture and even draw it, but the colors are a little bit lighter than they are supposed to be. I've tried running various different ways, and have come to the conclusion that it must be the texture class code as opposed to the implementation settings (blending, alpha testing, etc.). Could anyone point out what I messed up? (Loading a resource from a file is also currently broken). Note that the class can only load a 32 bit uncompressed TGA image, that will hopefully be fixed in the future.

// CTexture.h

#ifndef __TEXTURE_H__
#define __TEXTURE_H__

struct PIXEL
{
	unsigned char red;
	unsigned char green;
	unsigned char blue;
	unsigned char alpha;

	PIXEL( unsigned char _red = 0, unsigned char _green = 0, unsigned char _blue = 0, unsigned
		char _alpha = 0 ) :	red(_red), green(_green), blue(_blue), alpha(_alpha)
	{
		// Nothing else to do
	}
};

#pragma pack(push,1)
struct _TARGA 
{
	unsigned char  idlength;
	unsigned char  colourmaptype;
	unsigned char datatypecode;
	short int colourmaporigin;
	short int colourmaplength;
	unsigned char  colourmapdepth;
	short int x_origin;
	short int y_origin;
	short width;
	short height;
	unsigned char  bitsperpixel;
	unsigned char  imagedescriptor;
	PIXEL data;
};
#pragma pack(pop,1)

class CTexture
{
public:

	static unsigned int numTextures;

	CTexture();
	CTexture( unsigned int resourceID );
	CTexture( const char* fileName );
	~CTexture();

	void Bind() const;
	bool Initialize( const char* fileName );
	bool Initialize( unsigned int resourceID );

private:
	unsigned int id;

	bool LoadResourceTGA( _TARGA* targa, PIXEL* data, unsigned int resourceID );
	bool LoadFileTGA( const char* fileName );
};


#endif




#include "CTexture.h"

#include <windows.h>
#include <gl/gl.h>
#include <stdio.h>

unsigned int CTexture::numTextures = 0;

CTexture::CTexture()
{
	// Nothing else to do
}

CTexture::CTexture( unsigned int resourceID )
{
	_TARGA* tga = (_TARGA*)LockResource( LoadResource(NULL, 
		FindResource(NULL, MAKEINTRESOURCE(resourceID), "TGA") ) );

	if ( tga )
	{
		glGenTextures(1, &numTextures);
		id = numTextures;
		LoadResourceTGA( tga, &tga->data, id );
	}
}

CTexture::CTexture( const char* fileName )
{	
	glGenTextures(1, &numTextures);
	id = numTextures;

	LoadFileTGA( fileName );
}

CTexture::~CTexture()
{
	glDeleteTextures(1, &id);
}

void CTexture::Bind() const
{
	glBindTexture(GL_TEXTURE_2D, id);
}

bool CTexture::Initialize( const char* fileName )
{
	glGenTextures(1, &numTextures);
	id = numTextures;

	if ( ! LoadFileTGA( fileName ) )
	{
		return false;
	}

	return true;
}

bool CTexture::Initialize( unsigned int resourceID )
{
	_TARGA* tga = (_TARGA*)LockResource( LoadResource(NULL, 
		FindResource(NULL, MAKEINTRESOURCE(resourceID), "TGA") ) );

	if ( tga )
	{	
		glGenTextures(1, &numTextures);
		id = numTextures;
		
		if ( ! LoadResourceTGA( tga, &tga->data, id ) )
		{
			return false;
		}
	}
	
	return true;
}

bool CTexture::LoadResourceTGA( _TARGA* targa, PIXEL* data,  unsigned int resourceID )
{
	PIXEL* pixels = new PIXEL[targa->height*targa->width];

	for ( int height = 0; height < targa->height; ++height )
	{
		for ( int width = 0; width < targa->width; ++width )
		{
			pixels[(targa->height - height - 1) * targa->width + width].blue  = data->red;
			pixels[(targa->height - height - 1) * targa->width + width].green = data->green;
			pixels[(targa->height - height - 1) * targa->width + width].red   = data->blue;
			pixels[(targa->height - height - 1) * targa->width + width].alpha = data->alpha;

			data++;
		}
	}

	glBindTexture(GL_TEXTURE_2D, resourceID);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, targa->width, targa->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
	
	delete[] pixels;

	return true;
}

bool CTexture::LoadFileTGA( const char *fileName )
{
	_TARGA* tga = new _TARGA;
	FILE* file = NULL;
	PIXEL* pixels;

	if ( ! fileName )
	{
		return false;
	}
	
	file = fopen(fileName,"rb");

	if ( ! file )
	{
		return false;
	}
	
	fread(tga, 1, sizeof(_TARGA) - sizeof(PIXEL), file);

	pixels = new PIXEL[tga->width * tga->height];

	fread(pixels, 1, tga->width * tga->height * sizeof(PIXEL), file);

	if ( ! LoadResourceTGA(tga, pixels, id))
	{
		return false;
	}

	delete tga;
	fclose(file);

	return true;
}




[Edited by - Cypher777 on September 17, 2004 3:17:10 PM]
Advertisement
Perhaps if you posted a picture of the problem and how it should look like.
Good idea, here's the before (loaded from a file) and after (loaded from a resource) pictures.



Before



After
Hmmm... the only reasonable expenation for the difference must be that you have some kind of blending turned on, what blendfunk are you using?

The difference in the images could be the alpha channel.
Depth Testing is on (tried off too), blending enabled with GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA, alpha testing enabled with GL_GREATER and 0.1f. I made a small testing program based off NeHe's framework, and the initialization and drawing functions are shown below. Included are the expected and actual results of the image.

TGA Image in PSP 8.0 (Expected Result)

TGA Image in During Program Execution (Actual Result)


CTexture tex;int InitGL(GLvoid)							{	tex.Initialize(IDR_TGA1);	glShadeModel(GL_SMOOTH);						        glClearColor(0.0f, 0.0f, 0.0f, 0.5f);	glClearDepth(1.0f);							glEnable(GL_DEPTH_TEST);						glDepthFunc(GL_LEQUAL);							glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);		return TRUE;							}int DrawGLScene(GLvoid)							{	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);		glLoadIdentity();										glEnable(GL_TEXTURE_2D);	glEnable(GL_BLEND);	glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );	glEnable(GL_ALPHA_TEST);	glAlphaFunc(GL_GREATER, 0.1f);	glTranslatef(-0.4f,-0.4f,-2.0f);	glColor4f(1.0f,1.0f,1.0f,1.0f);	tex.Bind();	glBegin(GL_QUADS);		glTexCoord2f(0.0f, 0.0f); glVertex3f( 0.0f,0.0f,0.0f);		glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,0.0f,0.0f);		glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,1.0f,0.0f);		glTexCoord2f(0.0f, 1.0f); glVertex3f (0.0f,1.0f,0.0f);	glEnd();		return TRUE;							}
Sorry, here are the links to the images.


TGA Image in PSP 8.0 (Expected Result)

TGA Image During Program Execution (Actual Result)
I think you have an alpha problem, with that blendfunc it's supposed to look like that(given that you have a correct alphamap), you could perhaps try to reduce the alpha values in the tga file to next to nothing.
Remember, PSP8 has a somewhat "wonky" alpha map support.
I normaly use PSP8 for most of my texturing and graphics needs, but when i need an alphamapped texture, i do that in photoshop.

This topic is closed to new replies.

Advertisement