先从最基础的写起吧,关于Device的渲染流程.
D3D9的Device就是D3D给我们提供的一个绘制3D图形的工具,它的绘制流程大致是这样的:
*.首先Device的使用者要准备好顶点数据,也就是一个顶点的数组,称为A
*.然后这个数组A被传入device的渲染管线
*.device内部依次对每个顶点进行处理,有两种模式,固定管线和shader模式,所谓固定管线就是device内部实现的一个固定的程 序,用户只能通过设定各种参数(一些RenderState)来控制它,当然这不够灵活,所以有了shader模式,也就是说,用户需要写一个程序片段 (所谓vertex shader),传给device,然后device使用这个片段对每个顶点进行处理.这个程序片段是在显卡上执行的.
*.传入的顶点数组A的每一个元素被转换后,存储到另一个数组B中.数组B中的每个元素必须至少包含一个透视空间的位置,用来做裁剪.
*.数组B被传入到device的下一个计算阶段,在这个阶段里,数组B中的(被转换过的)顶点被组织成一个个三角形,然后对这些三角形进行裁 剪(视域体裁剪! 利用顶点数据里包含的那一个透视空间的位置),背面剔除(注意背面剔除和顶点的法线是没关系的),最后剩下的三角形被保存到一个数组C中.(注意在这 个阶段里顶点数组变成了三角形数组)
*.数组C被传入到下一个计算阶段,光栅化,对于数组C中每一个三角形,首先把它们从透视空间映射到屏幕空间,然后找出它们在屏幕上覆盖的像素 (一个三角形覆盖的像素的数量有可能是很多的),对于每一个像素,根据它在三角形中的位置,通过三角形的顶点进行线性插值,计算出一个像素数据(注意像素 数据是通过三角形的顶点数据插值而来,所以它们的数据类型是一致的),所有三角形算出来的像素数据最后被存储到一个数组D中.(在这个阶段里,三角形的数组变成了像素数据数组)
*.数组D被传入到下一个计算阶段,在这个阶段里,device会对这些像素做一些初步的过滤,主要是进行stencil test(根据stencil
buffer上的值)和z-test(根据这个像素的Z值和z-buffer上的值进行比较),根据测试结果会对stencil buffer进行一些修改(使用一组render state来控制这个过程),通过这些test的像素被存储到数组E.
*.数组E被传入到下一个计算阶段,在这个阶段里,device对每个像素数据进行处理,这个阶段也有两种模式,固定管线和shader模式, 与顶点处理阶段类似,用户也可以写一个程序片段,来对每一个像素数据进行处理,称为pixel shader.像素数据可能包含各种类型的数据,但经过这一阶段的处理后,输出是很简单的,一般就是一个颜色值和一个alpha值(透明度),也可以输出 一个Z值,不过好像不常用.在pixel shader里还可以使用专门的指令来放弃某一个像素的后续处理.所有的像素数据被处理后,结果存在一个数组F中.
*.数组F进入下一个阶段,在这一个阶段里,进行alpha test(根据像素的alpha 值),alpha test是最后一个test了,通过了alpha test的像素可以保证绘制到屏幕上去,通过test的像素会把它们的z值更新到z-buffer中去(具体由一组render state控制),通过test的像素被存入数组G
*.数组G进入下一个阶段,在这个阶段里,主要是把数组G里的像素和屏幕上已有的像素进行混合,具体混合的方式有多种多样,由一系列render state进行控制.混合以后的像素就被"画"到屏幕上了
基本上的流程就是这样了,环节很多,每个环节也有很多技巧,很多需要注意的地方,太多了,就不铺开来写了,我觉得这个流程很重要,虽然理解起来 并不困难,但真的能够非常熟练的记住它,并且运用其中的各个环节来解决实际的问题就不是那么容易的事了.所以不厌其烦的又把它粗粗的写了一遍,希望自己也 能进一步加深印象.
最近正在写关于多线程渲染的代码,下一回可能写写这方面的东西.
谢谢楼下的评论纠正了我的一个错误,stencil test和depth test的确是在pixel shader后才进行的,虽然这看上去没什么道理, 不过标准的渲染应该是这样的流程,但好像某些显卡会在pixelshader前做一些早期的test(early-z和early-stencil)来提高性能,我希望这样的显卡越多越好.看来我要去重新check一下引擎中使用stencil buffer提高性能的地方了,不过好像当时的测试的确是提高了一些性能的.
是先进行pixel shader的处理,再进行test的。所以事实上就存在博主所说的问题,在一些情况下,会有大量的pixel经过复杂的处理最终却在test阶段被扔掉了。正是因为如此才会有Deferred shading的出现。
#7楼 起名字好麻烦[未注册用户]
当前的显卡都支持所谓的early-z技术吧,即先depth/stencil test再ps。
因此会出现先绘制一遍depth的做法,一是因为n卡(a卡不清楚)只写depth不写color时速度是2倍,二是因为可以通过early-z裁掉可能被遮挡的像素,避免出现像素重绘的情况。
至于Deferred Shading,是为了处理其他的问题,跟这个讨论关联不大
#8楼 起名字好麻烦[未注册用户]
不好意思没看见楼主下面的红字。
按照GPU标准流程确实是depth test在ps之后,不过我估计这样做是有历史原因的,在FFP时代,GPU瓶颈还不是(或不全是)ps,所以早期裁掉一些pixel可能意义不大。
#9楼 champson[未注册用户]
pixel shader有可能会改变depth的值,所以如果在PS之前做depth test可能会有些错误,同时还要考虑alpha blending,alpha test,texkill等情况。如果没有这些情况发生的,那可以在PS之前做depth test进行优化。
建议楼主看看DirectX流式数据优化和延迟着色,这个是未来图形引擎的发展方向:)
回7楼:deferred shading还是有关系的,deferred shading在某种程度上也是一种early z-out的方式.
回10楼:DirectX流式数据优化还真没听说过,google了一下,好像是dx10的东西,目前dx10没打算研究,主要是没有时间,而且vista也不是一个成功的操作系统,等它再流行一点再说吧,或者直接跳到将来的dx11呵呵.deferred shading已经在用了,对配置要求还是挺高的,架构影响也不小.