青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

天行健 君子當自強而不息

2D和3D圖形引擎的混合(2)

 

本篇是2D和3D圖形引擎的混合(1)的續(xù)篇。

 

在游戲如最終幻想和寄生前夜(兩者都是由Square公司出品)中,可以在欣賞三維模型的同時,享受到非常精美的預(yù)先渲染好的背景圖像。將二維和三維圖形混合在一起,一直以來都是游戲公司高度保密的技術(shù),現(xiàn)在可以 揭開謎底一看究竟。

如何從一個二維圖像中獲取三維的深度信息呢?有幾種方法可以實現(xiàn)三維物體在二維圖像中的背景幕效果。

(1)在一個三維建模工具中創(chuàng)建預(yù)先進行渲染的背景幕,例如Caligari公司的gamespace lightdiscreet公司的3D Studio Max,并將圖像與包含每個像素z值的深度緩沖區(qū)一起保存。對于游戲中的每一幀,將圖像的深度緩沖區(qū)拷貝到背景深度緩沖區(qū)中,并繼續(xù)繪制三維物體。

(2)在層次中創(chuàng)建背景幕,從底層開始,一個接一個地繪制每個圖像,并將三維角色繪制到適當?shù)膶哟紊希@樣就可以使用后面的層次覆蓋較低層次的部分內(nèi)容(以及三維物體)。

(3)使用一個非常詳盡的預(yù)先渲染好的背景幕,以及一個在三維建模軟件中渲染場景的簡化的網(wǎng)格模型。使用網(wǎng)格模型以呈現(xiàn)z數(shù)值并進行碰撞檢測,三維物體可以使用z緩沖區(qū)負責繪制正確的深度。

我們采用第三種方法來繪制。

 

二維背景幕的處理

用一個三維建模軟件開發(fā)二維的背景幕,例如gamespace light(而不是使用一個繪圖程序,因為需要從建模軟件中獲取多邊形的數(shù)據(jù)),下圖顯示了一個簡單的網(wǎng)格模型以及最終的渲染效果:

一旦場景被渲染好,就需要將它作為一個位圖保存到磁盤上,那個位圖文件需要被切分成較小的紋理,如下圖所示,這個背景幕被切割成多個Direct3D可以處理的紋理,比如背景幕圖像為640 x 480,所以紋理將為256 x 256(對于塊1245),以及128 x 256(對于塊36)。

 

場景網(wǎng)格模型的處理

詳盡的層次看起來非常不錯,現(xiàn)在想要包含一些三維物體到它里面。首先,需要構(gòu)造一個簡化的場景,可使用兩種方法,包括填充每一幀的深度緩沖區(qū),以便三維物體能夠正確地與二維的背景幕進行混合;作為運動物體的碰撞網(wǎng)格模型。

因為網(wǎng)格模型必須在每幀中被渲染出來,以便創(chuàng)建場景中的z緩存,使用越少的多邊形當然越好,然而必須使用足夠的多邊形以確保三維物體能夠被正確地混合,如下圖所示,它顯示了最終渲染好的圖像,實際的場景網(wǎng)格模型,以及簡化的場景網(wǎng)格模型。

當處理一個簡化的網(wǎng)格模型時,僅使用了兩種材質(zhì)(沒有紋理)。第一種材質(zhì)代表了實際繪制到背景幕上的多邊形區(qū)域,而第二種材質(zhì)隱藏了在交集測試中所使用的多邊形,對于第二種材質(zhì),使用的alpha的數(shù)值為0.0(意味著它是不可見的,不會被實際渲染)。

應(yīng)該使用正確的多邊形數(shù)量去渲染場景。如果有太多的多邊形,引擎將變得非常緩慢。如果多邊形太少,將會在玩游戲時得到貼圖錯誤的信息。請這樣思考一下:一個使用了500個多邊形的球形網(wǎng)格模型,很明顯比一個簡化的網(wǎng)格模型復雜許多,在一個簡化的網(wǎng)格模型里,僅需要足夠的多邊形去表示球體,并確保它在進行渲染時覆蓋相同的屏幕區(qū)域。

下圖演示了在創(chuàng)建簡化網(wǎng)格模型時常出現(xiàn)的一個錯誤,那就是使用了太少的多邊形。

