午夜精品理论片,午夜久久久久,亚洲一区二区三区影院http://www.shnenglu.com/flagship/category/9250.html創(chuàng)新+實(shí)踐zh-cnWed, 25 Mar 2009 17:30:47 GMTWed, 25 Mar 2009 17:30:47 GMT60幾種多線(xiàn)程3D引擎架構(gòu)的比較http://www.shnenglu.com/flagship/archive/2009/03/25/77886.htmlflagshipflagshipWed, 25 Mar 2009 15:22:00 GMThttp://www.shnenglu.com/flagship/archive/2009/03/25/77886.htmlhttp://www.shnenglu.com/flagship/comments/77886.htmlhttp://www.shnenglu.com/flagship/archive/2009/03/25/77886.html#Feedback0http://www.shnenglu.com/flagship/comments/commentRss/77886.htmlhttp://www.shnenglu.com/flagship/services/trackbacks/77886.html1、在CPU上進(jìn)行的邏輯計(jì)算(比如骨骼動(dòng)畫(huà)粒子發(fā)射等)不影響渲染速度
2、較差的GPU渲染速度的低下不影響邏輯速度

      第一個(gè)目標(biāo)已經(jīng)很明確了,我來(lái)解釋下需要達(dá)到第二個(gè)目標(biāo)的原因:許多動(dòng)作游戲的邏輯判定是基于幀的,所以在渲染較慢的情況下,邏輯不能跳幀,而仍然需要嚴(yán)格執(zhí)行才能保證游戲邏輯的正確性,這就導(dǎo)致了游戲速度的放慢,而實(shí)際上個(gè)人認(rèn)為渲染保持15幀以上就已經(jīng)可以正常進(jìn)行游戲了。
      在較差的GPU上跑《鬼泣4》《刺客信條》《波斯王子4》簡(jiǎn)直就像是慢鏡頭一樣,完全沒(méi)法玩。而實(shí)際上CPU跑滿(mǎn)幀是沒(méi)有問(wèn)題的,如果能把邏輯幀和渲染幀徹底分離,即使渲染幀達(dá)不到要求,但CPU仍能正確的執(zhí)行游戲邏輯,就可以解決動(dòng)作游戲?qū)PU要求過(guò)高的問(wèn)題。

      我們先來(lái)看多線(xiàn)程O(píng)gre的兩種架構(gòu),第一種是middle-level multithread


      如上圖所示,每個(gè)需渲染的實(shí)體被復(fù)制成了兩份,主線(xiàn)程和渲染線(xiàn)程交替更新和渲染同一個(gè)實(shí)體的兩個(gè)備份,并在一幀結(jié)束時(shí)同步,這種解決方案達(dá)到了第一個(gè)目標(biāo)而并沒(méi)有達(dá)到第二個(gè)目標(biāo),同時(shí)兩份實(shí)體的維護(hù)也相對(duì)復(fù)雜,并且沒(méi)法為更多核數(shù)的CPU進(jìn)行擴(kuò)展優(yōu)化。
      第二種Ogre多線(xiàn)程的方法是 low-level multithread

      如圖,將D3D對(duì)象復(fù)制兩份,同樣是在幀結(jié)束時(shí)同步并交換,和上面的優(yōu)缺點(diǎn)類(lèi)似。兩種多線(xiàn)程O(píng)gre的解決方案都是在引擎層完成的,對(duì)上層應(yīng)用透明,對(duì)于用戶(hù)而言無(wú)需考慮多線(xiàn)程細(xì)節(jié),這點(diǎn)是非常不錯(cuò)的。

      接下來(lái)我們來(lái)看SIGGRAPH2008上,id soft提出的多線(xiàn)程3D引擎的方案

      這里是已PS3的引擎結(jié)構(gòu)為例的,與PC有較大的差別,其中SPU是Cell芯片的8個(gè)協(xié)處理器,擁有強(qiáng)大的并行能力,id的解決方案在SPU上進(jìn)行了諸如骨骼動(dòng)畫(huà)、形變動(dòng)畫(huà)、頂點(diǎn)和索引緩存的壓縮、Progressive Mesh的計(jì)算等諸多內(nèi)容,同時(shí)與PPU上的物理計(jì)算RSX上的渲染工作交錯(cuò)進(jìn)行,最大化的利用了PS3的硬件結(jié)構(gòu),最終的游戲產(chǎn)品《Rage》很快就會(huì)面世了!

      最后是我的解決方案

      特點(diǎn)是邏輯完全分離,無(wú)需同步,雖然成功的達(dá)到了文章開(kāi)始提出的兩個(gè)目標(biāo),但對(duì)于引擎的使用者必須考慮多線(xiàn)程的諸多問(wèn)題,各種計(jì)算需放在哪個(gè)線(xiàn)程,如何在兩個(gè)線(xiàn)程間交互,都需要深入思考,所以要應(yīng)用到實(shí)際的游戲制作,恐怕還有很長(zhǎng)的一段路要走。
      結(jié)合目前的架構(gòu)和上面看到的幾種多線(xiàn)程架構(gòu),同時(shí)也為了迎接DX11的到來(lái),我準(zhǔn)備將我的方案進(jìn)一步改進(jìn)成如下所示

      場(chǎng)景剪裁與提交渲染交替進(jìn)行,并在渲染幀末進(jìn)行一次同步,而多個(gè)渲染表面的場(chǎng)景剪裁可再并行執(zhí)行。
      圖片多,文字少,需更詳細(xì)資料請(qǐng)自行g(shù)oogle,本文就此結(jié)束!


