我在学习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,谢谢。

最新文章

  1. js厘米与英寸尺码转换
  2. Python积木之with
  3. AutoCompleteTextView输入汉字拼音首字母实现过滤提示(支持多音字,Filterable的使用)
  4. 第一个c++程序 helloworld
  5. 4.2 CUDA Reduction 一步一步优化
  6. 说说读卡应用那点事儿,以SCL010为例
  7. aStar算法求第k短路
  8. ng自定义一个过滤器
  9. JAVA课设---五子棋
  10. java分页算法,传入当前pageIndex,pageSise,dataTotal可计算出页面上显示的页码,和是否启动上一页下一页
  11. shell脚本解压多个jar包
  12. [Swift]LeetCode698. 划分为k个相等的子集 | Partition to K Equal Sum Subsets
  13. spring-data-mongodb中的MongoTemplate与MongoRepository
  14. 运维wiki
  15. python 模块之-ffmpeg 中文参数对照表
  16. java获取当前时间精确到毫秒
  17. python函数-基础篇
  18. (转)怎么实时查看mysql当前连接数
  19. python之WSGI与Guincorn
  20. Linux 各种软件的安装-Apache + php 篇

热门文章

  1. var 和 dynamic在实际项目中的应用
  2. NGUI无法按住鼠标按住时无法监听OnHover事件
  3. List Comprehensions
  4. LINUX下的时间与时区的设置
  5. Codeforces 294B Shaass and Bookshelf(记忆化搜索)
  6. P==NP??
  7. swift循环
  8. ****Web API 版本控制的几种方式
  9. C# 调用Windows API实现两个进程间的通信
  10. Integral类型的跨平台使用