OpenGL学习5

Posted by 蒋波涛 15 August,2006 Views (9)Comment
1.        颜色
讲了这么多,突然想起自己忘记了介绍颜色,在前面的例子中,我已经使用了glColor3f这个函数。用这个函数为我绘制的立方体的面来配上颜色。
OpenGL的颜色有两种模式,一是RGBA,即使用RGB作为颜色,最后面的AAlpha,即透明度,其值都是[0 1]之间;另一种是颜色表模式。还记得前面我写的例子中的SetupPixelFormat函数,其中有个参数就是:
      pfd->iPixelType=PFD_TYPE_RGBA;
表示我使用的是RGBA模式。
除此以为,我还写了一个判断语句:
      if (pfd->dwFlags&PFD_NEED_PALETTE)
      {
             SetLogicalPalette();       //有必要的话设置逻辑调色板
      }
       在大多情况下,采用RGBA模式比颜色表模式的要多,尤其许多效果处理,如阴影、光照、雾、反走样、混合等,采用RGBA模式效果会更好些;另外,纹理映射只能在RGBA模式下进行。下面提供几种运用颜色表模式的情况(仅供参考):
1)若原来应用程序采用的是颜色表模式则转到OpenGL上来时最好仍保持这种模式,便于移植。
2)若所用颜色不在缺省提供的颜色许可范围之内,则采用颜色表模式。
3)在其它许多特殊处理,如颜色动画,采用这种模式会出现奇异的效果。
2.        纹理
前面三节足够让我们建立一个立方体并旋转起来了,而且这个立方体还是彩色的,下面我们就该研究下纹理和打光的技术了。
纹理的图片尺寸必须是2N次方,但最大不能超过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);
然后将RenderSceneglBindTexture函数改为:
       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");
       }
}
编译运行,然后点击“变换纹理”,看看怎么样情况发生。

Related Items

Categories : OpenGL Tags : 计算机图形学  OpenGL  
Comments
2007-1-20 21:34:15

可以加你的QQ ,向你请教opengl吗?我的是349404146 谢谢了

Posted by nancy Gravatar Icon

2007-11-19 20:40:58

正头疼呢,啥也不说了!~~~~~谢谢~~~
可以加我么 我的QQ:303237109
加我的话说明一下是你~~~

Posted by 刘立明 Gravatar Icon

2007-11-19 20:45:24

我还不如你呢 ~~我只会C语言,没有编程经验。哈哈 从零开始~~~

Posted by 刘立明 Gravatar Icon

2007-11-24 21:24:47

看到纹理那有好多不明白的地方,不知道是怎么回事,比如你那个mfc2.bmp是什么来的?还有你那一堆文件操作是怎么回事啊
能不能推荐一本纹理方面将的比较详细的书我看看也可以啊
我们现在做一个东西,急啊

Posted by 刘立明 Gravatar Icon

2007-11-24 21:28:06

我现在看的是OpenGL编程指南,感觉做东西也用不上啊
代码都是C的 和在MFC里弄一点都不一样~~
他那些纹理都是自己用程序写的 你那个怎么是位图文件呢
那个也是你自己写的么 ?

Posted by 刘立明 Gravatar Icon

2007-11-25 13:25:59

我的位图文件为什么打不开File=fopen(Filename,"r");
我自己裁剪的16*16的一个图片 格式是bmp的
怎么不说话呢 ~你不上你的博客的么~

Posted by 刘立明 Gravatar Icon

2008-7-17 12:11:06

很牛,有有关三维模型导入的吗?急需,谢谢!

Posted by 可可西里 Gravatar Icon

2008-7-17 17:26:58

不好意思,没有Nothing_to_say

Posted by 蒋波涛 Gravatar Icon

2008-12-10 10:15:04

我有3DMAX文件3DS文件整成GL能识别的方法,1000RMB出售,zt00@tom.com

Posted by zt00 Gravatar Icon

Leave a comment

Or, take a look at Archives and Categories

目录

存档