flagship 2009-03-25 23:22 發(fā)表評(píng)論
]]>
多Pass渲染體系與多線(xiàn)程渲染的矛盾http://www.shnenglu.com/flagship/archive/2009/03/15/76630.htmlflagshipflagshipSun, 15 Mar 2009 04:45:00 GMThttp://www.shnenglu.com/flagship/archive/2009/03/15/76630.htmlhttp://www.shnenglu.com/flagship/comments/76630.htmlhttp://www.shnenglu.com/flagship/archive/2009/03/15/76630.html#Feedback2http://www.shnenglu.com/flagship/comments/commentRss/76630.htmlhttp://www.shnenglu.com/flagship/services/trackbacks/76630.html    最近為了實(shí)現(xiàn)多光源和多陰影的渲染,把渲染系統(tǒng)改成了多Pass的,對(duì)每一個(gè)可見(jiàn)光源進(jìn)行一次光照、ShadowMap和最終陰影的渲染,雖然這樣等于是把整個(gè)場(chǎng)景重復(fù)渲染了很多次,但為了實(shí)現(xiàn)靈活的實(shí)時(shí)光照系統(tǒng),這似乎是唯一的辦法了。
    但實(shí)踐后發(fā)現(xiàn),陰影和光照會(huì)隨著骨骼動(dòng)畫(huà)的播放而閃爍,甚至鏡頭的移動(dòng)也會(huì)造成閃爍,究其原因,還是邏輯線(xiàn)程和渲染線(xiàn)程的同步問(wèn)題,由于對(duì)場(chǎng)景內(nèi)的同一個(gè)物體渲染了多次,而邏輯線(xiàn)程又在不停的更新攝像機(jī)和骨骼動(dòng)畫(huà)數(shù)據(jù),導(dǎo)致了兩Pass渲染取到的數(shù)據(jù)很可能不一致,造成了光照和陰影的閃爍。
    所以共享數(shù)據(jù)結(jié)構(gòu)必須做一些修改,在多Pass渲染開(kāi)始前進(jìn)行一次備份,渲染中只取備份數(shù)據(jù),這樣就保證了多次渲染的數(shù)據(jù)一致性了

    也就是加這么兩個(gè)簡(jiǎn)單的set和get方法,在渲染相關(guān)數(shù)據(jù)讀取時(shí)調(diào)用get,邏輯相關(guān)時(shí)調(diào)用read

template <class T>
struct SharedData
   
{
        T        m_pData[DATACENTER_CACHE];
        T        m_kCloneData;
        
int      m_iIndex;

        SharedData()
      
{
            ZeroMemory( m_pData, DATACENTER_CACHE 
* sizeof(T) );
            m_iIndex 
= 0;
        }


        
void    Write( T& rData )
      
{
            
int iNewIndex = m_iIndex == DATACENTER_CACHE - 1 ? 0 : m_iIndex + 1;
            m_pData[iNewIndex] 
= rData;
            m_iIndex 
= iNewIndex;
        }


        T
&    Read()
      
{
           
return m_pVector[m_iIndex];
        }


        
void    Set()
      
{
           m_kCloneData 
= Read();
        }


