转至繁体中文版     | 网站首页 | 图文教程 | 资源下载 | 站长博客 | 图片素材 | 武汉seo | 武汉网站优化 | 
最新公告:     敏韬网|教学资源学习资料永久免费分享站!  [mintao  2008年9月2日]        
您现在的位置: 学习笔记 >> 图文教程 >> 软件开发 >> Delphi程序 >> 正文
NeHe的opengl教程delphi版(8)----简单的透明         ★★★★

NeHe的opengl教程delphi版(8)----简单的透明

作者:闵涛 文章来源:闵涛的学习笔记 点击数:1463 更新时间:2009/4/23 18:37:36

{

呵呵,这两课早就翻译好了,一直没贴,大家久等了(有人再等吗?)

简单的透明
OpenGL中的绝大多数特效都与某些类型的(色彩)混合有关。
混色的定义为,将某个象素的颜色和已绘制在屏幕上与其对应的象素颜色相互结合。
至于如何结合这两个颜色则依赖于颜色的alpha通道的分量值,以及/或者所使用的混色函数。
Alpha通常是位于颜色值末尾的第4个颜色组成分量。
前面这些课我们都是用GL_RGB来指定颜色的三个分量。
相应的GL_RGBA可以指定alpha分量的值。
更进一步,我们可以使用glColor4f()来代替glColor3f()。

绝大多数人都认为Alpha分量代表材料的透明度。
这就是说,alpha值为0.0时所代表的材料是完全透明的。
alpha值为1.0时所代表的材料则是完全不透明的。

混色的公式
若您对数学不感冒,而只想看看如何实现透明,请跳过这一节。
若您想深入理解(色彩)混合的工作原理,这一节应该适合您吧。
『CKER的补充:其实并不难^-^。原文中的公式如下,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,最后才到达观察者的眼睛。)
在深度缓存启用时,您应该将透明图形按照深度进行排序,
并在全部场景绘制完毕之后再绘制这些透明物体。否则您将得到不正确的结果。
我知道某些时候这样做是很令人痛苦的,但这是正确的方法。

我们将使用第七课的代码。
一开始先在代码开始处增加两个新的变量。出于清晰起见,我重写了整段代码。

}
Var
   h_RC             : HGLRC;            // Rendering Context(着色描述表)。
   h_DC             : HDC;              // Device Context(设备描述表)
   h_Wnd            : HWND;             // 窗口句柄
   h_Instance       : HINST;            // 程序Instance(实例)。
   keys             : Array[0..255] Of Boolean; // 用于键盘例程的数组

   light            : Boolean;          // 光源的开/关

   blend            : Boolean;          // Blending OFF/ON? ( 新增 )

   lp               : Boolean;          // L键按下了么?
   fp               : Boolean;          // F键按下了么?

   bp               : Boolean;          // B 键按下了么? ( 新增 )

   xrot             : GLfloat;          // X 旋转
   yrot             : GLfloat;          // Y 旋转
   xspeed           : GLfloat;          // X 旋转速度
   yspeed           : GLfloat;          // Y 旋转速度

   z                : GLfloat = -5.0 f; // 深入屏幕的距离
   LightAmbient     : Array[0..3] Of GLfloat = (0.5, 0.5, 0.5, 1.0);  //环境光参数 ( 新增 )
   LightDiffuse     : Array[0..3] Of GLfloat = (1.0, 1.0, 1.0, 1.0);  // 漫射光参数 ( 新增 )
   LightPosition    : Array[0..3] Of GLfloat = (0.0, 0.0, 2.0, 1.0);  // 光源位置 ( 新增 )
   filter           : GLuint;           // 滤波类型
   texture          : Array[0..2] Of GLuint; // 3种纹理的储存空间

Procedure glGenTextures(n: GLsizei; Var textures: GLuint); stdcall; external
   opengl32;

Procedure glBindTexture(target: GLenum; texture: GLuint); stdcall; external
   opengl32;

Function gluBuild2DMipmaps(target: GLenum; components, width, height: GLint;
   format, atype: GLenum; data: Pointer): Integer; stdcall; external glu32 name
   ''''gluBuild2DMipmaps'''';

