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

天行健 君子當(dāng)自強(qiáng)而不息

D3D中的模板緩存(2)

8.2實(shí)例程序:鏡子

在自然界中的很多表面象鏡子一樣允許我們通過(guò)它的反射來(lái)看物體,我們來(lái)看看怎樣用3D應(yīng)用程序來(lái)模擬鏡子,為了簡(jiǎn)單起見(jiàn)我們只模擬平面鏡。舉個(gè)例子,一輛擦亮的小汽車(chē)能夠反射;然而車(chē)的車(chē)身是光滑的圓的,不是一個(gè)平面。我們渲染的是那些光滑的大理石地板、掛在墻上的鏡子的反射,換句話(huà)說(shuō)就是在一個(gè)平面的鏡子。

實(shí)現(xiàn)鏡子的程序需要我們解決兩個(gè)問(wèn)題。第一,我們必須學(xué)習(xí)沿著一個(gè)面怎樣反射一個(gè)物體以便能夠正確地繪制反射結(jié)果。第二,我們必須只能在一個(gè)鏡子范圍內(nèi)顯示反射結(jié)果。即,我們必須標(biāo)記一個(gè)表面作為鏡子,且只渲染那些在鏡子里物體。圖8.1就是說(shuō)的這個(gè)內(nèi)容。

第一個(gè)問(wèn)題只需要用一些幾何向量就可以簡(jiǎn)單解決,我們能夠利用模板緩存解決第二個(gè)問(wèn)題。下兩小節(jié)分別介紹怎樣解決這兩個(gè)問(wèn)題。第三小節(jié)把它們?nèi)岷驮谝黄鸩⑶医榻B一下本章的第一個(gè)應(yīng)用程序?qū)嵗a——鏡子。

8.2.1反射數(shù)學(xué)

我們現(xiàn)在演示怎樣計(jì)算點(diǎn)V=(Vx, Vy, Vz)被平面n*p+d=0反射的點(diǎn)V’=(Vx, V’y, V’z),請(qǐng)參閱圖8.2:

根據(jù)Part I中的“平面”部分,我們能夠知道q=v-kn,這里k是有符號(hào)的從v到平面的距離。下面是v相對(duì)與平面(n,d)的反射推導(dǎo):

 

在D3DX庫(kù)中用下面的函數(shù)來(lái)創(chuàng)建反射矩陣R。

D3DXMATRIX *D3DXMatrixReflect(

       D3DXMATRIX *pOut, // The resulting reflection matrix.

       CONST D3DXPLANE *pPlane // The plane to reflect about.

);

一旦我們說(shuō)到反射變換的話(huà)題,就讓我們看看其他3種特殊的反射變換。它們是關(guān)于三個(gè)坐標(biāo)平面的反射—yz平面,xz平面,和xy平面—它們分別通過(guò)下面三個(gè)矩陣來(lái)表現(xiàn):

通過(guò)yz平面反射一個(gè)點(diǎn),我們只需要簡(jiǎn)單的將x分量取反就可以了。同樣的,通過(guò)xz平面反射一個(gè)點(diǎn),我們只需要簡(jiǎn)單的將y分量取反。通過(guò)xy平面反射一個(gè)點(diǎn),我們只需要簡(jiǎn)單的將z分量取反。這種反射是非常容易理解的。

8.2.2鏡面實(shí)現(xiàn)流程

當(dāng)實(shí)現(xiàn)一個(gè)鏡面,一個(gè)物體假如在一面鏡子前那么它就會(huì)被反射。然而,我們不想測(cè)試空間一個(gè)物體是否在一面鏡子前,要做它是非常復(fù)雜的。因此,為了簡(jiǎn)化事情,我們總是反射物體并且無(wú)限制地渲染它。但是這樣就有一個(gè)象本章開(kāi)頭的圖8.1一樣的問(wèn)題。即,物體反射被渲染到了沒(méi)有鏡子的表面。我們能夠用模板緩存來(lái)解決這個(gè)問(wèn)題,因?yàn)槟0寰彺嬖试S我們阻止渲染在后緩存中的特定區(qū)域。因此,我們使用模板緩存來(lái)阻止渲染被反射的不在鏡子里的茶壺。下面的步驟簡(jiǎn)要的說(shuō)明了怎樣實(shí)現(xiàn):

1、 正常渲染所有的場(chǎng)景——地板,墻,鏡子和茶壺——不包含反射的茶壺。注意這一步?jīng)]有修改模板緩存。

2、 清除模板緩存為0。圖8.3顯示了后臺(tái)緩存和模板緩存。

