• OpenGL 纹理映射 画三维de篱笆


    以上是我今天练习的一段纹理贴图程序的效果图

    今天是学习OpenGL第九天,一天一个小例子,写了九段程序了,一直以来都想着要为自己画得三维图 变得 真实一点。

    这一个小程序算是向这一个小目标更加接近了一点。

    但是也发现蛮多问题。 ------------希望能够得到 有经验的朋友指点

    1.OpenGL的各种状态,在设置Projection状态的时候做了什么, 能做什么,

    modelView 状态又能做什么?viewport是干嘛用的?这些状态搞不清楚 做什么事情的时候需要转变状态。设定错了出不来想要的 openGL也不会提示。真是无奈。

    2.Projection状态时的坐标规则。view 状态。

    3.gluPerspective 视线角稍微容易设定一点,可是 gluLookAt 这一大堆参数的用处倒是知道,只是自己设定的时候还是不知道设定 它 为自己想要的视点

    4.设定glTexCoord2f 和 glVertex3f 是怎么对应,repeat 的

    代码如下:

    #include "windows.h"
    #include
    "gl/gl.h"
    #include
    "gl/glu.h"
    #include
    "gl/glut.h"
    #include
    <stdio.h>

    #define BmpHeaderLength 54 //文件长度
    #define WidthPosition 0x0012 //width值在文件中的位置
    #define HeightPosition 0x0016 //height在文件中的位置

    typedef
    struct{

    char *filename; //文件名
    FILE *fp; //文件指针
    GLint width; //
    GLint height; //
    GLubyte * pPixelData; //文件中 实际的像素信息

    }FileDataInfo;
    //文件数据信息

    GLuint texGround;
    GLuint texWall;

    FileDataInfo LoadBMP(
    char *filename)
    {

    FileDataInfo fileinfo;
    fileinfo.filename
    = filename;
    fileinfo.fp
    = fopen(fileinfo.filename,"rb");

    fseek(fileinfo.fp,WidthPosition,SEEK_SET);
    fread(
    &fileinfo.width,sizeof(fileinfo.width),1,fileinfo.fp);

    fseek(fileinfo.fp,HeightPosition,SEEK_SET);
    fread(
    &fileinfo.height,sizeof(fileinfo.height),1,fileinfo.fp);

    fseek(fileinfo.fp,BmpHeaderLength,SEEK_SET);


    int widthInBmpFile = fileinfo.width*3;

    //因为微软的bmp格式文件宽度 像素值 是 4 整数倍,不是的话,会在后面补上,
    //也就是说 (像素宽*3)*像素高 <= 文件大小-54; ---54是bmp文件头部大小。
    //所以在读取文件的时候需要调整内存大小,而不是 直接的(width*3)*height ;
    while(widthInBmpFile%4 != 0)
    {
    widthInBmpFile
    ++;
    }

    int pixelDataLen = widthInBmpFile *fileinfo.height;
    fileinfo.pPixelData
    = (GLubyte*)malloc(pixelDataLen);

    if(fileinfo.pPixelData == 0)
    {
    printf(
    "malloc() failed");

    free(fileinfo.pPixelData);

    exit(
    0);
    }

    fread(fileinfo.pPixelData,pixelDataLen,
    1,fileinfo.fp);

    fclose(fileinfo.fp);

    return fileinfo;
    }


    //释放资源
    void destroy(FileDataInfo *p)
    {
    free(p
    ->pPixelData);
    fclose(p
    ->fp);
    }

    int getTexture(FileDataInfo fileinfo)
    {
    GLuint last_texture_ID,texture_ID
    =0;
    GLubyte
    * pTextureData;
    GLubyte
    * newData ;
    GLint max;

    //OpenGL 低版本中,纹理大小不能超过 一定值。
    glGetIntegerv(GL_MAX_TEXTURE_SIZE,&max);

    //为保证openGL向低版本的兼容性,超过了的话,需要将其缩小。
    if(fileinfo.width > max||fileinfo.height >max)
    {
    //最大宽 和 高
    int maxWidth =256;
    int maxHeight = 256;


    int lines = (int)maxWidth*3;

    if(lines % 4 != 0)
    {
    lines
    ++;
    }

    int total = lines * maxHeight;

    newData
    = (GLubyte*)malloc(total);

    if(newData == 0)
    {
    printf(
    "newData=malloc() failed");
    return -1;
    }

    //缩小
    gluScaleImage(GL_RGB,fileinfo.width,fileinfo.height,GL_UNSIGNED_BYTE,fileinfo.pPixelData,maxWidth,maxHeight,GL_UNSIGNED_BYTE,newData);

    pTextureData
    = newData;

    }
    else
    {
    pTextureData
    = fileinfo.pPixelData;

    }

    //generate a texture ID
    glGenTextures(1,&texture_ID);

    if(texture_ID == 0)
    {
    free(pTextureData);
    printf(
    "get textureID failed !");
    return -1;
    }

    glGetIntegerv(GL_TEXTURE_BINDING_2D,(GLint
    *)&last_texture_ID);

    glBindTexture(GL_TEXTURE_2D,texture_ID);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);

    glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);

    glTexImage2D(GL_TEXTURE_2D,
    0,GL_RGB,fileinfo.width,fileinfo.height,0,GL_BGR_EXT,GL_UNSIGNED_BYTE,pTextureData);
    glBindTexture(GL_TEXTURE_2D,last_texture_ID);

    return texture_ID;
    }




    void display()
    {
    glClear(GL_COLOR_BUFFER_BIT
    |GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(
    65,1,1,21);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(
    1,5,5,0,0,0,0,0,1);


    //开始绑定地表图像 作为纹理
    glBindTexture(GL_TEXTURE_2D,texGround);

    glBegin(GL_QUADS);
    glTexCoord2f(
    0.0f,0.0f); glVertex3f(-8.0f,-8.0f,0.0f);
    glTexCoord2f(
    0.0,5.0f); glVertex3f(-8.0f,8.0f,0.0f);
    glTexCoord2f(
    5.0f,5.0f); glVertex3f(8.0f,8.0f,0.0f);
    glTexCoord2f(
    5.0f,0.0f); glVertex3f(8.0f,-8.0f,0.0f);
    glEnd();



    // 使用“墙”纹理绘制栅栏
    glBindTexture(GL_TEXTURE_2D, texWall);

    glBegin(GL_QUADS);
    glTexCoord2f(
    0.0f, 0.0f); glVertex3f(-6.0f, -3.0f, 0.0f);
    glTexCoord2f(
    0.0f, 1.0f); glVertex3f(-6.0f, -3.0f, 1.5f);
    glTexCoord2f(
    5.0f, 1.0f); glVertex3f(6.0f, -3.0f, 1.5f);
    glTexCoord2f(
    5.0f, 0.0f); glVertex3f(6.0f, -3.0f, 0.0f);
    glEnd();

    // 旋转后再绘制一个
    glRotatef(-90, 0, 0, 1);

    glBegin(GL_QUADS);
    glTexCoord2f(
    0.0f, 0.0f); glVertex3f(-6.0f, -3.0f, 0.0f);
    glTexCoord2f(
    0.0f, 1.0f); glVertex3f(-6.0f, -3.0f, 1.5f);
    glTexCoord2f(
    5.0f, 1.0f); glVertex3f(6.0f, -3.0f, 1.5f);
    glTexCoord2f(
    5.0f, 0.0f); glVertex3f(6.0f, -3.0f, 0.0f);
    glEnd();


    // 交换缓冲区,并保存像素数据到文件
    glutSwapBuffers();

    }

    int main(int argc, char ** argv)
    {
    glutInit(
    &argc,argv);
    glutInitDisplayMode(GLUT_RGBA
    |GLUT_DOUBLE);

    glutInitWindowPosition(
    100,100);
    glutInitWindowSize(
    500,500);
    glutCreateWindow(
    "Texture Image");

    glutDisplayFunc(
    &display);

    glEnable(GL_DEPTH_TEST);
    glEnable(GL_TEXTURE_2D);


    FileDataInfo groundFileInfo
    = LoadBMP("ground.bmp");
    texGround
    = getTexture(groundFileInfo);

    FileDataInfo wallFileInfo
    = LoadBMP("wall.bmp");
    texWall
    = getTexture(wallFileInfo);

    glutMainLoop();

    destroy(
    &groundFileInfo);
    destroy(
    &wallFileInfo);

    return 0;
    }

    ground.bmp

    wall.bmp

    //结果

  • 相关阅读:
    【力扣 089】24. 两两交换链表中的节点
    【力扣 086】19. 删除链表的倒数第 N 个结点
    【力扣 085】2. 两数相加
    【力扣 093】92. 反转链表 II
    【力扣 090】25. K 个一组翻转链表
    【力扣 091】61. 旋转链表
    【力扣 088】23. 合并K个升序链表
    【力扣 087】21. 合并两个有序链表
    【力扣 092】82. 删除排序链表中的重复元素 II
    vim命令
  • 原文地址:https://www.cnblogs.com/ToDoToTry/p/2156406.html
Copyright © 2020-2023  润新知