        T
&      Get()
      {

           
return m_kCloneData;
        }

    }
;



flagship 2009-03-15 12:45 發(fā)表評(píng)論
]]>
DX11與多線(xiàn)程渲染http://www.shnenglu.com/flagship/archive/2009/02/16/73951.htmlflagshipflagshipMon, 16 Feb 2009 09:11:00 GMThttp://www.shnenglu.com/flagship/archive/2009/02/16/73951.htmlhttp://www.shnenglu.com/flagship/comments/73951.htmlhttp://www.shnenglu.com/flagship/archive/2009/02/16/73951.html#Feedback4http://www.shnenglu.com/flagship/comments/commentRss/73951.htmlhttp://www.shnenglu.com/flagship/services/trackbacks/73951.html    本來(lái)只是以為自己只是火星了而已,裝好一看,完。。。徹底冥王星了,DX11的Preview版出了!真是又激動(dòng)又懊悔,粗略看了看,新特性真是太令人激動(dòng)了,主要有以下幾點(diǎn):

一、SM5.0 從類(lèi)C變成類(lèi)C++了,有類(lèi)有繼承有虛函數(shù),太夸張了。。。
二、支持Shader動(dòng)態(tài)Link,DX9里面就有個(gè)FragmentLinker,不太好用,DX10直接取消了,這次變本加厲的又回來(lái)了!
三、渲染的多線(xiàn)程支持,我重點(diǎn)來(lái)談?wù)勥@個(gè)

    DX11提供了一個(gè)新的接口:ID3D11DeviceContext,取代了以前Device接口所有與渲染相關(guān)的功能,有兩個(gè)類(lèi)型:immediate和deferred,前者和現(xiàn)在的效果一樣,收到渲染指令就立即執(zhí)行,而后者則會(huì)將命令緩存起來(lái),由用戶(hù)決定何時(shí)執(zhí)行。
    在例子MultithreadedRendering11中,渲染了三面帶反射的鏡子和一個(gè)人物模型,Sample創(chuàng)建了四個(gè)Context,三個(gè)deferred用于鏡子反射表面的渲染,一個(gè)immediate用于最終場(chǎng)景,Sample創(chuàng)建了三個(gè)線(xiàn)程,渲染幀開(kāi)始時(shí),首先并行的執(zhí)行三個(gè)鏡子反射的渲染,完成后,在主線(xiàn)程順序執(zhí)行三個(gè)Context,然后用immediate的Context渲染最終場(chǎng)景。
    由這個(gè)例子,我們來(lái)展望一下美好的未來(lái):所有的渲染表面都可以并行執(zhí)行,比如水面、鏡子、甚至ShadowMap,并行的進(jìn)行場(chǎng)景剪裁,使得多核CPU的使用更有效率。
    DX11預(yù)計(jì)在今年年底推出,于Windows7捆綁,到那時(shí),四核CPU應(yīng)該已經(jīng)普及了吧。。。


flagship 2009-02-16 17:11 發(fā)表評(píng)論
]]>
3D引擎多線(xiàn)程:邏輯操作http://www.shnenglu.com/flagship/archive/2009/01/24/72556.htmlflagshipflagshipSat, 24 Jan 2009 15:38:00 GMThttp://www.shnenglu.com/flagship/archive/2009/01/24/72556.htmlhttp://www.shnenglu.com/flagship/comments/72556.htmlhttp://www.shnenglu.com/flagship/archive/2009/01/24/72556.html#Feedback1http://www.shnenglu.com/flagship/comments/commentRss/72556.htmlhttp://www.shnenglu.com/flagship/services/trackbacks/72556.html        解決辦法其實(shí)在上一篇中已經(jīng)提到了,仍然是利用天然的同步機(jī)制——Windows消息,添加實(shí)體時(shí),邏輯線(xiàn)程只是new了一個(gè)Entity對(duì)象,設(shè)置這個(gè)對(duì)象的初始共享數(shù)據(jù),比如位置信息,同時(shí)向渲染線(xiàn)程發(fā)送一條WM_ADDENTITY的自定義消息,將Entity指針作為wParam傳遞。渲染線(xiàn)程接受到消息后調(diào)用Entity的UpdateScene方法,更新Entity在場(chǎng)景樹(shù)中的位置,并加載資源。
        刪除也是一樣,邏輯線(xiàn)程向渲染線(xiàn)程發(fā)送WM_DELETEENTITY消息,并不再使用該Entity指針,渲染對(duì)象則處理改消息,將此Entity從場(chǎng)景中刪除并卸載資源。
        這里有一個(gè)非常危險(xiǎn)的情況,前面一篇提到,資源加載也是通過(guò)消息傳遞實(shí)現(xiàn)的,同樣是傳遞的資源指針,如果邏輯線(xiàn)程添加了一個(gè)Entity,還沒(méi)加載就刪掉了它,則資源加載線(xiàn)程會(huì)拿到一個(gè)過(guò)期指針,一切就結(jié)束了。。。
        解決這一問(wèn)題,最穩(wěn)妥的方法是消息的wParam并不傳遞指針,而是傳遞該Entity或資源的唯一ID,這樣的話(huà)即使ID過(guò)期,也可輕松忽略掉這條消息,壞處是每次消息處理都的從全局的map里檢查是否存在此ID對(duì)應(yīng)的Entity或資源,這可是筆不小的開(kāi)銷(xiāo)。
        第二種方案,我們?nèi)匀粋鬟f指針,只是在接受到WM_DELETEENTITY消息時(shí),檢查該Entity是否已經(jīng)加載完成,如果沒(méi)有完成,則重新將此消息加入消息隊(duì)列,下個(gè)渲染幀再次判斷。
       FlagshipEngine的多線(xiàn)程設(shè)計(jì)大致就是如此了。

