• <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>

            2010年7月9日

            MMORPG游戲服務器框架的可行性報告 (提高生產效率)

            縱觀游戲服務器技術框架,  以運行在Linux操作系統上的居多, 為什么要運行在Linux上呢? 相信很多人會給出肯定的答案, Linux操作系統是開源的,而且是免費的,那叫做專業!是的,不錯,是專業。但有一個問題讓我們值得思考的是,雖然是免費的,但Linux工具比較貧乏,在某種程度上大大加在了開發成本及后期調試時間,所以我們不得不研究出一種代碼可以運行在Linux,但又要節省開發成本,提高生產效率的可行性方案。

            在Linux上,古老的Linux C程序員一般會采用一個文本編輯工具,比如:VI等,由于我以前是在windows下生活的,對VS.net這一類的工具頗為喜愛,它的開發方便快捷,又有開發輔助插件的支持,使你可以盡情使用智能提示,快捷鍵,代碼模板等高效生產代碼。可以說編碼更多的是依靠可視化工具查錯,快速跳轉代碼等。反正我的意思就是開發相當愉悅。但Linux下的C程序員則不然,我也曾經問過他們為什么要采用VI等編輯工具來編代碼,首先,他們給到我的第一答案是"專業", 其實我也不太懂他們說的專業是什么,是傳統意義上的,還是習慣性必須的;然后他們說:“使用makefile文件來編譯代碼很爽,速度很快”,這一點我是贊同的,但有個問題是程序員的入門門檻比較高,要求大家都要會這東西,還是麻煩,從HR招聘處可以看到,本來投C++程序員的人就比較少了,因為C++應用的領域基礎是應用軟件,游戲啊,電信啊,還是一些MFC界面性的東西,而且要求功底比較好,確實有時候招人還是挺難的,更不用說還要有Linux開發經驗的人了。最后,我問了linux開發不員說那你們的調試用什么工具,他們說:“gdb”, 又是一個"手打牛肉丸",自我感覺很痛苦,心里想“為什么有那么先進的工具,比方說:Eclipse CDT, 你們不用呢?”,其實他們心中也是有答案的,“編碼要養成一種好習慣,而不是依靠于某種工具”,顯然Linux程序員在編碼上大體要比windows上的程序員來得嚴格,也感覺到他們的代碼比較有質量。但很顯然的,由于開發環境的布署比較麻煩,對于大規模生產是否能夠每個人都有那么高素質的編程能力,那就是個"謎"!------ “猜不準!”

            針對上面的情況,我也自己分析了一下,軟件開發的三大要素是什么,成本,質量,進度, 只有這三項東西控制得好,那才能控制好項目。
            那軟件編程的基礎是什么? 當然是調用操作系統的API了,很顯然的, 不同操作系統有不同的API,除非你有一個跨平臺的開發框架,或者叫類庫也行。
            接下來軟件架構在不同領域是否通用?比方說:通信框架,很顯然的,還是有區別的,比方說電信系統與游戲系統,那顯然還是不一樣的。
            最后,軟件編碼與接口(API)是不是應該更多人常用的,而且容易上手的(友好第一!),這樣才可以減少開發成本及協調工作。

            總結一下,我心中已有答案了,必須采用一種大多數程序員可以接受的,而且是他們熟悉的(不要DIY的),而且開發速度快速的開發方式那才是真道理。
            以下是我的基本方案:
             

            一、   跨平臺框架的基礎設施 (組件圖)

            1.    MySQL數據庫操作組件

            2.    線程池 讀寫鎖

            3.    基礎數據類型,容器,內存池,環形緩沖區

            4.    IOCPEpoll跨平臺的面向對象通信框架

            5.    集成LuaTinker腳本交互模塊等

             

            二、   開發方式與調試環境

            本框架的初步設想是前期在Windows下使用VS.net 2008進行開發調試,爭取在Windows下解決80%左右的邏輯錯誤。之后由主程序員把代碼移植到Linux,并使用Eclipse CDT可視化開發環境進行后期的調試工作。這樣也大大降低招聘人員的知識要求(不用懂Linux),在某一程度降低了人員成本和加快了開發效率。


            posted @ 2010-07-09 02:45 RedLight 閱讀(1587) | 評論 (2)編輯 收藏

            MMORPG服務器組集群方案






             

            1.     LoginApp

            即登錄服務器, 它主要完成玩家帳號的驗證, 同時它通過BaseAppMgr并向玩家發送一個SessionKey作為基礎服務器(BaseApp)的登錄密鑰;同時LoginServer還向玩家發送服務器列表信息。

            2. BaseApp

                 即基礎服務器, 也稱連接服務器,它還維持著一個客戶端連接列表(用戶列表), 這樣它可以實現區域消息廣播及通過BaseAppMgr實現世界聊天, 玩家信息查看等功能;它還負責消息的分發到CellApp進行處理,并把結果返回到客戶端。

            3. CellApp

            即游戲服務器,它負責世界數據的加載,游戲邏輯的處理及世界對象的管理。在本架構中當為支線服務器。

            4. DBMgr

            用戶服務器,它負責用戶相關數據的存取。一般是用戶登錄選擇角色后就獲得角色所有相關數據給到MapServer, 并由MapServer定時保存角色的相關數據。

            5. BaseAppMgr

                        基礎服務器管理器,主要負責分配基礎服務器給到客戶端連接,同時它采用某種策略可以實現用戶的均衡負載等。

            6. CellAppMgr

                        支線服務器管理器, 它主要根據支線ID為基礎代理對象分配支線服務器實體, 這樣就可以實現與客戶端的通信了。

            7. DB

                 數據庫服務器主要分為三個庫來存取,AccountDB為玩家賬戶信息,CharacterDB為玩家角色相關信息,WorldDB為所胡的世界數據。

            posted @ 2010-07-09 02:05 RedLight 閱讀(2219) | 評論 (2)編輯 收藏

            2009年12月15日

            編程常用快捷鍵

            1. 調試快捷鍵
            2. 編輯快捷鍵
            3. 代碼快捷鍵
            4. 窗口快捷鍵


            Ctrl+Tab 切換編輯主窗口中的代碼選項頁

            Esc鍵關閉當前的非模式窗口 (比方說 查找窗口, 切誤用 Alt + F4, 這樣會連VS.net2005都關掉)

            F5: 啟動調試
            Ctrl+F5: 開始執行(不調試)

            Shift+F5: 停止調試
            Ctrl+Shift+F5: 重啟調試

            F7: 生成解決方案
            Ctrl+U: 生成當前項目

            F11: 獨句調試
            F10: 過程調試

            F9: 打斷點 或 取消斷點
            Alt+F9: 顯示斷點窗口

            F12: 定位到函數的實現體
            ???: 定位到函數的聲明, 只能用右鍵--->選擇A

            Shift+Alt+Enter: 切換全屏編輯

            Ctrl+F: 查找
            Ctrl+Shift+F: 在文件中查找

            F3: 查找下一個
            Shift+F3: 查找上一個

            Ctrl+H: 替換
            Ctrl+Shift+H: 在文件中替換

            Ctrl+左右箭頭鍵: 一次可以移動一個單詞
            Ctrl+上下箭頭鍵: 滾動代碼屏幕,但不移動光標位置。

            Ctrl+L: 刪除當前行


            Ctrl+M,M: 隱藏或展開當前嵌套的折疊狀態
            Ctrl+M,L: 將所有過程設置為相同的隱藏或展開狀態 或者 右鍵 + L + O
            Ctrl+M,P: 停止大綱顯示 或者再按一次Ctrl+M,L  或者 右鍵 + L + O

            Ctrl+G: 轉到指定行
            Shift+Alt+箭頭鍵: 選擇矩形文本
            Alt+鼠標左按鈕: 選擇矩形文本
            Ctrl+Shift+U: 全部變為大寫
            Ctrl+U: 全部變為小寫

            //有點難度的:
            Ctrl+K, Ctrl+C: 注釋   
            Ctrl+K, Ctrl+U: 解除注釋

            Ctrl+Shift+A: 添加新項
            //----------------------------------------
            VAssistX: 操作
            1. 定義標準的代碼段, 并設置快捷鍵
            2. Alt+M, 再打上函數名的前幾個字母, 就會過濾掉很多函數, 最后按Enter定位到當前文件所查找的函數體
            3. Shift+Alt+O, 查找文件, 輸入文件名的前幾個字母, 就會過濾掉很多文件, 最后按Enter定位到當前文件所查找的文件
            4. Alt+O: 切換到.h和.cpp文件
            5. 右鍵+查看所有引用 或 VassistX菜單中的Find References, Find References in Files : 查看函數引用的所有地方
            6. Shift+Alt+S: 查找全局變量
            //----------------------------------------
            F7: 查看代碼
            Shift+F7: 查看窗體設計器

            Windows鍵+E 打開資源管理器。
            Windows鍵+D 顯示桌面。
            Windows鍵+M 最小化所有被打開的窗口。
            Alt+Tab  切換任務欄中的激活窗口


             

            posted @ 2009-12-15 06:12 RedLight 閱讀(711) | 評論 (0)編輯 收藏

            2009年12月11日

            WOW地形Shader分析(轉)

            SPXG // 標識
            // 用到5張圖片:
            {
               blendTexture  = 0
               layer0Texture = 1
               layer1Texture = 2
               layer2Texture = 3
               layer3Texture = 4
            }
            !!ARBfp1.0
            // 定義常量:
            PARAM c[1] = { { 1, 0.30000001, 0.69999999 } };
            // 聲明3個寄存器:
            TEMP R0;
            TEMP R1;
            TEMP R2;
            // 開始混合:
            // 一.第0層和第1層使用第4張圖的x通道作為alpha進行混合:
            TEX R1, fragment.texcoord[0], texture[0], 2D;
            TEX R0, fragment.texcoord[1], texture[1], 2D;
            ADD R2, R0, -R1;
            // r2=Tex1-Tex0
            TEX R0, fragment.texcoord[4], texture[4], 2D;
            MAD R2, R0.x, R2, R1;
            // r2 = Tex4.x*r2+Tex0
            // 說明:
            // 其中的Tex4.x是對應第1層alpha值, 下面把Tex4.x當a1看
            // 即 r2 = a1 * (Tex1-Tex0) + Tex0
            // 轉換一下即是: Tex0*(1-a1)+a1*Tex1, 呵呵,看到了吧,這就是混合公式!
            // 二.第2層和前面結果使用第4張圖的y通道作為alpha進行混合:
            TEX R1, fragment.texcoord[2], texture[2], 2D;
            ADD R1, R1, -R2;
            // r1=Tex2-r2
            MAD R2, R0.y, R1, R2;
            // r2 = Tex4.y*r1+r2, 即 a2*r1+r2 = a2*(Tex2-r2)+r2, 即r2*(1-a2)+Tex2*a2, 其中r2即是上次0和1層混合后的結果
            // 三.第3層和前面結果使用第4張圖的z通道作為alpha進行混合:
            TEX R1, fragment.texcoord[3], texture[3], 2D;
            ADD R1, R1, -R2;
            // r1=Tex3-r2
            MAD R1, R0.z, R1, R2;
            // r1=a3*r1+r2 , 即 a3*r1+r2 = a3*(Tex3-r2)+r2, 即r2*(1-a3)+Tex3*a3
            // 這樣r1就保存了最終的混合結果
            // 四.讓陰影地表光澤系數為0(Tex4.w即a通道代表地形的陰影,0為陰影,1為正常.而每層貼圖中的a通道是光澤通道,所以R1.w保存的是最終的光澤通道值):
            MUL R0.x, R1.w, R0.w;
            // r0.x = r1.w(光澤)*Tex4.w(陰影值, 是陰影則=0,否則=1)
            // 計算削減系數?
            MAD R0.w, R0, c[0].y, c[0].z; // r0乘上0.3(削減了30%)再加上一個常量0.69999999
            // 反射高光 = secondary_color(反射光)*光澤:
            MUL R0.xyz, R0.x, fragment.color.secondary;
            // 貼圖最終color = 最終貼圖混出的color*削減系數:
            MUL R1.xyz, R1, R0.w;
            // 貼圖最終color * primary_color(光照色或是頂點色) + 反射高光:
            MAD result.color.xyz, R1, fragment.color.primary, R0;
            // alpha:
            MOV result.color.w, c[0].x;
            END
              
              

            本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/flipcode/archive/2008/03/03/2143452.aspx

            posted @ 2009-12-11 02:04 RedLight 閱讀(843) | 評論 (0)編輯 收藏

            2009年12月5日

            RedLight引擎原型初成

            一直都沒勇氣去寫一個游戲引擎,也許是太懶了,也許是太大了。雖然寫了些零零碎碎的Test Case! 但你知道的,這始終不成氣候!
            最近我被安排到一個小組中,做的項目是一個體感游戲,之前考慮過用ogre開源引擎來做,可惜我對這東西又不熟的,聽人家說還要用第三方類庫CEGUI, 還要配置一些東西,一聽頭都大了,光學習理想都用半個月了,我們的工程只給兩個月的時間,唉呀!算了吧,自己不是還有些亂七八糟的代碼可用嗎?狠下決心,決定干它一把!哪怕辛苦一點,做下來一個游戲引擎以后就容易干事了。
            經過和另外一個同事兩個月的時間奮斗,一路中雖說遇到些困難,也常加班的,項目終于也做完了。





            一個游戲引擎原型基本蛋生了,我們命名它為 RedLight,它基本實現了

            (0) Win32程序渲染框架
            (1) UI的基本消息交互流程,XML窗體配置管理,UI皮膚配置管理,基本的UI控件庫,多分辯率無縫UI拼圖
            (2) 室外場景管理
            (3) 攝相機路徑攝像
            (4) 3D Max8模型及骨骼動畫導出插件
            (5) 模型渲染, 關鍵幀動畫及骨骼動畫控制
            (6) 基本的水面反射效果
            (7) 簡單的面粒子系統
            (8) 聲音控制接口

            這是一個單機游戲引擎的原型,功能有限,但它總算不辱使命完成了一個項目了,以后再擴展使它日益強大吧!

            posted @ 2009-12-05 09:36 RedLight 閱讀(768) | 評論 (0)編輯 收藏

            超級工具-----NVPerfHUD分析Beijing 2008

                 摘要:   閱讀全文

            posted @ 2009-12-05 09:06 RedLight 閱讀(1259) | 評論 (0)編輯 收藏

            2009年12月1日

            WOW字體研究報告

            我喜歡玩WOW的UI風格,尤其是它的高清字體-------任務窗口的內容總感覺十分舒暢。這是從魔獸世界中任務窗口的游戲截圖
                                                  

            經研究, 其實,上面的字體是用方正楷體(不是windows楷體)字體來做的, 用Freetype類庫得到每個字符的對應圖,并組裝排版到一張預先創建好的空紋理中(256*256),  組成一張灰度圖,這樣可以防止重復字符貼圖兩遍,提高效率,就像活字印刷術一樣靈活組合。
            渲染的時候,采用字體顏色RGB + 灰度圖合成最終效果。

            也許你會發現,左圖為什么這么清晰,右圖好像稍差一點。對了,其實人的眼睛很奇怪,對顏色的識別是通過對比的,wow正是利用這一點,背景色采用以黃色為主色調,夾雜一些噪聲,然后再渲上黑色的文字,這樣可以給人感覺到很清晰。

            其實wow中還是其他一些文字效果,比方說:陰影文字,原理是渲染兩次同一字符,并在第二次遍渲染作偏移即可。當然,還有那種字體外邊包起來的效果,不過這種我還沒研究它的算法。

            怎么說呢?一個游戲世界中,字體我覺得相當重要,豐富的字體表現會給人相當美滿的效果,帶給人美好的印象,所以還是相當重要的。我也在做我的文字配置系統,祝福我早日完成吧! 謝謝!

            posted @ 2009-12-01 09:13 RedLight 閱讀(945) | 評論 (1)編輯 收藏

            2009年11月14日

            BigWorld引擎初識大觀

                 摘要:   閱讀全文

            posted @ 2009-11-14 05:16 RedLight 閱讀(2218) | 評論 (2)編輯 收藏

            D3D與OpenGL常用API對譯

            作為一個3D程序員, 我用了OpenGL兩年多, 最近在搞一個項目, 從OpenGL轉到D3D, 雖然工程外在的框架都封裝得不錯, 但想完全地從OpenGL轉換到D3D, 看起來還是有難度的, 花了我兩個星期的時間, 我終于轉換過來了。
            D3D與OpenGL的幾點比較明顯不同的地方:
            (一)、正交投影時:OpenGL以屏幕左上角為(0,0), 而D3D卻以屏幕中心為(0,0)
            (二)、OpenGL使用右手坐標系, 而D3D使用左手坐標系
            (三)、OpenGL使用旋轉操作等轉入的角度參數是 角度, 而D3D是 弧度,所以注意要PI * Angle / 180

            下面我把具體地API對照關系列出來(不是很全,以后添加中.......)


            1. 坐標變換
             pos = D3DXVECTOR3(0,2,-1.5);
             at  = D3DXVECTOR3(0,0,0);
             up  = D3DXVECTOR3(0,1,0);
             D3DXMatrixLookAtLH(&view,&pos,&at,&up);
             pd3dDevice->SetTransform(D3DTS_VIEW,&view);

            2. 繪制
             pd3dDevice->SetRenderState(D3DRS_FILLMODE,D3DFILL_WIREFRAME);

                DrawPrimitive()
             DrawIndexedPrimitive()
             
             DrawPrimitiveUP()
             DrawIndexedPrimitiveUP()
            3. 顏色


            4. 片段測試

             (1) 深度測試
             g_pDevice->SetRenderState(D3DRS_ZENABLE, TRUE);           //glEnable(GL_DEPTH_TEST);  
             g_pDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);    //glDepthFunc(GL_LEQUAL);
             //--------------------------------------------------------------------------------------------------------
             g_pDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);      //glEnable(GL_CULL_FACE);

             
             (2) Alpha測試
             //-------------------------------------------------------------------------------------------------------- 
             g_pDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);                //glEnable(GL_ALPHA_TEST);
             g_pDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER);    //glAlphaFunc(GL_GREATER, 0.1f);
             g_pDevice->SetRenderState(D3DRS_ALPHAREF, 0.1 * 255); //取值范圍 0 ~ 255
             
             (3) 剪裁測試 (平面剪切)
             //--------------------------------------------------------------------------------------------------------
             // Enable clip plane for reflection map
             CMatrix44f pWorldViewProjIT=m_pWorldViewProj;
             //pWorldViewProjIT.Transpose();
             pWorldViewProjIT.Invert();   

             // Transform plane to clip-space
             float pClipSpacePlane[4];
             float pClipPlane[]= { 0, 0, 1, 0};   

             // Check if camera is below water surface, if so invert clip plane
             CVector3f pEye=(CVector3f)m_pCamera.GetPosition();
             if(-pEye.m_fZ<0.0)
             {
              pClipPlane[2]=-pClipPlane[2];
             }

             MatrixTransformPlane(pClipSpacePlane, pClipPlane, pWorldViewProjIT);

             // enable clip plane now
             g_pDevice->SetClipPlane(0, pClipSpacePlane);  
             g_pDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 1);
             
             
             
             (4) 模板測試
             //--------------------------------------------------------------------------------------------------------
             g_pDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE);
                g_pDevice->SetRenderState(D3DRS_STENCILFUNC, 3DCMP_ALWAYS);
                g_pDevice->SetRenderState(D3DRS_STENCILREF, 0x1); //取值范圍 0 ~ 255
               
                Device->SetRenderState(D3DRS_STENCILPASS,  D3DSTENCILOP_KEEP);
             
            5. 紋理操作
             
             g_pDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
               g_pDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
               g_pDevice->SetSamplerState( 0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
               
             g_pDevice->SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
              g_pDevice->SetSamplerState( 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);

            6. 緩沖區操作
              
             (1) 顏色緩沖
             //--------------------------------------------------------------------------------------------------------
             g_pDevice->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA);
             g_pDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0x000000F);
             
             (2) 深度緩沖
             //--------------------------------------------------------------------------------------------------------
             g_pDevice->SetRenderState(D3DRS_ZENABLE, TRUE);           //glEnable(GL_DEPTH_TEST);
             g_pDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);        //glDepthMask(GL_TRUE);

             (3) 模板緩沖
             //--------------------------------------------------------------------------------------------------------
             
             (4) 渲染到紋理
             //--------------------------------------------------------------------------------------------------------
             // Render targets
             IDirect3DSurface9 *m_plD3DBackbufferSurf,
              *m_plD3DDepthStencilSurfAA,
              *m_plD3DDepthStencilSurf;

             CRenderTarget *m_pRTRefraction, *m_pRTReflection; //(自定義紋理類)

             //-----------------------------------------------------------------------------------

             // Get backbuffer
             g_pDevice->GetRenderTarget(0, &m_plD3DBackbufferSurf);
             
             // Get depthstencil
             g_pDevice->GetDepthStencilSurface(&m_plD3DDepthStencilSurfAA);
             

             // Restore previous states
             g_pDevice->SetRenderTarget(0, m_plD3DBackbufferSurf);
             g_pDevice->SetDepthStencilSurface(m_plD3DDepthStencilSurfAA);
             
             // (1)折射圖--------------------------------------------------------------------------
             
             //下面的語句調用了 g_pDevice->CreateRenderTarget(iWidth, iHeight, (D3DFORMAT) iFormat, (D3DMULTISAMPLE_TYPE)iAASamples, 0, 0, &m_plD3Surf, 0));
             if(FAILED(m_pRTRefraction->Create(m_fWidth>>1, m_fHeight>>1, D3DFMT_A8R8G8B8)))
             {
              return APP_ERR_INITFAIL;
             }
             
             // Create depthstencil withouth multisampling
             g_pDevice->CreateDepthStencilSurface(m_fWidth, m_fHeight, D3DFMT_D24X8, (D3DMULTISAMPLE_TYPE)0, 0, 0, &m_plD3DDepthStencilSurf, 0);
             
             
             g_pDevice->SetRenderTarget(0, m_pRTReflection->GetSurface());
             
             g_pDevice->StretchRect(m_plD3DBackbufferSurf, 0, m_pRTRefraction->GetSurface(), 0, D3DTEXF_NONE);
             
             // (2)反射圖-----------------------------------------------------------------------------------
             m_pRTReflection=new CRenderTarget;
             if(FAILED(m_pRTReflection->Create(m_fWidth>>2, m_fHeight>>2, D3DFMT_A8R8G8B8)))
             {
              return APP_ERR_INITFAIL;
             }
             
             g_pDevice->SetRenderTarget(0, m_pRTReflection->GetSurface());
             
             
             //-----------------------------------------------------------------------------------
             g_pDevice->SetRenderTarget(0, m_pRTReflection->GetSurface());
             g_pDevice->SetDepthStencilSurface(m_plD3DDepthStencilSurf);
             g_pDevice->Clear(0, 0, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(255, 0, 0, 128), 1.0f, 0);  
             SetViewport(m_pRTReflection->GetWidth(), m_pRTReflection->GetHeight());
             //-----------------------------------------------------------------------------------
             
             D3DXSaveTextureToFile("imageTex.jpg",D3DXIFF_JPG,(IDirect3DTexture9*)m_pWavesBump->GetTexture(),NULL);
             
            7. 混合操作
             g_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);    //glDisable(GL_BLEND);
             g_pDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);  //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
             g_pDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
             

            8. 燈光與材質
             g_pDevice->SetRenderState(D3DRS_LIGHTING, FALSE); //glDisable(GL_LIGHTING);
             
             D3DMATERIAL9 mtrl;
             mtrl.Ambient  = a;
             mtrl.Diffuse  = d;
             mtrl.Specular = s;
             mtrl.Emissive = e;
             mtrl.Power    = p;
             Device->SetMaterial(&mtrl);  //在設置紋理前設定
             //設置當前使用的紋理
             

            posted @ 2009-11-14 04:49 RedLight 閱讀(1673) | 評論 (0)編輯 收藏

            2009年9月25日

            wmo(wow map object) research

            wmo(wow map object) research
            The wmo是一個非常有趣的設計,wow中比較小的物體使用doodad,而building使用wmo,
            這里的building可以是橋梁、了望臺、簡單的小房子、復雜點的旅館這樣的房屋、非常
            復雜的建筑群(例如地下城場景),本文對wmo場景文件進行簡單的介紹,關于wmo文件的具
            體信息請參考wowmapview的source code,這里非常感謝ufoz所做的貢獻。
            1、命名規則
            wmo保存在以.wmo結尾的文件中,這個文件使用數據塊來保存數據。一個wmo通常由一個或多個
            group組成,而group數據也保存在以.wmo結尾的文件中,不過文件名稱存在不同,例如一個wmo
            保存在name.wmo文件中,那么group文件名就為name_001.wmo name_002.wmo......
            2、結構
            wmo就組織結構來說包含兩個層次,group和batch。一個group通常包含多個batch,其中group包含
            一個AABB。batch是wmo最小的渲染單元,它保存了頂點索引列表,可以直接調用DP進行渲染。group
            內保存一個標志位,可以將group分為indoor/outdoor兩類,這一個信息非常重要,通過它wmo就將
            building分成了內外兩部分,outdoor group就是building的外殼,他通過portal與室內場景連接
            在一起。
            3、portal
            wmo文件中保存了portal信息,在wmo中規定group必須通過portal進行連接,portal由PVS和PRS
            兩部分組成,PVS記錄portal頂點信息,PRS記錄portal和group的連接信息,PRS結構如下:
            struct WMOPR {
            int portal;
            int group;
            int dir;
            };
            需要注意的是dir,這個成員只有兩個值-1或1,由于portal的頂點信息按照順時針記錄,因此group
            位于portal的正面時dir為1,否則為-1,通過dir可以快速確定group到底位于portal的哪一側。
            通過wmo中記錄的portal信息可以使用portal culling來檢查group的可見性,但是這里還是有一些
            難度,主要是指portal的記錄方式。由于一個group可能有多個portal,而查找連接的portal只能
            通過PRS,這樣在大的場景中非常不方便。而且在wmo中竟然沒有記錄portal的plane信息,如何確定
            camera到底是位于portal的正面還是反面呢?(現在wmo文件由于沒有完全破解,存在一些wowmapview
            未讀入的數據塊,例如MVER、MOPT、MOVV、MOVB等,其中MVER應該是wmo文件的版本號,MOPT懷疑是保
            存所有plane信息,而MOVV可能是保存包圍體頂點信息,而MOVB保存包圍體信息,MOVV、MOVB應當用于
            碰撞檢測,這些暫時沒有驗證)我的做法是在載入時計算portal的plane信息,并將PRS信息轉換為類似
            Q3 BSP中portal的結構。
            struct portal_t {
            int othergroup;
            int pvs;//pvs index
            int dir;
            };
            struct group_t {
            int firstportal;
            int numportals;
            };
            4、碰撞檢測
            在wmo中并沒有使用BSP、OC TREE這樣的結構來進行場景管理,可能所有人都感覺非常困惑。
            場景管理的功能主要是為了加速渲染和方便碰撞檢測,由于存在portal,這樣第一個功能已經完成。
            而對于碰撞檢測,我的想法應當是AABB TREE。仔細觀察WOW的場景可以發現在indoor場景中曲面、斜面
            這樣的幾何物體非常少,大多數是規則物體,因此可以判斷在wmo中所有的物體都是嚴格按照軸對齊
            方式進行建模,也就是對規則性物體AABB=OBB。由于MOVV和MOVB信息并沒有完全研究透徹,因此關于
            這一部分只能是我的猜測。
            5、渲染
            對wmo的渲染由于batch的存在從而變的簡單化,但還有可以優化的地方。由于wmo中使用portal將其分割
            成group,因此有大量的材質相同的model被分割成不同的batch,在渲染時將材質相同的batch合并到一起
            渲染可以避免一些無謂的DP調用。wmo一個令人詬病的地方是使用vertex light,為了減少圖元數量從而
            使頂點數量降低,造成渲染的時候出現色帶效果,應當加入lightmap,由于wmo的場景通常不大,預處理
            時做radiosity的時間也不會太長。
            6、動態載入
            對于只包含幾個group的小場景的wmo,由于載入時間不是太長,在動態載入時一次性載入對程序影響
            并不會太大。但是對于超大場景的wmo就需要考慮載入策略,這樣場景典型的就是wow中的地下城場景,
            它一個wmo中包含了幾百個group,一次性載入時間非常長,需要分段進行載入。此時就顯示出wmo分
            文件保存group的優勢了,為了實現動態載入wmo場景,一種可能的做法是在載入wmo后需要根據camera
            所在的group快速的建立group連接層次圖,這個圖通過PRS數據建立,建立流程如下:
            一、將camera所在group作為當前group,獲得所有相連的protal;
            二、將protal連接的group保存到第一層列表中,遍歷第一層列表中所有的group;
            三、獲得第一層列表中group的portal,檢查portal所連接的group是否保存在第一層列表中,如果沒有
                將其保存到第二層列表中;
            四、重復上述過程,直到整個層次圖建立。
            這個層次圖可以預先建立然后保存到文件中運行時載入,這樣wmo就是分層載入而不需要一次性載入。
            (這里我考慮是否在wmo中也可以建立類似bsp的pvs數據呢?雖然pvs現在已經開始淘汰,但是如果
            存在pvs就可以方便確定哪些group需要立即載入,只是不知被portal分割后的group到底是不是convex
            hull,如果是的話可以建立pvs,但對建模時限制更加明顯,兩難的選擇!!!)
            7、建模
            由于wmo是按照group對場景進行保存,因此為了建立wmo需要設計一個強力的模型構建工具,這個工具
            主要功能就是對從建模工具(3DS MAX)中建立的場景模型進行分組和處理。美工在制作模型時需要非常
            小心,所有的模型要嚴格的軸對齊(軸對齊的原因是需要模型的AABB=OBB),然后將模型導入工具中。
            模型構建工具有以下功能:分組(group)功能、group選擇、group顯示/隱藏、指定portal,portal對
            齊(考慮門、窗戶這樣天然的portal,手動指定portal時肯定無法與外表墻壁對齊,需要程序自動對齊)
            、batch操作(分割、選擇、顯示/隱藏等)、圖元級操作(triangle揀選,用于batch分割)、光照運算
            (產生vertex light數據)、放置光源、放置doodad(場景中的道具,如桌子、椅子等)。可能還需要其
            他一些功能,但是對比其他引擎的場景建模工具(hammer、sandbox)明顯簡單化許多。
            8、優勢及不足
            當前處理室內場景的主流技術依然是bsp,但是隨著硬件的發展bsp的優勢在慢慢地喪失,bsp賴以生存的
            預處理PVS現在已經完全被實時的portal culling所取代,bsp優勢只剩下對圖元排序(用于透明物體的
            渲染)和基于brush的快速碰撞檢測上,但是對比建模工具的復雜化和場景的限制,采用bsp的開銷確實
            顯得太大。而基于純portal引擎的結構開始流行,例如cryengine中處理室內場景時就完全拋棄bsp,
            場景完全由一塊塊固定大小的墻壁組成,一塊墻壁基本和bsp中brush類似,這樣做的好處是建模工具變
            的簡單(不需要進行CSG運算),而且非常容易的產生portal,同時由于場景使用brush構成也兼具了
            bsp方便進行碰撞檢測的優勢。wmo有些類似cryengine,但是在某些方面更具優勢。
            首先在建模方面,wmo的場景完全可以通過成熟的建模工具來構建,這樣對于美工不需要重新學習新的
            建模工具,可以節約大量的時間。其次模型構建工具需要的功能非常少,減少了程序的復雜性,縮短了
            編寫相關工具的時間。再次,場景管理簡單化,相應代碼量大幅度減少,同時由于portal的存在,可以方便
            的與其他引擎相對接。可以說wmo是一種可以進行快速開發的場景結構。

            posted @ 2009-09-25 08:39 RedLight 閱讀(616) | 評論 (0)編輯 收藏

            僅列出標題  下一頁
            <2025年5月>
            27282930123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567

            導航

            統計

            公告


            Name: Galen
            QQ: 88104725

            常用鏈接

            留言簿(3)

            隨筆分類

            隨筆檔案

            相冊

            My Friend

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            伊人久久综在合线亚洲2019 | 国内精品伊人久久久影院| 国产—久久香蕉国产线看观看| 嫩草影院久久99| 国产A三级久久精品| 国产91久久精品一区二区| 久久国产精品一区| 久久亚洲欧美国产精品| 久久久精品国产Sm最大网站| 亚洲精品无码久久一线| 亚洲国产精品一区二区三区久久 | 久久男人Av资源网站无码软件| 国产精品免费久久久久久久久 | 99久久精品免费观看国产| 久久精品国产亚洲av麻豆蜜芽 | 亚洲人成伊人成综合网久久久| 国内精品伊人久久久久影院对白 | 国产精品岛国久久久久| 无码人妻久久一区二区三区蜜桃| 久久精品国产亚洲网站| 久久久噜噜噜www成人网| 18禁黄久久久AAA片| 婷婷久久综合| 久久无码国产| 欧美日韩精品久久久久| 国产综合精品久久亚洲| 国产一区二区精品久久岳| 久久精品国产99国产电影网| 久久精品国产99久久久| 久久国产精品77777| 99久久国产热无码精品免费| 久久综合久久自在自线精品自| 中文精品久久久久人妻不卡| 91麻豆国产精品91久久久| 久久香综合精品久久伊人| 热99RE久久精品这里都是精品免费 | 久久精品国产亚洲精品2020| 久久婷婷成人综合色综合| 国产综合久久久久| 97久久超碰国产精品2021| 久久99国产精品二区不卡|