Basic Texturing...

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, &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.

It doesn’t look as though you call LoadBMP, if you arn’t thats probably your problem

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?

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(&bmfh, sizeof(BITMAPFILEHEADER), 1, texfile);
fread(&bmih, sizeof(BITMAPINFOHEADER), 1, texfile);
fread(&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, &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?

Isn’t it suppose to be

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

instead of

GLubyteimage[32][32][4];

because you have 24 bits BMP

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

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?

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.

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.