opengl多个纹理

时间:2011-03-22 08:57:55

标签: c++ opengl textures

我想在我的场景中添加多个纹理我有一个纹理工作,但我不知道如何包含其他纹理。

#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();
}

2 个答案:

答案 0 :(得分:18)

我只会评论你的代码

#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个字节)会告诉你pixeldata的确切位置。

    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:如果中止,你应该关闭文件。

    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);

WTF是这个?你觉得这有什么影响?是的,只有部分清除帧缓冲的多通道技术,但你没有这样做。摆脱is_depth

    textureLoader();

textureLoader属于init;加载纹理顶点缓冲区对象是OpenGL“初始化程序”无论如何都可以做的唯一有用的东西。有了更多的经验,你也可以从显示路由开始做这些事情,实现交错纹理加载等功能,这样你就可以在不加载延迟的情况下导航大型场景。

这里缺少重要的东西:你没有设置你的矩阵。 投影模型视图转换矩阵都应该在渲染函数中设置。

所以你想绘制纹理四边形。那你为什么不:

  • 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)
{

啊,画布函数

    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);

您正在drawcube块内调用glBegin(…)...glEnd(),但随后尝试打开另一个块。这是一个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();
}

http://www.osnews.com/story/19266/WTFs_m

答案 1 :(得分:0)

您需要启用要渲染的纹理。

看看this example它是如何完成的。这个例子可能有点复杂,但是接缝完全正是你要做的事情。

修改

顺便说一下,每次要渲染它们时都不会创建纹理。您只需创建一次,稍后再使用它们(在渲染之前启用并绑定到纹理)。