我在学习D3D的深度测试和Alpha混合的时候,有一些遗憾。书上提供的例子里说一定要先渲染不透明物体,再渲染透明物体,对渲染状态的设置也有特殊要求。我看的很晕。自己查图形学的书,上网找资料,结果还是糊里糊涂。在和一个正在做游戏开发的大学同学的一点点的讨论中,我慢慢理解了深度测试和Alpha混合的关系,也就是为什么要那样设置渲染状态,为什么对渲染顺序有特殊要求。

在继续看之前,我推荐您看一下这个链接里的内容http://www.cnblogs.com/cocoaleaves/archive/2009/04/19/1438978.html,其中讲了一些理论知识,但是不够精细。所以我做了下面的补充。

我所说的前提是当前场景里同时需要深度测试和Alpha混合的情况。

Alpha混合不总是必需的。没有透明物体的场景就不需要Alpha混合了。如果Alpha测试足够了,就不需要Alpha混合了。Alpha混合需要更多的计算,所以不要随意使能。

先说说为什么对渲染顺序有特殊要求。为什么要先渲染不透明物体,再渲染透明物体呢?因为需要做Alpha混合,和谁混合呢?和颜色缓冲区里的像素颜色去混合。像素颜色来源于先渲染的不透明物体。所以要先渲染不透明物体。然后我想强调一点,“没有被不透明物体遮挡的透明物体”才需要和“被它遮挡住的物体”进行Alpha混合(被不透明物体遮挡了的透明物体做alpha就没意义了)。

再说说为什么在渲染不透明和透明物体的时候,渲染状态要分别做调整。下面用D3D代码说明。

g_pd3dDevice是有效的D3D设备对象指针,

// 绘制不透明物体的设置

g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, TRUE);

g_pd3dDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESS);

g_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);

g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);

对于不透明物体,使能ZBUFFER;设置ZFUNC,通过ZFUNC比较的像素才会被更新到颜色缓冲区;将新的Z值写入ZBUFFER;不需要ALPHA混合。这些设置是容易理解的,不需要特别解释了。

// 绘制透明物体的设置

//g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, TRUE);

//g_pd3dDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESS);

g_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);

g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);

g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND,  D3DBLEND_SRCALPHA);

g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);

然后来绘制透明物体,保持ZBUFFER使能,保持ZFUNC的比较,但是关闭ZBUFFER的写入。使能alpha混合,并设置混合方法。

保持ZFUNC的比较,使得透明物体的还可以被ZFUNC处理。也就是说,所以物体的遮挡关系保持正确,被不透明物体遮挡的物体还是看不到的。

关闭ZBUFFER的写入,是为了在透明物体遮挡了某些物体的时候,阻止ZBUFFER更新深度值。因为这时候我们看到的透明物体遮挡了某些物体的区域中的像素的颜色不是由不透明物体决定的,而是由“不透明物体的颜色”和“颜色缓冲区中的像素颜色”一起决定的。从这一点来看,该区域的像素深度值不应该更新。虽然不更新深度值,但是颜色缓冲区中的像素的颜色会被更新,更新的方法就是由alpha混合来决定。

设Z值取值范围是[0.0,1.0]。前面处理了不透明物体,假设现在ZBUFFER里面,最近的不透明物体的Z值是0.3。假设将要绘制的透明物体的Z值是0.1。因为ZBUFFER和ZFUNC都是参与渲染计算的,所以知道要将透明物体绘制在不透明物体前面。因为关闭了ZBUFFER的写入,所以当前Z值最小值还维持为0.3,也就是说由Z缓冲器处理的像素,透明物体的像素颜色不会代替不透明物体的颜色(不会发生颜色的完全覆盖)。

因为打开了alpha混合,所以具有0.3的Z值的像素点的颜色,由透明物体和被其遮挡的物体做某种混合计算得到。

最后的渲染结果就是,不透明和透明物体的远近关系是正确的,被不透明物体遮挡的物体依然不可见。而且,透明物体后面有其它物体时,像素点的颜色也是经过混合处理的。

希望我的解释可以给初学者有所帮助。

如需转载,请注明出处http://blog.sina.com.cn/zhangguangxu2011julyhope,谢谢。

