欢迎您来到GIS动力

加入收藏 免费注册 用户登陆 帮助中心
首页 新闻动态 技术专栏 银杏树下 学习考研 软件下载 求职招聘 许愿瓶 节日祝福 用户中心 精彩推荐 资源搜索 地图
专栏导航: AO开发 | SO开发 | ArcGIS桌面 | 超图桌面 | 开发语言 | 数据库 | WebGIS | 银杏文学 | 研究生考题 | FreeMap 谈天说地
   您现在位于: 首页技术专栏开发语言 → 正文
OpenGL起步4
07-12-28 00:00:00 作者:浩淼的天空 出处:浩淼的天空
1.         颜色
讲了这么多,突然想起自己忘记了介绍颜色,在前面的例子中,我已经使用了glColor3f 这个函数。用这个函数为我绘制的立方体的面来配上颜色。
OpenGL 的颜色有两种模式,一是RGBA ,即使用RGB 作为颜色,最后面的A Alpha ,即透明度,其值都是[0 1] 之间;另一种是颜色表模式。还记得前面我写的例子中的SetupPixelFormat 函数,其中有个参数就是:
      pfd->iPixelType=PFD_TYPE_RGBA;
表示我使用的是RGBA 模式。
除此以为,我还写了一个判断语句:
      if (pfd->dwFlags&PFD_NEED_PALETTE)
      {
             SetLogicalPalette();       // 有必要的话设置逻辑调色板
      }
       在大多情况下,采用RGBA 模式比颜色表模式的要多,尤其许多效果处理,如阴影、光照、雾、反走样、混合等,采用RGBA 模式效果会更好些;另外,纹理映射只能在RGBA 模式下进行。下面提供几种运用颜色表模式的情况(仅供参考):
1 )若原来应用程序采用的是颜色表模式则转到OpenGL 上来时最好仍保持这种模式,便于移植。
2 )若所用颜色不在缺省提供的颜色许可范围之内,则采用颜色表模式。
3 )在其它许多特殊处理,如颜色动画,采用这种模式会出现奇异的效果。
2.         纹理
前面三节足够让我们建立一个立方体并旋转起来了,而且这个立方体还是彩色的,下面我们就该研究下纹理和打光的技术了。
纹理的图片尺寸必须是2 N 次方,但最大不能超过256 象素,当然肯定有方法绕过这个限制,不过我现在也不知道,有知道的人请告诉一声。
首先是纹理,先在视图类中添加一个变量:
       GLuint m_texture[1];     // 存储一个纹理
一个数组,这就意味着我们完全可以使用多个纹理咯,暂时使用一个先。
添加下面两个函数,用于将一个文件变成纹理:
AUX_RGBImageRec* CCOpenGLDemoView::LoadBMP(char *Filename)
{
       FILE* File=NULL;
       if (!Filename)         // 文件名是否存在
       {
              return NULL;
       }
       File=fopen(Filename,"r");      // 读取文件
       if (File)                                // 文件读取成功
       {           
              fclose(File);                  // 关闭文件流
              return auxDIBImageLoad(Filename);    // 载入位图并返回指针
       }
       return NULL;
}
 
int CCOpenGLDemoView::LoadGLTextures()
{
       int Status=FALSE; // 状态参数跟踪是否能够载入位图以及能否创建纹理
       AUX_RGBImageRec* TextureImage[1];      // 设置纹理数组
       memset(TextureImage,0,sizeof(void*)*1);          // 清除图像记录 , 将指针设置为 NULL
       if (TextureImage[0]=LoadBMP("mfc2.bmp"))     // 载入位图
       {
              Status=TRUE;
              glGenTextures(1,&m_texture[0]);               // 创建纹理
             
              glBindTexture(GL_TEXTURE_2D,m_texture[0]);// 根据来自位图的数据创建 NEAREST 纹理
              glTexImage2D(GL_TEXTURE_2D,                          // 产生的是 2D 纹理
                     0,                                                            // 图像的详细程度,一般为 0
                     3,                                                            // 图像的成分,为 RGB
                     TextureImage[0]->sizeX,                           // 图像宽
                     TextureImage[0]->sizeY,                            // 图像高
                     0,                                                            // 图像边框
                     GL_RGB,                                                        // 图像是 RGB 三色组成
                     GL_UNSIGNED_BYTE,                                   // 图像数据是无符号字节类型
                     TextureImage[0]->data);                            // 图像数据来源
             
              // 采用 GL_LINEAR 使得纹理从很远处到离屏幕很近时都平滑显示
              glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); // 线形滤波
       glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); // 线形滤波
 
              // 释放位图内存
              if (TextureImage[0])
              {
                     if (TextureImage[0]->data)
                     {
                            free(TextureImage[0]->data);
                     }
                     free(TextureImage[0]);
              }
       }
       return Status;
}
在获得了纹理后,我们现在需要绑定纹理了,在InitOpenGL 中加入以下代码:
       if (!LoadGLTextures())// 纹理是否载入
       {
              return FALSE;
       }
       glEnable(GL_TEXTURE_2D);// 启用纹理映射