{
然后往下移动到 LoadGLTextures() 这里。
找到 if (TextureImage[0]=LoadBMP(''''Data/Crate.bmp''''))
这一行。我们现在使用有色玻璃纹理来代替上一课中的木箱纹理。
if (TextureImage[0]=LoadBMP("Data/glass.bmp")); // 载入玻璃位图 ( 已修改 )
}

Function LoadTexture: boolean;          // 载入位图并转换成纹理
Var
   Status           : boolean;          // Status 指示器
   TextureImage     : Array[0..1] Of PTAUX_RGBImageRec; // 创建纹理的存储空间
Begin
   Status := false;
   ZeroMemory(@TextureImage, sizeof(TextureImage)); // 将指针设为 NULL
   TextureImage[0] := LoadBMP(''''Walls.bmp'''');
   If TextureImage[0] <> Nil Then
      Begin
         Status := TRUE;                // 将 Status 设为 TRUE
         glGenTextures(1, texture[0]);  // 创建纹理
         // 创建 Nearest 滤波贴图
         glBindTexture(GL_TEXTURE_2D, texture[0]);
         // 生成纹理
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);  // ( 新增 )
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);  // ( 新增 )

         glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0].sizeX,
            TextureImage[0].sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE,
            TextureImage[0].data);
         glBindTexture(GL_TEXTURE_2D, 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_MIN_FILTER, GL_LINEAR);  // 线形滤波
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);  // 线形滤波
         // 创建 MipMapped 纹理
         glBindTexture(GL_TEXTURE_2D, texture[2]);
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
            GL_LINEAR_MIPMAP_NEAREST);  // ( 新增 )
         gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TextureImage[0].sizeX,
            TextureImage[0].sizey, GL_RGB, GL_UNSIGNED_BYTE,
            TextureImage[0].data);      //(新增)  }
      End;
   If assigned(TextureImage[0]) Then    // 纹理是否存在
      If assigned(TextureImage[0].data) Then // 纹理图像是否存在
         TextureImage[0].data := Nil;   // 释放纹理图像占用的内存
   TextureImage[0] := Nil;              // 释放图像结构
   result := Status;                    // 返回 Status
End;

{
在glInit()代码段加入以下两行。
第一行以全亮度绘制此物体,并对其进行50%的alpha混合(半透明)。
当混合选项打开时,此物体将会产生50%的透明效果。
第二行设置所采用的混合类型。

Rui Martins 的补充:
alpha通道的值为 0.0意味着物体材质是完全透明的。
1.0 则意味着完全不透明。
}

Procedure glInit();                     // 此处开始对OpenGL进行所有设置
Begin
   If (Not LoadTexture) Then   

[1] [2]  下一页


[系统软件]InstallShield Express for delphi制作安装程序定…  [常用软件]InstallShield Express制作Delphi数据库安装程序
[Delphi程序]为什么选择Delphi.Net ?  [Delphi程序]《关于VisiBroker For Delphi的使用》(4)
[Delphi程序]Delphi 程序员代码编写标准指南  [Delphi程序]转贴:Conversion to Delphi 6: Missing unit Pro…
[Delphi程序]Borland Delphi 9 的新特性  [Delphi程序]Delphi 键盘码表
[Delphi程序]Chuck Jazdzewski的离开意味着Delphi的终结吗?  [Delphi程序]Delphi Access violations 问题的解决之道
教程录入:mintao    责任编辑:mintao 
  • 上一篇教程:

  • 下一篇教程:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
      注:本站部分文章源于互联网,版权归原作者所有!如有侵权,请原作者与本站联系,本站将立即删除! 本站文章除特别注明外均可转载,但需注明出处! [MinTao学以致用网]
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)

    同类栏目
    · C语言系列  · VB.NET程序
    · JAVA开发  · Delphi程序
    · 脚本语言
    更多内容
    热门推荐 更多内容
  • 没有教程
  • 赞助链接
    更多内容
    闵涛博文 更多关于武汉SEO的内容
    500 - 内部服务器错误。

    500 - 内部服务器错误。

    您查找的资源存在问题,因而无法显示。

    | 设为首页 |加入收藏 | 联系站长 | 友情链接 | 版权申明 | 广告服务
    MinTao学以致用网

    Copyright @ 2007-2012 敏韬网(敏而好学,文韬武略--MinTao.Net)(学习笔记) Inc All Rights Reserved.
    闵涛 投放广告、内容合作请Q我! E_mail:admin@mintao.net(欢迎提供学习资源)

    站长:MinTao ICP备案号:鄂ICP备11006601号-18

    闵涛站盟:医药大全-武穴网A打造BCD……
    咸宁网络警察报警平台