PDA

View Full Version : Basic Texturing...



Sephiroth
12-26-2001, 02:38 PM
OK, I've tried everything to get texturing working in my 3D engine, and it won't texture anything, so I am left with a bunch of solid white triangles! Here is my source thus far (note that until I get basic texturing up, I am trying to make a simple purple square surrounded by a green box for the image).



//Global Vars
GLubyte image[32][32][3];

//Initialize OpenGL!
BOOL InitGL(GLvoid)
{
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glFrontFace(GL_CCW);
glEnable(GL_TEXTURE_2D);
glShadeModel(GL_SMOOTH);
glClearColor(0.5f, 0.5f, 0.5f, 0.5f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

return TRUE;
}

//Create Our Texture
void LoadBMP()
{
for(short int loop = 0; loop < 32; loop++)
{
for(short int h_loop = 0; h_loop < 32; h_loop++)
{
image[loop][h_loop][0] = 255;
image[loop][h_loop][1] = 0;
image[loop][h_loop][2] = 255;
}
image[loop][0][0] = 0;
image[loop][0][1] = 255;
image[loop][0][2] = 0;
image[loop][31][0] = 0;
image[loop][31][1] = 255;
image[loop][31][2] = 0;
image[0][loop][0] = 0;
image[0][loop][1] = 255;
image[0][loop][2] = 0;
image[31][loop][0] = 0;
image[31][loop][1] = 255;
image[31][loop][2] = 0;
}

glGenTextures(1, &amp;texture[0]);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 32, 32, 0, GL_RGB, GL_UNSIGNED_BYTE, image);

return;
}

//Here's Where I Draw The Screen
BOOL DrawGLScene(GLvoid)
{
player.lx = player.xpos + cos(player.heading * (pi / 180)) * 2;
player.ly = player.ypos + sin(player.lookup * (pi / 180)) * 2;
player.lz = player.zpos + sin(player.heading * (pi / 180)) * 2;

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(player.xpos, player.ypos, player.zpos, player.lx, player.ly, player.lz, 0.0, 1.0, 0.0);
glBindTexture(GL_TEXTURE_2D, texture[0]);

for(unsigned long o_loop = 0; o_loop < area.numObjects; o_loop++)
{
for(int t_loop = 0; t_loop < area.object[o_loop].numTriangles; t_loop++)
{
glBegin(GL_TRIANGLES);
glNormal3f(0.0f, 0.0f, 1.0f);

glVertex3f(area.object[o_loop].triangle[t_loop].vertex[0].x, area.object[o_loop].triangle[t_loop].vertex[0].y, area.object[o_loop].triangle[t_loop].vertex[0].z);
glTexCoord2f(area.object[o_loop].triangle[t_loop].vertex[0].u, area.object[o_loop].triangle[t_loop].vertex[0].v);

glVertex3f(area.object[o_loop].triangle[t_loop].vertex[1].x, area.object[o_loop].triangle[t_loop].vertex[1].y, area.object[o_loop].triangle[t_loop].vertex[1].z);
glTexCoord2f(area.object[o_loop].triangle[t_loop].vertex[1].u, area.object[o_loop].triangle[t_loop].vertex[1].v);

glVertex3f(area.object[o_loop].triangle[t_loop].vertex[2].x, area.object[o_loop].triangle[t_loop].vertex[2].y, area.object[o_loop].triangle[t_loop].vertex[2].z);
glTexCoord2f(area.object[o_loop].triangle[t_loop].vertex[2].u, area.object[o_loop].triangle[t_loop].vertex[2].v);

glEnd();
}
}

return TRUE;
}

Now the level is loaded into "area" and properly displays all polygons, so I have marked that off the problem list. I also tried commenting my norml code and drawing a single triangle manually, and it didn't texture either. Does anybody know what's wrong here? All I need to do is finish texturing and add collision detection and the engine will work. I can add lighting and all the fancy doo-dads later :P.

chowe6685
12-26-2001, 05:30 PM
It doesn't look as though you call LoadBMP, if you arn't thats probably your problem

Sephiroth
12-26-2001, 06:00 PM
OK, youc an call me a f*cking idiot now. I had the line to call LoadBMP() in my level loading function commented! When I first wrote the function it had errors and I guess I forgot to un-comment it. Jesus, do I feel like an idiot. I call LoadBMP() only during level loading, which works so it wasn't pasted, lol! Thanks chowe, but the texture doesn't appear right on my triangles, and a few of those triangles come out solid gray. Any ideas?

Sephiroth
12-26-2001, 06:27 PM
I just found out something strange. LoadBMP only seems to work when called from InitGL(). I un-commented the line in LoadWorld() and deleted my call in InitGL() and everything was white again. I'm not worried about it right now though.
I am now trying to figure out how to load bitmaps and read in JUST the bitmap data. Here is how I am currently trying:



