Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this questionI'm wanting to add multiple textures to my scene I have one texture working but I don't know how to include other textures as well.
#include <windows.h>
#include <gl\gl.h>
#include <gl\glut.h>
#include <stdlib.h>
#include <iostream>
void init(void);
void display(void);
void keyboard(unsigned char, int, int);
void resize(int, int);
void drawcube(float, float, float, float, float, float, int);
int is_depth;
#define ROAD 0
struct Image
{
unsigned long size_x;
unsigned long size_y;
char *data;
};
typedef struct Image Image;
const int textureCount = 1;
Image myTextureData[textureCount];
GLuint theTexture[textureCount];
char* textureFilenames[textureCount] = {"road.bmp"};
int main (int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(600, 600);
glutInitWindowPosition(40, 40);
glutCreateWindow("3D World");
init();
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
glEnable(GL_TEXTURE_2D);
glutReshapeFunc(resize);
glutMainLoop();
return 0;
}
int imageLoader(const char *filename, Image *image)
{
FILE *file;
unsigned long size;
unsigned long i;
unsigned short int planes;
unsigned short int bpp;
char temp;
char finalName[80];
glTexCoord2f(1.开发者_如何学Python0, 0.0);
strcpy(finalName, "" );
strcat(finalName, filename);
if ((file = fopen(finalName, "rb"))==NULL)
{
printf("File Not Found : %s\n",finalName);
return 0;
}
fseek(file, 18, SEEK_CUR);
glTexCoord2f(1.0, 0.0);
if ((i = fread(&image->size_x, 4, 1, file)) != 1)
{
printf("Error reading width from %s.\n", finalName);
return 0;
}
if ((i = fread(&image->size_y, 4, 1, file)) != 1)
{
printf("Error reading height from %s.\n", finalName);
return 0;
}
size = image->size_x * image->size_y * 3;
if ((fread(&planes, 2, 1, file)) != 1)
{
printf("Error reading planes from %s.\n", finalName);
return 0;
}
if (planes != 1)
{
printf("Planes from %s is not 1: %u\n", finalName, planes);
return 0;
}
if ((i = fread(&bpp, 2, 1, file)) != 1)
{
printf("Error reading bpp from %s.\n", finalName);
return 0;
}
if (bpp != 24)
{
printf("Bpp from %s is not 24: %u\n", finalName, bpp);
return 0;
}
fseek(file, 24, SEEK_CUR);
image->data = (char *) malloc(size);
if (image->data == NULL)
{
printf("Error allocating memory for color-corrected image data");
return 0;
}
if ((i = fread(image->data, size, 1, file)) != 1)
{
printf("Error reading image data from %s.\n", finalName);
return 0;
}
for (i=0;i<size;i+=3)
{
temp = image->data[i];
image->data[i] = image->data[i+2];
image->data[i+2] = temp;
}
return 1;
}
void textureLoader()
{
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
for(int k=0; k < textureCount; k++)
{
if(!imageLoader(textureFilenames[k], &myTextureData[k]))
exit(1);
glGenTextures(1, &theTexture[k]);
glBindTexture(GL_TEXTURE_2D, theTexture[k]);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, myTextureData[k].size_x, myTextureData[k].size_y, GL_RGB, GL_UNSIGNED_BYTE, myTextureData[k].data);
}
}
void init(void)
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_MODELVIEW);
is_depth = 1;
}
void display(void)
{
if (is_depth)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
else
glClear(GL_COLOR_BUFFER_BIT);
textureLoader();
glBegin(GL_QUADS);
glTexCoord2f(0.0,0.0);
glVertex3f(-75.0, 0.0, -400.0);
glTexCoord2f(0.0,1.0);
glVertex3f(-75.0, 0.0, 100.0);
glTexCoord2f(1.0,0.0);
glVertex3f(75.0, 0.0, 100.0);
glTexCoord2f(1.0,1.0);
glVertex3f(75.0, 0.0, -400.0);
drawcube(-70,15,72,8,15,28,4);
drawcube(-70,10,10,8,10,28,0);
drawcube(-70,15,-45,8,15,18,0);
drawcube(-70,15,-85,8,15,18,0);
drawcube(-70,35,-125,8,35,12,0);
drawcube(-70,9,-170,8,9,28,0);
drawcube(-70,15,-220,8,15,18,0);
drawcube(-70,15,-265,8,15,28,0);
drawcube(-70,15,-330,8,15,28,0);
drawcube(67,15,72,8,15,28,0);
drawcube(67,10,10,8,10,28,0);
drawcube(67,15,-45,8,15,18,0);
drawcube(67,15,-85,8,15,18,0);
drawcube(67,35,-125,8,35,12,0);
drawcube(67,9,-170,8,9,28,0);
drawcube(67,15,-220,8,15,18,0);
drawcube(67,15,-265,8,15,28,0);
drawcube(67,15,-330,8,15,28,0);
drawcube(-33,18,-364,25,18,10,0);
drawcube(25,28,-364,30,28,10,0);
drawcube(25,28,90,30,28,10,0);
drawcube(-33,18,90,25,18,10,0);
drawcube(0,60,-125,18,60,22,0);
drawcube(0,25,-225,8,25,28,0);
drawcube(0,25,0,8,25,28,0);
glEnd();
glutSwapBuffers();
}
void keyboard(unsigned char key, int x, int y)
{
switch (key)
{
case 'a':
glTranslatef(5.0, 0.0, 0.0);
break;
case 'd':
glTranslatef(-5.0, 0.0, 0.0);
break;
case 'w':
glTranslatef(0.0, 0.0, 5.0);
break;
case 's':
glTranslatef(0.0, 0.0, -5.0);
break;
}
display();
}
void resize(int width, int height)
{
if (height == 0) height = 1;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, width / height, 1.0, 400.0);
glTranslatef(0.0, -5.0, -150.0);
glMatrixMode(GL_MODELVIEW);
}
void drawcube(float xc, float yc, float zc, float x_offset, float y_offset, float z_offset, int color)
{
switch(color)
{
case 1:
glColor3f(1.0,0.0,0.0);
break;
case 2:
glColor3f(0.0,1.0,0.0);
break;
case 3:
glColor3f(0.0,0.0,1.0);
break;
}
glBegin(GL_QUADS);
glVertex3f(xc - x_offset,yc - y_offset,zc - z_offset);
glVertex3f(xc + x_offset,yc - y_offset,zc - z_offset);
glVertex3f(xc + x_offset,yc + y_offset,zc - z_offset);
glVertex3f(xc - x_offset,yc + y_offset,zc - z_offset);
glVertex3f(xc + x_offset,yc + y_offset,zc - z_offset);
glVertex3f(xc + x_offset,yc + y_offset,zc + z_offset);
glVertex3f(xc + x_offset,yc - y_offset,zc + z_offset);
glVertex3f(xc + x_offset,yc - y_offset,zc - z_offset);
glVertex3f(xc - x_offset,yc - y_offset,zc + z_offset);
glVertex3f(xc - x_offset,yc - y_offset,zc - z_offset);
glVertex3f(xc - x_offset,yc + y_offset,zc - z_offset);
glVertex3f(xc - x_offset,yc + y_offset,zc + z_offset);
glVertex3f(xc + x_offset,yc + y_offset,zc - z_offset);
glVertex3f(xc - x_offset,yc + y_offset,zc - z_offset);
glVertex3f(xc - x_offset,yc + y_offset,zc + z_offset);
glVertex3f(xc + x_offset,yc + y_offset,zc + z_offset);
glVertex3f(xc - x_offset,yc - y_offset,zc + z_offset);
glVertex3f(xc + x_offset,yc - y_offset,zc + z_offset);
glVertex3f(xc + x_offset,yc - y_offset,zc - z_offset);
glVertex3f(xc - x_offset,yc - y_offset,zc - z_offset);
glVertex3f(xc + x_offset,yc + y_offset,zc + z_offset);
glVertex3f(xc - x_offset,yc + y_offset,zc + z_offset);
glVertex3f(xc - x_offset,yc - y_offset,zc + z_offset);
glVertex3f(xc + x_offset,yc - y_offset,zc + z_offset);
glEnd();
}
I'll just comment your code
#include <windows.h>
#include <gl\gl.h>
#include <gl\glut.h>
#include <stdlib.h>
#include <iostream>
void init(void);
void display(void);
void keyboard(unsigned char, int, int);
void resize(int, int);
void drawcube(float, float, float, float, float, float, int);
int is_depth;
#define ROAD 0
struct Image
{
unsigned long size_x;
unsigned long size_y;
char *data;
};
typedef struct Image Image;
const int textureCount = 1;
You're using a const int
for array sizeing. This tells me, you're using C++, so why don't you use STL std::vector or std::list for this?
Image myTextureData[textureCount];
GLuint theTexture[textureCount];
char* textureFilenames[textureCount] = {"road.bmp"};
int main (int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(600, 600);
glutInitWindowPosition(40, 40);
glutCreateWindow("3D World");
init();
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
glEnable(GL_TEXTURE_2D);
OpenGL state is set on demand. That glEnable makes no sense here.
glutReshapeFunc(resize);
glutMainLoop();
return 0;
}
int imageLoader(const char *filename, Image *image)
{
FILE *file;
unsigned long size;
unsigned long i;
unsigned short int planes;
unsigned short int bpp;
char temp;
char finalName[80];
glTexCoord2f(1.0, 0.0);
WTF?! What for do you call glTexCoord
in the texture loader? It's a drawing command.
strcpy(finalName, "" );
strcat(finalName, filename);
WTF?! what do you copy filename
for? Also 80 characters will probably not be sufficient.
if ((file = fopen(finalName, "rb"))==NULL)
{
A file not being properly opened can have a lot more reasons than just a wrong path.
printf("File Not Found : %s\n",finalName);
return 0;
}
fseek(file, 18, SEEK_CUR);
You shouldn't mindlessly try to read a file, assuming it is what you expect. Binary files, like the DIB you're trying to read here have headers for a reason, so you should definitely read and parse this header, too!
glTexCoord2f(1.0, 0.0);
Again?!
if ((i = fread(&image->size_x, 4, 1, file)) != 1)
{
printf("Error reading width from %s.\n", finalName);
return 0;
}
if ((i = fread(&image->size_y, 4, 1, file)) != 1)
{
printf("Error reading height from %s.\n", finalName);
return 0;
}
You're reading values from a file, assuming your system's endianess and alignment rule match the file format? You must've got balls of steel!
size = image->size_x * image->size_y * 3;
Integer overflow, yeah! You just made your program exploitable.
if ((fread(&planes, 2, 1, file)) != 1)
{
printf("Error reading planes from %s.\n", finalName);
return 0;
}
if (planes != 1)
{
printf("Planes from %s is not 1: %u\n", finalName, planes);
return 0;
}
if ((i = fread(&bpp, 2, 1, file)) != 1)
{
printf("Error reading bpp from %s.\n", finalName);
return 0;
}
Again reading binary values w/o properly caring for endianess and alignment...
if (bpp != 24)
{
printf("Bpp from %s is not 24: %u\n", finalName, bpp);
return 0;
}
fseek(file, 24, SEEK_CUR);
Why do you perform a relative seek here? The BITMAPFILEHEADER (you know those 18 bytes you mindlessly skipped previously) tells you where exactly the pixeldata starts.
image->data = (char *) malloc(size);
if (image->data == NULL)
{
printf("Error allocating memory for color-corrected image data");
return 0;
}
if ((i = fread(image->data, size, 1, file)) != 1)
{
printf("Error reading image data from %s.\n", finalName);
return 0;
}
BTW: You should close the file if aborting.
for (i=0;i<size;i+=3)
{
temp = image->data[i];
image->data[i] = image->data[i+2];
image->data[i+2] = temp;
}
This is not doing a colour correction, it just swaps elements. Newer OpenGL directly support the BGR alignment of DIB files.
return 1;
Still not closing the file...
}
void textureLoader()
{
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
for(int k=0; k < textureCount; k++)
{
if(!imageLoader(textureFilenames[k], &myTextureData[k]))
exit(1);
Well, okay, doing it through those global arrays does the job. But seriously: textureLoader should return the texture ID of the loaded texture.
glGenTextures(1, &theTexture[k]);
glBindTexture(GL_TEXTURE_2D, theTexture[k]);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, myTextureData[k].size_x, myTextureData[k].size_y, GL_RGB, GL_UNSIGNED_BYTE, myTextureData[k].data);
}
}
void init(void)
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_MODELVIEW);
is_depth = 1;
}
What you "initialize" here belongs into the display function.
void display(void)
{
if (is_depth)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
else
glClear(GL_COLOR_BUFFER_BIT);
WTF was this? What effect do you think does this have? Yes there are multipass techniques clearing the framebuffer only partially, but you're not doing such. Get rid of is_depth
.
textureLoader();
textureLoader
belongs into init
; loading textures and vertex buffer objects is the only usefull thing an OpenGL "initializer" can do anyways. With more experience you start to do such things from the display routing as well, to implement stuff like staggered texture loading, so that you can navigate large scenes without loading delays.
Something important is missing here: You don't set up your matrices. Both the projection and the modelview transformation matrices should be set in the rendering function.
So you want to draw textured quads. So why don't you:
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, theTexture[0]);
or whichever ID you want to use here?glBegin(GL_QUADS); glTexCoord2f(0.0,0.0); glVertex3f(-75.0, 0.0, -400.0); glTexCoord2f(0.0,1.0); glVertex3f(-75.0, 0.0, 100.0); glTexCoord2f(1.0,0.0); glVertex3f(75.0, 0.0, 100.0); glTexCoord2f(1.0,1.0); glVertex3f(75.0, 0.0, -400.0);
Looking good so far, except that you don't supply normals. You'll need those for lighting.
But WTF is this:
drawcube(-70,15,72,8,15,28,4);
drawcube(-70,10,10,8,10,28,0);
drawcube(-70,15,-45,8,15,18,0);
drawcube(-70,15,-85,8,15,18,0);
drawcube(-70,35,-125,8,35,12,0);
drawcube(-70,9,-170,8,9,28,0);
drawcube(-70,15,-220,8,15,18,0);
drawcube(-70,15,-265,8,15,28,0);
drawcube(-70,15,-330,8,15,28,0);
drawcube(67,15,72,8,15,28,0);
drawcube(67,10,10,8,10,28,0);
drawcube(67,15,-45,8,15,18,0);
drawcube(67,15,-85,8,15,18,0);
drawcube(67,35,-125,8,35,12,0);
drawcube(67,9,-170,8,9,28,0);
drawcube(67,15,-220,8,15,18,0);
drawcube(67,15,-265,8,15,28,0);
drawcube(67,15,-330,8,15,28,0);
drawcube(-33,18,-364,25,18,10,0);
drawcube(25,28,-364,30,28,10,0);
drawcube(25,28,90,30,28,10,0);
drawcube(-33,18,90,25,18,10,0);
drawcube(0,60,-125,18,60,22,0);
drawcube(0,25,-225,8,25,28,0);
drawcube(0,25,0,8,25,28,0);
You're in a glBegin(…)...glEnd()
block here, so the only valid OpenGL calls are glColor, glNormal, glTexCoord, glVertexAttrix, glVertex and glEnd. So let's see what's in drawcube
then...
glEnd();
glutSwapBuffers();
}
void keyboard(unsigned char key, int x, int y)
{
switch (key)
{
case 'a':
glTranslatef(5.0, 0.0, 0.0);
break;
case 'd':
glTranslatef(-5.0, 0.0, 0.0);
break;
case 'w':
glTranslatef(0.0, 0.0, 5.0);
break;
case 's':
glTranslatef(0.0, 0.0, -5.0);
break;
}
display();
}
NO! NO! NO! This is not how OpenGL works. glTranslate
is a matrix manipulation function and it's only proper use is in the context of a rendering pass. You're just messing with the OpenGL state here.
void resize(int width, int height)
{
if (height == 0) height = 1;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, width / height, 1.0, 400.0);
glTranslatef(0.0, -5.0, -150.0);
glMatrixMode(GL_MODELVIEW);
This stuff belongs into display. I know, many (most) tutorials write it that way, like you, but trust me: As soon as you want to implement something like a HUD or multipass rendering setting the projection in the resize handler will bite you.
}
void drawcube(float xc, float yc, float zc, float x_offset, float y_offset, float z_offset, int color)
{
Ahh, the drawcube function
switch(color)
{
case 1:
glColor3f(1.0,0.0,0.0);
break;
case 2:
glColor3f(0.0,1.0,0.0);
break;
case 3:
glColor3f(0.0,0.0,1.0);
break;
}
glBegin(GL_QUADS);
You're calling drawcube
from within a glBegin(…)...glEnd()
block, but then try to open another block. This is an OpenGL error. glBegin(…)...glEnd()
don't nest.
glVertex3f(xc - x_offset,yc - y_offset,zc - z_offset);
glVertex3f(xc + x_offset,yc - y_offset,zc - z_offset);
glVertex3f(xc + x_offset,yc + y_offset,zc - z_offset);
glVertex3f(xc - x_offset,yc + y_offset,zc - z_offset);
glVertex3f(xc + x_offset,yc + y_offset,zc - z_offset);
glVertex3f(xc + x_offset,yc + y_offset,zc + z_offset);
glVertex3f(xc + x_offset,yc - y_offset,zc + z_offset);
glVertex3f(xc + x_offset,yc - y_offset,zc - z_offset);
glVertex3f(xc - x_offset,yc - y_offset,zc + z_offset);
glVertex3f(xc - x_offset,yc - y_offset,zc - z_offset);
glVertex3f(xc - x_offset,yc + y_offset,zc - z_offset);
glVertex3f(xc - x_offset,yc + y_offset,zc + z_offset);
glVertex3f(xc + x_offset,yc + y_offset,zc - z_offset);
glVertex3f(xc - x_offset,yc + y_offset,zc - z_offset);
glVertex3f(xc - x_offset,yc + y_offset,zc + z_offset);
glVertex3f(xc + x_offset,yc + y_offset,zc + z_offset);
glVertex3f(xc - x_offset,yc - y_offset,zc + z_offset);
glVertex3f(xc + x_offset,yc - y_offset,zc + z_offset);
glVertex3f(xc + x_offset,yc - y_offset,zc - z_offset);
glVertex3f(xc - x_offset,yc - y_offset,zc - z_offset);
glVertex3f(xc + x_offset,yc + y_offset,zc + z_offset);
glVertex3f(xc - x_offset,yc + y_offset,zc + z_offset);
glVertex3f(xc - x_offset,yc - y_offset,zc + z_offset);
glVertex3f(xc + x_offset,yc - y_offset,zc + z_offset);
Wasn't your question how to use textures? I don't see calls to glTexCoord
up there...
glEnd();
}
You need to enable the texture which you want to be rendered.
Take a look into this example how it is done. The example might be a bit complex, but it seams to be doing exactly what you are trying to do.
EDIT
btw do not create textures every time you want to render them. You just need to create them once, and use them later on (enabled and bind to a texture before rendering).
精彩评论