OpenGL学习5
Posted by
蒋波涛
15 August,2006 Views
(9)Comment
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");
}
}
编译运行,然后点击“变换纹理”,看看怎么样情况发生。
Related Items
Categories :
OpenGL
Comments
正头疼呢,啥也不说了!~~~~~谢谢~~~
可以加我么 我的QQ:303237109
加我的话说明一下是你~~~
我还不如你呢 ~~我只会C语言,没有编程经验。哈哈 从零开始~~~
看到纹理那有好多不明白的地方,不知道是怎么回事,比如你那个mfc2.bmp是什么来的?还有你那一堆文件操作是怎么回事啊
能不能推荐一本纹理方面将的比较详细的书我看看也可以啊
我们现在做一个东西,急啊
我现在看的是OpenGL编程指南,感觉做东西也用不上啊
代码都是C的 和在MFC里弄一点都不一样~~
他那些纹理都是自己用程序写的 你那个怎么是位图文件呢
那个也是你自己写的么 ?
我的位图文件为什么打不开File=fopen(Filename,"r");
我自己裁剪的16*16的一个图片 格式是bmp的
怎么不说话呢 ~你不上你的博客的么~
很牛,有有关三维模型导入的吗?急需,谢谢!
不好意思,没有![]()
我有3DMAX文件3DS文件整成GL能识别的方法,1000RMB出售,zt00@tom.com
Leave a comment
Or, take a look at Archives and Categories
可以加你的QQ ,向你请教opengl吗?我的是349404146 谢谢了