3、 渲染只有鏡子部分的圖元到模板緩存中。設(shè)置模板測(cè)試總是成功,并且假如測(cè)試成功就指定模板緩存入口為1。我們僅僅渲染鏡子,在模板緩存中的所有像素都將為0,除了鏡子部分為1以外。圖8.4顯示了更新以后的模板緩存。也就是說(shuō),我們?cè)谀0寰彺嬷袑?duì)鏡子像素做了標(biāo)記。

4、 現(xiàn)在我們渲染被反射的茶壺到后臺(tái)緩存和模板緩存中。但是假如模板測(cè)試通過(guò),我們就只渲染后臺(tái)緩存。假如在模板緩存中的值為1,那么我們?cè)O(shè)置模板測(cè)試通過(guò)。這樣,茶壺就僅僅被渲染到模板緩存為1的地方了。因?yàn)橹挥戌R子對(duì)應(yīng)的模板緩存值為1,所以反射的茶壺就只能被渲染到鏡子里。

 

8.2.3代碼和解釋

這個(gè)例子的相關(guān)代碼在RenderMirror函數(shù)中,它首先渲染鏡子圖元到模板緩存,然后渲染那些能被渲染到鏡子里的反射茶壺。我們現(xiàn)在一行一行的分析RenderMirror函數(shù)的代碼,并解釋為什么要這么做。

假如你想使用8.2.2部分的步驟實(shí)現(xiàn)代碼,注意我們從第3步開(kāi)始,因?yàn)閷?duì)模板緩存來(lái)說(shuō)1和2步已經(jīng)沒(méi)有什么事做了。同樣我們通過(guò)這個(gè)解釋來(lái)討論通過(guò)鏡子渲染的信息。

注意我們將分成幾個(gè)部分來(lái)討論它。

8.2.3.1第一部分

我們通過(guò)允許模板緩存和設(shè)置渲染狀態(tài)來(lái)開(kāi)始:

void RenderMirror()

{

       Device->SetRenderState(D3DRS_STENCILENABLE, true);

       Device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);

       Device->SetRenderState(D3DRS_STENCILREF, 0x1);

       Device->SetRenderState(D3DRS_STENCILMASK, 0xffffffff);

       Device->SetRenderState(D3DRS_STENCILWRITEMASK,0xffffffff);

       Device->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP);

       Device->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP);

Device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);

這是非常容易理解的。我們?cè)O(shè)置模板比較運(yùn)算為D3DCMP_ALWAYS,這就是說(shuō)讓所有模板測(cè)試都通過(guò)。

假如深度測(cè)試失敗了,我們指定D3DSTENCILOP_KEEP,它表明不更新模板緩存入口。即,我們保存當(dāng)前值。這樣做的原因是假如深度測(cè)試失敗了,那么就意味著像素被“遮擋”了。我們不想渲染被“遮擋”的反射像素。

同樣假如模板測(cè)試失敗了,我們也指定D3DSTENCILOP_KEEP。但是在這里這樣做不是必須的,因?yàn)槲覀冎付ǖ氖荄3DCMP_ALWAYS,當(dāng)然這樣的測(cè)試也就永遠(yuǎn)不會(huì)失敗。然而,我們只改變比較運(yùn)算的一位,那么設(shè)置模板失敗渲染狀態(tài)是必須的。我們現(xiàn)在就這樣做。

假如深度測(cè)試和模板測(cè)試都通過(guò)了,我們就指定D3DSTENCILOP_REPLACE,更新模板緩存入口,設(shè)置模板參考值為0x1。

8.2.3.2第二部分

這下一步阻止渲染鏡子代碼,除了模板緩存。我們通過(guò)設(shè)置D3DRS_ZWRITEENABLE并指定為false來(lái)阻止寫(xiě)深度緩存。我們能夠防止更新后臺(tái)緩存,混合和設(shè)置源混合要素為D3DBLEND_ZERO目的混合要素為D3DBLEND_ONE。將這些混合要素代入混合等式,我們得到后臺(tái)緩存是不會(huì)改變的:

       // disable writes to the depth and back buffers

       Device->SetRenderState(D3DRS_ZWRITEENABLE, false);

       Device->SetRenderState(D3DRS_ALPHABLENDENABLE, true);

       Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);

       Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);

       // draw the mirror to the stencil buffer

       Device->SetStreamSource(0, VB, 0, sizeof(Vertex));

       Device->SetFVF(Vertex::FVF);

       Device->SetMaterial(&MirrorMtrl);

       Device->SetTexture(0, MirrorTex);

       D3DXMATRIX I;

       D3DXMatrixIdentity(&I);

       Device->SetTransform(D3DTS_WORLD, &I);

       Device->DrawPrimitive(D3DPT_TRIANGLELIST, 18, 2);

       // re-enable depth writes

