PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Texturen laden in OpenGL


Ganon
2003-12-08, 18:45:54
Hi.

Sorry, das ich in letzter Zeit so viel Frage, aber momentan habe ich viel Zeit und Lust weiter zu machen. *ggg*

Diesmal geht es wieder um die Texturen.

Und zwar habe ich damals das Linux-Tutorial von NeHe "kopiert" und es funktionierte soweit auch. Nur wollte ich jetzt mehrere Texturen laden und dazu eine Klasse schreiben, damit es etwas aufgeräumter ist.

Nur merkte ich jetzt, das der Code den ich habe wohl nicht gerade ideal ist, oder? Zumindet habe ich ein paar Verständnisprobleme.

Das ImageLoad() verstehe ich noch. Nur bei LoadGLTextures() habe ich ein paar Probleme.

Und zwar diese 3 Zeilen:

1. glGenTextures(1, &texture[0]);

2. glBindTexture(GL_TEXTURE_2D, texture[0]);

3. gluBuild2DMipmaps(GL_TEXTURE_2D, 3, image1->sizeX, image1->sizeY, GL_RGB, GL_UNSIGNED_BYTE, image1->data);

Was machen diese 3 Befehle? Besonders 3. verstehe ich nicht. Es wird doch später nur der 2. Befehl benutzt. Der wird in 3. aber gar nicht angegeben, bzw. hat nix mit texture[0] zu tun.

Kann ich mit diesem Code überhaupt mehrere Texturen laden, ohne große Verrenkungen zu machen?

Soweit ich weiß wird doch später nur der Wert in texture[0] gebraucht, oder? Müsste man dann nicht den angelegten Speicher von image1 wieder frei geben?

Wäre nett wenn mir das mal jemand erklären könnte.

Danke.



GLuint texture[1];

// quick and dirty bitmap loader...for 24 bit bitmaps with 1 plane only.
typedef struct
{
unsigned long sizeX;
unsigned long sizeY;
char *data;
} Image;
//++++++++++++++++++++++++++++++++++++++++++++++++++++
int ImageLoad(char *filename, Image *image) {
FILE *file;
unsigned long size; // size of the image in bytes.
unsigned long i; // standard counter.
unsigned short int planes; // number of planes in image (must be 1)
unsigned short int bpp; // number of bits per pixel (must be 24)
char temp; // temporary color storage for bgr-rgb conversion.

// make sure the file is there.
if ((file = fopen(filename, "rb"))==NULL)
{
printf("Datei nicht gefunden : %s\n",filename);
return 0;
}

// seek through the bmp header, up to the width/height:
fseek(file, 18, SEEK_CUR);

#ifdef _M_IX86
#else
char *revert, swap;
#endif

// read the width
if ((i = fread(&image->sizeX, 4, 1, file)) != 1)
{
printf("Fehler beim Lesen der Breite von %s.\n", filename);
return 0;
}

// Wenn Prozessor kein x86 ist, dann Bild-Header umstellen auf Big-Endian
#ifdef _M_IX86
#else
revert = (char *) &(image->sizeX);
swap = revert[0]; revert[0] = revert[3]; revert[3] = swap;
swap = revert[1]; revert[1] = revert[2]; revert[2] = swap;
#endif

printf("Breite von %s: %lu\n", filename, image->sizeX);

// read the height
if ((i = fread(&image->sizeY, 4, 1, file)) != 1)
{
printf("Fehler beim Lesen der Hoehe von %s.\n", filename);
return 0;
}

#ifdef _M_IX86
#else
revert = (char *) &(image->sizeY);
swap = revert[0]; revert[0] = revert[3]; revert[3] = swap;
swap = revert[1]; revert[1] = revert[2]; revert[2] = swap;
#endif

printf("Hoehe von %s: %lu\n", filename, image->sizeY);

// calculate the size (assuming 24 bits or 3 bytes per pixel).
size = image->sizeX * image->sizeY * 3;

// read the planes
if ((fread(&planes, 2, 1, file)) != 1)
{
printf("Fehler beim Lesen der Planes von %s.\n", filename);
return 0;
}

#ifdef _M_IX86
#else
revert = (char *) &planes;
swap = revert[0]; revert[0] = revert[1]; revert[1] = swap;
#endif

if (planes != 1)
{
printf("Planes von %s ist nicht 1: %u\n", filename, planes);
return 0;
}

// read the bpp
if ((i = fread(&bpp, 2, 1, file)) != 1)
{
printf("Fehler beim Lesen der Farbtiefe von %s.\n", filename);
return 0;
}

#ifdef _M_IX86
#else
revert = (char *) &bpp;
swap = revert[0]; revert[0] = revert[1]; revert[1] = swap;
#endif

if (bpp != 24) {
printf("Farbtiefe von %s ist nicht 24: %u\n", filename, bpp);
return 0;
}

// seek past the rest of the bitmap header.
fseek(file, 24, SEEK_CUR);

// read the data.
image->data = (char *) malloc(size);
if (image->data == NULL)
{
printf("Fehler beim Ansteuern vom Speicher für Farb-korrigiertes Bild");
return 0;
}

if ((i = fread(image->data, size, 1, file)) != 1)
{
printf("Fehler beim Lesen der Daten von %s.\n", filename);
return 0;
}

for (i=0;i<size;i+=3) // reverse all of the colors. (bgr -> rgb)
{
temp = image->data[i];
image->data[i] = image->data[i+2];
image->data[i+2] = temp;
}

// we're done.
return 1;
}

