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

天行健 君子當自強而不息

D3D中的光照(1)

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

5.1燈光的組成

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

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

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

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

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

Device->SetRenderState(D3DRS_SPECULARENABLE, true);

每一種燈光都是通過D3DCOLORVALUE結構或者描述燈光顏色的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材質

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

typedef struct _D3DMATERIAL9 {

       D3DCOLORVALUE Diffuse, Ambient, Specular, Emissive;

       float Power;

} D3DMATERIAL9;

Diffuse——指定此表面反射的漫射光數量。

Ambient——指定此表面反射的環境光數量。

Specular——指定此表面反射的鏡面光數量

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

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

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

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;

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

 

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

因為手工填充一個材質結構將是乏味的工作,我們添加下列有用的函數和全局材質常數到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;
}

 

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

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

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需要知道每個頂點的表面方向。注意頂點法線不一定和面法線相同。球體/環形物就是很好的實物例子,它們的頂點法線和三角形法線是不相同的(如圖5.3)。

為了描述頂點的頂點法線,我們必須更新原來的頂點結構::

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;

 

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

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

  • 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函數,它通過三角形的三個頂點計算三角形的面法線。注意這個函數的三個頂點是按照順時針方向指定的。假如不是這樣,那么法線方向將是相反的。

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);

}

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

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

變換過程中把頂點法線變為non-normal,這是有可能的。因此最好通過D3DRS_NORMALIZENORMALS設置渲染狀態,Direct3D重新單位化所有法線。

Device->SetRenderState(D3DRS_NORMALIZENORMALS, true);


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


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


公告

導航

統計

常用鏈接

隨筆分類(178)

3D游戲編程相關鏈接

搜索