Device->SetRenderState(D3DRS_ZWRITEENABLE, true);

 

8.2.3.3第三部分

在模板緩存中,符合鏡子可視像素的為0x1,因此對(duì)已經(jīng)渲染的鏡子區(qū)域做記號(hào)。我們現(xiàn)在準(zhǔn)備渲染被反射的茶壺。回憶一下,我們僅僅想渲染鏡子范圍內(nèi)的反射像素。我們現(xiàn)在可以很容易的做到了,因?yàn)樵谀0寰彺嬷羞@些像素已經(jīng)被做了記號(hào)。

我們?cè)O(shè)置下面的渲染狀態(tài):

       Device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_EQUAL);

Device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);

用一個(gè)新的比較運(yùn)算設(shè)置,我們進(jìn)行下面的模板測(cè)試:

       (ref & mask == (value & mask)

       (0x1 & 0xffffffff) == (value & 0xffffffff)

(0x1)== (value & 0xffffffff)

這說(shuō)明了只有當(dāng)value=0x1時(shí)模板測(cè)試才成功。因?yàn)樵谀0寰彺嬷兄挥戌R子相應(yīng)位置的值才是0x1,若我們渲染這些地方那么測(cè)試將會(huì)成功。因此,被反射的茶壺只會(huì)在鏡子里繪制而不會(huì)在鏡子以外的表面上繪制。

注意我們已經(jīng)將渲染狀態(tài)由D3DRS_STENCILPASS變?yōu)榱薉3DSTENCILOP_KEEP,簡(jiǎn)單的說(shuō)就是假如測(cè)試通過(guò)那么就保存模板緩存的值。因此,在下一步的渲染中,我們不改變模板緩存的值。我們僅僅使用模板緩存來(lái)對(duì)鏡子相應(yīng)位置的像素做標(biāo)記。

8.2.3.4第四部分

RenderMirror函數(shù)的下一部分就是計(jì)算在場(chǎng)景中反射位置的矩陣:

       // position reflection

       D3DXMATRIX W, T, R;

       D3DXPLANE plane(0.0f, 0.0f, 1.0f, 0.0f); // xy plane

       D3DXMatrixReflect(&R, &plane);

       D3DXMatrixTranslation(&T,

              TeapotPosition.x,

              TeapotPosition.y,

              TeapotPosition.z);

       W = T * R;

注意我們首先確定沒(méi)有反射的茶壺位置,然后就通過(guò)xy平面來(lái)反射。這種變換規(guī)則是通過(guò)矩陣相乘來(lái)指定的。

 

8.2.3.5第五部分

我們已經(jīng)為渲染反射茶壺做好了準(zhǔn)備。然而,假如我們現(xiàn)在就渲染它,它是不會(huì)被顯示的。為什么呢?因?yàn)楸环瓷涞牟鑹氐纳疃缺如R子的深度大,因此鏡子的圖元將把被反射茶壺的圖元弄模糊。為了避免這種情況,我們清除深度緩存:

Device->Clear(0, 0, D3DCLEAR_ZBUFFER, 0, 1.0f, 0);

并不是所有問(wèn)題都解決了。假如我們簡(jiǎn)單的清除深度緩存,被反射的茶壺會(huì)被繪制到鏡子的前面,物體看起來(lái)就不對(duì)了。我們想做的是清除深度緩存并且要混合被反射的茶壺和鏡子。這樣,被反射的茶壺看起來(lái)就象在鏡子里了。我們能夠通過(guò)下面的混合等式來(lái)混合被反射的茶壺和鏡子:

因?yàn)樵袼兀╯ourcePixel)來(lái)自被反射的茶壺,目的像素(DestPixel)來(lái)自鏡子,我們能夠通過(guò)這個(gè)等式明白它們是怎么被混合到一起的。我們有如下的代碼:

       Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_DESTCOLOR);

Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);

最后,我們準(zhǔn)備繪制被反射的茶壺:

       Device->SetTransform(D3DTS_WORLD, &W);

       Device->SetMaterial(&TeapotMtrl);

       Device->SetTexture(0, 0);

       Device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);

Teapot->DrawSubset(0);

回顧一下8.2.3.4部分的W,它能夠正確的將被反射的茶壺變換到場(chǎng)景中恰當(dāng)?shù)奈恢谩M瑯樱覀円惨淖儽趁鎾x模式。必須這樣做的原因是當(dāng)一個(gè)物體被反射以后,它的正面和背面將會(huì)被交換。因此為了改變這種情況,我們必須改變背面揀選模式。

       Device->SetRenderState(D3DRS_ALPHABLENDENABLE, false);

       Device->SetRenderState( D3DRS_STENCILENABLE, false);

       Device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);

} // end RenderMirror()

 