flagship 2009-01-24 23:38 發(fā)表評(píng)論
]]>
3D引擎多線(xiàn)程:框架http://www.shnenglu.com/flagship/archive/2009/01/10/71688.htmlflagshipflagshipSat, 10 Jan 2009 15:37:00 GMThttp://www.shnenglu.com/flagship/archive/2009/01/10/71688.htmlhttp://www.shnenglu.com/flagship/comments/71688.htmlhttp://www.shnenglu.com/flagship/archive/2009/01/10/71688.html#Feedback1http://www.shnenglu.com/flagship/comments/commentRss/71688.htmlhttp://www.shnenglu.com/flagship/services/trackbacks/71688.html        首先,資源讀取線(xiàn)程可以簡(jiǎn)單設(shè)計(jì)為一個(gè)循環(huán)等待的線(xiàn)程結(jié)構(gòu),每隔一段時(shí)間檢查加載隊(duì)列中是否有內(nèi)容,如果有則進(jìn)行加載工作,如果沒(méi)有則繼續(xù)等待一段時(shí)間。這種方式雖然簡(jiǎn)單清晰,但卻存在問(wèn)題,如果等待時(shí)間設(shè)得過(guò)長(zhǎng),則加載會(huì)產(chǎn)生延遲,如果設(shè)得過(guò)短,則該線(xiàn)程被喚醒的次數(shù)過(guò)于頻繁,會(huì)耗費(fèi)很多不必要的CPU時(shí)間。
        然后,主線(xiàn)程是邏輯線(xiàn)程還是渲染線(xiàn)程?因?yàn)檫壿嬀€(xiàn)程需要處理鍵盤(pán)鼠標(biāo)等輸入設(shè)備的消息,所以我起初將邏輯線(xiàn)程設(shè)為主線(xiàn)程,而渲染線(xiàn)程另外創(chuàng)建,但實(shí)際發(fā)現(xiàn),幀數(shù)很不正常,估計(jì)與WM_PAINT消息有關(guān),有待進(jìn)一步驗(yàn)證。于是掉轉(zhuǎn)過(guò)來(lái),幀數(shù)正常了,但帶來(lái)了一個(gè)新的問(wèn)題,邏輯線(xiàn)程如何處理鍵盤(pán)鼠標(biāo)消息?
      
        對(duì)于第一個(gè)問(wèn)題,有兩種解決方案:
        第一,我們可以創(chuàng)建一個(gè)Event,資源讀取線(xiàn)程使用WaitForSingleObject等待著個(gè)Event,當(dāng)渲染線(xiàn)程向加載隊(duì)列添加新的需加載的資源后,將這個(gè)Event設(shè)為Signal,將資源讀取線(xiàn)程喚醒,為了安全,我們?nèi)孕枰阡秩揪€(xiàn)程向加載隊(duì)列添加元素,以及資源加載線(xiàn)程從加載隊(duì)列讀取元素時(shí)對(duì)操作過(guò)程加鎖。
        第二,使用在渲染線(xiàn)程調(diào)用PostThreadMessage,將資源加載的請(qǐng)求以消息的形式發(fā)送到資源價(jià)值線(xiàn)程,并在wParam中傳遞該資源對(duì)象的指針,資源加載線(xiàn)程調(diào)用WaitMessage進(jìn)行等待,收到消息后即被喚醒,這種解決方案完全不需要加鎖。
        對(duì)于第二個(gè)問(wèn)題,我們同樣可以用PostThreadMessage來(lái)解決,在主線(xiàn)程的WndProc中,將邏輯線(xiàn)程需要處理的消息發(fā)送出去,邏輯線(xiàn)程收到后進(jìn)行相關(guān)處理。

        需要注意的是,我們必須搞清楚線(xiàn)程是在何時(shí)創(chuàng)建消息隊(duì)列的,微軟如是說(shuō):

