OpenGL学习笔记(五)

这篇博客详细介绍了在OpenGL环境下实现纹理映射和光照系统的过程,包括环境搭建、位图加载、纹理创建及滤波器设置。作者通过LoadBMP和LoadGLTextures函数展示了如何读取位图并将其转化为纹理,同时讲解了光照系统中环境光、漫射光的概念,以及如何设置光源和法线。此外,还添加了按键控制功能,如L键开关灯光,方向键控制图形旋转。
摘要由CSDN通过智能技术生成

龙云尧个人博客,转载请注明出处。

CSDN地址:http://blog.csdn.net/michael753951/article/details/71316132

个人blog地址:http://yaoyl.cn/nehexue-xi-bi-ji-wu/


这次我们将尝试Lesson6和Lesson7的内容。这个部分我们将学习怎么给一个模型进行纹理映射(其实就是贴图)。

环境搭建

这次实验因为需要使用OpenGL的glaux.h库头使用位图对构建的图形进行纹理映射。所以我们需要进一步进行环境搭建。(注:环境搭建很麻烦,因为微软的VS环境很乱)

如何布置这个库头可以参考【 VS2008无法打开gl/glaux.h头文件的解决方法】我使用的是方法4,测试能够正确include库头。

在高版本的VS中,因为VS使用的是自己重新修改过的C++,所以在进行编译的过程中,可能会出现ERROR LNK2019报错,无法解析“_sscanf,_sscanf_s”,这个时候我们可以参考【 VS2015 无法解析的外部符号 __vsnwprintf_s】

如果我们在使用AUX_RGBImageRec定义变量的时候,系统没有报错的话,就说明我们本次基本的环境已经搭建好了。

另外,因为我们在实验中需要使用fopen,而微软的VS2015中会强行报错,为了避免不必要的麻烦,我们需要关掉fopen的报错。这个部分我们可以参考【百度经验:VS2013中如何解决error C4996: ‘fopen’问题】

开始实现

如果没出什么问题的话,到这里我们应该能够正常的编写这一刻的代码了。(如果还有什么报错请尝试自行解决或者戳我)。

本次需要在3维图像上添加纹理映射,首先需要的是读取位图像文件。读取的代码如下。

AUX_RGBImageRec *LoadBMP(char *Filename)                // Loads A Bitmap Image
{
    FILE *File=NULL;                                    // File Handle

    if (!Filename)                                      // Make Sure A Filename Was Given
    {
        return NULL;                                    // If Not Return NULL
    }

    File=fopen(Filename,"r");                           // Check To See If The File Exists

    if (File)                                           // Does The File Exist?
    {
        fclose(File);                                   // Close The Handle
        return auxDIBImageLoad(Filename);               // Load The Bitmap And Return A Pointer
    }

    return NULL;                                        // If Load Failed Return NULL
}

int LoadGLTextures()                                    // Load Bitmaps And Convert To Textures
{
    int Status=FALSE;                                   // Status Indicator

    AUX_RGBImageRec *TextureImage[1];                   // Create Storage Space For The Texture

    memset(TextureImage,0,sizeof(void *)*1);            // Set The Pointer To NULL

    // Load The Bitmap, Check For Errors, If Bitmap's Not Found Quit
    if (TextureImage[0]=LoadBMP("Data/NeHe.bmp"))
    {
        Status=TRUE;                                    // Set The Status To TRUE

        glGenTextures(1, &texture[0]);                  // Create The Texture

        // Typical Texture Generation Using Data From The Bitmap
        glBindTexture(GL_TEXTURE_2D, texture[0]);
        glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    }

    if (TextureImage[0])                                    // If Texture Exists
    {
        if (TextureImage[0]->data)                          // If Texture Image Exists
        {
            free(TextureImage[0]->data);                    // Free The Texture Image Memory
        }

        free(TextureImage[0]);                              // Free The Image Structure
    }

    return Status;                                      // Return The Status
}

第一个函数LoadBMP不需要解释,主要功能就是探寻目的位置中是否存在该图像文件。如果存在就调用auxDIBImageLoad将位图加载成渲染文件返回出来。

第二个函数LoadGLTextures要稍微注意一下,在本次实验中是很重要的一个功能函数。

函数中定义了一个LoadGLTextures数组用来存放位图的句柄,这里因为我们只读取了一张位图,所以只开了一个大小的数组。

接着调用LoadBMP将位图转换成为纹理渲染文件存进TextureImage, glGenTextures(1, &texture[0]) 告诉OpenGL我们想生成一个纹理名字,glBindTexture将纹理名字 texture[0] 绑定到纹理目标上。

然后我们调用glTexImage2D进行纹理的创建。然后使用glTexParameteri对图像进行放大和缩小的滤波器进行设置。

最后再纹理穿件完成之后,我们需要释放掉纹理渲染数组中的内容。

整个纹理渲染工作到这里也就结束了。我们对InitGL稍作修改,使用LoadGLTextures检验位图是否存在,然后调用glEnable启用映射

int InitGL(GLvoid)        // 此处开始对OpenGL进行所有设置
{
 if (!LoadGLTextures())       // 调用纹理载入子例程
 {
  return FALSE;       // 如果未能载入,返回FALSE
 }
 glEnable(GL_TEXTURE_2D);      // 启用纹理映射
 glShadeModel(GL_SMOOTH);      // 启用阴影平滑
 glClearColor(0.0f, 0.0f, 0.0f, 0.5f);     // 黑色背景
 glClearDepth(1.0f);       // 设置深度缓存
 glEnable(GL_DEPTH_TEST);      // 启用深度测试
 glDepthFunc(GL_LEQUAL);       // 所作深度测试的类型
 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);   // 真正精细的透视修正
 return TRUE;        // 初始化 OK
}

最后我们按照惯例,修改DrawGLScene方法,需要注意的是,在将纹理贴上模型的时候,需要调用glTexCoord2f方法,第一个参数是X坐标,0.0是纹理的左侧,0.5是纹理的中点,1.0是纹理的右侧。第二个参数是Y坐标,0.0是纹理的底部,0.5是纹理的中点,1.0是纹理的顶部。将4个点全部绑定在张芳行上面之后,便能够正常的显示了。需要注意的是,在glTexCoord2f方法中,参考系是以图像的右下角作为原点,左边为X轴正方向,上方为Y轴正方向(和绘图中的直角坐标系的设定相似)。

int DrawGLScene(GLvoid)                                 // Here's Where We Do All The Drawing
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
    glLoadIdentity();                                   // Reset The View
    glTranslatef(0.0f,0.0f,-5.0f);

    glRotatef(xrot,1.0f,0.0f
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值