運(yùn)行截圖:

 

主程序:

/**************************************************************************************
  Demonstrates mirrors with stencils.  
  Use the arrow keys and the 'A' and 'S' key to navigate the scene and translate the teapot. 
 *************************************************************************************
*/

#include 
"d3dUtility.h"

#pragma warning(disable : 
4100)

class cTextureVertex
{
public:
    
float _x, _y, _z;
    
float _nx, _ny, _nz;
    
float _u, _v;

    cTextureVertex() { }

    cTextureVertex(
float x, float y, float z, 
                   
float nx, float ny, float nz,
                   
float u, float v)
    {
        _x  
= x;  _y  = y;  _z  = z;
        _nx 
= nx; _ny = ny; _nz = nz;
        _u  
= u;  _v  = v;
    }    
};

const DWORD TEXTURE_VERTEX_FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1;

const int WIDTH  = 640;
const int HEIGHT = 480;

IDirect3DDevice9
*        g_d3d_device;
IDirect3DVertexBuffer9
*    g_vertex_buffer;

IDirect3DTexture9
*        g_floor_texture;
IDirect3DTexture9
*        g_wall_texture;
IDirect3DTexture9
*        g_mirror_texture;

D3DMATERIAL9    g_floor_material  
= WHITE_MATERIAL;
D3DMATERIAL9    g_wall_material   
= WHITE_MATERIAL;
D3DMATERIAL9    g_mirror_material 
= WHITE_MATERIAL;

ID3DXMesh
*        g_teapot_mesh;
D3DXVECTOR3        g_teapot_pos(
0.0f3.0f-7.5f);
D3DMATERIAL9    g_teapot_material 
= YELLOW_MATERIAL;

void render_scene();
void render_mirror();

////////////////////////////////////////////////////////////////////////////////////////////////////