最新評論

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            国产精品一区二区在线观看网站| 亚洲三级网站| 亚洲视频在线观看视频| 在线中文字幕不卡| 久久久无码精品亚洲日韩按摩| 欧美电影在线| 欧美激情综合五月色丁香| 亚洲国产精品成人精品| 欧美中文字幕在线| 日韩一级黄色av| 久久精品国产77777蜜臀| 久久蜜桃资源一区二区老牛| 99精品国产在热久久下载| 亚洲一区二区三区精品动漫| 欧美一区视频在线| 宅男噜噜噜66一区二区| 欧美一级在线播放| 麻豆9191精品国产| 欧美中文字幕在线播放| 亚洲福利免费| 久久久久久夜| 欧美伊人久久| 欧美一区二区精品久久911| 一区二区三区免费网站| 亚洲精品视频在线观看免费| 久久福利毛片| 欧美成人激情视频| 久久免费高清| 亚洲欧美国产毛片在线| 红桃av永久久久| 99re6热只有精品免费观看| 一区二区三区在线不卡| 99精品国产一区二区青青牛奶| 亚洲国产一区二区在线| 欧美色图首页| 亚洲国产美女精品久久久久∴| 国产在线国偷精品产拍免费yy| 有码中文亚洲精品| 亚洲国产成人在线| 国外成人免费视频| 99精品99| 亚洲午夜久久久久久尤物| 正在播放欧美视频| 欧美亚洲在线视频| 亚洲精品1234| 夜夜爽99久久国产综合精品女不卡| 亚洲国产99| 一区二区不卡在线视频 午夜欧美不卡在| 91久久精品一区二区别| 国产精品不卡在线| 亚洲国产精品成人一区二区 | 欧美啪啪一区| 欧美激情麻豆| 久久精品视频在线免费观看| 久久久久久精| 国产一区二区三区在线免费观看| 国产一区二区三区精品久久久| 午夜久久久久| 欧美激情91| 亚洲欧洲一二三| 洋洋av久久久久久久一区| 欧美a级片网| 欧美黄免费看| 国产日产精品一区二区三区四区的观看方式| 国产精品欧美精品| 欧美精品一区在线播放| 亚洲人成小说网站色在线| 国产精品99久久99久久久二8 | 欧美成黄导航| 欧美日韩精品一区二区三区| 欧美图区在线视频| 亚洲欧美日韩一区在线观看| 可以免费看不卡的av网站| 亚洲精品欧美一区二区三区| 久久精品欧洲| 欧美三级视频在线播放| 这里只有视频精品| 你懂的国产精品永久在线| 每日更新成人在线视频| 久久婷婷丁香| 国产精品一区二区久久国产| 久久久久一区二区三区四区| 亚洲精品小视频在线观看| 99精品国产福利在线观看免费| 久久久久久久一区二区三区| 欧美日韩一本到| 久久久精彩视频| 洋洋av久久久久久久一区| 日韩亚洲欧美精品| 国产欧美精品xxxx另类| 99国产精品视频免费观看一公开| 亚洲一区二区三区免费观看| 欧美日本不卡视频| 欧美日韩美女一区二区| 久久国产一区二区| 亚洲视频中文| 亚洲欧洲在线免费| 美女精品网站| 99在线精品视频| 欧美日韩免费在线视频| 伊人婷婷久久| 亚洲香蕉网站| 国产精品久久久亚洲一区| 看片网站欧美日韩| 久久精品人人做人人爽| 欧美美女福利视频| 欧美一区二区三区播放老司机| 亚洲免费不卡| 在线日韩中文| 欧美激情二区三区| 性8sex亚洲区入口| 亚洲精选视频在线| 亚洲自拍偷拍福利| 国产精品久久网| 亚洲欧洲日本在线| 欧美三级网址| 亚洲国产合集| 欧美日韩影院| 久久精品欧洲| 亚洲女同同性videoxma| 亚洲视频成人| 一区二区三区蜜桃网| 中文日韩在线视频| 久久精品理论片| 亚洲国产人成综合网站| 欧美激情精品久久久久久免费印度| 国产麻豆视频精品| 久久婷婷亚洲| 老司机免费视频一区二区| 欧美亚洲免费高清在线观看| 亚洲一级在线| 午夜视频在线观看一区二区三区| 午夜国产精品视频| 亚洲电影第三页| 另类春色校园亚洲| 在线亚洲观看| 99国产精品久久久久久久成人热| 好吊日精品视频| 亚洲理伦在线| 亚洲欧美另类久久久精品2019| 亚洲欧美国产日韩中文字幕| 伊人狠狠色j香婷婷综合| 99视频一区二区| 欧美亚洲成人免费| 亚洲欧美日韩在线一区| 国产精品美女视频网站| 午夜精品一区二区在线观看 | 夜夜夜久久久| 欧美精品在欧美一区二区少妇| 亚洲精品国产精品国自产观看浪潮| 亚洲精品久久久久久久久久久久久 | 国产亚洲欧美激情| 久久精品国产亚洲精品| 欧美在线观看网址综合| 国内成人精品视频| 久久综合伊人| 亚洲精品欧美激情| 午夜精品久久99蜜桃的功能介绍| 国产精品一区二区久久久久| 久久久久久精| 亚洲精品中文在线| 久久精品人人做人人爽电影蜜月| 激情久久一区| 欧美日韩精品三区| 午夜亚洲福利| 欧美激情久久久| 欧美激情亚洲一区| 亚洲承认在线| 亚洲婷婷综合色高清在线 | 欧美日韩视频一区二区| 亚洲图片欧美午夜| 欧美99在线视频观看| 亚洲一级黄色片| 红桃视频成人| 国产精品免费网站| 免费不卡在线视频| 亚洲欧美一区二区在线观看| 欧美电影免费观看高清| 亚洲一区视频在线| 亚洲国产成人精品久久| 国产精品欧美日韩一区二区| 鲁大师成人一区二区三区| 亚洲在线观看视频网站| 亚洲国产你懂的| 久久亚洲精品一区| 午夜精品福利一区二区三区av| 91久久国产综合久久91精品网站| 国产精品久久久久9999高清 | 欧美va日韩va| 久久精品人人爽| 亚洲图片欧洲图片日韩av| 欧美激情自拍| 久久在线视频| 香蕉免费一区二区三区在线观看| 亚洲精选久久| 亚洲国产乱码最新视频| 国产日本欧美一区二区| 欧美视频在线观看| 欧美精品亚洲精品| 免费国产自线拍一欧美视频|