基本上是《3D Game Engine Architecture》第3章的剩余内容,说实话我有点后悔看这个了,应该直接看《3D Game Engine Design 2nd》,不过好歹记录一下,有些“亮点”我第一次看到还是不错的。
1 wild magic3 render state
主要包括global state, lights, texture, effects
1) global state包括:
alpha: 是否启用混合,srcblend, dstblend; 是否启用alpha test, test方法,test ref value
cull: 是否启用culling, front face ccw or cw, cull face back or front
dither:是否开启抖动
fog: 是否启用fog, fog mode(linear,exp, exp_sqr), start,end, density, color, per_vertex/per_pixel
material: 即光照材质,emissive, ambient, diffuse, specular和shininess
shade:flat or smooth(Gouraud shading)
wireframe: 是否启用线框模式
zbuffer: 是否使用zbuffer, zwrite, z compare func
每种state都是集成自GlobalState的一个类,比如ZBufferState
每个Spatial拥有一个 global state列表,列表里每种global state只能有一个。Spatial的global state列表不是直接用来渲染的,后面还要通过UpdateRS来沿着tree收集所有的global state,最终给Geometry使用。Geometry类里面有一个global state数组,维数为global state种类数目。(UpdateRS机制后面说)
2) light
Light 类继承自Spatial,没啥可说的,都是光源的属性。不过WM3中,AMBIENT也算是一种光源,和平行光,点光源等并列了,我们知道在OpenGL 中是可以设置一个场景的ambient的,WM3中的这种光源是否就是场景ambient,如果是,只能有一个吗?
和global state一样,每个Spatial也拥有一个Light列表,Geometry类有一个使用到的Light smart ptr数组,其实是指向挂在scene tree上的那些light的。
3) Texture
WM3的texture类中封装了如下内容:
Image: 贴图(是个smart ptr)
texture correction hint: 即是否使用透视纹理校正 ( perspective or affine)
filter mode: nearest or linear
mipmap mode: nearest , linear(这两个和filter mode里面其实是一样,就是不用mipmap了)
nearest_nearset, nearset_linear, linear_nearest, linear_linear(所谓的三线性过滤)
u,v的clamp mode: clamp, repeat, clamp_border, clamp_edge (没有mirror), 以及border color
tex gen: 支持environment map, projected_texture (不知道当硬件不支持时是否可以手动计算)
apply mode和blend color:即opengl的tex env mode,包括:replace, decal, modulate, blend, add, combine
multi-texture设置(针对apply mode为combine):combine func RGB/RGBA, combine src RGB/Alpha 0,1,2; CombineOpRGB/Alpha 0,1,2; scaleRGB, scaleAlpha
基本上他封装了所有纹理相关的内容了
4)Effect
这个Effect包含顶点色数组(RGB or RGBA),一组纹理的smart ptr, 一组uv坐标
2 wild magic3渲染状态更新体系
WM3 可以scene grapha的各个节点上挂接渲染状态和灯光(上面说的global state和light),而只有叶子节点也就是Geometry使用渲染状态和灯光,通过UpdateRS,将每层挂接的global state和light向下传递,对于同类型的global state,子一层的设置会屏蔽上层的设置(每种state都有一个stack,遇到设置该state就push进去,最后使用的是pop出来的,也就是最后一次push的,显然是最后一次设置的状态),到叶子节点也就是Geometry这儿,将各类状态stack的top pop出来存放到Geometry的global state数组中,供渲染时使用。
这儿还有另外一个问题,引发UpdateRS的那个节点,需要向上直到ROOT收集渲染状态和灯光,而所有的状态都有一个默认值。这是通过PropagateStateFromRoot实现的。
所有这些状态和灯光都是shared ptr,所以WM3里面,只有状态被添加或移走时才需要更新RS。
关于这些,我不想多写了,看代码一目了然,而且我想知道WM4里面是怎么弄的了。不过这种基于scene grapha的渲染状态树我之前没见到过,irrlicht中,每个需要渲染的节点是自己设置这些状态的,driver层会设置默认状态。WM3这种机制有什么好处还要看看~
3 scene渲染
1)首先camera会有个culling操作,基于bound volume,这儿有两个东西有点意思:
camera有个32bit的标志,每个裁剪面占一位,执行culling时,由于是从上到下沿着树深度优先绘制的,所以父空间先检测,这个标志位就是标志父空间是否完全在某个面的内部,如果是,那么子空间做检测时就不用检测这个面了。(当然反过来是不行的)这样效率确实要高些。
camera支持手动push/pop culling面(不是clip plane).这些面只用来做culling检测,这对于portal系统很有用,WM3利用push/pop culling面实现了一套portal系统检测
2)scene渲染:这块儿没怎么看了,准备直接看WM4的,大概就是一个OnDraw和一个Draw, onDraw里面检测culling,并且调用draw, 而draw对于spatial是一个纯虚函数,Node的draw会调用子节点的OnDraw形成递归,Geometry的draw直接调用 renderer的draw(Geometry*),这里面会设置当前使用的geometry和effect,调用DrawPrimitive去执行。当然这儿还有一个所谓DrawDeferred,后面才讲不知道是什么。另外还有所谓global effect被设置时,node会直接调用draw。
DrawPrimitve里面就是:
设置渲染状态,
启用lighting,vertices,normals,vertex colors,texture units,
设置transformation matrix
draw object
restore transformation matrix
禁用texture units, vertex colors, normals, vertices, lighting