void LoadBMP()
{
GLubyte fixer;
GLubyte image[32][32][4];
FILE *texfile;
BITMAPFILEHEADER bmfh;
BITMAPINFOHEADER bmih;

texfile = fopen("Textures\\Tiles.bmp", "rb");
fread(&amp;bmfh, sizeof(BITMAPFILEHEADER), 1, texfile);
fread(&amp;bmih, sizeof(BITMAPINFOHEADER), 1, texfile);
fread(&amp;image, sizeof(image), 1, texfile);
fclose(texfile);

for(short int x_loop = 0; x_loop < 32; x_loop++)
{
for(short int y_loop = 0; y_loop < 32; y_loop++)
{
fixer = image[y_loop][x_loop][0];
image[y_loop][x_loop][0] = image[y_loop][x_loop][2];
image[y_loop][x_loop][2] = fixer;
}
}

glGenTextures(1, &amp;texture[0]);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);

return;
}

Tiles.bmp is the one from the windows directory, only saved as a 24bit bitmap instead of it's default format. Now when I load it, it textures my whole room, but it's all black with red, green, and blue dots scattered around instead of the brickish-looking thing it should be. How should I properly read the bits into my image[][][] array?

Questions Burner
12-26-2001, 08:32 PM
Isn't it suppose to be

GLubyte image[32][32][3];

instead of

GLubyteimage[32][32][4];

because you have 24 bits BMP

Heaven
12-27-2001, 05:49 AM
From what I read, Windows BMPs don't have an alpha channel. First I load the bitmap into a temporary buffer, then I copy that buffer to my texture adding a 4th byte for the alpha. This means I have to generate an alpha for each texture based on some kind of formula (i.e., color [0,0,0] becomes alpha 1.0f to make black pixels transparent).

If you want alpha in the image, use TGA image files. You can easily find a TGA loader on the net.

As far as why your code isn't working, Questions Burner had it right. You're loading 3 bytes per pixel into a 4 bytes per pixel buffer.

Try this:

void LoadBMP()
{
GLubyte fixer;
GLubyte temp[32][32][3];
GLubyte image[32][32][4];
FILE *texfile;
BITMAPFILEHEADER bmfh;
BITMAPINFOHEADER bmih;
texfile = fopen("Textures\\Tiles.bmp", "rb");
fread(&bmfh, sizeof(BITMAPFILEHEADER), 1, texfile);
fread(&bmih, sizeof(BITMAPINFOHEADER), 1, texfile);
fread(&image, sizeof(image), 1, texfile);
fclose(texfile);
for(int x=0; x < 32; x++)
{
for(int y=0; y < 32; y++)
{
GLubyte r=image[y][x][0]=temp[y][x][0];
GLubyte g=image[y][x][1]=temp[y][x][1];
GLubyte B=image[y][x][2]=temp[y][x][2];
if (r+g+b)
image[y][x][3]=0;
else
image[y][x][3]=255;
}
}
glGenTextures(1, &texture[0]);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
return;
}

Have you read any of NeHe's tutorials? He uses a glaux function to load the bitmap, and it looks a lot more elegant than your approach. Check it out here:
http://nehe.gamedev.net

I believe Tutorial #6 is when he starts doing texture stuff.

Hope the above helps.

Care,
Heaven http://www.knology.net/~heaven

Sephiroth
12-27-2001, 08:10 AM
Yeah I figured it out last night after I posted. I now properly load bitmaps, but they will NOT texture onto my triangles properly. How do I properly place a texture onto a triangle? I thought I had it figured out but I was mistaken, BIG-TIME! Here is a sample of how I am trying it:



//In drawing routine...

glBegin(GL_TRIANGLES);
glVertex3f(-256, 0, 256);
glTexCoord2f(0, 0);
glVertex3f(-256, 128, 256);
glTexCoord2f(0, 1);
glVertex3f(256, 128, 256);
glTexCoord2f(1, 1);

glVertex3f(-256, 0, 256);
glTexCoord2f(0, 0);
glVertex3f(256, 128, 256);
glTexCoord2f(1, 1);
glVertex3f(256, 0, 256);
glTexCoord2f(1, 0);

glEnd();

As you can probably figure out, that would draw a large rectangle that is 128 units tall, starting at -256 and going to 256 along the X axis. The way the textures wind up looking is as though they are triangular bitmaps! Anybody know what I am doing wrong?

Questions Burner
12-27-2001, 11:23 PM
If you want to draw rectangle, how about
using GL_QUADS and specify 4 vertexs and 4 texture coordinates.
And put glTexCoord2f before glVertex2f.
By the way, have you forgot to glBindTexture

Just some idea, hope this can fix the problems.

Sephiroth
12-28-2001, 07:26 AM
I'll try moving the texcoord in front of the vertex commands, but I am drawing triangles for a reason. Triangles draw faster than anything else, and on 90% of the video accelerators out there, a rectangle is broken down into two triangles before it is drawn anyway. Heck, all geometry is in most cases. This saves time, thus improving framerate, CPU/GPU usage, and allows slower machines to run it as well. Now I'll test that command swap...

Success! Aside from one triangle (which I probably didn't supply proper coordinates for), the texture loaded and applied properly! But let me tell you, a 32x32 image stretched onto a 512w x 128h wall does NOT look good, lol! Thanks for the help here people. Once i get collision-detection running, I will post a link to a small demo, but don't expect it to have any sound or music yet.