书法字典:https://www.shufadict.com

用DirectX实现粒子系统(一)

引言

Point sprites,中文译成点精灵,是粒子系统的基础,本篇主要介绍point sprites的相关知识,为后续的粒子系统做准备。

Point Sprites(点精灵)

Point sprites是DirectX8中引入的一个新特性,主要是用来高效渲染粒子系统,使用point sprites做为底层数据结构,表示层配以纹理,可以呈现出任意形状的粒子。粒子系统应用十分广泛,可以用来模拟许多特殊效果,比如常见的爆炸,烟雾,火焰等,都可以用粒子系统实现。point sprites不支持固定的几何管线,只能使用可编程的顶点处理程序。

Point Primitive Rendering Controls(点的渲染控制)

DX8支持额外的参数来控制point sprites。这些参数使得点的大小是可变的并且可以进行完整的纹理映射。

Point size控制

点的大小由两个因素决定,一个是应用程序自定义的大小,另一个是点到摄像机的距离。应用程序可以通过两种方式来指定点的大小,一是逐个顶点设置,二是通过设置D3DRS_POINTSIZE,点的大小是基于camera space的,除非你使用的是post-transformed flexible vertex format(FVF)vertices。这种格式的顶点是经过变换的,所以点的大小是基于render target上的像素单位。下面的代码通常用来设置point size,由于SetRenderState接受DWORD类型的参数,所以需要一个float到DWORD的转换过程。

float pointSize =1.0f ;
m_device
->SetRenderState( D3DRS_POINTSIZE, *((DWORD*)&pointSize) );

如果D3DRS_POINTSCALEENABLE设置为TRUE,那么D3DRS_POINTSIZE中指定的值是基于word space的,如果D3DRS_POINTSCALEENABLE设置为FALSE,则D3DRS_POINTSIZE中指定的值是基于screen space的。如果用户逐个顶点指定了point size,那么D3DRS_POINTSIZE的值就不起作用了。

m_device->SetRenderState( D3DRS_POINTSPRITEENABLE, TRUE) ;

纹理坐标控制

D3D通过下面的方式计算点的纹理坐标,如果D3DRS_POINTSPRITEENABLE设置为TRUE,那么每个点都显示一个完整的纹理(具体的算法,稍后有述),通常,这只在点大于一个像素的时候有用。当D3DRS_POINTSPRITEENABLE设置为FALSE的时候,每个点的纹理坐标都应用于整个顶点。

Point size computation(计算点的大小)

点的大小由D3DRS_POINTSCALEENABLE决定,如果该字段设置为FALSE,就使用程序指定的大小(经过变换的)作为屏幕坐标系中的最终大小。如果该字段设置为TRUE,D3D使用下面的公式计算。

这里Si表示输入点的大小,可能是Vertex定义中指定的值,也可能是D3DRS_POINTSIZE指定的值。A,B和C分别代表D3DRS_POINTSCALE_A,D3DRS_POINTSCALE_B和D3DRS_POINTSCALE_C,Vh是Viewport的高度,De是眼睛到该点的距离(眼睛位于原点),De的计算方式如下

point size的最大值Pmax由D3DCAPS中的MaxPointSize和D3DRS_POINTSIZE_MAX这个渲染状态共同决定,取二者的最小值。最小值Pmin则由D3DRS_POINTSIZE_MIN这个渲染状态决定,所以点在屏幕坐标系中的最终大小由下面的方式决定。

Point Rendering(点的渲染)

一个屏幕坐标系中的点P = (X, Y, Z, W),若它在屏幕坐标系中的大小是S,则它被渲染成一个四边形,公式如下((X+S/2, Y+S/2, Z, W), (X+S/2, Y-S/2, Z, W), (X-S/2, Y-S/2, Z, W), (X-S/2, Y+S/2, Z, W)),这四个点的颜色是相同的,所以,点的颜色通常都是单一的。纹理的坐标是由D3DRS_POINTSPRITEENABLE这个渲染状态控制的。如果这个值被设置为FALSE,那么四个点的纹理坐标就是相同的,如果这个值设置为TRUE,则四个点的纹理坐标如下(0.F, 0.F), (0.F, 1.F), (1.F, 0.F), (1.F, 1.F)。详见下图。

如果开启了剪裁,则使用如下方式对points进行剪裁。若顶点超出了Viewport的深度范围(在D3DVIEWPORT9的MinZ及MaxZ之外),则点被剪掉,不渲染。如果point size超出了Viewport的X和Y范围,则point也被剪掉,不渲染。也有如下情况,point的位置超出了viewport的X或Y的范围,但是仍然可以部分被显示。

对于用户自定义的剪裁平面来说,point不一定会被正确的剪裁,如果D3DCAPS中PrimitiveMiscCaps字段的值不是D3DPMISCCAPS_CLIPPLANESCALEDPOINTS,则point使用用户定义的剪裁平面进行剪裁,这时仅仅使用顶点的位置,而忽略点的大小。在这种情况下,经过缩放的点将完全被显示(如果顶点位置位于剪裁平面内),硬件顶点处理可能支持point size,也可能不支持,比如,如果使用D3DCREATE_HARDWARE_VERTEXPROCESSING在HAL设备(D3DDEVTYPE_HAL)上来创建设备,并且D3DCAPS中的MaxPointSize被设置为1.0或0.0,则所有的point都只对应一个像素,如果想渲染size小于1.0的point,只能使用FVF(flexible vertex format)TL(transformed and lit)顶点格式或者软件顶点处理(D3DCREATE_SOFTWARE_VERTEXPROCESSING),在这种情况下D3D会模拟点精灵的渲染。

对于支持顶点处理和点精灵渲染的硬件设备来说,如果MaxPointSize设置为大于1.0f,那么对于为转换的point sprites,需要为每个顶点计算大小,对于转换过的顶点,需要为每个顶点计算D3DRS_POINTSIZE。

posted on 2012-06-25 12:45  翰墨小生  阅读(5552)  评论(0编辑  收藏  举报

导航

书法字典:https://www.shufadict.com