// 使用DirectX 9來繪圖 void RenderFrameDX9(void) { LPDIRECT3DDEVICE9 device = GutGetGraphicsDeviceDX9(); LPDIRECT3DTEXTURE9 pBlurredTexture = NULL; Matrix4x4 light_projection_matrix; Matrix4x4 light_view_matrix; Matrix4x4 view_matrix = g_Control.GetViewMatrix(); Matrix4x4 world_matrix = g_Control.GetObjectMatrix(); // 開始下繪圖指令 device->BeginScene(); { // 保存主framebuffer LPDIRECT3DSURFACE9 pFrameBufferBackup, pDepthBufferBackup; device->GetRenderTarget(0, &pFrameBufferBackup); pFrameBufferBackup->Release(); device->GetDepthStencilSurface(&pDepthBufferBackup); pDepthBufferBackup->Release(); // 取出動態貼圖中的surface 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(255, 255, 255, 255), 1.0f, 0); // 設定光源位置 Vector4 vLightPos = g_Light.m_Position; Vector4 vLightUp(0.0f, 1.0f, 0.0f); Vector4 vLightLookat(0.0f, 0.0f, 0.0f); light_projection_matrix = GutMatrixPerspectiveRH_DirectX(60.0f, 1.0f, 0.1f, 100.0f); light_view_matrix = GutMatrixLookAtRH(vLightPos, vLightLookat, vLightUp); // 把鏡頭放到光源位置來畫陰影 device->SetTransform(D3DTS_PROJECTION, (D3DMATRIX *)&light_projection_matrix); device->SetTransform(D3DTS_VIEW, (D3DMATRIX *)&light_view_matrix); device->SetTransform(D3DTS_WORLD, (D3DMATRIX *)&world_matrix); // 把所有反射關閉,讓模型在畫面上呈現黑色。 D3DCOLORVALUE zero = {0.0f, 0.0f, 0.0f, 1.0f}; sModelMaterial_DX9 material; material.m_Material.Ambient = zero; material.m_Material.Emissive = zero; material.m_Material.Diffuse = zero; material.m_Material.Specular = zero; material.m_bCullFace = false; material.Submit(); SetupLightingDX9(); // 畫出模型 g_Model_DX9.Render(0); // 告知direct3d9裝置rendertarget使用完畢 pSurface->Release(); // 還原主framebuffer device->SetRenderTarget(0, pFrameBufferBackup); device->SetDepthStencilSurface(pDepthBufferBackup); } // 把影子柔化 { pBlurredTexture = BlurTexture(g_pTexture); } // 把上一個步驟的結果當成貼圖來使用 { // 消除畫面 device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_RGBA(0, 0, 150, 255), 1.0f, 0); // 設定轉換矩陣 device->SetTransform(D3DTS_PROJECTION, (D3DMATRIX *) &g_projection_matrix); device->SetTransform(D3DTS_VIEW, (D3DMATRIX *) &view_matrix); device->SetTransform(D3DTS_WORLD, (D3DMATRIX *) &world_matrix); // 設定光源 SetupLightingDX9(); device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP); device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP); device->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP); device->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP); // 畫出茶壼 g_Model_DX9.Render(); sModelMaterial_DX9 material; material.m_pTextures[0] = pBlurredTexture; material.Submit(); // 計算貼圖矩陣 Matrix4x4 inv_view_matrix = g_Control.GetCameraMatrix(); Matrix4x4 uv_offset_matrix; uv_offset_matrix.Identity(); uv_offset_matrix.Scale(0.5f, -0.5f, 0.5f); uv_offset_matrix[3].Set(0.5f, 0.5f, 0.5f, 1.0f); Matrix4x4 texture_matrix = inv_view_matrix * light_view_matrix * light_projection_matrix * uv_offset_matrix; Matrix4x4 indent_matrix = Matrix4x4::IdentityMatrix(); // 設定轉換矩陣 device->SetTransform(D3DTS_TEXTURE0, (D3DMATRIX *) &texture_matrix); device->SetTransform(D3DTS_WORLD, (D3DMATRIX *) &indent_matrix); // 開啟自動產生貼圖座標功能 device->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION); device->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT4 | D3DTTFF_PROJECTED); device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); device->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); device->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); // 畫出地表 g_Terrain_DX9.Render(0); device->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE); device->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0); } // 宣告所有的繪圖指令都下完了 device->EndScene(); // 把背景backbuffer的畫面呈現出來 device->Present( NULL, NULL, NULL, NULL ); }
// `使用Direct3D9來繪圖` void RenderFrameDX9(void) { LPDIRECT3DDEVICE9 device = GutGetGraphicsDeviceDX9(); Matrix4x4 light_projection_matrix; Matrix4x4 light_view_matrix; Matrix4x4 view_matrix = g_Control.GetViewMatrix(); Matrix4x4 world_matrix = g_Control.GetObjectMatrix(); // `開始下繪圖指令` device->BeginScene(); // `把剪影畫在動態貼圖中` if(1) { //! 设置临时framebuffer 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(255, 255, 255, 255), 1.0f, 0); Vector4 vLightPos = g_Light.m_Position; Vector4 vLightUp(0.0f, 1.0f, 0.0f); Vector4 vLightLookat(0.0f, 0.0f, 0.0f); // `把鏡頭放在光源的` light_projection_matrix = GutMatrixPerspectiveRH_DirectX(60.0f, 1.0f, 0.1f, 100.0f); light_view_matrix = GutMatrixLookAtRH(vLightPos, vLightLookat, vLightUp); // `設定轉換矩陣` device->SetTransform(D3DTS_PROJECTION, (D3DMATRIX *)&light_projection_matrix); device->SetTransform(D3DTS_VIEW, (D3DMATRIX *)&light_view_matrix); device->SetTransform(D3DTS_WORLD, (D3DMATRIX *)&world_matrix); D3DCOLORVALUE zero = {0.0f, 0.0f, 0.0f, 1.0f}; sModelMaterial_DX9 material; material.m_Material.Ambient = zero; material.m_Material.Emissive = zero; material.m_Material.Diffuse = zero; material.m_Material.Specular = zero; material.m_bCullFace = false; material.Submit(); device->SetRenderState(D3DRS_LIGHTING, 0); g_Model_DX9.Render(0); 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); // `設定轉換矩陣` device->SetTransform(D3DTS_PROJECTION, (D3DMATRIX *) &g_projection_matrix); device->SetTransform(D3DTS_VIEW, (D3DMATRIX *) &view_matrix); device->SetTransform(D3DTS_WORLD, (D3DMATRIX *) &world_matrix); #define DRAW_TEAPORT_FIRST 1 //! 画茶壶 if (DRAW_TEAPORT_FIRST) { SetupLightingDX9(); g_Model_DX9.Render(); } //! 设置矩形的纹理 sModelMaterial_DX9 material; material.m_pTextures[0] = g_pTexture; material.Submit(); Matrix4x4 inv_view_matrix = view_matrix; inv_view_matrix.FastInvert(); Matrix4x4 uv_offset_matrix; uv_offset_matrix.Identity(); uv_offset_matrix.Scale(0.5f, -0.5f, 0.5f); uv_offset_matrix[3].Set(0.5f, 0.5f, 0.5f, 1.0f); Matrix4x4 texture_matrix = inv_view_matrix * light_view_matrix * light_projection_matrix * uv_offset_matrix; Matrix4x4 indent_matrix = Matrix4x4::IdentityMatrix(); device->SetTransform(D3DTS_TEXTURE0, (D3DMATRIX *) &texture_matrix); device->SetTransform(D3DTS_WORLD, (D3DMATRIX *) &indent_matrix); device->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION); device->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT4 | D3DTTFF_PROJECTED ); device->SetRenderState(D3DRS_LIGHTING, FALSE); // `畫出矩形` device->SetFVF(D3DFVF_XYZ); device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, g_Quad, sizeof(Vertex_VT)); //! 关闭纹理矩阵 device->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE); if (!DRAW_TEAPORT_FIRST) { //SetupLightingDX9(); device->SetTransform(D3DTS_WORLD, (D3DMATRIX *) &world_matrix); g_Model_DX9.Render(); } } // `宣告所有的繪圖指令都下完了` device->EndScene(); // `把背景backbuffer的畫面呈現出來` device->Present( NULL, NULL, NULL, NULL ); }
// 使用OpenGL來繪圖 void RenderFrameOpenGL(void) { Matrix4x4 light_projection_matrix; Matrix4x4 light_view_matrix; Matrix4x4 light_world_view_matrix; Matrix4x4 view_matrix = g_Control.GetViewMatrix(); Matrix4x4 world_matrix = g_Control.GetObjectMatrix(); { // `使用` g_framebuffer framebuffer object glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, g_framebuffer); glViewport(0, 0, 512, 512); // `清除畫面` glClearColor(1.0f, 1.0f, 1.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // `光源位置` Vector4 vLightPos = g_Light.m_Position; Vector4 vLightUp(0.0f, 1.0f, 0.0f); Vector4 vLightLookat(0.0f, 0.0f, 0.0f); // `設定光源的轉換矩陣` light_projection_matrix = GutMatrixPerspectiveRH_OpenGL(60.0f, 1.0f, 0.1f, 100.0f); light_view_matrix = GutMatrixLookAtRH(vLightPos, vLightLookat, vLightUp); light_world_view_matrix = world_matrix * light_view_matrix; glMatrixMode(GL_PROJECTION); glLoadMatrixf( (float *) &light_projection_matrix ); glMatrixMode(GL_MODELVIEW); glLoadMatrixf( (float *) &light_world_view_matrix ); glDisable(GL_LIGHTING); // `畫出黑色的茶壼` sModelMaterial_OpenGL material; material.m_bCullFace = false; material.m_Diffuse.Set(0.0); material.Submit(NULL); g_Model_OpenGL.Render(0); } { // `使用主framebuffer object, 也就是視窗.` glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); int w, h; GutGetWindowSize(w, h); glViewport(0, 0, w, h); // `清除畫面` glClearColor(0.0f, 0.0f, 0.6f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // `計算出一個可以轉換到鏡頭座標系的矩陣` Matrix4x4 view_matrix = g_Control.GetViewMatrix(); glMatrixMode(GL_MODELVIEW); glLoadMatrixf( (float *) &view_matrix); SetupLightingOpenGL(); Matrix4x4 world_view_matrix = world_matrix * view_matrix; glMatrixMode(GL_PROJECTION); glLoadMatrixf( (float *) &g_projection_matrix); glMatrixMode(GL_MODELVIEW); glLoadMatrixf( (float *) &world_view_matrix); g_Model_OpenGL.Render(); glMatrixMode(GL_MODELVIEW); glLoadMatrixf( (float *) &view_matrix); glDisable(GL_LIGHTING); sModelMaterial_OpenGL material; material.m_Diffuse.Set(1.0f); material.m_Textures[0] = g_texture; material.Submit(NULL); Matrix4x4 uv_offset_matrix; uv_offset_matrix.Identity(); uv_offset_matrix.Scale(0.5f, 0.5f, 0.5f); uv_offset_matrix[3].Set(0.5f, 0.5f, 0.5f, 1.0f); Matrix4x4 texture_matrix = light_view_matrix * light_projection_matrix * uv_offset_matrix; glMatrixMode(GL_TEXTURE); glLoadMatrixf( (float *)&texture_matrix); glDisable(GL_LIGHTING); // `設定頂點資料格式` glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT); glEnableClientState(GL_VERTEX_ARRAY); glClientActiveTexture(GL_TEXTURE0_ARB); glEnableClientState(GL_TEXTURE_COORD_ARRAY); // glVertexPointer(3, GL_FLOAT, sizeof(Vertex_VT), &g_Quad[0].m_Position); // `直接把頂點資料拿來當貼圖座標使用` glTexCoordPointer(4, GL_FLOAT, sizeof(Vertex_VT), &g_Quad[0].m_Position); // `畫出看板` glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glPopClientAttrib(); glLoadIdentity(); } // 把背景backbuffer的畫面呈現出來 GutSwapBuffersOpenGL(); }
// 使用OpenGL來繪圖 void RenderFrameOpenGL(void) { Matrix4x4 light_projection_matrix; Matrix4x4 light_view_matrix; Matrix4x4 light_world_view_matrix; Matrix4x4 view_matrix = g_Control.GetViewMatrix(); Matrix4x4 world_matrix = g_Control.GetObjectMatrix(); GLuint blurred_texture = 0; { // 使用g_framebuffer framebuffer object glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, g_framebuffer); glViewport(0, 0, g_framebuffer_w, g_framebuffer_h); // 清除畫面 glClearColor(1.0f, 1.0f, 1.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 設定光源位置 Vector4 vLightPos = g_Light.m_Position; Vector4 vLightUp(0.0f, 1.0f, 0.0f); Vector4 vLightLookat(0.0f, 0.0f, 0.0f); light_projection_matrix = GutMatrixPerspectiveRH_OpenGL(60.0f, 1.0f, 0.1f, 100.0f); light_view_matrix = GutMatrixLookAtRH(vLightPos, vLightLookat, vLightUp); light_world_view_matrix = world_matrix * light_view_matrix; // 把鏡頭放到光源位置來畫陰影 glMatrixMode(GL_PROJECTION); glLoadMatrixf( (float *) &light_projection_matrix ); glMatrixMode(GL_MODELVIEW); glLoadMatrixf( (float *) &light_world_view_matrix ); SetupLightingOpenGL(); // 套用預設材質, 把貼圖全部關閉 sModelMaterial_OpenGL material; material.m_Ambient = Vector4::GetZero(); material.m_Emissive = Vector4::GetZero(); material.m_Diffuse = Vector4::GetZero(); material.m_Specular = Vector4::GetZero(); material.m_bCullFace = false; material.Submit(NULL); // 畫出模型 g_Model_OpenGL.Render(0); } // 把影子柔化 { blurred_texture = BlurTexture(g_texture); } { // 使用主framebuffer object, 也就是視窗. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); int w, h; GutGetWindowSize(w, h); glViewport(0, 0, w, h); // 清除畫面 glClearColor(0.0f, 0.0f, 0.6f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadMatrixf( (float *) &view_matrix); // 設定光源 SetupLightingOpenGL(); // 設定轉換矩陣 Matrix4x4 world_view_matrix = world_matrix * view_matrix; glMatrixMode(GL_PROJECTION); glLoadMatrixf( (float *) &g_projection_matrix); glMatrixMode(GL_MODELVIEW); glLoadMatrixf( (float *) &world_view_matrix); // 畫出茶壼 g_Model_OpenGL.Render(); glMatrixMode(GL_MODELVIEW); glLoadMatrixf( (float *) &view_matrix); sModelMaterial_OpenGL material; material.m_Textures[0] = blurred_texture; material.Submit(NULL); // 計算貼圖矩陣 Matrix4x4 uv_offset_matrix; uv_offset_matrix.Identity(); uv_offset_matrix.Scale(0.5f, 0.5f, 0.5f); uv_offset_matrix[3].Set(0.5f, 0.5f, 0.5f, 1.0f); Matrix4x4 texture_matrix = light_view_matrix * light_projection_matrix * uv_offset_matrix; glMatrixMode(GL_TEXTURE); glLoadMatrixf( (float *)&texture_matrix); // 開啟自動產生貼圖座標功能 // S/T/R分別代表貼圖座標的X/Y/Z軸 glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); glEnable(GL_TEXTURE_GEN_R); // 以光線的反射向量來做為貼圖座標 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); Matrix4x4 identMatrix = Matrix4x4::IdentityMatrix(); glTexGenfv(GL_S, GL_OBJECT_PLANE, &identMatrix[0][0]); glTexGenfv(GL_T, GL_OBJECT_PLANE, &identMatrix[1][0]); glTexGenfv(GL_R, GL_OBJECT_PLANE, &identMatrix[2][0]); // 畫出地表 g_Terrain_OpenGL.Render(0); glLoadIdentity(); } // 把背景backbuffer的畫面呈現出來 GutSwapBuffersOpenGL(); }