D3D中深度测试和Alpha混合的关系的更多相关文章

  1. 【转载】D3D深度测试和Alpha混合

    原文:D3D深度测试和Alpha混合 1.       深度测试 a)         深度缓冲区:屏幕上每个像素点的深度信息的一块内存缓冲区.D3D通过比较当前绘制的像素点的深度和对应深度缓冲区的点 ...

  2. 《逐梦旅程 WINDOWS游戏编程之从零开始》笔记8——载入三维模型&Alpha混合技术&深度测试与Z缓存

    第17章 三维游戏模型的载入 主要是如何从3ds max中导出.X文件,以及如何从X文件加载三维模型到DirextX游戏程序里.因为复杂的3D物体,要用代码去实现,那太反人类了,所以我们需要一些建模软 ...

  3. [ZZ] D3D中的模板缓存(3)

    http://www.cppblog.com/lovedday/archive/2008/03/25/45334.html http://www.cppblog.com/lovedday/ D3D中的 ...

  4. DirectDraw打造极速图形引擎(Alpha混合)

    显然DirectDraw是Windows下写2D图形程序的最好选择,虽然Direct3D也可以写,但是没DirectDraw简单方便,特别对于初学者,一来就接触那么多函数和参数总不是件愉快的事,所以我 ...

  5. 【转载】D3D中的Texture应用示例

    原文:D3D中的texture应用示例 本文列举了Direct3D中各种纹理应用实现:黑暗贴图,发光贴图,漫反射映射贴图,细节纹理,纹理混合,有较详尽的注解.其中黑暗贴图,发光贴图,细节纹理都是采用多 ...

  6. D3D中的渲染状态简介

    1). 设置着色模式: SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT) //设置平面着色模式 SetRenderState(D3DRS_SHADEMODE ...

  7. ImagXpress中如何修改Alpha通道方法汇总

    ImagXpress支持处理Alpha通道信息来管理图像的透明度,Alpha通道支持PNG ,TARGA和TIFF文件,同时还支持BMP和ICO文件.如果说保存的图像样式不支持Alpha通道,就将会丢 ...

  8. 【转载】Alpha混合物体的深度排序

    原文:Alpha混合物体的深度排序 先说个题外话, 本来我想解答一下最近Creators Club论坛上经常出现的一个问题, 意外的是在网上竟然找不到什么全面的答案.. 这是个有着复杂答案的简单问题: ...

  9. Alpha混合

    ShaderLab syntax: Blending 混合 Blending is used to make transparent objects. 混合是用来制作透明物体的. When graph ...

随机推荐

  1. nginx上如何支持.htaccess伪静态转向

    我们知道在apache上有一个常用的功能.htaccess转向,只要apache编译的时候指明支持rewrite模块就可以了. 但是换到nginx上方法会有一点不一样,网上很多人说把.htaccess ...

  2. UML状态图(转载)

    概述: 图表本身的名称,阐明该图的目的和其他细节.它描述了在一个系统中的一个组成部分不同的状态.状态是特定的一个系统的组件/对象. 状态图描述了一个状态机.我们阐明的状态机可以被定义为一台机器,它定义 ...

  3. 索引服务混战ASP.NET――微软的又一个隔离墩

    话说月初笔者在华山之巅搞定了ASP.NET一起莫名奇妙的异常,自此之后和公主过着…嘟--,不好意思,书都看杂了,串了台了.好,咱们闲言少叙,书归正传. 自从上次解决了由调试文件库引起的ASP.NET执 ...

  4. HDOJ 1398 Square Coins 母函数

    Square Coins Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Tota ...

  5. wordpress无法安装这个包。: PCLZIP_ERR_MISSING_FILE (-4) : Missing archive file 'C:\WINDOWS\TEMP/wordpress-4.tmp'

    朋友的wp博客好久没管理了,让ytkah帮忙打理一下,进到后台发现版本还是3.9的,那是比较早以前的版本了,早该升级了. 在升级wordpress时出现以下错误: 无法安装这个包: PCLZIP_ER ...

  6. maven 构建spring ssh mybatis 配置

    详情参与 http://blog.csdn.net/yuguiyang1990/article/details/8811817 前面我们使用Maven构建了Struts2项目,这里我们来试一下Hibe ...

  7. PHP-Java-Bridge使用笔记,2014年9月最新版

    这是我在做平安银行开发的时候,本地使用PHP环境,平安银行接口为Java接口的时候,采用PHP-Java-Bridge的方式调用接口的笔记.因为现在网上的教程基本上都不行了,所以在这里贴出我能使用的而 ...

  8. STM32 对内部FLASH读写接口函数

    因为要用内部FLASH代替外部EEPROM,把参数放在STM32的0x08000000+320K处,其中20K是bootloader,300K是应用程序. 原理:先要把整页FLASH的内容搬到RAM中 ...

  9. 【译】Python中如何创建mock?

    原文地址:http://engineroom.trackmaven.com/blog/making-a-mockery-of-python/ 今天我们来谈论下mock的使用.当然,请不要误会,这里的m ...

  10. Android内存泄漏问题(一)

    前言 不少人认为JAVA程序,因为有垃圾回收机制,应该没有内存泄露. 其实如果我们一个程序中,已经不再使用某个对象,但是因为仍然有引用指向它,垃圾回收器就无法回收它,当然该对象占用的内存就无法被使用, ...