The thread to which the message is posted must have created a message queue, or else the call to PostThreadMessage fails. Use one of the following methods to handle this situation.

  • Call PostThreadMessage. If it fails, call the Sleep function and call PostThreadMessage again. Repeat until PostThreadMessage succeeds.
  • Create an event object, then create the thread. Use the WaitForSingleObject function to wait for the event to be set to the signaled state before calling PostThreadMessage. In the thread to which the message will be posted, call PeekMessage as shown here to force the system to create the message queue.
    PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE)
    Set the event, to indicate that the thread is ready to receive posted messages.

        看來(lái),我們只需要在線(xiàn)程初始化時(shí)調(diào)一句PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE)就可以了,然后在主線(xiàn)程中如此這般:

switch ( uMsg )
        
{
        
case WM_PAINT:
            
{
                hdc 
= BeginPaint(hWnd, &ps);
                EndPaint(hWnd, 
&ps);
            }

            
break;
        
case WM_DESTROY:
            
{
                m_pLogic
->StopThread();
                WaitForSingleObject( m_pLogic
->GetThreadHandle(), INFINITE );
                PostQuitMessage(
0);
            }

            
break;
        
default:
            
{
                
if ( IsLogicMsg( uMsg ) )
                
{
                    PostThreadMessage( m_pLogic
->GetThreadID(), uMsg, wParam, lParam );
                }

                
else
                
{
                    
return DefWindowProc( hWnd, uMsg, wParam, lParam );
                }

            }

            
break;
        }

        在邏輯線(xiàn)程中這般如此:
MSG msg;
        
while ( m_bRunning )
        
{
            
if ( PeekMessage( &msg, NULL, 00, PM_NOREMOVE ) )
            
{
                
if ( ! GetMessageW( &msg, NULL, 00 ) )
                
{
                    
return (int) msg.wParam;
                }


                MessageProc( msg.message, msg.wParam, msg.lParam );
            }


            LogicTick();
        }
        完成!

flagship 2009-01-10 23:37 發(fā)表評(píng)論
]]>
3D引擎多線(xiàn)程:渲染與邏輯分離http://www.shnenglu.com/flagship/archive/2009/01/04/71165.htmlflagshipflagshipSun, 04 Jan 2009 13:15:00 GMThttp://www.shnenglu.com/flagship/archive/2009/01/04/71165.htmlhttp://www.shnenglu.com/flagship/comments/71165.htmlhttp://www.shnenglu.com/flagship/archive/2009/01/04/71165.html#Feedback7http://www.shnenglu.com/flagship/comments/commentRss/71165.htmlhttp://www.shnenglu.com/flagship/services/trackbacks/71165.html        如果考慮使用多線(xiàn)程優(yōu)化,最容易想到的就是采用平行分解模式,將骨骼動(dòng)畫(huà)計(jì)算和粒子計(jì)算寫(xiě)成兩個(gè)for循環(huán),然后用OpenMP將其多線(xiàn)程化,但事實(shí)上這樣并不會(huì)提高多少效率,這兩者計(jì)算仍然要阻滯渲染幀,線(xiàn)程的創(chuàng)建也有一定的消耗。于是我想到了一種極端的解決方案,采用任務(wù)分解模式,將渲染和邏輯完全分離到兩個(gè)線(xiàn)程去,互不影響,當(dāng)然這樣線(xiàn)程同步會(huì)是大問(wèn)題,畢竟線(xiàn)程的數(shù)量和BUG的數(shù)量是成正比的。
        我們首先來(lái)分析下這兩個(gè)線(xiàn)程分別需要做什么工作,需要那些數(shù)據(jù)。渲染線(xiàn)程需要獲取實(shí)體的位置、材質(zhì)等信息,并交給GPU渲染,邏輯線(xiàn)程需要更新實(shí)體的位置、材質(zhì)、骨骼動(dòng)畫(huà)等數(shù)據(jù),很顯然一個(gè)寫(xiě)入一個(gè)讀取,這為我們實(shí)現(xiàn)一個(gè)沒(méi)有線(xiàn)程同步的多線(xiàn)程3D渲染系統(tǒng)提供了可能。
        為了讓讀取和寫(xiě)入不需要Lock,我們需要為每一份數(shù)據(jù)設(shè)計(jì)一個(gè)帶有冗余緩存的結(jié)構(gòu),讀取線(xiàn)程讀取的是上次寫(xiě)入完成的副本,而寫(xiě)入線(xiàn)程則向新的副本寫(xiě)入數(shù)據(jù),并在完成后置上最新標(biāo)記,置標(biāo)記的操作為原子操作即可。以Vector為例,這個(gè)結(jié)構(gòu)大致是這樣的:
