如何在openGL中使用纹理图像加载和填充立方体

时间:2015-11-29 18:17:01

标签: c opengl graphics textures glut

我有一个带有立方体的网格,我想用两种不同的颜色和3种不同的图像(.bmp)填充立方体。所以每个立方体都充满了颜色或图像。 我写了一个代码,当我按下<>按钮网格填充5种不同的颜色。任何人都可以告诉我如何更改我的代码以3个不同的图像(随机)填充网格? 这是我的代码:

void randomFilling();
void myprint();


struct square{
    int v1x, v1y;
    int v2x, v2y;
    int v3x, v3y;
    int v4x, v4y;
    int color;
};

struct square Squares[12][15];

struct flags{
    int b;
}flags;


void drawScene();

void findVerticesPosition(){
    int counter=0;

    for(int i=0; i<600; i+=40){
        for(int j=0; j<480; j+=40){
            Squares[j/40][i/40].v1x = i;
            Squares[j/40][i/40].v1y = j;
            Squares[j/40][i/40].v2x = i;
            Squares[j/40][i/40].v2y = j+40;
            Squares[j/40][i/40].v3x = i+40;
            Squares[j/40][i/40].v3y = j+40;
            Squares[j/40][i/40].v4x = i+40;
            Squares[j/40][i/40].v4y = j;
        }
    }

    for(int i=0; i<12; i++){
        for(int j=0; j<15; j++){
            Squares[i][j].color = rand()%5 + 1;
        }
    }


}



void handleKeypress(unsigned char key, int x, int y) {
    switch (key) {
        case 27: //Escape key
            exit(0);
        case 98: //b
            randomFilling();
            flags.b = 1;
            drawScene();
    }
}



void randomFilling(){
    int randomNumber;

    srand(time(NULL));
    //randomNumber = rand() % 5 + 1;

    for(int i=0; i<12; i++){
        for(int j=0; j<15; j++){
            randomNumber = Squares[i][j].color;
            if(randomNumber == 1){
                glBegin(GL_QUADS);
                glColor3f(1.0,0.9,0.1);
                glVertex2f(Squares[i][j].v1x, Squares[i][j].v1y);
                glVertex2f(Squares[i][j].v2x, Squares[i][j].v2y);
                glVertex2f(Squares[i][j].v3x, Squares[i][j].v3y);
                glVertex2f(Squares[i][j].v4x, Squares[i][j].v4y);
                glEnd();
            }
            else if(randomNumber == 2){
                 glBegin(GL_QUADS);
                 glColor3f(1.0,0.0,0.1);
                 glVertex2f(Squares[i][j].v1x, Squares[i][j].v1y);
                 glVertex2f(Squares[i][j].v2x, Squares[i][j].v2y);
                 glVertex2f(Squares[i][j].v3x, Squares[i][j].v3y);
                 glVertex2f(Squares[i][j].v4x, Squares[i][j].v4y);
                 glEnd();
            }
            else if(randomNumber == 3){
                glBegin(GL_QUADS);
                glColor3f(0,0.9,0.1);
                glVertex2f(Squares[i][j].v1x, Squares[i][j].v1y);
                glVertex2f(Squares[i][j].v2x, Squares[i][j].v2y);
                glVertex2f(Squares[i][j].v3x, Squares[i][j].v3y);
                glVertex2f(Squares[i][j].v4x, Squares[i][j].v4y);
                glEnd();
            }
            else if(randomNumber == 4){
                glBegin(GL_QUADS);
                glColor3f(0,0,1);
                glVertex2f(Squares[i][j].v1x, Squares[i][j].v1y);
                glVertex2f(Squares[i][j].v2x, Squares[i][j].v2y);
                glVertex2f(Squares[i][j].v3x, Squares[i][j].v3y);
                glVertex2f(Squares[i][j].v4x, Squares[i][j].v4y);
                glEnd();
            }
            else if(randomNumber == 5){
                glBegin(GL_QUADS);
                glColor3f(0,0.9,1);
                glVertex2f(Squares[i][j].v1x, Squares[i][j].v1y);
                glVertex2f(Squares[i][j].v2x, Squares[i][j].v2y);
                glVertex2f(Squares[i][j].v3x, Squares[i][j].v3y);
                glVertex2f(Squares[i][j].v4x, Squares[i][j].v4y);
                glEnd();
            }
            else{
                printf("WTF\n");
            }
        }
    }

}



