简单的透明:Jeff Molofee(NeHe) 的 OPENGL 教程-第八课

原创 2001年10月08日 22:11:00

 

 

Jeff Molofee(NeHe) 的 OPENGL 教程

第八课

Translated by
CKER
 

Lesson 8第八课

简单的透明

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,最后才到达观察者的眼睛。)
深度缓存启用时,您应该将透明图形按照深度进行排序,并在全部场景绘制完毕之后再绘制这些透明物体。否则您将得到不正确的结果。我知道某些时候这样做是很令人痛苦的,但这是正确的方法。
我们将使用第七课的代码。一开始先在代码开始处增加两个新的变量。出于清晰起见,我重写了整段代码。


然后往下移动到 LoadGLTextures() 这里。找到" if (TextureImage[0]=LoadBMP("Data/Crate.bmp")) "这一行。我们现在使用有色玻璃纹理来代替上一课中的木箱纹理。
InitGL()代码段加入以下两行。第一行以全亮度绘制此物体,并对其进行50%的alpha混合(半透明)。当混合选项打开时,此物体将会产生50%的透明效果。第二行设置所采用的混合类型。
Rui Martins 的补充: alpha通道的值为 0.0意味着物体材质是完全透明的。1.0 则意味着完全不透明。

在接近第七课结尾处的地方找到下面的代码段。

接着上面的代码,我们增加如下的代码。这几行监视B键是否按下。如果是的话,计算机检查混合选项是否已经打开。然后将其置为相反的状态。

但是怎样才能在使用纹理贴图的时候指定混合时的颜色呢?很简单,在调整贴图模式时,文理贴图的每个象素点的颜色都是由alpha通道参数与当前地象素颜色相乘所得到的。比如,绘制的颜色是 (0.5, 0.6, 0.4),我们会把颜色相乘得到(0.5, 0.6, 0.4, 0.2) (alpha参数在没有指定时,缺省为零)。
就是如此!OpenGL实现Alpha混合的确很简单!

原文注 (11/13/99)

我(NeHe)混色代码进行了修改,以使显示的物体看起来更逼真。同时对源象素和目的象素使用alpha参数来混合,会导致物体的人造痕迹看起来很明显。 会使得物体的背面沿着侧面的地方显得更暗。基本上物体会看起来很怪异。我所用的混色方法也许不是最好的,但的确能够工作。启用光源之后,物体看起来很逼真。感谢Tom提供的原始代码,他采用的混色方法是正确的,但物体看起来并不象所期望的那样吸引人:)
代码所作的再次修改是因为在某些显卡上glDepthMask()函数存在寻址问题。这条命令在某些卡上启用或关闭深度缓冲测试时似乎不是很有效,所以我已经将启用或关闭深度缓冲测试的代码转成老式的glEnableglDisable

纹理贴图的Alpha混合

用于纹理贴图的alpha参数可以象颜色一样从问题贴图中读取。方法如下,您需要在载入所需的材质同时取得其的alpha参数。然后在调用glTexImage2D()时使用GL_RGBA的颜色格式。

『译者:NeHe的文档似乎很简单,似乎很罗嗦。但仔细想来这样的高手您又见过几个?还是那句话,我不是高手,希望您是,真诚的。』
下面是源代码下载链接。祝您好运!

Tom Stanis

* DOWNLOAD
Visual C++ Code For This Lesson.
* DOWNLOAD
Visual C++ / OpenIL Code For This Lesson. ( Conversion by Denton Woods )
* DOWNLOAD
Visual Basic Code For This Lesson. ( Conversion by Peter De Tagyos )
* DOWNLOAD
Visual Fortran Code For This Lesson. ( Conversion by Jean-Philippe Perois )
* DOWNLOAD
GLUT Code For This Lesson. ( Conversion by Andy Restad )
* DOWNLOAD
Game GLUT Code For This Lesson. ( Conversion by Milikas Anastasios )
* DOWNLOAD
Cygwin (FREE Language) Code For This Lesson. ( Conversion by Stephan Ferraro )
* DOWNLOAD
Delphi Code For This Lesson. ( Conversion by Marc Aarts )
* DOWNLOAD
MASM Code For This Lesson. ( Conversion by Nico (Scalp) )
* DOWNLOAD
Linux/GLX Code For This Lesson. ( Conversion by Mihael Vrbanec )
* DOWNLOAD
MacOS X/GLUT Code For This Lesson. ( Conversion by Raal Goff )
* DOWNLOAD
Linux Code For This Lesson. ( Conversion by Richard Campbell )
* DOWNLOAD
Linux/SDL Code For This Lesson. ( Conversion by Ti Leggett )
* DOWNLOAD
Irix Code For This Lesson. ( Conversion by Lakmal Gunasekara )
* DOWNLOAD
Solaris Code For This Lesson. ( Conversion by Lakmal Gunasekara )
* DOWNLOAD
Mac OS Code For This Lesson. ( Conversion by Anthony Parker )
* DOWNLOAD
Power Basic Code For This Lesson. ( Conversion by Angus Law )
* DOWNLOAD
BeOS Code For This Lesson. ( Conversion by Chris Herborth )
* DOWNLOAD
Java Code For This Lesson. ( Conversion by Darren Hodges )
* DOWNLOAD
MingW32 & Allegro Code For This Lesson. ( Conversion by Peter Puck )
* DOWNLOAD
Borland C++ Builder 4.0 Code For This Lesson. ( Conversion by Patrick Salmons )