struct VectorData 
{
        Vector4f    m_pVector[DATACENTER_CACHE];
       
int         m_iIndex;

        VectorData()
    
{
            memset( m_pVector, 
0, DATACENTER_CACHE * sizeof(Vector4f) );
            m_iIndex 
= 0;
        }


       
void    Write( Vector4f& rVector )
    
{
           
int iNewIndex = m_iIndex == DATACENTER_CACHE - 1 ? 0 : m_iIndex + 1;
            m_pVector[iNewIndex] 
= rVector;
            m_iIndex 
= iNewIndex;
        }


        Vector4f
&    Read()
  
{
            
return m_pVector[m_iIndex];
        }

}
;
        當(dāng)然我們可以用模板來(lái)寫(xiě)這個(gè)結(jié)構(gòu),讓其適用于int,float,matrix等多種數(shù)據(jù)類(lèi)型,余下的工作就簡(jiǎn)單了,將所有有共享數(shù)據(jù)的類(lèi)的成員變量都定義為以上這種數(shù)據(jù)類(lèi)型,例如我們可以定義:
        SharedData<Matrix4f>  m_matWorld;
        在渲染線(xiàn)程中調(diào)用pDevice->SetWorldMatrix( m_matWorld.Read() );
        在邏輯線(xiàn)程中調(diào)用m_matWorld.Write( matNewWorld );

        需要注意的是,這種方案并非絕對(duì)健壯,當(dāng)渲染線(xiàn)程極慢且邏輯線(xiàn)程極快的情況下,有可能寫(xiě)入了超過(guò)了DATACENTER_CACHE次,而讀取卻尚未完成,那么數(shù)據(jù)就亂套了,當(dāng)然真要出現(xiàn)了這種情況,游戲早已經(jīng)是沒(méi)法玩了,我測(cè)試的結(jié)果是渲染幀小于1幀,邏輯幀大于10000幀,尚未出現(xiàn)問(wèn)題。
        FlagshipEngine采用了這一設(shè)想,實(shí)際Demo測(cè)試結(jié)果是,計(jì)算25個(gè)角色的骨骼動(dòng)畫(huà),從靜止到開(kāi)始奔跑,單線(xiàn)程的情況下,幀數(shù)下降了20%~30%,而使用多線(xiàn)程的情況下,幀數(shù)完全沒(méi)有變化!


flagship 2009-01-04 21:15 發(fā)表評(píng)論
]]>
3D引擎多線(xiàn)程:資源異步加載http://www.shnenglu.com/flagship/archive/2009/01/03/71086.htmlflagshipflagshipSat, 03 Jan 2009 13:37:00 GMThttp://www.shnenglu.com/flagship/archive/2009/01/03/71086.htmlhttp://www.shnenglu.com/flagship/comments/71086.htmlhttp://www.shnenglu.com/flagship/archive/2009/01/03/71086.html#Feedback0http://www.shnenglu.com/flagship/comments/commentRss/71086.htmlhttp://www.shnenglu.com/flagship/services/trackbacks/71086.html
首先我們需要定義一個(gè)Resource基類(lèi),它大致上是這樣的:
class _DLL_Export Resource : public Base
    
