opengl多个纹理[关闭]
Posted
技术标签:
【中文标题】opengl多个纹理[关闭]【英文标题】:opengl multiple textures [closed] 【发布时间】:2011-03-22 08:57:55 【问题描述】:我想在我的场景中添加多个纹理我有一个纹理正在工作,但我不知道如何也包含其他纹理。
#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.0, 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();
【问题讨论】:
我已经格式化了代码,但我无法想象这会引起多大的吸引力——要求人们重写一个 big 代码块,用一个简单的 "请让它做我想做的事。”不太可能走得很远。当您尝试加载更多纹理时,您确实需要将问题缩小到遇到的问题,并将代码减少到可以证明问题的最小数量。 我要求为我的drawbox函数添加第二个结构更好吗? opengl texturing的可能重复 【参考方案1】:我只会评论你的代码
#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;
您正在使用const int
进行数组大小调整。这告诉我,您使用的是 C++,那么为什么不为此使用 STL std::vector 或 std::list 呢?
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 状态是按需设置的。那个 glEnable 在这里没有意义。
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?!你在纹理 loader 中调用 glTexCoord
是为了什么?这是一个绘图命令。
strcpy(finalName, "" );
strcat(finalName, filename);
WTF?!你复制filename
做什么?此外,80 个字符可能还不够。
if ((file = fopen(finalName, "rb"))==NULL)
文件未正确打开可能有更多原因,而不仅仅是路径错误。
printf("File Not Found : %s\n",finalName);
return 0;
fseek(file, 18, SEEK_CUR);
您不应该盲目地尝试读取文件,假设它是您所期望的。二进制文件,例如您在此处尝试读取的 DIB 具有标头是有原因的,因此您也绝对应该阅读并解析此标头!
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);
为什么要在这里进行相对搜索? BITMAPFILEHEADER(你知道你之前无意跳过的那 18 个字节)告诉你像素数据的确切开始位置。
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;
这不是进行颜色校正,它只是交换元素。较新的OpenGL直接支持DIB文件的BGR对齐。
return 1;
仍然没有关闭文件...
void textureLoader()
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
for(int k=0; k < textureCount; k++)
if(!imageLoader(textureFilenames[k], &myTextureData[k]))
exit(1);
好吧,通过这些全局数组来完成这项工作。但说真的:textureLoader 应该返回已加载纹理的纹理 ID。
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);
这是什么鬼?你认为这有什么影响?是的,有多通道技术仅部分清除帧缓冲区,但您没有这样做。摆脱is_depth
。
textureLoader();
textureLoader
属于init
;加载 textures 和 vertex buffer objects 是 OpenGL“初始化程序”无论如何都可以做的唯一有用的事情。随着经验的增加,您也开始从显示路由开始做这些事情,实现交错纹理加载等东西,这样您就可以在没有加载延迟的情况下导航大型场景。
这里缺少一些重要的东西:您没有设置矩阵。 projection 和 modelview 变换矩阵都应该在渲染函数中设置。
所以你想绘制带纹理的四边形。那你为什么不呢:
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, theTexture[0]);
或您想在此处使用的任何 ID?
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);
到目前为止看起来不错,只是您不提供法线。您将需要那些用于照明。
但是WTF是这样的:
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);
您在此处处于glBegin(…)...glEnd()
块中,因此唯一有效的 OpenGL 调用是 glColor、glNormal、glTexCoord、glVertexAttrix、glVertex 和 glEnd。那么让我们看看drawcube
中的内容......
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();
不!不!不! 这不是 OpenGL 的工作方式。 glTranslate
是一个矩阵操作函数,只有在渲染通道的上下文中才能正确使用。你只是在搞乱 OpenGL 的状态。
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);
这东西属于陈列。我知道,许多(大多数)教程都是这样写的,就像你一样,但相信我:只要你想实现像 HUD 或多通道渲染设置这样的东西,调整大小处理程序中的投影就会咬你。
void drawcube(float xc, float yc, float zc, float x_offset, float y_offset, float z_offset, int color)
啊,drawcube函数
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);
您在 glBegin(…)...glEnd()
块内调用 drawcube
,但随后尝试打开另一个块。这是一个 OpenGL 错误。 glBegin(…)...glEnd()
不要嵌套。
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);
您的问题不是如何使用纹理吗?我没有看到上面对glTexCoord
的呼叫...
glEnd();
【讨论】:
对代码的彻底总结表示敬意,+1。【参考方案2】:您需要启用要渲染的纹理。
看看this example 是如何完成的。这个例子可能有点复杂,但它似乎正在做你想做的事情。
编辑
顺便说一句,每次你想要渲染它们时不要创建纹理。您只需要创建一次,然后再使用它们(在渲染之前启用并绑定到纹理)。
【讨论】:
以上是关于opengl多个纹理[关闭]的主要内容,如果未能解决你的问题,请参考以下文章