简单的透明:Jeff Molofee(NeHe) 的 OPENGL 教程-第八课

简单的透明OpenGL中的绝大多数特效都与某些类型的(色彩)混合有关。混色的定义为,将某个象素的颜色和已绘制在屏幕上与其对应的象素颜色相互结合。至于如何结合这两个颜色则依赖于颜色的alpha通道的分量...
  • feijj2002_
  • feijj2002_
  • 2005年09月07日 13:12
  • 1038

Jeff Molofee(NeHe)的OpenGL教程--着色

原 文:Lesson 3: Colors译 者:CKER  上一课中我教给您三角形和四边形的绘制方法。这一课我将教您给三角形和四边形添加2种不同类型的着色方法。使用单调着色(Flat coloring...
  • llldddrrr
  • llldddrrr
  • 2006年11月03日 19:55
  • 566

Jeff Molofee(NeHe)的OpenGL教程--二次曲面

原 文:Lesson 18: Quadrics译 者:sakura  二次曲面是一种画复合对象的方法,这种方法通常并不需要很多的三角形。我们将要使用第七课的代码。我们将要增加7个变量以及修改纹理以增加...
  • llldddrrr
  • llldddrrr
  • 2006年11月03日 19:41
  • 747

Jeff Molofee(NeHe)的OpenGL教程

原 文:Lesson 16: Cool Looking Fog译 者:sakura  难道你不想把“雾”加入到你的OpenGL程序中吗?那么在这课里我将要为您展现如何实现这项功能。这是我第一次写教程,...
  • llldddrrr
  • llldddrrr
  • 2006年11月03日 19:28
  • 798

Jeff Molofee(NeHe)的OpenGL教程--纹理映射

原 文:Lesson 6: Texture Mapping译 者:CKER  学习Texture Map纹理映射(贴图)有很多好处。比方说您想让一颗导弹飞过屏幕。根据前几课的知识,我们最可行的办法可能...
  • llldddrrr
  • llldddrrr
  • 2006年11月03日 19:51
  • 1422

Jeff Molofee(NeHe) 的 OPENGL 教程-第一课

{ 译者的话:NeHe的教程一共有30多课,内容翔实,并且不断更新。国内的网站实在应该向他们学习。令人惊讶的是,NeHe提供的例程源码几乎都有跨平台的不同编译版本,涉及从Visual C++、Borl...
  • feijj2002_
  • feijj2002_
  • 2005年09月07日 12:55
  • 1427

opengl学习笔记1:vs2013 nehe教程第一课 创建窗口

近来需要想学习一下opengl,但是小白没有任何基础,也非计算机专业出身,只能一步一步学习nehe的程序来学习了。这里实现了在WIN10 vs2013 opengl2.0 环境下跑通nehe教程第一课...
  • caimagic
  • caimagic
  • 2016年01月29日 15:11
  • 1014

【OpenGL】nehe教程第一课学习笔记

nehe教程的第一课主要讲了OpenGL程序的创建。 它引用了最基本的gl.h、glu.h、glaux.h三个头文件。 包含了五个函数,分别是InitGL、ResizeGLScene、DrawGLSc...
  • lzh1590
  • lzh1590
  • 2017年03月22日 16:22
  • 238

新手上路:Jeff Molofee(NeHe) 的 OPENGL 教程-第一课

Jeff Molofee(NeHe) 的 OPENGL 教程#1
  • cker
  • cker
  • 2001年04月28日 00:04
  • 4198

对OpenGL的初步认识及多版本框架介绍(基于NeHe的OpenGL教程)

由于以后接触的技术和图形有关,所以最近也是来学学习一下opengl的相关知识点。当然有看到《opengl编程指南》这本红宝书,但是对于初学者来言,这本书需要花很多精力,所以我找到了《NeHe的open...
  • aptx704610875
  • aptx704610875
  • 2014年06月30日 01:25
  • 1440
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:简单的透明:Jeff Molofee(NeHe) 的 OPENGL 教程-第八课
举报原因:
原因补充:

(最多只允许输入30个字)