{
    
public:
        Resource();
        
virtual ~Resource();

        
// 是否過(guò)期
        bool                IsOutOfDate();
       

    
public:
        
// 是否就緒
        virtual bool    IsReady();

        
// 讀取資源
        virtual bool    Load();

        
// 釋放資源
        virtual bool    Release();

        
// 緩存資源
        virtual bool    Cache();

        
// 釋放緩存
        virtual void    UnCache();

    
protected:
        
// 加載標(biāo)記
        bool            m_bLoad;

        
// 完成標(biāo)記 
        bool            m_bReady;
        

    
private:

    }
;
        在實(shí)際游戲中,加載資源的范圍大于視野,當(dāng)攝像機(jī)移動(dòng)到單元格邊緣(必須有一定的緩沖區(qū)),就應(yīng)將新的單元格中的對(duì)象加入到資源加載隊(duì)列中,喚醒資源加載線(xiàn)程調(diào)用Load接口進(jìn)行加載,完成后將該資源的加載標(biāo)記設(shè)為true。而通過(guò)可視剪裁所得到的最終可視實(shí)體,則需要調(diào)用Cache接口構(gòu)建圖像API所需對(duì)象,當(dāng)Load和Cache都完成后IsReady才會(huì)返回true,這時(shí)該資源才能開(kāi)始被渲染。
        卸載方面,在加載新的單元同時(shí),卸載身后舊的單元,對(duì)單元內(nèi)所有資源調(diào)用Release,Load/Release帶有引用計(jì)數(shù),仍被引用的資源不會(huì)被卸載。當(dāng)某一資源長(zhǎng)時(shí)間沒(méi)有被看見(jiàn),則超時(shí),調(diào)用UnCache釋放VertexBuffer等資源。
        為了實(shí)現(xiàn)超時(shí)卸載功能,我們需要一個(gè)ResourceManager類(lèi),每幀檢查幾個(gè)已Cache的資源,看起是否超時(shí),另外也需對(duì)已加載的資源進(jìn)行分類(lèi)管理,注冊(cè)其資源別名(可以為其文件名),提供查找資源的接口。
        另外為了方便使用,我們需要一個(gè)模板句柄類(lèi)ResHandle<T>,設(shè)置該資源的別名,其內(nèi)部調(diào)用ResourceManange的查找方法,看此資源是否已存在,如不存在則new一個(gè)新的,GetImpliment則返回該資源對(duì)象,之后可以將該資源添加到實(shí)體中,而無(wú)需關(guān)心其是否已被加載,代碼如下:
template <class T>
    
class _DLL_Export ResHandle
    
{
    
public:
        ResHandle() 
{ m_pResource = NULL; }
        
virtual ~ResHandle() {}

        
// 設(shè)置資源路徑
        void            SetPath( wstring szPath )
        
{
            Resource 
* pResource = ResourceManager::GetSingleton()->GetResource( Key( szPath ) );
            
if ( pResource != NULL )
            
{
                m_pResource 
= (T *) pResource;
            }

            
else
            
{
                m_pResource 
= new T;
                m_pResource
->SetPath( szPath );
                ResourceManager::GetSingleton()
->AddResource( m_pResource );
            }

        }


        
// 模板實(shí)體類(lèi)指針
        T *             GetImpliment() return (T *) m_pResource; }

        T 
*             operator-> () return (T *) m_pResource; }

    
protected:
        
// 模板實(shí)體類(lèi)指針
        Resource *      m_pResource;

    
private:
    }
;



flagship 2009-01-03 21:37 發(fā)表評(píng)論
]]>
開(kāi)篇:關(guān)于FlagshipEnginehttp://www.shnenglu.com/flagship/archive/2009/01/03/71083.htmlflagshipflagshipSat, 03 Jan 2009 13:10:00 GMThttp://www.shnenglu.com/flagship/archive/2009/01/03/71083.htmlhttp://www.shnenglu.com/flagship/comments/71083.htmlhttp://www.shnenglu.com/flagship/archive/2009/01/03/71083.html#Feedback1http://www.shnenglu.com/flagship/comments/commentRss/71083.htmlhttp://www.shnenglu.com/flagship/services/trackbacks/71083.html      首先要感謝旗艦工作室的倒掉,讓我可以名正言順的使用FlagshipEngine這個(gè)名字,話(huà)說(shuō)這個(gè)實(shí)驗(yàn)引擎,當(dāng)初只是我的大學(xué)畢業(yè)設(shè)計(jì),工作之后實(shí)在太忙,寫(xiě)寫(xiě)停停,進(jìn)度緩慢,到今天也只能算V0.001,其特性主要有以下三點(diǎn):

