• <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)自強而不息

            D3D中的光照(1)

            為了提高場景的真實性,我們可以為其加入燈光。燈光也能幫助表現(xiàn)物體的立體感以及物體的實體形狀。當(dāng)使用燈光時,我們不再自己指定頂點的顏色;Direct3D中每個頂點都通過燈光引擎來計算頂點顏色,該計算是基于定義的燈光資源,材質(zhì)以及燈光資源關(guān)心的表面方向。通過燈光模型計算頂點顏色會得到更真實的場景。

            5.1燈光的組成

                   在Direct3D燈光模型中,燈光是通過燈光資源的三個成員之一來照射的,即有三種燈光。

            環(huán)境光(Ambient Light)——這種類型的燈光將被其他所有表面反射且被用在照亮整個場景。例如,物體的各部分都被照亮,對于一個角度,甚至穿過不在光源直接照射的地方他們都能被照亮。環(huán)境光的使用是粗略的,便宜的,它模仿反射光。

            漫反射(Diffuse Reflection)——這種燈光按照特殊方向傳播。當(dāng)它照射到一個表面,它將在所有方向上均勻的反射。因為漫射光在所有方向上都均勻的反射,被反射的光線將到達眼睛而與觀察點無關(guān),因此我們不必為觀察者考慮。因而,漫射光僅僅需要考慮燈光方向和表面的朝向。這種燈光將成為你的資源中照射的普通燈光。

            鏡面反射(Specular Reflection)——這種燈光按照特殊方向傳播。當(dāng)它照射到一個表面時,它嚴(yán)格地按照一個方向反射。這將產(chǎn)生一個明亮的光澤,它能在某角度被看見。因為這種燈光在一個方向反射。明顯的觀察點,必須考慮燈光的方向和表面朝向,且必須按照鏡面燈光等式來考慮。鏡面燈光被用在物體上產(chǎn)生高光的地方,這種光澤只有在燈光照射在磨光的表面上才會產(chǎn)生。

            鏡面光比其他燈光類型要求更多的計算;因此,Direct3D提供了一個開關(guān)選擇。實際上,它默認(rèn)是被關(guān)閉的;要使用鏡面光你必須設(shè)置D3DRS_SPECULARENABLE渲染狀態(tài)。

            Device->SetRenderState(D3DRS_SPECULARENABLE, true);

            每一種燈光都是通過D3DCOLORVALUE結(jié)構(gòu)或者描述燈光顏色的D3DXCOLOR來描繪的。這里有幾個燈光顏色的例子:

            D3DXCOLOR redAmbient(1.0f, 0.0f, 0.0f, 1.0f);

            D3DXCOLOR blueDiffuse(0.0f, 0.0f, 1.0f, 1.0f);

            D3DXCOLOR whiteSpecular(1.0f, 1.0f, 1.0f, 1.0f);

            注意:在D3DXCOLOR類中的alpha值用在描述燈光顏色時是被忽略的。

            5.2材質(zhì)

            在現(xiàn)實世界中我們看到的物體顏色將由物體反射回來的燈光顏色來決定。比如,一個紅色的球是紅色的,因為它吸收所有的燈光顏色除了紅色光。紅色光是被球反射回來進入我們眼睛的,因此我們看到的球是紅色的。Direct3D通過我們定義的物體材質(zhì)來模擬這些所有的現(xiàn)象。材質(zhì)允許我們定義表面反射燈光的百分比。在代碼中通過D3DMATERIAL9結(jié)構(gòu)描述一個材質(zhì)。

            typedef struct _D3DMATERIAL9 {

                   D3DCOLORVALUE Diffuse, Ambient, Specular, Emissive;

                   float Power;

            } D3DMATERIAL9;

            Diffuse——指定此表面反射的漫射光數(shù)量。

            Ambient——指定此表面反射的環(huán)境光數(shù)量。

            Specular——指定此表面反射的鏡面光數(shù)量

            Emissive——這個是被用來給表面添加顏色,它使得物體看起來就象是它自己發(fā)出的光一樣。

            Power——指定銳利的鏡面高光;它的值是高光的銳利值。

            舉例,想得到一個紅色的球。我們將定義球的材質(zhì)來只反射紅光吸收其他顏色的所有光:

            D3DMATERIAL9 red;

            ::ZeroMemory(&red, sizeof(red));

            red.Diffuse = D3DXCOLOR(1.0f, 0.0f, 0.0f, 1.0f); // red

            red.Ambient = D3DXCOLOR(1.0f, 0.0f, 0.0f, 1.0f); // red

            red.Specular = D3DXCOLOR(1.0f, 0.0f, 0.0f, 1.0f); // red

            red.Emissive = D3DXCOLOR(0.0f, 0.0f, 0.0f, 1.0f); // no emission

            red.Power = 5.0f;

            這里我們設(shè)置綠色和藍(lán)色的值為0,這表明材質(zhì)反射0%此顏色的光。我們設(shè)置紅色為1,表示材質(zhì)反射100%的紅光。注意,我們能夠控制每種燈光反射的顏色(環(huán)境、漫射和鏡面光)。

             

            同樣假如我們定義一個只發(fā)出藍(lán)色光的光源,對球的光照將失敗因為藍(lán)色光將被全部吸收而沒有紅光被反射。當(dāng)物體吸收了所有光以后,物體看起來就為黑色。同樣的,當(dāng)物體反射100%的紅、綠和藍(lán)光,物體就將呈現(xiàn)為白色。

            因為手工填充一個材質(zhì)結(jié)構(gòu)將是乏味的工作,我們添加下列有用的函數(shù)和全局材質(zhì)常數(shù)到d3dUtility.h/cpp文件中:

            // lights
            D3DLIGHT9 init_directional_light(D3DXVECTOR3* direction, D3DXCOLOR* color);
            D3DLIGHT9 init_point_light(D3DXVECTOR3
            * position, D3DXCOLOR* color);
            D3DLIGHT9 init_spot_light(D3DXVECTOR3
            * position, D3DXVECTOR3* direction, D3DXCOLOR* color);

            // materials
            D3DMATERIAL9 init_material(D3DXCOLOR ambient, D3DXCOLOR diffuse, D3DXCOLOR specular, 
                                       D3DXCOLOR emissive, 
            float power);

            const D3DMATERIAL9 WHITE_MATERIAL  = init_material(WHITE,  WHITE,  WHITE,  BLACK, 2.0f);
            const D3DMATERIAL9 RED_MATERIAL       = init_material(RED,       RED,       RED,    BLACK, 2.0f);
            const D3DMATERIAL9 GREEN_MATERIAL  = init_material(GREEN,  GREEN,  GREEN,  BLACK, 2.0f);
            const D3DMATERIAL9 BLUE_MATERIAL   = init_material(BLUE,   BLUE,   BLUE,   BLACK, 2.0f);
            const D3DMATERIAL9 YELLOW_MATERIAL = init_material(YELLOW, YELLOW, YELLOW, BLACK, 2.0f);

            D3DLIGHT9 init_directional_light(D3DXVECTOR3
            * direction, D3DXCOLOR* color)
            {
                D3DLIGHT9 light;
                ZeroMemory(
            &light, sizeof(light));

                light.Type        
            = D3DLIGHT_DIRECTIONAL;
                light.Ambient    
            = *color * 0.6f;
                light.Diffuse    
            = *color;
                light.Specular    
            = *color * 0.6f;
                light.Direction 
            = *direction;

                
            return light;
            }

            D3DLIGHT9 init_point_light(D3DXVECTOR3
            * position, D3DXCOLOR* color)
            {
                D3DLIGHT9 light;
                ZeroMemory(
            &light, sizeof(light));

                light.Type            
            = D3DLIGHT_POINT;
                light.Ambient        
            = *color * 0.6f;
                light.Diffuse        
            = *color;
                light.Specular        
            = *color * 0.6f;
                light.Position        
            = *position;
                light.Range            
            = 1000.0f;
                light.Falloff        
            = 1.0f;
                light.Attenuation0    
            = 1.0f;
                light.Attenuation1    
            = 0.0f;
                light.Attenuation2    
            = 0.0f;

                
            return light;
            }

            D3DLIGHT9 init_spot_light(D3DXVECTOR3
            * position, D3DXVECTOR3* direction, D3DXCOLOR* color)
            {
                D3DLIGHT9 light;
                ZeroMemory(
            &light, sizeof(light));

                light.Type            
            = D3DLIGHT_SPOT;
                light.Ambient        
            = *color * 0.6f;
                light.Diffuse        
            = *color;
                light.Specular        
            = *color * 0.6f;
                light.Position        
            = *position;
                light.Direction        
            = *direction;
                light.Range            
            = 1000.0f;
                light.Falloff        
            = 1.0f;
                light.Attenuation0    
            = 1.0f;
                light.Attenuation1    
            = 0.0f;
                light.Attenuation2    
            = 0.0f;
                light.Theta            
            = 0.4f;
                light.Phi            
            = 0.9f;

                
            return light;
            }

            D3DMATERIAL9 init_material(D3DXCOLOR ambient, D3DXCOLOR diffuse, D3DXCOLOR specular, 
                                       D3DXCOLOR emissive, 
            float power)
            {
                D3DMATERIAL9 material;

                material.Ambient  
            = ambient;
                material.Diffuse  
            = diffuse;
                material.Specular 
            = specular;
                material.Emissive 
            = emissive;
                material.Power      
            = power;

                
            return material;
            }

             

            頂點結(jié)構(gòu)沒有材質(zhì)屬性;一個通用的材質(zhì)必須被設(shè)置。設(shè)置它我們使用IDirect3DDevice9::SetMaterial(CONST D3DMATERIAL9*pMaterial)方法。

            假設(shè)我們想渲染幾個不同材質(zhì)的物體;我們將按照如下的寫法去做:

            D3DMATERIAL9 blueMaterial, redMaterial;

             

            // set up material structures

            Device->SetMaterial(&blueMaterial);

            drawSphere(); // blue sphere

             

            Device->SetMaterial(&redMaterial);

            drawSphere(); // red sphere

            5.3頂點法線

                   面法線(face normal)是描述多邊形表面方向的一個向量(如圖5.1)。

            頂點法線(Vertex normals)也是基于同樣的概念,但是我們與其指定每個多邊形的法線,還不如為每個頂點指定(如圖5.2)。

            Direct3D需要知道頂點法線以便它能夠確定燈光照射到物體表面的角度,并且一旦計算了每個頂點的燈光,Direct3D需要知道每個頂點的表面方向。注意頂點法線不一定和面法線相同。球體/環(huán)形物就是很好的實物例子,它們的頂點法線和三角形法線是不相同的(如圖5.3)。

            為了描述頂點的頂點法線,我們必須更新原來的頂點結(jié)構(gòu)::

            class cLightVertex
            {
            public:
                
            float m_x, m_y, m_z;
                
            float m_nx, m_ny, m_nz; 

                cLightVertex() {}

                cLightVertex(
            float x, float y, float z, float nx, float ny, float nz)
                {
                    m_x  
            = x;    m_y  = y;    m_z  = z;
                    m_nx 
            = nx;    m_ny = ny;    m_nz = nz;
                }
            };

            const DWORD LIGHT_VERTEX_FVF = D3DFVF_XYZ | D3DFVF_NORMAL;

             

            作為一個簡單的物體比如立方體和球體,我們能夠通過觀察看見頂點法線。對于更多復(fù)雜的網(wǎng)格,我們需要一個更多的機械方法。假設(shè)一個由p0,p1,p2構(gòu)成的三角形,我們需要計算每個頂點的法線n0,n1,n2。

            簡單的步驟,我們列舉它是為了找到由三個點構(gòu)成的三角形的面法線,同時使用面法線作為頂點法線。首先計算三角形上的兩個向量:

            • p1p0 = u

            • p2p0 = v

            Then the face normal is:

            • n = u × v

            Since each vertex normal is the same as the face normal:

            • n0 = n1 = n2 = n

            下面是一個C函數(shù),它通過三角形的三個頂點計算三角形的面法線。注意這個函數(shù)的三個頂點是按照順時針方向指定的。假如不是這樣,那么法線方向?qū)⑹窍喾吹摹?/p>

            void ComputeNormal(D3DXVECTOR3* p0, D3DXVECTOR3* p1, D3DXVECTOR3* p2, D3DXVECTOR3* out)

            {

                   D3DXVECTOR3 u = *p1 - *p0;

                   D3DXVECTOR3 v = *p2 - *p0;

                   D3DXVec3Cross(out, &u, &v);

                   D3DXVec3Normalize(out, out);

            }

            當(dāng)用三角形近似表示曲面時,使用面法線作為頂點法線不能表現(xiàn)一個平滑的結(jié)果。一個更好的方法是找到頂點法線的平均法線。為了找到頂點v的頂點法線vn,我們找到網(wǎng)格模型中所有三角形的面法線記為頂點v。vn是通過計算他們的平均面法線得到的。這里有一個例子,假設(shè)有3個三角形它們的面法線分別是n0,n1,n2,指定為頂點v。那么vn的平均法線就是:

            vn = (1/3) . (n0 + n1 + n2)

            變換過程中把頂點法線變?yōu)閚on-normal,這是有可能的。因此最好通過D3DRS_NORMALIZENORMALS設(shè)置渲染狀態(tài),Direct3D重新單位化所有法線。

            Device->SetRenderState(D3DRS_NORMALIZENORMALS, true);


            posted on 2008-03-16 13:39 lovedday 閱讀(1150) 評論(0)  編輯 收藏 引用


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


            公告

            導(dǎo)航

            統(tǒng)計

            常用鏈接

            隨筆分類(178)

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

            搜索

            最新評論

            久久人人爽人人爽人人片av麻烦 | 亚洲欧美伊人久久综合一区二区| 久久婷婷人人澡人人| 色播久久人人爽人人爽人人片aV| 亚洲成av人片不卡无码久久| 久久久久亚洲AV片无码下载蜜桃 | 国产高潮国产高潮久久久91| 国产成人综合久久久久久| 开心久久婷婷综合中文字幕| 精品久久久久成人码免费动漫| 精品综合久久久久久97| 精品无码久久久久久午夜| 97精品国产97久久久久久免费| 精品久久综合1区2区3区激情| 亚洲精品无码久久久久AV麻豆| 囯产精品久久久久久久久蜜桃| 久久久久99精品成人片直播| 99久久99久久精品国产片果冻| 久久亚洲国产成人精品无码区| 成人综合久久精品色婷婷| 久久w5ww成w人免费| 久久精品国产精品亜洲毛片| 精品国产青草久久久久福利| 69久久精品无码一区二区| 久久精品国产一区二区电影| 久久精品一区二区三区AV| 99久久国产热无码精品免费| 久久久国产一区二区三区| 性色欲网站人妻丰满中文久久不卡| 久久se精品一区二区| 色综合合久久天天给综看| 久久久久久九九99精品| 久久无码国产| 久久99精品久久久久久| 久久久久久伊人高潮影院| 久久婷婷国产麻豆91天堂| 久久久久亚洲AV无码专区首JN| 成人精品一区二区久久久| 久久国产色AV免费看| 亚洲国产成人乱码精品女人久久久不卡 | 久久人人爽人人爽人人片AV东京热|