• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            天行健 君子當(dāng)自強(qiáng)而不息

            D3D中的粒子系統(tǒng)(3)

            14.2.1 繪制粒子系統(tǒng)

            因?yàn)榱W酉到y(tǒng)是動(dòng)態(tài)的,在每一個(gè)幀中我們需要更新系統(tǒng)中的粒子,對(duì)于渲染粒子系統(tǒng)的一種直觀但效率低下的方法如下:

            創(chuàng)建一個(gè)足夠大的頂點(diǎn)緩存保存最大數(shù)量的粒子。

            每一幀里執(zhí)行:

            A.       更新所有粒子。

            B.       COPY所有活著的粒子到頂點(diǎn)緩存。

            C.       繪制頂點(diǎn)緩存。

            這個(gè)方法正確,不過(guò)不是最有效率的。第一,頂點(diǎn)緩沖必須足夠大以保存系統(tǒng)中所有粒子。但是非常重要的是,當(dāng)我們從列表拷貝所有粒子到頂點(diǎn)緩沖(步驟B)時(shí),顯卡卻什么也不做。舉個(gè)例子,假設(shè)我們系統(tǒng)有10,000個(gè)粒子,首先我們需要一個(gè)能容納10,000個(gè)粒子的頂點(diǎn)緩沖,這是一個(gè)很大的內(nèi)存。另外顯卡將停著什么也不做直到列表中的10,000個(gè)粒子拷到頂點(diǎn)緩沖,直到我們調(diào)用DrawPrimitive。這個(gè)特定情況是CPU與顯卡不同時(shí)工作的一個(gè)很好的例子。

            更好的辦法(SDK中點(diǎn)精靈例程中用到的方法)就象這樣:

            提示:這是一個(gè)簡(jiǎn)單的描述,但它說(shuō)明了這一思想。它假定我們總是有500個(gè)粒子以填充一個(gè)緩存片段,但是這是不可能發(fā)生的,因?yàn)槲覀兘?jīng)常殺死并創(chuàng)建粒子,所以從一幀到另一幀粒子數(shù)量是變化的。舉個(gè)例子,假設(shè)我們只剩下200個(gè)粒子要在當(dāng)前幀拷貝并渲染。因?yàn)?span lang="EN-US">200個(gè)粒子不能填充整個(gè)緩存片段,我們用代碼處理這個(gè)特定情形。這個(gè)特定情形只有在最后的緩存片段中才會(huì)出現(xiàn),因?yàn)槿绻皇亲詈蟮钠瑪啵鸵馕吨厝挥?span lang="EN-US">500個(gè)粒子將被移到下一緩存片段。

            創(chuàng)建一個(gè)合適尺寸的頂點(diǎn)緩存(能夠保存2000個(gè)粒子),然后我們劃分頂點(diǎn)緩存為幾個(gè)小的塊,就像這個(gè)例子,我們?cè)O(shè)置每個(gè)緩存片斷的尺寸為500個(gè)粒子。

            l然后創(chuàng)建一個(gè)全局變量 i = 0 ,用來(lái)記錄片段。

            每一幀里執(zhí)行:

            A.       更新所有粒子。

            B.       直到所有粒子渲染完畢。

            1.        如果頂點(diǎn)緩存沒(méi)有滿:

            a         D3DLOCK_NOOVERWRITE標(biāo)記鎖定緩存片段i

            b         COPY 500個(gè)粒子到片段i

            2.        如果頂點(diǎn)緩存滿了:

            a         從起始的地方開(kāi)始頂點(diǎn)緩沖: i=0

            b         D3DLOCK_NOOVERWRITE標(biāo)記鎖定緩存段i

            c          COPY 500個(gè)粒子到片段i

            3.        渲染片段i.

            4.        下一片段: i+ +

            備注:頂點(diǎn)緩存是動(dòng)態(tài)的, 因此我們能利用動(dòng)態(tài)鎖定標(biāo)記D3DLOCK_NOOVERWRITED3DLOCK_DISCARD。這兩個(gè)標(biāo)記允許我們鎖定頂點(diǎn)緩存的某一部分。當(dāng)頂點(diǎn)緩存中的其他部分被渲染時(shí),它是不能渲染的。例如,假如我們正在使用D3DLOCK_NOOVERWRITE標(biāo)記渲染片段0時(shí), 當(dāng)渲染片段0的時(shí)候我們能鎖定并填充片段1。這樣可以防止渲染的延遲。

            這個(gè)方法更有效率。首先,我們減少頂點(diǎn)緩存的尺寸;然后, CPU與顯卡在協(xié)調(diào)的工作。也就是說(shuō),當(dāng)我們繪制一小批粒子時(shí)(graphics card work),同時(shí)拷貝另一小批粒子到頂點(diǎn)緩存 (CPU work)。這個(gè)動(dòng)作是連續(xù)執(zhí)行的,直到所有的粒子都被渲染完畢,就像你了解的一樣, 顯卡在全部頂點(diǎn)緩存被填充的時(shí)候是不用處于空閑狀態(tài)的。

            我們現(xiàn)在將注意力轉(zhuǎn)向這一個(gè)渲染方案的實(shí)現(xiàn),為了方便使用這個(gè)粒子系統(tǒng)的渲染方案, 我們使用 cParticleSystem 類中的下列數(shù)據(jù)成員:

            m_vb_num在給定時(shí)間內(nèi)我們的頂點(diǎn)緩存能夠保存的粒子數(shù)量。這個(gè)值與實(shí)際的粒子系統(tǒng)中的粒子數(shù)無(wú)關(guān)。

            m_vb_offset這個(gè)變量是頂點(diǎn)緩存中的偏移,在頂點(diǎn)緩存里我們將用它開(kāi)始COPY下一批粒子,例如,如果第一批在緩存中是0499,偏移到第二批COPY的開(kāi)始處將是500

            m_vb_batch_size定義一批緩存中的粒子數(shù)量。

            我們現(xiàn)在介紹渲染方法的代碼:

                void cParticleSystem::render()
                {
                    
            // The render method works by filling a section of the vertex buffer with data, then we render that section.  
                    // While that section is rendering we lock a new section and begin to fill that section.  
                    // Once that sections filled we render it. This process continues until all the particles have been drawn.  
                    // The benifit of this method is that we keep the video card and the CPU busy.  
               

                    
            if(m_particles.empty())
                        
            return;
               
                    
            // set render states
               

                    pre_render();
               
                    m_device->SetTexture(0, m_texture);
                    m_device->SetFVF(PARTICLE_FVF);
                    m_device->SetStreamSource(0, m_vertex_buffer, 0, 
            sizeof(sParticle));
               
                    
            //
                    // render batches one by one
                    //
               
                    // start at beginning if we're at the end of the vertex buffer
               
                if(m_vb_offset >= m_vb_num)
                        m_vb_offset = 0;
               
                    sParticle* v;
               
                    m_vertex_buffer->Lock(
                        m_vb_offset * 
            sizeof(sParticle),
                        m_vb_batch_num * 
            sizeof(sParticle),
                        (
            void**)&v,
                        m_vb_offset ? D3DLOCK_NOOVERWRITE : D3DLOCK_DISCARD);
               
                    DWORD num_particles_in_batch = 0;
               
                    
            // until all particles have been rendered
               
                for(list<sParticleAttribute>::iterator iter = m_particles.begin(); iter != m_particles.end(); iter++)
                    {
                        
            if(! iter->is_alive)
                            
            continue;
               
                        
            // copy a batch of the living particles to the next vertex buffer segment
               
                
                        v->position = iter->position;
                        v->color    = (D3DCOLOR) iter->color;
                        v++;    
            // next element
               

                        num_particles_in_batch++;
               
                        
            // if this batch full?
               
                    if(num_particles_in_batch == m_vb_batch_num)
                        {
                            
            // draw the last batch of particles that was copied to the vertex buffer
               
                            m_vertex_buffer->Unlock();
                            m_device->DrawPrimitive(D3DPT_POINTLIST, m_vb_offset, m_vb_batch_num);
               
                            
            // 
                            // While that batch is drawing, start filling the next batch with particles.
                            //
               
                            // move the offset to the start of the next batch
               
                            m_vb_offset += m_vb_batch_num;
               
                            
            // Don't offset into memory that is outside the vb's range.
                            // If we're at the end, start at the beginning.
               
                        if(m_vb_offset >= m_vb_num)
                                m_vb_offset = 0;
               
                            m_vertex_buffer->Lock(
                                m_vb_offset * 
            sizeof(sParticle),
                                m_vb_batch_num * 
            sizeof(sParticle),
                                (
            void**)&v,
                                m_vb_offset ? D3DLOCK_NOOVERWRITE : D3DLOCK_DISCARD);
                            
                            num_particles_in_batch = 0;    
            // reset for new batch
               
                    }
                    }
               
                    m_vertex_buffer->Unlock();
               
                    
            // Its possible that the LAST batch being filled never got rendered because the condition 
                    // (num_particles_in_batch == m_vb_batch_num) would not have been satisfied.  
                    // We draw the last partially filled batch now.    
               
                if(num_particles_in_batch)
                        m_device->DrawPrimitive(D3DPT_POINTLIST, m_vb_offset, num_particles_in_batch);
               
                    m_vb_offset += m_vb_batch_num;    
            // next block
               
                    post_render();                    // reset render states
               
            }

            14.2.2 隨機(jī)

            如果我們模擬雪花,不能讓所有雪花以完全相同的方式落下。我們要讓它們按相似的方式落下而不是完全相同的方式。為了使粒子系統(tǒng)的隨機(jī)功能更簡(jiǎn)單,我們?cè)黾恿讼铝袃蓚€(gè)函數(shù)到d3dUtility.h/cpp文件。

            第一個(gè)函數(shù)在[low_bound, high_bound]區(qū)間內(nèi)隨機(jī)的返回一個(gè)float類型值:

                float get_random_float(float low_bound, float high_bound)
                {
                    
            if(low_bound >= high_bound)    // bad input
               
                    return low_bound;
               
                    
            // get random float in [0, 1] interval
               
                float f = (rand() % 10000) * 0.0001f;
               
                    
            // return float in [low_bound, high_bound] interval
               
                return f * (high_bound - low_bound) + low_bound;
                }

            第二個(gè)函數(shù)在邊界盒的范圍內(nèi),輸出一個(gè)隨機(jī)的向量。
                void get_random_vector(D3DXVECTOR3* out, D3DXVECTOR3* min, D3DXVECTOR3* max)
                {
                    
            out->x = get_random_float(min->x, max->x);
                    
            out->y = get_random_float(min->y, max->y);
                    
            out->z = get_random_float(min->z, max->z);
                }

            posted on 2008-04-03 18:08 lovedday 閱讀(1241) 評(píng)論(0)  編輯 收藏 引用


            只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


            公告

            導(dǎo)航

            統(tǒng)計(jì)

            常用鏈接

            隨筆分類(178)

            3D游戲編程相關(guān)鏈接

            搜索

            最新評(píng)論

            国产叼嘿久久精品久久| 中文字幕日本人妻久久久免费| 亚洲精品无码久久久| 久久久久亚洲AV无码观看| 欧美日韩中文字幕久久伊人| 一97日本道伊人久久综合影院| 精品久久久久久国产| 久久亚洲国产欧洲精品一| 亚洲国产成人精品91久久久| 99久久99这里只有免费费精品| 精品国产乱码久久久久软件| 亚洲午夜精品久久久久久人妖| 婷婷久久久亚洲欧洲日产国码AV| 久久强奷乱码老熟女网站| 久久99精品久久只有精品 | 久久精品国产91久久综合麻豆自制 | 欧美久久久久久精选9999| 色综合久久久久久久久五月| 97精品伊人久久久大香线蕉| 亚洲精品无码久久久久| 亚洲精品成人久久久| 国产伊人久久| 99久久国产综合精品网成人影院| 2020国产成人久久精品| 欧美久久天天综合香蕉伊| 97精品国产97久久久久久免费| 狠狠色丁香久久婷婷综| 亚洲精品tv久久久久久久久| 亚洲欧美成人久久综合中文网| 久久99精品久久久久久秒播| 99久久亚洲综合精品成人| 国产婷婷成人久久Av免费高清| 97久久国产露脸精品国产| 久久精品国产亚洲AV影院| 人妻无码精品久久亚瑟影视| 亚洲国产香蕉人人爽成AV片久久| 欧美与黑人午夜性猛交久久久| 久久久这里有精品中文字幕| 日韩亚洲国产综合久久久| 日韩中文久久| 亚洲精品白浆高清久久久久久 |