//Initialize OpenGL 
void init(void) {
    glClearColor(1.0,1.0,1.0,1.0); 
    glMatrixMode(GL_PROJECTION); 
    gluOrtho2D(0.0,600.0,-60.0,480.0);  
    flags.b=0;
} 



void drawScene(void) {
    glClear(GL_COLOR_BUFFER_BIT);  
    glColor3f(0.0,0.0,0.0); 
    //glPointSize(3.0);  
    if(flags.b==1){
        randomFilling();    //------------
    }
    glColor3f(0,0,0);
    glBegin(GL_LINES);
    for(int i = 0; i <= 600; i += 40)
    {
        glVertex2f((float)i, 0.0f);
        glVertex2f((float)i, 480.0f);
        glVertex2f(0.0f, (float)i);
        glVertex2f(600.0f, (float)i);
    }
    glEnd();


    glFlush();
} 



int main(int argc, char**argv) {
    findVerticesPosition();
    //myprint();
    glutInit(&argc, argv);  
    glutInitWindowPosition(300,80); 
    glutInitWindowSize(600,540); 
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); 

    glutCreateWindow("BraXaPsa II"); 
    init(); 
    glutDisplayFunc(drawScene);
    //glutDisplayFunc(randomFilling);
    glutKeyboardFunc(handleKeypress);
    glutMainLoop();
}

1 个答案:

答案 0 :(得分:0)

这里我发布代码来显示图像(纹理)而不是颜色。

// relative path to texture bitmaps
char* texture_names[] = {
    "textures\\grass.tga", 
    "textures\\wood\\brown wood.tga",
    "textures\\ceiling.tga"
};

void randomFilling();
void myprint();


struct square{
    int v1x, v1y;
    int v2x, v2y;
    int v3x, v3y;
    int v4x, v4y;
    int texture;
};

struct square Squares[12][15];

struct flags{
    int b;
}flags;


void drawScene();

void findVerticesPosition(){
    int counter=0;

    for(int i=0; i<600; i+=40){
        for(int j=0; j<480; j+=40){
            Squares[j/40][i/40].v1x = i;
            Squares[j/40][i/40].v1y = j;
            Squares[j/40][i/40].v2x = i;
            Squares[j/40][i/40].v2y = j+40;
            Squares[j/40][i/40].v3x = i+40;
            Squares[j/40][i/40].v3y = j+40;
            Squares[j/40][i/40].v4x = i+40;
            Squares[j/40][i/40].v4y = j;
        }
    }

    for(int i=0; i<12; i++){
        for(int j=0; j<15; j++){
            Squares[i][j].texture = rand()%3;
        }
    }


}



void handleKeypress(unsigned char key, int x, int y) {
    switch (key) {
        case 27: //Escape key
            exit(0);
        case 98: //b
            randomFilling();
            flags.b = 1;
            drawScene();
    }
}

// creating texture objects array
GLuint g_pnTextures[3];


void randomFilling(){

    for(int i=0; i<12; i++){
        for(int j=0; j<15; j++){

            glColor3f(1.0f, 1.0f, 1.0f);

            glBindTexture(GL_TEXTURE_2D, g_pnTextures[Squares[i][j].texture]);

            glBegin(GL_QUADS);
            // specify texture coords
            glTexCoord2f(0.0f, 0.0f);
            glVertex2f(Squares[i][j].v1x, Squares[i][j].v1y);
            // specify texture coords
            glTexCoord2f(0.0f, 1.0f);
            glVertex2f(Squares[i][j].v2x, Squares[i][j].v2y);
            // specify texture coords
            glTexCoord2f(1.0f, 1.0f);
            glVertex2f(Squares[i][j].v3x, Squares[i][j].v3y);
            // specify texture coords
            glTexCoord2f(1.0f, 0.0f);
            glVertex2f(Squares[i][j].v4x, Squares[i][j].v4y);

            glEnd();
        }
    }

}




