• <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)自強(qiáng)而不息

            D3D中的模板緩存(2)

            8.2實例程序:鏡子

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

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

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

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

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

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

             

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

            D3DXMATRIX *D3DXMatrixReflect(

                   D3DXMATRIX *pOut, // The resulting reflection matrix.

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

            );

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

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

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

            當(dāng)實現(xiàn)一個鏡面,一個物體假如在一面鏡子前那么它就會被反射。然而,我們不想測試空間一個物體是否在一面鏡子前,要做它是非常復(fù)雜的。因此,為了簡化事情,我們總是反射物體并且無限制地渲染它。但是這樣就有一個象本章開頭的圖8.1一樣的問題。即,物體反射被渲染到了沒有鏡子的表面。我們能夠用模板緩存來解決這個問題,因為模板緩存允許我們阻止渲染在后緩存中的特定區(qū)域。因此,我們使用模板緩存來阻止渲染被反射的不在鏡子里的茶壺。下面的步驟簡要的說明了怎樣實現(xiàn):

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

            2、 清除模板緩存為0。圖8.3顯示了后臺緩存和模板緩存。

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

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

             

            8.2.3代碼和解釋

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

            假如你想使用8.2.2部分的步驟實現(xiàn)代碼,注意我們從第3步開始,因為對模板緩存來說1和2步已經(jīng)沒有什么事做了。同樣我們通過這個解釋來討論通過鏡子渲染的信息。

            注意我們將分成幾個部分來討論它。

            8.2.3.1第一部分

            我們通過允許模板緩存和設(shè)置渲染狀態(tà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);

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

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

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

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

            8.2.3.2第二部分

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

                   // 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,因此對已經(jīng)渲染的鏡子區(qū)域做記號。我們現(xiàn)在準(zhǔn)備渲染被反射的茶壺。回憶一下,我們僅僅想渲染鏡子范圍內(nèi)的反射像素。我們現(xiàn)在可以很容易的做到了,因為在模板緩存中這些像素已經(jīng)被做了記號。

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

                   Device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_EQUAL);

            Device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);

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

                   (ref & mask == (value & mask)

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

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

            這說明了只有當(dāng)value=0x1時模板測試才成功。因為在模板緩存中只有鏡子相應(yīng)位置的值才是0x1,若我們渲染這些地方那么測試將會成功。因此,被反射的茶壺只會在鏡子里繪制而不會在鏡子以外的表面上繪制。

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

            8.2.3.4第四部分

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

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

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

             

            8.2.3.5第五部分

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

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

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

            因為原像素(sourcePixel)來自被反射的茶壺,目的像素(DestPixel)來自鏡子,我們能夠通過這個等式明白它們是怎么被混合到一起的。我們有如下的代碼:

                   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,它能夠正確的將被反射的茶壺變換到場景中恰當(dāng)?shù)奈恢谩M瑯樱覀円惨淖儽趁鎾x模式。必須這樣做的原因是當(dāng)一個物體被反射以后,它的正面和背面將會被交換。因此為了改變這種情況,我們必須改變背面揀選模式。

                   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 閱讀(2407) 評論(0)  編輯 收藏 引用


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


            公告

            導(dǎo)航

            統(tǒng)計

            常用鏈接

            隨筆分類(178)

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

            搜索

            最新評論

            99久久成人国产精品免费| 亚洲国产成人久久笫一页| 性做久久久久久久| 性高湖久久久久久久久| 人妻精品久久久久中文字幕69| 久久这里的只有是精品23| 久久发布国产伦子伦精品| 大美女久久久久久j久久| 人人狠狠综合久久亚洲高清| 亚洲国产精品成人AV无码久久综合影院 | 精品国产婷婷久久久| 香蕉99久久国产综合精品宅男自 | 久久成人18免费网站| 2021国产精品午夜久久| 国产精品九九久久精品女同亚洲欧美日韩综合区 | 香蕉久久av一区二区三区| 亚洲国产成人久久综合野外| 99久久综合狠狠综合久久止| 久久91精品国产91| 婷婷久久五月天| 久久乐国产综合亚洲精品| 国产福利电影一区二区三区,免费久久久久久久精| 国产午夜福利精品久久| 91精品国产91久久久久久| 99久久精品免费观看国产| 香蕉久久一区二区不卡无毒影院| 狠狠色丁香婷婷综合久久来| 久久香蕉国产线看观看精品yw| 亚洲人成精品久久久久| 久久精品国产亚洲av水果派 | 久久综合香蕉国产蜜臀AV| 色综合久久夜色精品国产| 久久精品国产亚洲av麻豆色欲| 日韩久久久久久中文人妻 | 亚洲国产天堂久久综合网站| 国产综合精品久久亚洲| 久久久久久久精品成人热色戒| 久久午夜羞羞影院免费观看| 久久se精品一区二区影院 | 天天综合久久久网| 久久无码国产专区精品|