// Load Bitmaps And Convert To Textures
void LoadGLTextures() {
// Load Texture
Image *image1;

// allocate space for texture
image1 = (Image *) malloc(sizeof(Image));

if (image1 == NULL)
{
printf("Fehler beim ansteuern von Speicher für das Bild.");
exit(0);
}

if (!ImageLoad("Texturen/Bild.bmp", image1))
{
exit(1);
}

// Create Textures
glGenTextures(1, &texture[0]);

// mipmapped texture
glBindTexture(GL_TEXTURE_2D, texture[0]); // 2d texture (x and y size)
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, image1->sizeX, image1->sizeY, GL_RGB, GL_UNSIGNED_BYTE, image1->data);
};

MeLLe
2003-12-08, 19:14:10
Original geschrieben von Ganon
glGenTextures(1, &texture[0]);
Mit glGenTextures() werden sogenannte Texture names generiert, d.h. damit legst du die Texturen an sich als Objekte im speicher erstmal an, die dann auf deine Polygone gepappt werden können.
Der erste Parameter gibt dabei an, wieviele Texture names du haben möchtest, und der zweite ist einfach ein Pointer auf das erste Element des Arrays, das die Texture names dann aufnimmt.
Für drei Texturen würdest du das dann so machen:
GLint texture[3];
glGenTextures(3, &texture[0]);

Original geschrieben von Ganon
glBindTexture(GL_TEXTURE_2D, texture[0]);
Damit setzt du texture[0] als derzeit aktive Textur fest, die bei nachfolgenden Operationen (Texture-Setup wie s.u., oder Rendering) verwendet wird.

Original geschrieben von Ganon
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, image1->sizeX, image1->sizeY, GL_RGB, GL_UNSIGNED_BYTE, image1->data);
Damit wird aus den Daten, die in image1 liegen, die eigentliche Textur mitsamt zugehören MipMaps erzeugt, und der derzeit aktiven (s.o.) Textur zugewiesen.

Für mehrere Texturen würdest du den Code wie folgt abändern:


CString texture_files[NUM_OF_TEXTURES];
Image *image_tmp;
GLint texture[NUM_OF_TEXTURES];

FillTextureFileArray(&texture_files[0]); // Pseudo-Funktion - füllt Array mit Textur-Dateinamen

glGenTextures(NUM_OF_TEXTURES, &texture[0]);
for(int i = 0; i < NUM_OF_TEXTURES; i++)
{
ImageLoad(texture_files[i],image_tmp);
glBindTexture(GL_TEXTURE_2D, texture[i]);
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, image_tmp->sizeX, image_tmp->sizeY, GL_RGB, GL_UNSIGNED_BYTE, image_tmp->data);
}

Ganon
2003-12-08, 21:47:36
Achso! Danke erst mal!

Ich werde es morgen mal probieren.

Ich melde mich dann wieder.

Aber ich hätte noch ne andere Frage zu einer (dummen?) Idee.

Wenn ich eine Klasse für die Texturen mache. Was wäre dann "besser":

1. Eine Klasse, bzw. ein Objekt die alle Texturen läd und aufnimmt

oder

2. Eine Klasse die eine Textur läd und aufnimmt und für jede Textur wird dann ein Objekt erstellt

Was wäre ökonomischer?

Danke. :)