為了簡化網(wǎng)格模型中多邊形的數(shù)量,切割掉那些看不到的表面或者在交集測試中所使用的表面,同時僅繪制那些實際覆蓋三維物體的多邊形 。舉個例子,如果在背景幕中有一個盒子,而玩家角色從不會接近它,那么在簡化的網(wǎng)格模型中就不用繪制它。

對于本例中的背景幕,僅需要繪制如下的簡化網(wǎng)格模型:

 

場景的渲染

現(xiàn)在將完成最后一步,以確保背景幕圖像能夠包含深度信息(通過簡化的網(wǎng)格模型)。如果加載了背景幕圖像和簡化的網(wǎng)格模型,就可以很容易地渲染游戲中的每幀,通過使用如下步驟:

(1)將z緩沖區(qū)清除為1.0(并確保z緩沖區(qū)被啟動)。

(2)渲染簡化的網(wǎng)格模型(因而填充場景的z緩沖區(qū)),跳過那些數(shù)值為0.0的多邊形(它們是不可見的)。

(3)禁用z緩沖區(qū)。

(4)使用ID3DXSprite位塊傳送背景幕紋理。

(5)啟動z緩沖區(qū)。


絕大多數(shù)新近的顯卡都允許處理
1024 x 1024像素大小的紋理,這意味著可以將整個背景幕圖像加載到內(nèi)存中,而不需要將它切割成6個小紋理。

在繪制好背景幕后,剩下的就是將三維物體(網(wǎng)格模型)繪制到場景中,因為Z緩沖區(qū)包含了所有與每個像素相關(guān)的深度數(shù)值。請不要猶豫,隨心所欲繪制角色、物體、甚至是增強背景的圖像。

 

下載源碼和工程

 

代碼:

/************************************************************************************
PURPOSE:
     3D in 2D test.
************************************************************************************/


#include "core_common.h"
#include "core_framework.h"
#include "core_graphics.h"
#include "core_input.h"

#define ANIM_NONE   -1
#define ANIM_WALK    1
#define ANIM_IDLE    2

const float g_angles[13] = {
       0.0f, 4.71f, 0.0f, 5.495f, 1.57f, 0.0f,  
       0.785f, 0.0f,  3.14f, 3.925f, 0.0f, 0.0f, 2.355f 
};

class APP : public FRAMEWORK
{
private:  
    CAMERA          m_camera;
       
    INPUT           m_input;
    INPUT_DEVICE    m_keyboard; 

    TEXTURE         m_background[6];

    
// the simplified scene mesh and object
    MESH            m_scene_mesh;    
    OBJECT          m_scene;

    
// 3D meshes and objects
    MESH            m_monster_mesh;
    OBJECT          m_monster;
    ANIMATION       m_monster_anim;
    
    
static const float m_above_floor;

public:
    BOOL init()
    {
        
if(! create_display(g_hwnd, get_client_width(g_hwnd), get_client_height(g_hwnd), 16, TRUE, TRUE))
            
return FALSE;
        
        set_perspective(0.6021124f, 1.3333f, 1.0f, 10000.0f);                

        ShowCursor(TRUE);                          

        
// initialize input and input device
        m_input.create(g_hwnd, get_window_inst());
        m_keyboard.create_keyboard(&m_input);     

        
// load the backdrop textures
        for(short i = 0; i < 6; i++)
        {
            
char filename[81];
    
            sprintf(filename, "..\\data\\scene%u.bmp", i+1);

            
if(! m_background[i].load(filename, 0, D3DFMT_UNKNOWN))
                
return FALSE;
        }

        
// load the scene mesh and configure object

        
if(! m_scene_mesh.load("..\\Data\\Scene.x", ".\\"))
            
return FALSE;

        m_scene.create(&m_scene_mesh);

        
// load the monster mesh and setup monster object

        
if(! m_monster_mesh.load("..\\data\\yodan.x", "..\\data\\"))
            
return FALSE;

        m_monster_anim.load("..\\data\\yodan.x", &m_monster_mesh);
        m_monster_anim.set_loop(TRUE, "Idle");
        m_monster_anim.set_loop(TRUE, "Walk");

        m_monster.create(&m_monster_mesh);
        
        
// position the camera for the scene        

        m_camera.move(0.0f, 200.0f, -650.0f);
        m_camera.rotate(0.348888f, 0.0f, 0.0f);

        g_d3d_device->SetTransform(D3DTS_VIEW, m_camera.get_view_matrix());        
        
        
return TRUE;
    }