RenderScene 中选择纹理:
       glBindTexture(GL_TEXTURE_2D, m_texture[0]);      // 选择纹理
       DrawQuads();
选择纹理后,我们就该贴纹理了,这个过程如下:
              glTexCoord2f(1.0f,1.0f);glVertex3f(1.0f,1.0f,1.0f);
              glTexCoord2f(0.0f,1.0f);glVertex3f(-1.0f,1.0f,1.0f);
              glTexCoord2f(0.0f,0.0f);glVertex3f(-1.0f,-1.0f,1.0f);
              glTexCoord2f(1.0f,0.0f);glVertex3f(1.0f,-1.0f,1.0f);
 
              glColor3f(1.0f,0.0f,0.0f);
              glTexCoord2f(1.0f,1.0f);glVertex3f(-1.0f,1.0f,-1.0f);
              glTexCoord2f(0.0f,1.0f);glVertex3f(1.0f,1.0f,-1.0f);
              glTexCoord2f(0.0f,0.0f);glVertex3f(1.0f,-1.0f,-1.0f);
              glTexCoord2f(1.0f,0.0f);glVertex3f(-1.0f,-1.0f,-1.0f);
 
              glColor3f(0.5f,1.5f,0.5f);
              glTexCoord2f(1.0f,1.0f);glVertex3f(-1.0f,1.0f,1.0f);
              glTexCoord2f(0.0f,1.0f);glVertex3f(-1.0f,1.0f,-1.0f);
              glTexCoord2f(0.0f,0.0f);glVertex3f(-1.0f,-1.0f,-1.0f);
              glTexCoord2f(1.0f,0.0f);glVertex3f(-1.0f,-1.0f,1.0f);
 
              glColor3f(0.5f,0.0f,1.0f);
              glTexCoord2f(1.0f,1.0f);glVertex3f(1.0f,1.0f,-1.0f);
              glTexCoord2f(0.0f,1.0f);glVertex3f(1.0f,1.0f,1.0f);
              glTexCoord2f(0.0f,0.0f);glVertex3f(1.0f,-1.0f,1.0f);
              glTexCoord2f(1.0f,0.0f);glVertex3f(1.0f,-1.0f,-1.0f);
 
              glColor3f(1.0f,1.0f,0.0f);
              glTexCoord2f(1.0f,1.0f);glVertex3f(1.0f,1.0f,-1.0f);
              glTexCoord2f(0.0f,1.0f);glVertex3f(-1.0f,1.0f,-1.0f);
              glTexCoord2f(0.0f,0.0f);glVertex3f(-1.0f,1.0f,1.0f);
              glTexCoord2f(1.0f,0.0f);glVertex3f(1.0f,1.0f,1.0f);
 
              glColor3f(1.0f,0.0f,1.0f);
              glTexCoord2f(1.0f,1.0f);glVertex3f(1.0f,-1.0f,1.0f);
              glTexCoord2f(0.0f,1.0f);glVertex3f(-1.0f,-1.0f,1.0f);
              glTexCoord2f(0.0f,0.0f);glVertex3f(-1.0f,-1.0f,-1.0f);
              glTexCoord2f(1.0f,0.0f);glVertex3f(1.0f,-1.0f,-1.0f);
