zoukankan      html  css  js  c++  java
  • 用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。

    作者:zdd
    出处:http://www.cnblogs.com/graphics/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
  • 相关阅读:
    attr与prop
    Django框架学习
    库的操作
    javascript 基础知识
    进程
    正则表达式
    模块( collections , time , random , os , sys)
    内置函数
    生成器
    迭代器
  • 原文地址:https://www.cnblogs.com/graphics/p/2046106.html
Copyright © 2011-2022 走看看