    BOOL frame()
    {
        
static DWORD time_begin = timeGetTime();       

        
// calculate elapsed time (plus speed boost)
        DWORD time_end = timeGetTime();
        
ulong time_elapsed = time_end - time_begin;
        time_begin = time_end;

        
// read keyboard data        
        m_keyboard.read();

        
// process input and update everything, ESC quits program.
        if(m_keyboard.get_key_state(KEY_ESC))
            
return FALSE;
        
        
// process movement

        
long dir = 0;

        
if(m_keyboard.get_key_state(KEY_UP))
            dir |= 1;

        
if(m_keyboard.get_key_state(KEY_RIGHT))
            dir |= 2;

        
if(m_keyboard.get_key_state(KEY_DOWN))
            dir |= 4;

        
if(m_keyboard.get_key_state(KEY_LEFT))
            dir |= 8;

        
float x_move, z_move;

        x_move = z_move = 0.0f;

        
if(dir)
        {
            m_monster.rotate(0.0f, g_angles[dir], 0.0f);

            x_move =  cos(g_angles[dir]) * (time_elapsed * 0.25f);
            z_move = -sin(g_angles[dir]) * (time_elapsed * 0.25f);
        }

        
float x_pos, y_pos, z_pos;

        
// get monster coordinates in local variables (make it easier)
        x_pos = m_monster.get_x_pos();
        y_pos = m_monster.get_y_pos();
        z_pos = m_monster.get_z_pos();

        D3DXMESH_PTR d3d_mesh = m_scene_mesh.get_root_mesh_info()->m_d3d_mesh;

        
// check for collision in movement (4 points).
        //
        // I hard-coded the bounding size of the object (25 radius) and added ability to climb up at mose 32 units.
        for(long i = 0; i < 4; i++)
        {
            
float x_add[4] = {  0.0f, 25.0f,    0.0f,  -25.0f };
            
float z_add[4] = { 25.0f,  0.0f,  -25.0f,    0.0f };

            
float dist;            

            
if(is_ray_intersect_mesh(d3d_mesh,
                                     x_pos + x_add[i],           y_pos + m_above_floor, z_pos + z_add[i],
                                     x_pos + x_add[i] + x_move,  y_pos + m_above_floor, z_pos + z_add[i] + z_move,
                                     &dist))
            {
                
// clear out movement and break
                x_move = z_move = 0.0f;
                
break;
            }
        }
       
        
// fix height of monster
        y_pos = closest_height_below_object(d3d_mesh, x_pos, y_pos + m_above_floor, z_pos);

        
// move monster and set new animations as needed
        m_monster.move(x_pos + x_move, y_pos, z_pos + z_move);        

        
static short last_anim = ANIM_NONE;

        
if(!float_equal(x_move, 0.0f) || !float_equal(z_move, 0.0f))
        {
            
if(last_anim != ANIM_WALK)
            {
                last_anim = ANIM_WALK;
                m_monster.set_anim_info_set(&m_monster_anim, "Walk", time_end / 20);
            }
        }
        
else
        {
            
if(last_anim != ANIM_IDLE)
            {
                last_anim = ANIM_IDLE;
                m_monster.set_anim_info_set(&m_monster_anim, "Idle", time_end / 20);
            }
        }

        
// update monster animations
        m_monster.update_anim_info_set(time_end / 20, TRUE);       
        
        
// render everything
        clear_display_zbuffer(1.0f);                       

        
// begin render now
        if(SUCCEEDED(g_d3d_device->BeginScene()))        
        {
            
// render the level mesh
            g_d3d_device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
            m_scene.render();

            
// draw the backdrop (composed of six textures)

            g_d3d_device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);

            g_d3d_sprite->Begin(0);

            
for(int row = 0; row < 2; row++)
            {
                
for(int col = 0; col < 3; col++)
                    m_background[row * 3 + col].draw(col * 256, row * 256, 0, 0, 0, 0, 1.0f, 1.0f, 0xFFFFFFFF);
            }

            g_d3d_sprite->End();

            
// draw the 3D monster
            
            g_d3d_device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);

