用DirectX实现粒子系统(二)

简介:

引言

上一篇讲了点精灵的理论部分,这篇看一下如何在DX程序中使用点精灵。

定义顶点格式

为了简化程序,我们使用LT(Lit and transformed format)顶点格式,也就是不需要额外的光照和变换。

复制代码
//  点精灵对应的顶点
struct  POINTVERTEX
{
     
float  x, y, z ;  //  位置
     D3DCOLOR color;  //  颜色
};

//  点的格式是经过光照和变换的,无需设置光照和变换矩阵
#define  D3DFVF_POINTVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)
复制代码

创建顶点及顶点缓冲区

这里首先创建九个顶点,每行三个,三行的颜色分别是红绿蓝。然后创建一个顶点缓冲区,最后将顶点拷贝的顶点缓冲区中。

复制代码
HRESULT CreateVertex()
{
    POINTVERTEX points[] =
    {
        {-5.0f, 5.0f, 0.0f, 0xffff0000},
        { 0.0f, 5.0f, 0.0f, 0xffff0000},
        { 5.0f, 5.0f, 0.0f, 0xffff0000},

        {-5.0f, 0.0f, 0.0f, 0xff00ff00},
        { 0.0f, 0.0f, 0.0f, 0xff00ff00},
        { 5.0f, 0.0f, 0.0f, 0xff00ff00},

        {-5.0f, -5.0f, 0.0f, 0xff0000ff},
        { 0.0f, -5.0f, 0.0f, 0xff0000ff},
        { 5.0f, -5.0f, 0.0f, 0xff0000ff}
    } ;

    // 创建 Vertex buffer
    if (FAILED(g_pd3dDevice->CreateVertexBuffer(
        NUM_VERTEX *sizeof(POINTVERTEX),
        D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY | D3DUSAGE_POINTS,
        D3DFVF_POINTVERTEX,
        D3DPOOL_DEFAULT,
        &g_pVB,
        NULL)))
    {
        return E_FAIL ;
    }

    // 拷贝顶点到Vertex buffer中
    VOID* pVertices;
    if( FAILED( g_pVB->Lock( 0, sizeof(points), (void**)&pVertices, 0 ) ) )
        return E_FAIL;
    memcpy( pVertices, points, sizeof(points) );
    g_pVB->Unlock();
}
复制代码

渲染

渲染主要分三步,首先设置一系列渲染状态,比如开启Blend,因为我们用到了纹理,所以要使用纹理混合功能,最重要的两个渲染状态分别是D3DRS_POINTSPRITEENABLE和D3DRS_POINTSCALEENABLE,前者启用点精灵,后者使点精灵可缩放。然后是渲染部分,渲染的类型是POINTLIST。最后部分是恢复前面设置的某些状态,比如禁用Blend。

复制代码
if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
{
       // 设置渲染状态
    g_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE ); // 开启Blend
    g_pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE );
    g_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
    g_pd3dDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE) ;
    g_pd3dDevice->SetRenderState(D3DRS_POINTSCALEENABLE, TRUE) ;
    g_pd3dDevice->SetRenderState( D3DRS_POINTSIZE, FtoDW(0.2f) ); // 点大小


    // 设置纹理,纹理之前已经创建好
    g_pd3dDevice->SetTexture(0, g_pTexture) ;

    // 绘制points
    g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof(POINTVERTEX));
    g_pd3dDevice->SetFVF(D3DFVF_POINTVERTEX) ;
    g_pd3dDevice->DrawPrimitive( D3DPT_POINTLIST, 0, NUM_VERTEX) ;

       // 禁用Blend
    g_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );

    g_pd3dDevice->EndScene();
}
复制代码

效果图

为什么说点精灵是高效的呢,拿上面的图来说,我只使用了9个顶点,每个顶点配一个纹理图片。如果不使用点精灵儿直接贴图,那么至少需要4*9=36个顶点。可见点精灵是十分节省内存资源的。

Happy Coding!!!

== THE END ==


本文转自zdd博客园博客,原文链接:http://www.cnblogs.com/graphics/archive/2012/06/27/2052351.html,如需转载请自行联系原作者

相关文章
|
存储 索引
Directx11教程39 纹理映射(9)
在myTutorialD3D11_32中,我们在PlaneModelClass中增加一个纹理TextureClass* m_Texture;读入一个grass的纹理,程序执行后的效果如下: 完整的代码请参考: 工程文件myTutorialD3D11_32 代码下载: http://files.
902 0
|
C++ 索引
Directx11教程37 纹理映射(7)
本章是在教程35、36的基础上来实现一个光照纹理结合的程序,就是把场景中旋转的cube加上纹理。    lighttex.vs中顶点的结构现在为: struct VertexInputType {     float4 position : POSITION; ...
885 0
Directx11教程41 纹理映射(11)
1、第一副图我们采用各性异性的滤波方式,并设置最大各性异性值为8.     samplerDesc.Filter =  D3D11_FILTER_ANISOTROPIC;     samplerDesc.MaxAnisotropy = 8;      第二副图我们用了常用的3线性差值滤波方式   samplerDesc.Filter =  D3D11_FILTER_MIN_MAG_MIP_LINEAR;         按道理说,对于远处的纹理贴图,第一副图要好些,但我看起来,似乎这两个效果差不多,第二副效果也还可以,对于远处的贴图,我并没有发现模糊的效果。
889 0
Directx11教程38 纹理映射(8)
上篇日志中,我们用纹理和光照颜色调制的方式得到最终颜色,本章我们尝试用纹理采样的颜色,直接做为材质的漫反射系数Kd,并用它来做光照计算,最后再做个gamma校正,如果不做的话,效果会偏亮。      lighttex.
821 0
|
图形学
Directx11教程40 纹理映射(10)
本章尝试使用纹理行列式,或者说纹理数组,在ps中,使用2个纹理,最终的像素颜色,是光照颜色*纹理1采样颜色*纹理2采样颜色,主要是想达到如下的效果:    把这两个图像以及光照产生的颜色融合生成以下图像:   为此我们新建一个lighttex2.
1038 0
|
索引
Directx11教程36 纹理映射(6)
本章主要是整理代码,做以下两件事情: 1、把世界坐标矩阵的计算,放在GraphicsClass的渲染函数中,之前放在D3DClass中,而且只是返回一个单位矩阵,没任何作用。如果要使其起作用,就要对每个model类都单独设置,很麻烦,比如我要画两个颜色立方体,岂不是要建立两个model类,而只是世界坐标矩阵不同。
808 0
Directx11教程(32) 纹理映射(2)
在写代码之前,我们先制作一个dds文件。从网上找到了一张照片,处理成为512*512,保存为jpg格式。     启动微软的directx texture tool后,把图片拖到其内:      选择文件Format->Generate Mip Maps,可以在图像的标题栏看到Mip 1 of 10的字样,这是因为我们原始图像大小为512*512,生成MipMaps时,会产生256*256, 128*128,…, 1*1,一系列下采样的图像,加上原始图像总共10个。
826 0
Directx11教程(34) 纹理映射(4)
本篇教程中,我们尝试在myTutorialD3D_27中改变采样状态描述符的各种设置,看纹理贴图的方式有什么变化。 原始的代码是:     // 创建纹理采样描述符 samplerDesc.
856 0