深度測試與alpha混合(4)

2021-09-06 04:43:58 字數 4008 閱讀 2016

材質alpha

頂點alpha是沒有使用光照和材質的情況,如果對場景內的物體新增光照和材質而沒有新增紋理時,頂點alpha值取決於材質屬性中漫反射顏色的alpha係數和燈光顏色中的alpha係數,頂點alpha值是根據光照計算得到的。頂點光照計算是分別針對紅、綠、藍和alpha進行的,其中alpha光照計算的結果就是頂點的alpha值。有了頂點的alpha值就可根據著色模式計算出每個畫素的alpha值,第乙個示例程式就是材質alpha的例子。

紋理alpha

當對物體表面使用了紋理之後,畫素的alpha值就是紋理alpha混合之後的值,所以這又取決於紋理的alpha混合方法,紋理alpha混合方法決定了紋理alpha混合之後的alpha值是取自材質,還是取自紋理,或者取自二者的某種運算。畫素alpha值的具體計算過程是這樣的,首先得到頂點alpha值,頂點alpha值可能是直接指定的,也可能是光照計算得到,然後根據著色模式對頂點alpha值進行插值,得到的結果再根據紋理alpha混合方法和紋理取樣得到的alpha值進行指定的運算,得到最終每個畫素的alpha值。

示例程式中將一幅紋理應用到乙個矩形表面,其中紋理alpha混合的設定如下:

g_device->settexturestagestate(0, d3dtss_alphaop,	d3dtop_modulate);

g_device->settexturestagestate(0, d3dtss_alphaarg1, d3dta_texture);

g_device->settexturestagestate(0, d3dtss_alphaarg2, d3dta_diffuse);

d3dtop_modulate

multiply the components of the arguments.

srgba = arg1 x arg2

在示例程式中將矩形4個頂點的顏色值設定為0xffffffff,其alpha成分設定為ff,即alpha值為1.0f,所以紋理alpha混合的最終結果就是取紋理的alpha值。

scustomvertex vertices =,,	

, }

示例程式在乙個矩形表面貼了一顆樹的紋理,在樹的紋理中,沒有樹葉和樹枝的地方alpha值為0,即完全透明;有樹葉和樹枝的地方alpha值為1,即完全不透明。所以通過alpha混合後,渲染的結果就像是一棵真的樹。

按下數字鍵"1",啟用紋理alpha混合。

按下數字鍵"0",禁用紋理alpha混合。

將頂點alpha由ff改為88後啟用紋理混合的效果,可以看出紋理的顏色變暗了。

scustomvertex vertices =,,	

, };

源程式:

#include 

<

d3dx9.h

>

#pragma warning(disable : 

4127

)    

//disable warning: conditional expression is constant

#define

#define

release_com(p)    do  } while(0)

typedef unsigned 

char

uchar;

idirect3d9

*g_d3d;

idirect3ddevice9

*g_device;

idirect3dvertexbuffer9

*g_vertex_buffer;

idirect3dtexture9

*g_texture;

struct

scustomvertex

;#define

d3dfvf_custom_vertex (d3dfvf_xyz | d3dfvf_diffuse | d3dfvf_tex1) 

void

setup_matrices()

bool

init_vb()

scustomvertex vertices =,

,    

,    /*,

,    

,    

*/};

g_device

->

createvertexbuffer(

sizeof

(vertices), 

0, d3dfvf_custom_vertex, d3dpool_default, 

&g_vertex_buffer, null);

void

*ptr;

g_vertex_buffer

->

lock(0, 

0, &ptr, 0);

memcpy(ptr, vertices, 

sizeof

(vertices));

g_vertex_buffer

->

unlock();

return

true;}

bool

init_d3d(hwnd hwnd)if(

!init_vb())

return

false

;setup_matrices();

g_device

->

setrenderstate(d3drs_lighting, false);

g_device

->

setrenderstate(d3drs_alphablendenable, true);

g_device

->

setrenderstate(d3drs_srcblend,  d3dblend_srcalpha);

g_device

->

setrenderstate(d3drs_destblend, d3dblend_invsrcalpha);

g_device

->

settexturestagestate(

0, d3dtss_colorop,    d3dtop_selectarg1);

g_device

->

settexturestagestate(

0, d3dtss_colorarg1, d3dta_texture);

g_device

->

settexturestagestate(

0, d3dtss_alphaop,    d3dtop_modulate);

g_device

->

settexturestagestate(

0, d3dtss_alphaarg1, d3dta_texture);

g_device

->

settexturestagestate(

0, d3dtss_alphaarg2, d3dta_diffuse);

return

true;}

void

cleanup()

void

render()

lresult winapi winproc(hwnd hwnd, uint msg, wparam wparam, lparam lparam)

break

;case

wm_destroy:        

postquitmessage(0);

return0;

}return

defwindowproc(hwnd, msg, wparam, lparam);

}int

winapi winmain(hinstance inst, hinstance, lpstr, int)

render();

sleep(

10);}}

cleanup();

unregisterclass(class_name, wc.hinstance);    

return0;

}

深度測試與alpha混合(3)

alpha源混合係數通常設定為d3dblend srcalpha,即當前繪製畫素的alpha值。目標混合係數設定為d3dblend invsrcalpha,即1減去當前繪製畫素的alpha值。那麼當前繪製畫素的alpha值又是如何得到的呢?如果沒有使用材質和紋理,當前繪製畫素的alpha值來自每個頂...

深度測試與alpha混合(5)

透過那些透明度非常高的物體看其他物體,例如透過幾乎完全透明的玻璃看其他物體,會感到玻璃好像不存在,在三維圖形程式中渲染時就可以不渲染這些透明度非常高的物體,從而可以提高渲染速度,這可以通過alpha測試來實現。alpha測試根據當前畫素是否滿足alpha測試條件 即是否達到一定的透明度 來控制是否繪...

深度測試與alpha混合(3)

alpha源混合係數通常設定為d3dblend srcalpha,即當前繪製畫素的alpha值。目標混合係數設定為d3dblend invsrcalpha,即1減去當前繪製畫素的alpha值。那麼當前繪製畫素的alpha值又是如何得到的呢?如果沒有使用材質和紋理,當前繪製畫素的alpha值來自每個頂...