            m_monster.render();

            g_d3d_device->EndScene();            
        }

        present_display();

        
return TRUE;
    }

    BOOL shutdown()
    {
        destroy_display();

        
return TRUE;
    }
};

const float APP::m_above_floor = 32.0f;

int WINAPI WinMain(HINSTANCE inst, HINSTANCE, LPSTR cmd_line, int cmd_show)
{
    DWORD client_width  = 640;
    DWORD client_height = 480;
    DWORD x_pos = (get_screen_width()  - client_width) / 2;
    DWORD y_pos = (get_screen_height() - client_height) / 4;

    DWORD window_style = WS_BORDER | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU;

    
if(! build_window(inst, "3d_in_2d_class", "3D in 2D Test", window_style,
                      x_pos, y_pos, client_width, client_height))
    {
        
return -1;
    }

    APP app;
    app.run();

    
return 0;
}

 

截圖:


posted on 2007-10-28 01:09 lovedday 閱讀(1464) 評論(5)  編輯 收藏 引用

評論

# re: 2D和3D圖形引擎的混合(2) 2007-10-28 23:28 neoragex2002

有點意思。不過你這個場景選取得不太好,帶粒子效果的,很容易看出來是烘培出來的背景。  回復  更多評論   

# re: 2D和3D圖形引擎的混合(2) 2007-10-28 23:32 neoragex2002

至于簡化場景用的導航網(wǎng)格這種技法,至少在2000年前就有人用了,heh  回復  更多評論   

# re: 2D和3D圖形引擎的混合(2) 2007-10-29 00:11 lovedday

謝謝,你的博客寫的不錯,有空我會多去看看,順便請教請教。 ^_^  回復  更多評論   

# re: 2D和3D圖形引擎的混合(2) 2007-11-01 20:30 風在奔跑

本來就是烘培出來的背景吧?  回復  更多評論   

# re: 2D和3D圖形引擎的混合(2) 2010-06-02 15:45 guest

@風在奔跑
下載的代碼中data目錄沒有文件啊  回復  更多評論   


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


公告

導航

統(tǒng)計

常用鏈接

隨筆分類(178)

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

搜索

