NeHe OpenGL教程 第八课:混合
前言
声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改。对NeHe的OpenGL管线教程的编写,以及yarn的翻译整理表示感谢。

混合:
在这一课里,我们在纹理的基础上加上了混合,它看起具有透明的效果,当然解释它不是那么容易,当希望你喜欢它。
简单的透明
OpenGL中的绝大多数特效都与某些类型的(色彩)混合有关。混色的定义为,将某个像素的颜色和已绘制在屏幕上与其对应的像素颜色相互结合。至于如何结合这两个颜色则依赖于颜色的alpha通道的分量值,以及/或者所使用的混色函数。Alpha通常是位于颜色值末尾的第4个颜色组成分量。前面这些课我们都是用GL_RGB来指定颜色的三个分量。相应的GL_RGBA可以指定alpha分量的值。更进一步,我们可以使用glColor4f()来代替glColor3f()。
绝大多数人都认为Alpha分量代表材料的透明度。这就是说,alpha值为0.0时所代表的材料是完全透明的。alpha值为1.0时所代表的材料则是完全不透明的。
混色的公式
若您对数学不感冒,而只想看看如何实现透明,请跳过这一节。若您想深入理解(色彩)混合的工作原理,这一节应该适合您吧。『译者注:其实并不难^-^。原文中的公式如下,CKER再唠叨一下吧。其实混合的基本原理是就将要分色的图像各像素的颜色以及背景颜色均按照RGB规则各自分离之后,根据-图像的RGB颜色分量*alpha值+背景的RGB颜色分量*(1-alpha值)-这样一个简单公式来混合之后,最后将混合得到的RGB分量重新合并。』
公式如下:
(Rs Sr + Rd Dr, Gs Sg + Gd Dg, Bs Sb + Bd Db, As Sa + Ad Da)
OpenGL按照上面的公式计算这两个像素的混色结果。小写的s和r分别代表源像素和目标像素。大写的S和D则是相应的混色因子。这些决定了您如何对这些像素混色。绝大多数情况下,各颜色通道的alpha混色值大小相同,这样对源像素就有
(As, As, As, As),目标像素则有1, 1, 1, 1) - (As, As, As, As)。上面的公式就成了下面的模样:
(Rs As + Rd (1 - As), Gs As + Gd (1 - As), Bs As + Bs (1 - As), As As + Ad (1 - As))
这个公式会生成透明/半透明的效果。
OpenGL中的混色
在OpenGL中实现混色的步骤类似于我们以前提到的OpenGL过程。接着设置公式,并在绘制透明对象时关闭写深度缓存。因为我们想在半透明的图形背后绘制 对象。这不是正确的混色方法,但绝大多数时候这种做法在简单的项目中都工作的很好。
Rui Martins 的补充: 正确的混色过程应该是先绘制全部的场景之后再绘制透明的图形。并且要按照与深度缓存相反的次序来绘制(先画最远的物体)。
考虑对两个多边形(1和2)进行alpha混合,不同的绘制次序会得到不同的结果。(这里假定多边形1离观察者最近,那么正确的过程应该先画多边形2,再画多边形1。正如您再现实中所见到的那样,从这两个<透明的>多边形背后照射来的光线总是先穿过多边形2,再穿过多边形1,最后才到达观察者的眼睛。)
在深度缓存启用时,您应该将透明图形按照深度进行排序,并在全部场景绘制完毕之后再绘制这些透明物体。否则您将得到不正确的结果。我知道某些时候这样做是很令人痛苦的,但这是正确的方法。
我们将使用第七课的代码。一开始先在代码开始处增加两个新的变量。出于清晰起见,我重写了整段代码。
bool blend; // 是否混合?
bool bp; // B 键按下了么?
然后往下移动到 LoadGLTextures() 这里。找到" if (TextureImage[0]=LoadBMP("Data/Crate.bmp")) "这一行。我们现在使用有色玻璃纹理来代替上一课中的木箱纹理。
if (TextureImage[0]=LoadBMP("Data/glass.bmp")) // 载入玻璃位图
在InitGL()代码段加入以下两行。第一行以全亮度绘制此物体,并对其进行50%的alpha混合(半透明)。当混合选项打开时,此物体将会产生50%的透明效果。第二行设置所采用的混合类型。
Rui Martins 的补充: alpha通道的值为 0.0意味着物体材质是完全透明的。1.0 则意味着完全不透明。
glColor4f(1.0f,1.0f,1.0f,0.5f); // 全亮度, 50% Alpha 混合
glBlendFunc(GL_SRC_ALPHA,GL_ONE); // 基于源像素alpha通道值的半透明混合函数
在接近第七课结尾处的地方找到下面的代码段。
if (keys[VK_LEFT]) // Left方向键按下了么?
{
yspeed-=0.01f; // 若是, 减少yspeed
}
接着上面的代码,我们增加如下的代码。这几行监视B键是否按下。如果是的话,计算机检查混合选项是否已经打开。然后将其置为相反的状态。
if (keys['B'] && !bp) // B 健按下且bp为 FALSE么?
{
bp=TRUE; // 若是, bp 设为 TRUE
blend = !blend; // 切换混合选项的 TRUE / FALSE
if(blend) // 混合打开了么?
{
glEnable(GL_BLEND); // 打开混合
glDisable(GL_DEPTH_TEST); // 关闭深度测试
}
else // 否则
{
glDisable(GL_BLEND); // 关闭混合
glEnable(GL_DEPTH_TEST); // 打开深度测试
}
}
if (!keys['B']) // B 键松开了么?
{
bp=FALSE; // 若是, bp设为 FALSE
}
原文及其个版本源代码下载:
NeHe OpenGL教程 第八课:混合的更多相关文章
- NeHe OpenGL教程 第二十七课:影子
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- NeHe OpenGL教程 第二十课:蒙板
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- NeHe OpenGL教程 第十七课:2D图像文字
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- NeHe OpenGL教程 第十三课:图像字体
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- NeHe OpenGL教程 第十一课:飘动的旗帜
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- NeHe OpenGL教程 第五课:3D空间
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- NeHe OpenGL教程 第三课:颜色渲染
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- NeHe OpenGL教程 第二十三课:球面映射
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- NeHe OpenGL教程 第二十一课:线的游戏
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
随机推荐
- HTML5里autofocus属性
转载:http://www.webhek.com/html5-autofocus/ HTML5给我们带来了一大堆神奇的东西.以前需要用JavaScript和Flash完成的任务,例如表单校验,INPU ...
- C函数之memcpy()函数用法
函数原型 void *memcpy(void*dest, const void *src, size_t n); 功能 由src指向地址为起始地址的连续n个字节的数据复制到以destin指向地址为起始 ...
- kvo-观察者-iOS
#import <Foundation/Foundation.h> @interface Child : NSObject @property (nonatomic,assign) int ...
- Xcode 7安装KSImageNamed失败解决方法
## How do I use it? Build the KSImageNamed target in the Xcode project and the plug-in will automati ...
- 二十四种设计模式:中介者模式(Mediator Pattern)
中介者模式(Mediator Pattern) 介绍用一个中介对象来封装一系列的对象交互.中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互. 示例有一个Messa ...
- shell知识点
各个项目以实践为主.原理及更多细节介绍,请查看官方文档: 例如:bash,grub,postfix,pam,fastcgi,httpd,rsync等诸多项目. 各种总结表格 http://www.cn ...
- 【转】纯CSS设置Checkbox复选框控件的样式
Checkbox复选框是一个可能每一个网站都在使用的HTML元素,但大多数人并不给它们设置样式,所以在绝大多数网站它们看起来是一样的.为什么不把你的网站中的Checkbox设置一个与众不同的样式,甚至 ...
- 【转】DNS劫持和DNS污染的区别
什么是DNS服务器? 简单来说,DNS服务器就是域名管理系统. DNS(Domain Name System)是域名解析服务器的意思. DNS服务器是干什么的? DNS服务器在互联网的作用是:把域名转 ...
- 在eclipse中的tomcat内存设置
设置步骤如下: 1.点击eclipse上的debug图标旁边的下拉箭头 2.然后选择Run Configurations, 3.系统弹出设置tomcat配置页面,在Argument中末尾添加参数中的V ...
- 在数据库查询时解决大量in 关键字的方法
有时候在前台界面需要批量处理一些数据时,经常要用到update table set fields=value where keyid in ('1','2',....) 但如果这个数据量如果超过100 ...