//Initialize OpenGL 
void init(void) {

    GLbyte* pImage = NULL;
    GLint width = 0;
    GLint height = 0;
    GLint components = 0;
    GLenum format;

    glClearColor(1.0,1.0,1.0,1.0); 
    glMatrixMode(GL_PROJECTION); 
    gluOrtho2D(0.0,600.0,-60.0,480.0);  
    flags.b=0;

     // Generate texture object
    glGenTextures(3, g_pnTextures);

    for (int i = 0; i < 3; i++)
    {
            // bind current texture object
        glBindTexture(GL_TEXTURE_2D,g_pnTextures[i]);

            // load texture data
        pImage = gltLoadTGA(texture_names[i],&width,&height,&components,&format);

        glTexParameteri(GL_TEXTURE_2D,GL_GENERATE_MIPMAP,GL_TRUE);

        printf("texture: \"%s\" - %p\n",texture_names[i],pImage);
             // Load texture data to video memory
        glTexImage2D(GL_TEXTURE_2D,0,GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
            width,height,0,format,GL_UNSIGNED_BYTE,pImage);

        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_MAG_FILTER,GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_BASE_LEVEL,0);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAX_LEVEL,8);

        glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE);
        glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB,GL_MODULATE);

        delete [] pImage;
        pImage = NULL;
    }

    glEnable(GL_TEXTURE_2D);
} 



void drawScene(void) {
    glClear(GL_COLOR_BUFFER_BIT);  
    glColor3f(0.0,0.0,0.0); 
    //glPointSize(3.0);  
    if(flags.b==1){
        randomFilling();    //------------
    }
    glColor3f(0,0,0);
    glBegin(GL_LINES);
    for(int i = 0; i <= 600; i += 40)
    {
        glVertex2f((float)i, 0.0f);
        glVertex2f((float)i, 480.0f);
        glVertex2f(0.0f, (float)i);
        glVertex2f(600.0f, (float)i);
    }
    glEnd();


    glFlush();
} 



int main(int argc, char**argv) {
    findVerticesPosition();
    //myprint();
    glutInit(&argc, argv);  
    glutInitWindowPosition(300,80); 
    glutInitWindowSize(600,540); 
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); 

    glutCreateWindow("BraXaPsa II"); 
    init(); 
    glutDisplayFunc(drawScene);
    //glutDisplayFunc(randomFilling);
    glutKeyboardFunc(handleKeypress);
    glutMainLoop();

    // Unload texture data
    glDeleteTextures(3, g_pnTextures);
}

结果如下:

enter image description here

两个基本部分是将纹理加载到内存中,并将纹理坐标指定为基元,以便进行适当的纹理包装。

此处显示纹理加载过程。

    for (int i = 0; i < 3; i++)
    {
            // bind current texture object
        glBindTexture(GL_TEXTURE_2D,g_pnTextures[i]);

            // load texture data
        pImage = gltLoadTGA(texture_names[i],&width,&height,&components,&format);

        glTexParameteri(GL_TEXTURE_2D,GL_GENERATE_MIPMAP,GL_TRUE);

        printf("texture: \"%s\" - %p\n",texture_names[i],pImage);
             // Load texture data to video memory
        glTexImage2D(GL_TEXTURE_2D,0,GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
            width,height,0,format,GL_UNSIGNED_BYTE,pImage);

        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_MAG_FILTER,GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_BASE_LEVEL,0);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAX_LEVEL,8);

        glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE);
        glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB,GL_MODULATE);

        delete [] pImage;
        pImage = NULL;
    }