贴图必须是使用贴图坐标,其左下角为0 0 ,右上角为1 1 。搞定,下面我们看看效果:
 
我们知道,对于一个物体而言,在远处与在近处的感觉肯定不一致,就纹理而言,在远处的物体纹理应该模糊一些,因此我们可以尝试使用不同清晰度的纹理来试验看看。下面的代码就是控制立方体的纹理,当然咯,你也可以学习到换不同纹理的方法,举一反三嘛。
首先要修改的是变量m_texture[1] ,请改为m_texture[3] ,因为我们将试验三种纹理方式。然后设置一个int 型视图类变量filter ,用于标识使用何种纹理。
LoadGLTextures
              glGenTextures(1,&m_texture[0]);               // 创建纹理
修改为:
              glGenTextures(3,&m_texture[0]);               // 创建 3 个纹理
然后在第一个创建的纹理后面添加以下内容:
              glBindTexture(GL_TEXTURE_2D,m_texture[1]);// 创建线性滤波纹理
              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_MAG_FILTER,GL_LINEAR);
              glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
 
              glBindTexture(GL_TEXTURE_2D,m_texture[2]);// 创建 MipMapped 纹理
              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_MAG_FILTER,GL_LINEAR);
              glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
然后将RenderScene glBindTexture 函数改为:
       glBindTexture(GL_TEXTURE_2D, m_texture[filter]); // 选择纹理
控制filter 的操作就使用F5 键来进行:
       case VK_F5:
              filter++;
              if (filter>2) {
                     filter=0;
              }
              break;
编译执行代码,按F5 ,看看纹理是否会出现变化。
 
上面的例子是使用一个纹理的不同滤波方式,下面的例子我们使用两个纹理来试验看看。首先我改写LoadGLTextures 函数参数类型,改为:
LoadGLTextures(char* Filename)
然后我们再来改写这个函数的内容:
       if (TextureImage[0]=LoadBMP(Filename))   // 载入位图
       {
              Status=TRUE;
这样载入的位图就不必使用默认位图mfc2.bmp 产生纹理了,而是根据文件名载入纹理。接下来我们添加一个视图类变量m_textureFilter 判别是当前使用的是哪一个纹理。在视图类的构造函数中设置为m_textureFilter=0 ,用于标识默认纹理;在InitOpenGL 中添加以下一段(灰色部分),表示未使用纹理的标识:
       if (!LoadGLTextures("mfc2.bmp"))// 纹理是否载入
       {
              m_textureFilter=-1;
              return FALSE;
       }
下面我添加一个菜单:
 
然后添加这个菜单的处理函数OnOpenglTexture ,改写这个函数:
void CCOpenGLDemoView::OnOpenglTexture()
{
       // TODO: Add your command handler code here
       int i;
       // 如果未载入纹理或载入纹理为默认
       if ((m_textureFilter==0)||(m_textureFilter==-1))
       {
              m_textureFilter=1;
              // 载入新纹理
              i=LoadGLTextures("Water.bmp");
       }
       else if(m_textureFilter==1)    // 已经载入新纹理
       {
              m_textureFilter=0;
              // 改为默认纹理
              i=LoadGLTextures("mfc2.bmp");
       }
}
编译运行,然后点击“变换纹理”,看看怎么样情况发生。

(本文已被浏览 次)
发布人:admin
推荐给好友:发送给好友
上篇新闻:
下篇新闻:
相关评论
发表我的评论
  • 尊重网上道德,遵守《全国人大常委会关于维护互联网安全的决定》及中华人民共和国其他各项有关法律法;
  • 本站有权保留或删除您发表的任何评论内容;
  •   相关文章  
    OpenGL起步3
    OpenGL起步2
    OpenGL起步1

    关于我们 友情链接 ┋ 与我在线 ┋ 管理 ┋ TOP
    网站当前版本:GisPower CMS V3.0
    『GIS 动力』- http://www.gispower.org/
    联系我们:webmaster#gispower.org
    Copyright (c) 2003-2007 GisPOwer.Org. All Rights Reserved.

                   滇ICP备05006901号