bool setup()
{    
    g_wall_material.Specular 
= WHITE * 0.2f;    // make walls have low specular reflectance - 20%

    D3DXCreateTeapot(g_d3d_device, 
&g_teapot_mesh, NULL);

    
// Create and specify geometry.  For this sample we draw a floor and a wall with a mirror on it.  
    
// We put the floor, wall, and mirror geometry in one vertex buffer.
    
//
    
//   |----|----|----|
    
//   |Wall|Mirr|Wall|
    
//   |    | or |    |
    
//   /--------------/
    
//  /   Floor      /
    
// /--------------/

    g_d3d_device
->CreateVertexBuffer(24 * sizeof(cTextureVertex), 0, TEXTURE_VERTEX_FVF, D3DPOOL_MANAGED,
                                     
&g_vertex_buffer, NULL);

    cTextureVertex
* v;

    g_vertex_buffer
->Lock(00, (void**)&v, 0);

    
// floor
    v[0= cTextureVertex(-7.5f0.0f-10.0f0.0f1.0f0.0f0.0f1.0f);
    v[
1= cTextureVertex(-7.5f0.0f,   0.0f0.0f1.0f0.0f0.0f0.0f);
    v[
2= cTextureVertex( 7.5f0.0f,   0.0f0.0f1.0f0.0f1.0f0.0f);
    
    v[
3= cTextureVertex(-7.5f0.0f-10.0f0.0f1.0f0.0f0.0f1.0f);
    v[
4= cTextureVertex( 7.5f0.0f,   0.0f0.0f1.0f0.0f1.0f0.0f);
    v[
5= cTextureVertex( 7.5f0.0f-10.0f0.0f1.0f0.0f1.0f1.0f);

    
// wall
    v[6]  = cTextureVertex(-7.5f0.0f0.0f0.0f0.0f-1.0f0.0f1.0f);
    v[
7]  = cTextureVertex(-7.5f5.0f0.0f0.0f0.0f-1.0f0.0f0.0f);
    v[
8]  = cTextureVertex(-2.5f5.0f0.0f0.0f0.0f-1.0f1.0f0.0f);
    
    v[
9]  = cTextureVertex(-7.5f0.0f0.0f0.0f0.0f-1.0f0.0f1.0f);
    v[
10= cTextureVertex(-2.5f5.0f0.0f0.0f0.0f-1.0f1.0f0.0f);
    v[
11= cTextureVertex(-2.5f0.0f0.0f0.0f0.0f-1.0f1.0f1.0f);

    
// Note: We leave gap in middle of walls for mirror

    v[
12= cTextureVertex(2.5f0.0f0.0f0.0f0.0f-1.0f0.0f1.0f);
    v[
13= cTextureVertex(2.5f5.0f0.0f0.0f0.0f-1.0f0.0f0.0f);
    v[
14= cTextureVertex(7.5f5.0f0.0f0.0f0.0f-1.0f1.0f0.0f);
    
    v[
15= cTextureVertex(2.5f0.0f0.0f0.0f0.0f-1.0f0.0f1.0f);
    v[
16= cTextureVertex(7.5f5.0f0.0f0.0f0.0f-1.0f1.0f0.0f);
    v[
17= cTextureVertex(7.5f0.0f0.0f0.0f0.0f-1.0f1.0f1.0f);

    
// mirror
    v[18= cTextureVertex(-2.5f0.0f0.0f0.0f0.0f-1.0f0.0f1.0f);
    v[
19= cTextureVertex(-2.5f5.0f0.0f0.0f0.0f-1.0f0.0f0.0f);
    v[
20= cTextureVertex( 2.5f5.0f0.0f0.0f0.0f-1.0f1.0f0.0f);
    
    v[
21= cTextureVertex(-2.5f0.0f0.0f0.0f0.0f-1.0f0.0f1.0f);
    v[
22= cTextureVertex( 2.5f5.0f0.0f0.0f0.0f-1.0f1.0f0.0f);
    v[
23= cTextureVertex( 2.5f0.0f0.0f0.0f0.0f-1.0f1.0f1.0f);

    g_vertex_buffer
->Unlock();

    
// create the texture and set filters

    D3DXCreateTextureFromFile(g_d3d_device, 
"checker.jpg",    &g_floor_texture);
    D3DXCreateTextureFromFile(g_d3d_device, 
"brick0.jpg",    &g_wall_texture);
    D3DXCreateTextureFromFile(g_d3d_device, 
"ice.bmp",        &g_mirror_texture);

    g_d3d_device
->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
    g_d3d_device
->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
    g_d3d_device
->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);

    
// lights

    D3DXVECTOR3 light_dir(
0.707f-0.707f0.707f);
    D3DXCOLOR color(
1.0f1.0f1.0f1.0f);
    D3DLIGHT9 light 
= init_directional_light(&light_dir, &color);

    g_d3d_device
->SetLight(0&light);
    g_d3d_device
->LightEnable(0, TRUE);

    g_d3d_device
->SetRenderState(D3DRS_NORMALIZENORMALS, TRUE);
    g_d3d_device
->SetRenderState(D3DRS_SPECULARENABLE, TRUE);

    
// set the projection matrix
    D3DXMATRIX proj;
    D3DXMatrixPerspectiveFovLH(
&proj, D3DX_PI/4.0f, (float)WIDTH/HEIGHT, 1.0f1000.0f);
    g_d3d_device
->SetTransform(D3DTS_PROJECTION, &proj);
    
    
return true;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////

void cleanup()
{    
    safe_release
<IDirect3DVertexBuffer9*>(g_vertex_buffer);
    safe_release
<IDirect3DTexture9*>(g_floor_texture);
    safe_release
<IDirect3DTexture9*>(g_wall_texture);
    safe_release
<IDirect3DTexture9*>(g_mirror_texture);
    safe_release
<ID3DXMesh*>(g_teapot_mesh);    
}

///////////////////////////////////////////////////////////////////////////////////////////////////////

bool display(float time_delta)
{
    
// update the scene

    
if(GetAsyncKeyState(VK_LEFT) & 0x80000f)
        g_teapot_pos.x 
-= 3.0f * time_delta;

    
if(GetAsyncKeyState(VK_RIGHT) & 0x80000f)
        g_teapot_pos.x 
+= 3.0f * time_delta;

    
static float radius = 20.0f;

    
if(GetAsyncKeyState(VK_UP) & 0x80000f)
        radius 
-= 2.0f * time_delta;

    
if(GetAsyncKeyState(VK_DOWN) & 0x80000f)
        radius 
+= 2.0f * time_delta;

    
static float angle = (3.0f * D3DX_PI) / 2.0f;

    
if(GetAsyncKeyState('A'& 0x80000f)
        angle 
-= 0.5f * time_delta;

    
if(GetAsyncKeyState('S'& 0x80000f)
        angle 
+= 0.5f * time_delta;

    D3DXVECTOR3 position(cosf(angle) 
* radius, 3.0f, sinf(angle) * radius);
    D3DXVECTOR3 target(
0.0f0.0f0.0f);
    D3DXVECTOR3 up(
0.0f1.0f0.0f);

    D3DXMATRIX view_matrix;
    D3DXMatrixLookAtLH(
&view_matrix, &position, &target, &up);
    g_d3d_device
->SetTransform(D3DTS_VIEW, &view_matrix);

    
// render now

    g_d3d_device
->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, 0xff0000001.0f0);

    g_d3d_device
->BeginScene();
    render_scene();
    render_mirror();
    g_d3d_device
->EndScene();

    g_d3d_device
->Present(NULL, NULL, NULL, NULL);

    
return true;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////

void render_scene()
{
    
// draw teapot

    g_d3d_device
->SetMaterial(&g_teapot_material);
    g_d3d_device
->SetTexture(0, NULL);

    D3DXMATRIX world_matrix;
    D3DXMatrixTranslation(
&world_matrix, g_teapot_pos.x, g_teapot_pos.y, g_teapot_pos.z);
    g_d3d_device
->SetTransform(D3DTS_WORLD, &world_matrix);

    g_teapot_mesh
->DrawSubset(0);

    D3DXMATRIX identity_matrix;
    D3DXMatrixIdentity(
&identity_matrix);
    g_d3d_device
->SetTransform(D3DTS_WORLD, &identity_matrix);

    g_d3d_device
->SetStreamSource(0, g_vertex_buffer, 0sizeof(cTextureVertex));
    g_d3d_device
->SetFVF(TEXTURE_VERTEX_FVF);

    
// draw the floor
    g_d3d_device->SetMaterial(&g_floor_material);
    g_d3d_device
->SetTexture(0, g_floor_texture);
    g_d3d_device
->DrawPrimitive(D3DPT_TRIANGLELIST, 02);

    
// draw the walls
    g_d3d_device->SetMaterial(&g_wall_material);
    g_d3d_device
->SetTexture(0, g_wall_texture);
    g_d3d_device
->DrawPrimitive(D3DPT_TRIANGLELIST, 64);

    
// draw the mirror
    g_d3d_device->SetMaterial(&g_mirror_material);
    g_d3d_device
->SetTexture(0, g_mirror_texture);
    g_d3d_device
->DrawPrimitive(D3DPT_TRIANGLELIST, 182);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////

void render_mirror()
{
    
// Draw Mirror quad to stencil buffer ONLY.  In this way only the stencil bits that 
    
// correspond to the mirror will be on.  Therefore, the reflected teapot can only be 
    
// rendered where the stencil bits are turned on, and thus on the mirror only.

    g_d3d_device
->SetRenderState(D3DRS_STENCILENABLE,        TRUE);
    g_d3d_device
->SetRenderState(D3DRS_STENCILFUNC,            D3DCMP_ALWAYS);
    g_d3d_device
->SetRenderState(D3DRS_STENCILREF,            0x1);
    g_d3d_device
->SetRenderState(D3DRS_STENCILMASK,            0xffffffff);
    g_d3d_device
->SetRenderState(D3DRS_STENCILWRITEMASK,    0xffffffff);
    g_d3d_device
->SetRenderState(D3DRS_STENCILZFAIL,        D3DSTENCILOP_KEEP);
    g_d3d_device
->SetRenderState(D3DRS_STENCILFAIL,            D3DSTENCILOP_KEEP);
    g_d3d_device
->SetRenderState(D3DRS_STENCILPASS,            D3DSTENCILOP_REPLACE);

    
//// Disable writes to the depth and back buffers,
    
//// enable alpha blending so mirror will overwrite dest areas.

    
//g_d3d_device->SetRenderState(D3DRS_ZWRITEENABLE,        FALSE);
    
//g_d3d_device->SetRenderState(D3DRS_ALPHABLENDENABLE,    TRUE);
    
//g_d3d_device->SetRenderState(D3DRS_SRCBLEND,            D3DBLEND_ZERO);
    
//g_d3d_device->SetRenderState(D3DRS_DESTBLEND,            D3DBLEND_ONE);

    
//// draw the mirror to the stencil buffer

    
//g_d3d_device->SetStreamSource(0, g_vertex_buffer, 0, sizeof(cTextureVertex));
    
//g_d3d_device->SetFVF(TEXTURE_VERTEX_FVF);
    
//g_d3d_device->SetMaterial(&g_mirror_material);
    
//g_d3d_device->SetTexture(0, g_mirror_texture);

    D3DXMATRIX identity_matrix;
    D3DXMatrixIdentity(
&identity_matrix);
    g_d3d_device
->SetTransform(D3DTS_WORLD, &identity_matrix);
    g_d3d_device
->DrawPrimitive(D3DPT_TRIANGLELIST, 182);

    
// re-enalbe depth writes
    g_d3d_device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);

    
// only draw reflected teapot to the pixels where the mirror was drawn to
    g_d3d_device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_EQUAL);
    g_d3d_device
->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);

    
// clear depth buffer and blend the reflected teapot with the mirror
    g_d3d_device->Clear(0, NULL, D3DCLEAR_ZBUFFER, 01.0f0);
    g_d3d_device
->SetRenderState(D3DRS_SRCBLEND,  D3DBLEND_DESTCOLOR);
    g_d3d_device
->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);

    
// position reflection

    D3DXMATRIX world_matrix, translation_matrix, reflect_matrix;

    D3DXPLANE plane(
0.0f0.0f1.0f0.0f);    // xy plane
    D3DXMatrixReflect(&reflect_matrix, &plane);

    D3DXMatrixTranslation(
&translation_matrix, g_teapot_pos.x, g_teapot_pos.y, g_teapot_pos.z);

    world_matrix 
= translation_matrix * reflect_matrix;

    
// Finally, draw the reflected teapot.
    g_d3d_device->SetTransform(D3DTS_WORLD, &world_matrix);
    g_d3d_device
->SetMaterial(&g_teapot_material);
    g_d3d_device
->SetTexture(0, NULL);
    g_d3d_device
->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);

    g_teapot_mesh
->DrawSubset(0);

    
// restore render states
    g_d3d_device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
    g_d3d_device
->SetRenderState(D3DRS_STENCILENABLE,     FALSE);
    g_d3d_device
->SetRenderState(D3DRS_CULLMODE,         D3DCULL_CCW);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////

LRESULT CALLBACK wnd_proc(HWND hwnd, UINT msg, WPARAM word_param, LPARAM long_param)
{
    
switch(msg)
    {
    
case WM_DESTROY:
        PostQuitMessage(
0);
        
break;

    
case WM_KEYDOWN:
        
if(word_param == VK_ESCAPE)
            DestroyWindow(hwnd);
        
break;
    }

    
return DefWindowProc(hwnd, msg, word_param, long_param);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////

int WINAPI WinMain(HINSTANCE inst, HINSTANCE, PSTR cmd_line, int cmd_show)
{
    
if(! init_d3d(inst, WIDTH, HEIGHT, true, D3DDEVTYPE_HAL, &g_d3d_device))
    {
        MessageBox(NULL, 
"init_d3d() - failed."0, MB_OK);
        
return 0;
    }

    
if(! setup())
    {
        MessageBox(NULL, 
"Steup() - failed."0, MB_OK);
        
return 0;
    }

    enter_msg_loop(display);

    cleanup();
    g_d3d_device
->Release();

    
return 0;
}

 

下載源程序


posted on 2008-03-19 18:39 lovedday 閱讀(2418) 評(píng)論(0)  編輯 收藏 引用


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


公告

導(dǎo)航

統(tǒng)計(jì)

常用鏈接

隨筆分類(lèi)(178)

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

搜索

最新評(píng)論

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            久久久久这里只有精品| 亚洲一区日韩| 欧美日韩1234| 欧美福利视频网站| 欧美岛国在线观看| 欧美精品国产精品| 欧美揉bbbbb揉bbbbb| 国产精品国产精品| 国产精品亚洲激情| 国产一区免费视频| 在线成人激情视频| 亚洲精品乱码久久久久久日本蜜臀| 亚洲精品乱码久久久久久蜜桃麻豆| 日韩视频中文字幕| 久久aⅴ国产欧美74aaa| 玖玖在线精品| 日韩视频免费大全中文字幕| 亚洲欧美日韩成人高清在线一区| 亚洲欧美日韩精品久久| 美国十次了思思久久精品导航| 欧美精品日韩一区| 国外视频精品毛片| 一区二区欧美亚洲| 免费在线视频一区| 亚洲少妇一区| 欧美成人第一页| 国产亚洲网站| 亚洲一区日韩| 亚洲国产成人av| 99精品久久久| 久久一区亚洲| 亚洲日本在线观看| 日韩一级网站| 久久精品二区亚洲w码| 欧美黄色影院| 性色一区二区| 欧美肉体xxxx裸体137大胆| 国产一区二区三区网站| 亚洲乱码国产乱码精品精98午夜| 午夜在线观看免费一区| 亚洲第一在线| 久久精品视频在线| 国产麻豆日韩| 亚洲专区在线| 99精品国产在热久久婷婷| 免费的成人av| 激情久久久久久| 欧美一区二区在线免费播放| 99视频国产精品免费观看| 欧美大片一区二区| 91久久久在线| 欧美成人免费在线视频| 久久av在线看| 国产一区二区三区不卡在线观看| 亚洲欧美日产图| 99热免费精品| 国产精品久久久久久亚洲毛片| 亚洲国语精品自产拍在线观看| 久久久女女女女999久久| 亚洲欧美在线高清| 国产精品视区| 欧美一区二区免费观在线| 亚洲四色影视在线观看| 欧美性色视频在线| 香蕉av福利精品导航| aa日韩免费精品视频一| 欧美日韩一区二区三区| 中国成人在线视频| 在线一区观看| 国产精品欧美久久久久无广告| 亚洲天天影视| 亚洲欧洲av一区二区| 国产精品爽爽爽| 久久不射电影网| 久久精品日产第一区二区三区| 亚洲国产成人久久| 亚洲乱码国产乱码精品精天堂| 欧美日韩三级| 香蕉久久一区二区不卡无毒影院| 亚洲一区欧美激情| 毛片基地黄久久久久久天堂| 久久在线视频在线| 亚洲精品中文字| 一本色道久久综合亚洲精品按摩| 国产精品久99| 久久尤物电影视频在线观看| 美国成人毛片| 亚洲无线视频| 欧美一区二区三区久久精品| 在线观看国产精品淫| 最新国产の精品合集bt伙计| 欧美日韩中文在线观看| 国产亚洲精品aa| 亚洲激情综合| 亚洲少妇自拍| 一区二区在线视频播放| 亚洲国产美女| 国产亚洲精品一区二555| 欧美激情乱人伦| 国产精品久久久久久久久免费 | 免费不卡在线视频| 亚洲制服少妇| 米奇777超碰欧美日韩亚洲| 亚洲一区二区成人在线观看| 久久激情五月婷婷| 亚洲午夜在线观看| 卡一卡二国产精品| 欧美一区二区三区另类| 欧美国产日韩a欧美在线观看| 欧美在线高清视频| 欧美日韩mv| 欧美va亚洲va国产综合| 国产精品久久久久久影视| 欧美国产日韩精品免费观看| 国产精品色婷婷| 亚洲精品一区二区在线| 精品成人一区二区| 午夜精品福利一区二区蜜股av| 亚洲精品视频啊美女在线直播| 性欧美video另类hd性玩具| 夜夜嗨av一区二区三区四区| 久久精品1区| 亚洲你懂的在线视频| 欧美—级a级欧美特级ar全黄| 久久综合九色综合久99| 国产欧美一区二区三区久久| 亚洲免费av片| 日韩一区二区精品视频| 久久综合色影院| 久久在线免费观看| 国产一区二区黄| 校园春色国产精品| 久久国产主播精品| 国产日韩高清一区二区三区在线| 一区二区三区日韩| 亚洲欧美国产三级| 欧美三级电影网| 亚洲日本中文字幕免费在线不卡| 亚洲国产精品久久久久久女王 | 欧美精品激情| 亚洲国产高清在线| 亚洲激情网址| 欧美国产乱视频| 亚洲黄网站黄| 99综合精品| 欧美三区在线视频| 亚洲视频第一页| 欧美一级久久| 国产欧美va欧美不卡在线| 亚洲欧美日韩成人| 久久夜色精品国产噜噜av| 在线观看视频一区| 蜜桃精品一区二区三区| 亚洲国产欧美日韩精品| 一区二区三区欧美日韩| 国产精品电影网站| 欧美在线精品一区| 亚洲国产天堂久久国产91| 欧美成人免费大片| 99精品国产在热久久下载| 亚洲一本大道在线| 国产精品永久免费视频| 久久久人人人| 亚洲品质自拍| 亚洲欧美亚洲| 狠狠色丁香久久综合频道| 美女黄毛**国产精品啪啪 | 久久看片网站| 91久久夜色精品国产网站| 欧美激情视频在线播放| 一区二区国产日产| 久久人人爽人人爽| av成人老司机| 国产亚洲人成a一在线v站| 欧美粗暴jizz性欧美20| 亚洲网站视频| 亚洲福利视频一区| 久久av资源网| 日韩视频三区| 国产一区99| 欧美日韩一区二区在线视频| 久久国产精品电影| 亚洲最新中文字幕| 欧美大片第1页| 欧美一二三区在线观看| 日韩系列欧美系列| 狠狠久久综合婷婷不卡| 欧美三级乱人伦电影| 久久躁日日躁aaaaxxxx| 亚洲一二三区在线| 亚洲精品免费网站| 欧美成年人网站| 亚久久调教视频| 一区二区欧美激情| 91久久精品网| 在线看片成人| 国产无遮挡一区二区三区毛片日本| 欧美精品午夜| 欧美成人激情视频免费观看| 欧美一区二区日韩|