纹理坐标maping过程。

        glBegin(GL_QUADS);
        // specify texture coords
        glTexCoord2f(0.0f, 0.0f);
        glVertex2f(Squares[i][j].v1x, Squares[i][j].v1y);
        // specify texture coords
        glTexCoord2f(0.0f, 1.0f);
        glVertex2f(Squares[i][j].v2x, Squares[i][j].v2y);
        // specify texture coords
        glTexCoord2f(1.0f, 1.0f);
        glVertex2f(Squares[i][j].v3x, Squares[i][j].v3y);
        // specify texture coords
        glTexCoord2f(1.0f, 0.0f);
        glVertex2f(Squares[i][j].v4x, Squares[i][j].v4y);

        glEnd();

因为您无法直接加载tga位图。我发布代码来处理这个问题。

// Define targa header.
#pragma pack(1)
typedef struct
    {
    GLbyte  identsize;              // Size of ID field that follows header (0)
    GLbyte  colorMapType;           // 0 = None, 1 = paletted
    GLbyte  imageType;              // 0 = none, 1 = indexed, 2 = rgb, 3 = grey, +8=rle
    unsigned short  colorMapStart;          // First colour map entry
    unsigned short  colorMapLength;         // Number of colors
    unsigned char   colorMapBits;   // bits per palette entry
    unsigned short  xstart;                 // image x origin
    unsigned short  ystart;                 // image y origin
    unsigned short  width;                  // width in pixels
    unsigned short  height;                 // height in pixels
    GLbyte  bits;                   // bits per pixel (8 16, 24, 32)
    GLbyte  descriptor;             // image descriptor
    } TGAHEADER;
#pragma pack(8)

GLbyte *gltLoadTGA(const char *szFileName, GLint *iWidth, GLint *iHeight, GLint *iComponents, GLenum *eFormat)
    {
    FILE *pFile;            // File pointer
    TGAHEADER tgaHeader;        // TGA file header
    unsigned long lImageSize;       // Size in bytes of image
    short sDepth;           // Pixel depth;
    GLbyte  *pBits = NULL;          // Pointer to bits

    // Default/Failed values
    *iWidth = 0;
    *iHeight = 0;
    *eFormat = GL_BGR_EXT;
    *iComponents = GL_RGB8;

    // Attempt to open the fil
    pFile = fopen(szFileName, "rb");
    if(pFile == NULL)
        return NULL;

    // Read in header (binary)
    fread(&tgaHeader, 18/* sizeof(TGAHEADER)*/, 1, pFile);

    // Do byte swap for big vs little endian
#ifdef __APPLE__
    BYTE_SWAP(tgaHeader.colorMapStart);
    BYTE_SWAP(tgaHeader.colorMapLength);
    BYTE_SWAP(tgaHeader.xstart);
    BYTE_SWAP(tgaHeader.ystart);
    BYTE_SWAP(tgaHeader.width);
    BYTE_SWAP(tgaHeader.height);
#endif


    // Get width, height, and depth of texture
    *iWidth = tgaHeader.width;
    *iHeight = tgaHeader.height;
    sDepth = tgaHeader.bits / 8;

    // Put some validity checks here. Very simply, I only understand
    // or care about 8, 24, or 32 bit targa's.
    if(tgaHeader.bits != 8 && tgaHeader.bits != 24 && tgaHeader.bits != 32)
        return NULL;

    // Calculate size of image buffer
    lImageSize = tgaHeader.width * tgaHeader.height * sDepth;

    // Allocate memory and check for success
    pBits = new GLbyte[lImageSize];
    if(pBits == NULL)
        return NULL;

    // Read in the bits
    // Check for read error. This should catch RLE or other 
    // weird formats that I don't want to recognize
    if(fread(pBits, lImageSize, 1, pFile) != 1)
        {
        free(pBits);
        return NULL;
        }

    // Set OpenGL format expected
    switch(sDepth)
        {
        case 3:     // Most likely case
            *eFormat = GL_BGR_EXT;
            *iComponents = GL_RGB8;
            break;
        case 4:
            *eFormat = GL_BGRA_EXT;
            *iComponents = GL_RGBA8;
            break;
        case 1:
            *eFormat = GL_LUMINANCE;
            *iComponents = GL_LUMINANCE8;
            break;
        };


    // Done with File
    fclose(pFile);

    // Return pointer to image data
    return pBits;
    }