zoukankan      html  css  js  c++  java
  • 用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/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
  • 相关阅读:
    改造MFC程序,使原来不支持winsocket的工程支持winsocket
    算术移位和逻辑移位实现分析
    MFC 编辑框中字体大小改变,行高不能改变,只能显示一半的问题,已解决。
    在MFC中,使用控制台Console输出调试信息
    在MFC中使用GDI+的一般方法,以VC6.0编译器为例
    WinForm 实现主程序(exe)与其关联类库(*.dll)分开存放
    Deserializing/Serializing SOAP Messages in C#
    List分页
    ConvertJavaMiliSecondToDateTime
    中文数字大小写转阿拉伯数字
  • 原文地址:https://www.cnblogs.com/graphics/p/2052351.html
Copyright © 2011-2022 走看看