最新評論

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            亚洲精品在线视频观看| 国产精品久久久久久久久久尿| 欧美一区二区三区在线免费观看| 亚洲国产经典视频| 亚洲黄一区二区三区| 在线视频国产日韩| 日韩视频一区二区| 香蕉免费一区二区三区在线观看| 一区二区三区四区五区视频| 在线日本高清免费不卡| 亚洲第一精品影视| 在线亚洲一区二区| 久久爱www.| 亚洲国产精品久久久久秋霞影院| 欧美成人免费观看| 亚洲精品社区| 午夜日韩av| 欧美激情乱人伦| 欧美四级电影网站| 亚洲第一主播视频| 亚洲欧美清纯在线制服| 久久精品亚洲一区| 亚洲免费av网站| 欧美一级精品大片| 欧美日韩国产麻豆| 在线观看成人av| 亚洲欧美日韩中文视频| 久久综合伊人77777| 亚洲黄网站黄| 久久精选视频| 国产精品视频免费在线观看| 国产精品永久在线| 日韩视频一区二区| 欧美成年人网站| 亚洲直播在线一区| 欧美日韩成人一区二区三区| 国产精品一区视频| 一区二区三欧美| 亚洲高清电影| 国产精品乱人伦一区二区 | 99亚洲伊人久久精品影院红桃| 日韩亚洲一区在线播放| 欧美一级艳片视频免费观看| 久久久久久69| 国产视频自拍一区| 性欧美在线看片a免费观看| 欧美激情一区二区久久久| 亚洲一区二区三区影院| 欧美韩日高清| 亚洲激情校园春色| 美日韩免费视频| 久久蜜臀精品av| 在线观看一区欧美| 欧美~级网站不卡| 久久精品国产亚洲高清剧情介绍| 欧美视频日韩视频在线观看| 在线播放日韩| 欧美va天堂| 久热精品在线| 亚洲国产精品一区在线观看不卡 | 亚洲伦理中文字幕| 欧美日韩精品一区二区天天拍小说| 激情校园亚洲| 欧美高清自拍一区| 欧美成人亚洲成人| 亚洲毛片一区| 国产精品99久久久久久人| 欧美剧在线观看| 99re8这里有精品热视频免费 | 激情综合色丁香一区二区| 午夜精品国产| 性欧美8khd高清极品| 国产亚洲精品成人av久久ww| 亚洲素人一区二区| 亚洲一区影音先锋| 国产一区再线| 欧美国产一区视频在线观看 | 亚洲欧洲日本一区二区三区| 久久久www免费人成黑人精品| 精品成人一区二区| 亚洲大片av| 欧美午夜片欧美片在线观看| 99国产欧美久久久精品| 亚洲日本乱码在线观看| 欧美激情精品久久久久久变态| 日韩午夜激情电影| 亚洲一区二区三区四区五区黄 | 亚洲国产91色在线| 欧美激情第五页| 亚洲在线电影| 久久亚洲精品一区| 一区二区激情| 久久国产一区| 亚洲神马久久| 久久久久久久久久久久久女国产乱| 伊人夜夜躁av伊人久久| 亚洲大片精品永久免费| 欧美三级乱码| 免费黄网站欧美| 国产精品美女久久久久久免费| 欧美在线一二三| 欧美精品v日韩精品v韩国精品v| 在线亚洲欧美| 免费日韩成人| 久久精品午夜| 国产精品毛片a∨一区二区三区|国| 久久精品123| 欧美精品入口| 免费久久久一本精品久久区| 欧美/亚洲一区| 久久免费精品视频| 国产精品另类一区| 一级日韩一区在线观看| 精品成人久久| 欧美在线视频不卡| 欧美一区二区三区在线看| 免费看的黄色欧美网站| 亚洲在线免费| 欧美日韩一区二区视频在线| 欧美在线视频二区| 国产精品国产| 99re66热这里只有精品4| 国内精品免费午夜毛片| 99精品国产福利在线观看免费| 国产一区再线| 欧美亚洲一级| 久久精品夜夜夜夜久久| 欧美三日本三级少妇三99| 欧美成人资源| 亚洲电影自拍| 麻豆成人精品| 亚洲高清激情| 99re在线精品| 欧美三级不卡| 一区二区三区波多野结衣在线观看| 亚洲福利视频一区二区| 久久动漫亚洲| 麻豆av一区二区三区久久| 国产一区二区三区无遮挡| 亚洲一区免费看| 久久久久国内| 在线观看亚洲视频| 久久综合亚州| 亚洲精品美女久久7777777| 亚洲激情小视频| 欧美日韩国产免费| 亚洲男女毛片无遮挡| 午夜伦理片一区| 国产亚洲综合在线| 久久综合久色欧美综合狠狠| 久久都是精品| 在线观看视频一区二区欧美日韩 | 久久av二区| 欧美亚洲综合另类| 免费成人网www| 亚洲免费电影在线| 欧美午夜视频在线观看| 这里是久久伊人| 久久精品99国产精品日本| 国产一区二区电影在线观看| 亚洲天堂av高清| 久久久欧美精品| 亚洲精品亚洲人成人网| 欧美精品色综合| 欧美中在线观看| 亚洲三级影片| 欧美专区在线观看| 亚洲片国产一区一级在线观看| 欧美成人一区二区在线| 91久久精品日日躁夜夜躁欧美| 99国产精品99久久久久久| 欧美天堂在线观看| 久久久国产精品一区二区三区| 欧美激情精品久久久久久久变态| 99亚洲视频| 激情五月婷婷综合| 欧美日韩亚洲成人| 久久久欧美精品sm网站| 亚洲欧洲日本在线| 久久久久国产精品厨房| 日韩视频―中文字幕| 国产精品日韩在线| 欧美国产精品久久| 久久爱www.| 艳女tv在线观看国产一区| 久久都是精品| 亚洲欧美国产精品桃花| 亚洲国产导航| 韩国女主播一区二区三区| 欧美另类高清视频在线| 校园春色国产精品| 一本色道久久综合亚洲91| 狼狼综合久久久久综合网| 一本一本久久a久久精品综合麻豆 一本一本久久a久久精品牛牛影视 | 亚洲一区二区三区影院| 国内激情久久| 国产精品盗摄一区二区三区| 午夜亚洲福利| 亚洲女优在线| 亚洲一级黄色片|