一、多線(xiàn)程
      多核CPU早已普及,但3D引擎卻遲遲不能享受到其好處,還僅僅停留在資源異步加載,音頻獨(dú)立線(xiàn)程等不疼不癢的應(yīng)用,就在一年前吧,公司的牛人們?yōu)榱藘?yōu)化骨骼動(dòng)畫(huà)和粒子計(jì)算煞費(fèi)苦心,這兩樣計(jì)算,特別是在無(wú)法控制同屏資源的網(wǎng)絡(luò)游戲中,對(duì)CPU資源的占用非??捎^(guān),自然也拖累了游戲幀數(shù),于是我便有了將邏輯計(jì)算與渲染分離的想法。
      FlagshipEngine實(shí)現(xiàn)了一套沒(méi)有線(xiàn)程同步的雙線(xiàn)程結(jié)構(gòu),可以做到骨骼動(dòng)畫(huà)、粒子計(jì)算、光源移動(dòng)等邏輯計(jì)算分離到一個(gè)單獨(dú)的線(xiàn)程運(yùn)行,完全不影響渲染幀數(shù)。

二、shader渲染器
      DX10已經(jīng)放棄了固定管線(xiàn),那么我們也沒(méi)理由再留戀它,完全基于shader的渲染器實(shí)現(xiàn)起來(lái)更加清晰簡(jiǎn)潔,并且易于擴(kuò)展,目前FlagshipEngine已經(jīng)實(shí)現(xiàn)了DX9和DX10兩個(gè)渲染器,可以方便的添加特效。

三、統(tǒng)一剪裁
      場(chǎng)景組織和剪裁永遠(yuǎn)是3D引擎的核心功能,視錐、四叉樹(shù)、BSP、Portal如何選擇,如何統(tǒng)一是個(gè)難題,我的做法是將所有的剪裁都抽象成剪裁面,并用壓棧和出棧的方式,遞歸的對(duì)場(chǎng)景進(jìn)行剪裁,另外我們還可以對(duì)大塊實(shí)體綁定簡(jiǎn)單模型的遮擋體,使用邊緣檢測(cè)算法生成遮擋剪裁面,實(shí)現(xiàn)遮擋剪裁。
      這套機(jī)制還沒(méi)有經(jīng)過(guò)嚴(yán)格的測(cè)試,有待進(jìn)一步的驗(yàn)證。

      就這么多了,希望它有朝一日能修成正果,阿門(mén)。。。


flagship 2009-01-03 21:10 發(fā)表評(píng)論
]]>
久久综合伊人77777| 久久精品无码免费不卡| 99久久精品费精品国产一区二区 | 狠狠色丁香婷综合久久| 亚洲国产精品久久久久网站| 久久综合九色综合欧美就去吻 | 久久久无码精品亚洲日韩蜜臀浪潮| 色诱久久久久综合网ywww| 69久久夜色精品国产69| 香蕉久久夜色精品国产2020| 国产精品久久久久久福利漫画| 久久91精品综合国产首页| 无码AV波多野结衣久久| 久久一区二区三区99| 色婷婷综合久久久久中文一区二区| 久久午夜电影网| 亚洲午夜久久久久久久久久| 久久久青草青青国产亚洲免观| 国产aⅴ激情无码久久| 久久精品国产国产精品四凭| 精品久久久久久久无码| 午夜精品久久久内射近拍高清| 国产精品久久自在自线观看| 亚洲精品国产第一综合99久久| 国产精品狼人久久久久影院 | 777久久精品一区二区三区无码| 久久精品国产清自在天天线| 久久精品这里只有精99品| 欧美亚洲国产精品久久蜜芽| 午夜天堂精品久久久久| 国产成人精品三上悠亚久久| 狠狠色丁香久久婷婷综合蜜芽五月| 成人精品一区二区久久| 国产欧美一区二区久久| 久久九九精品99国产精品| 久久精品国产亚洲αv忘忧草| 久久97久久97精品免视看秋霞| 99久久精品免费| 国产精品永久久久久久久久久| 国产2021久久精品| 国产高清美女一级a毛片久久w |