// 使用Direct3D9來繪圖 void RenderFrameDX9(void) { LPDIRECT3DDEVICE9 device = GutGetGraphicsDeviceDX9(); Vector4 vPlane(0.0f, 0.0f, 1.0f, -g_mirror_z); device->BeginScene(); // 消除畫面 device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, D3DCOLOR_RGBA(0, 0, 150, 255), 1.0f, 0); // 畫出茶壼 RenderModelDX9(false, NULL); // 畫出鏡面, 同時把stencil值設為1. { device->SetRenderState(D3DRS_STENCILENABLE, TRUE); device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE); device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS); device->SetRenderState(D3DRS_STENCILREF, 1); Matrix4x4 identity_matrix = Matrix4x4::IdentityMatrix(); device->SetTransform(D3DTS_WORLD, (D3DMATRIX *) &identity_matrix); sModelMaterial_DX9 material; material.m_Material.Diffuse.r = material.m_Material.Diffuse.g = material.m_Material.Diffuse.b = material.m_Material.Diffuse.a = 0.0f; material.Submit(); // 畫出鏡面 device->SetFVF(D3DFVF_XYZ); device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, g_Quad_v, sizeof(Vertex_V)); } // 把鏡面范圍的ZBuffer清為1.0 { // 設定stencil test條件, 只更新鏡面范圍的像素. device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_EQUAL); device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP); device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS); // 關閉z test device->SetRenderState(D3DRS_COLORWRITEENABLE, 0); // 關閉RGBA的輸出 // 經由修改viewport Z范圍的方法, 把3D物件的Z值輸出固定為1. int w, h; GutGetWindowSize(w, h); D3DVIEWPORT9 viewport; viewport.X = viewport.Y = 0; viewport.Width = w; viewport.Height = h; viewport.MinZ = 1.0f; viewport.MaxZ = 1.0f; device->SetViewport(&viewport); // 畫出鏡面 device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, g_Quad_v, sizeof(Vertex_V)); // 把Z值范圍還原成0-1 viewport.MinZ = 0.0f; viewport.MaxZ = 1.0f; device->SetViewport(&viewport); // 還原zbuffer test的測試條件 device->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL); // 重新打開RGBA的輸出 device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_ALPHA); } // 在鏡面范圍里畫出鏡射的茶壼 { RenderModelDX9(true, &vPlane); device->SetRenderState(D3DRS_STENCILENABLE, FALSE); } // 宣告所有的繪圖指令都下完了 device->EndScene(); // 把背景backbuffer的畫面呈現出來 device->Present( NULL, NULL, NULL, NULL ); }
// 使用DirectX 9來繪圖 void RenderFrameDX9(void) { LPDIRECT3DDEVICE9 device = GutGetGraphicsDeviceDX9(); Vector4 vPlane(0.0f, 0.0f, 1.0f, -g_mirror_z); // 開始下繪圖指令 device->BeginScene(); { LPDIRECT3DSURFACE9 pFrameBufferBackup, pDepthBufferBackup; device->GetRenderTarget(0, &pFrameBufferBackup); pFrameBufferBackup->Release(); device->GetDepthStencilSurface(&pDepthBufferBackup); pDepthBufferBackup->Release(); LPDIRECT3DSURFACE9 pSurface; g_pTexture->GetSurfaceLevel(0, &pSurface); device->SetRenderTarget(0, pSurface); device->SetDepthStencilSurface(g_pDepthStencil); device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_RGBA(0, 0, 200, 255), 1.0f, 0); RenderModelDX9(true, &vPlane); pSurface->Release(); device->SetRenderTarget(0, pFrameBufferBackup); device->SetDepthStencilSurface(pDepthBufferBackup); } // 把上一個步驟的結果當成貼圖來使用 { // 消除畫面 device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_RGBA(0, 0, 150, 255), 1.0f, 0); RenderModelDX9(false, NULL); Matrix4x4 identMat; identMat.Identity(); device->SetTransform(D3DTS_WORLD, (D3DMATRIX *) &identMat); sModelMaterial_DX9 material; material.m_pTextures[0] = g_pTexture; material.Submit(); device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_NONE); device->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); device->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); device->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_NONE); Matrix4x4 uv_offset_matrix; uv_offset_matrix.Scale_Replace(0.5f, -0.5f, 1.0f); uv_offset_matrix[3].Set(0.5f, 0.5f, 0.5f, 1.0f); Matrix4x4 inv_view_matrix = g_Control.GetViewMatrix(); inv_view_matrix.FastInvert(); Matrix4x4 texture_matrix = inv_view_matrix * g_mirror_view_matrix * g_projection_matrix * uv_offset_matrix; device->SetTransform(D3DTS_TEXTURE0, (D3DMATRIX *) &texture_matrix); device->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION); // D3DTTFF_PROJECTED告知direct3d裝置texcoord需要除以w device->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT4|D3DTTFF_PROJECTED); float v[12]; for ( int i=0; i<4; i++ ) { g_Quad[i].m_Position.StoreXYZ(&v[i*3]); } // 畫出矩形 device->SetFVF(D3DFVF_XYZ); //device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, g_Quad, sizeof(Vertex_V)); device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, v, 12); } // 宣告所有的繪圖指令都下完了 device->EndScene(); // 把背景backbuffer的畫面呈現出來 device->Present( NULL, NULL, NULL, NULL ); }