//1).获取效果文件,hlsl注意fx要是asscii格式,不能是utf8格式
//2).结构体不能VS_OUTPUT outData = VS_OUTPUT(0);而是直接VS_OUTPUT outData就好了。
//3).顶点着色器输入输出都要float4类型,且像素着色器不能输入顶点,因为已经是在光栅化阶段了。
// 顶点着色器的输入
//struct VS_INPUT
//{
// float4 POS : POSITION;
// float2 UV : TEXCOORD0;
//};
//// 顶点着色器的输出
//struct VS_OUTPUT
//{
// float4 POS : POSITION;
// float2 UV : TEXCOORD0;
//};
// 4).纹理需要用Sampler正确,不能用texture代替sampler,或者输入texture当sampler来用的方式
// 5).alpha融合需要注意,否则会导致渲染层次有问题,融合结果
// 6).渲染框架要正确,无论是固定管线还是着色器,每帧的Clear,BeginSecne,渲染设置顶点格式/顶点数据/索引数据/Draw函数,EndScene
// 都是要首先正确的。
// 7).对于顶点部分:
// 顶点位置要正确,索引下标要正确,还有世界视图投影变换,特别是索引如果是拷贝的那么很容易什么都不提交PIX也看不到原因
// 8). 对于像素部分:颜色没有出来,可能是光照没有关闭又没有设置材质,也可能是纹理缺失或者设置错误,alpha融合和各种融合情况
// 9).注意视口外裁剪不可见,背面剔除,深度剔除,模板过滤,导致物体绘制不出来。
// 10).要使用上述思维进行代码分析,errorBuffer/Control panel/#define D3D_DEBUG_INFO/PIX来调试分析,反复对比注释提高理论查找问题
// 如果有N卡用NVIDIA Nsight,GPA分析问题和性能更好。
// 11).图像异常:UV坐标没对,PIX传入都没对,那么是UV相关设置出了问题,最后对比发现是顶点声明出了问题:
//D3DVERTEXELEMENT9 Decl_Element [] =
//{
// {eBlurDT_Pos, 0, D3DDECLTYPE_FLOAT4,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_POSITION, 0},
// {eBlurDT_UV, 0, D3DDECLTYPE_FLOAT2,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_TEXCOORD, 0},
// D3DDECL_END()
//};
//而不是:
//D3DVERTEXELEMENT9 Decl_Element [] =
//{
// {0, 0, D3DDECLTYPE_FLOAT4,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_POSITION, 0},
// {0, 16, D3DDECLTYPE_FLOAT2,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_TEXCOORD, 0},
// D3DDECL_END()
//};
// Globals // 纹理 texture BlurTex; // 世界视图投影矩阵 matrix WorldViewProj; // 纹理大小 float2 TexSize; // 高斯过滤矩阵,暂时用3x3的 float3x3 ArrayGaussianFilter; sampler BlurSampler = sampler_state { Texture = <BlurTex>; MinFilter = LINEAR; MagFilter = LINEAR; MipFilter = LINEAR; }; // // Structures // 顶点着色器的输入 struct VS_INPUT { float4 POS : POSITION; float2 UV : TEXCOORD0; }; // 顶点着色器的输出 struct VS_OUTPUT { float4 POS : POSITION; float2 UV : TEXCOORD0; }; VS_OUTPUT VS_Main( VS_INPUT input ) { VS_OUTPUT outData; outData.POS = mul( input.POS, WorldViewProj); outData.UV = input.UV; return outData; } // 像素着色器的输入 struct PS_INPUT { float2 UV : TEXCOORD0; }; // 像素着色器的输出 struct PS_OUTPUT { vector diffuse : COLOR0; }; //用来做滤波操作的函数 float4 dip_filter3(float3x3 _filter , sampler2D _image, float2 _xy, float2 texSize) { //纹理坐标采样的偏移 float2 _filter_pos_delta[3][3] = { { float2(-1.0 , -1.0) , float2(0,-1.0), float2(1.0 , -1.0) }, { float2( -1.0 , 0.0) , float2(0.0, 0.0), float2(1.0 , 0.0) }, { float2( -1.0 , 1.0) , float2(0, 1.0), float2(1.0 , 1.0) }, }; //最终的输出颜色 float4 final_color = float4(0.0,0.0,0.0,1.0f); //对图像做滤波操作 for(int i = 0 ; i < 3 ; i++ ) { for(int j = 0 ; j < 3 ; j++ ) { //计算采样点,得到当前像素附近的像素的坐标 float2 _xy_new = float2(_xy.x + _filter_pos_delta[i][j].x , _xy.y + _filter_pos_delta[i][j].y); float2 _uv_new = float2(_xy_new.x/texSize.x , _xy_new.y/texSize.y); //采样并乘以滤波器权重,然后累加 final_color += tex2D( _image, _uv_new ) * _filter[i][j]; } } return final_color; } PS_OUTPUT PS_Main( PS_INPUT input) { PS_OUTPUT output; float2 intXY = float2(input.UV.x * TexSize.x , input.UV.y * TexSize.y); //用于模糊操作的滤波器 // output.diffuse = tex2D(BlurSampler, input.UV); output.diffuse = dip_filter3( ArrayGaussianFilter , BlurSampler , intXY, TexSize); return output; } // 效果框架 technique BurTechnique { pass P0 { // 状态设置 Lighting = false; // 编译 vertexShader = compile vs_2_0 VS_Main(); AlphaBlendEnable = false; StencilEnable = false; pixelShader = compile ps_2_0 PS_Main(); } }
/*LPDIRECT3D9等加入*/ //#define D3D_DEBUG_INFO #include <d3d9.h> #include <d3dx9.h> #include <time.h> #include <tchar.h> /*D3DXMATRIX加入*/ #include <d3dx9math.h> /*LPDIRECT3D9等加入*/ #pragma comment(lib,"d3d9.lib") /*D3DXMatrixPerspectiveFovLH加入*/ #pragma comment(lib,"d3dx9.lib") // 媒体相关的库,用于抵挡的游戏音频和游戏手柄 #pragma comment(lib, "winmm.lib") // 工程属性->清单工具->输入输出->嵌入清单->是改为否 #include <d3dx9.h> #include <string> #include <limits> namespace d3d { // // Init // bool InitD3D( HINSTANCE hInstance, // [in] Application instance. int width, int height, // [in] Backbuffer dimensions. bool windowed, // [in] Windowed (true)or full screen (false). D3DDEVTYPE deviceType, // [in] HAL or REF IDirect3DDevice9** device);// [out]The created device. int EnterMsgLoop( bool (*ptr_display)(float timeDelta)); LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); // // Cleanup // template<class T> void Release(T t) { if( t ) { t->Release(); t = 0; } } template<class T> void Delete(T t) { if( t ) { delete t; t = 0; } } }
#include "d3dUtility.h" // vertex formats const DWORD d3d::Vertex::FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1; bool d3d::InitD3D( HINSTANCE hInstance, int width, int height, bool windowed, D3DDEVTYPE deviceType, IDirect3DDevice9** device) { // // Create the main application window. // WNDCLASS wc; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = (WNDPROC)d3d::WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(0, IDI_APPLICATION); wc.hCursor = LoadCursor(0, IDC_ARROW); wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wc.lpszMenuName = 0; wc.lpszClassName = "Direct3D9App"; if( !RegisterClass(&wc) ) { ::MessageBox(0, "RegisterClass() - FAILED", 0, 0); return false; } HWND hwnd = 0; hwnd = ::CreateWindow("Direct3D9App", "Direct3D9App", WS_EX_TOPMOST, 0, 0, width, height, 0 /*parent hwnd*/, 0 /* menu */, hInstance, 0 /*extra*/); if( !hwnd ) { ::MessageBox(0, "CreateWindow() - FAILED", 0, 0); return false; } ::ShowWindow(hwnd, SW_SHOW); ::UpdateWindow(hwnd); // // Init D3D: // HRESULT hr = 0; // Step 1: Create the IDirect3D9 object. IDirect3D9* d3d9 = 0; d3d9 = Direct3DCreate9(D3D_SDK_VERSION); if( !d3d9 ) { ::MessageBox(0, "Direct3DCreate9() - FAILED", 0, 0); return false; } // Step 2: Check for hardware vp. D3DCAPS9 caps; d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, deviceType, &caps); int vp = 0; if( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ) vp = D3DCREATE_HARDWARE_VERTEXPROCESSING; else vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING; // Step 3: Fill out the D3DPRESENT_PARAMETERS structure. D3DPRESENT_PARAMETERS d3dpp; d3dpp.BackBufferWidth = width; d3dpp.BackBufferHeight = height; d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8; d3dpp.BackBufferCount = 1; d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE; d3dpp.MultiSampleQuality = 0; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.hDeviceWindow = hwnd; d3dpp.Windowed = windowed; d3dpp.EnableAutoDepthStencil = true; d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8; d3dpp.Flags = 0; d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; // Step 4: Create the device. hr = d3d9->CreateDevice( D3DADAPTER_DEFAULT, // primary adapter deviceType, // device type hwnd, // window associated with device vp, // vertex processing &d3dpp, // present parameters device); // return created device if( FAILED(hr) ) { // try again using a 16-bit depth buffer d3dpp.AutoDepthStencilFormat = D3DFMT_D16; hr = d3d9->CreateDevice( D3DADAPTER_DEFAULT, deviceType, hwnd, vp, &d3dpp, device); if( FAILED(hr) ) { d3d9->Release(); // done with d3d9 object ::MessageBox(0, "CreateDevice() - FAILED", 0, 0); return false; } } d3d9->Release(); // done with d3d9 object return true; } int d3d::EnterMsgLoop( bool (*ptr_display)(float timeDelta) ) { MSG msg; ::ZeroMemory(&msg, sizeof(MSG)); static float lastTime = (float)timeGetTime(); while(msg.message != WM_QUIT) { if(::PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { ::TranslateMessage(&msg); ::DispatchMessage(&msg); } else { float currTime = (float)timeGetTime(); float timeDelta = (currTime - lastTime)*0.001f; ptr_display(timeDelta); lastTime = currTime; } } return msg.wParam; }
#ifndef _GAUSSIANBLUR_H_ #define _GAUSSIANBLUR_H_ class CGaussianBlur { public: CGaussianBlur(){}; ~CGaussianBlur(){}; // 计算高斯权值 void CalculateGaussianFilter(int nLength, float rho); float* GetFilter3(); float* GetFilter4(); float GaussianFilter3[9]; private: // 参数高斯权值 float GetGaussianDistribution( float x, float y, float rho ); // 是否接近0 inline bool FEqual(float fValue1, float fValue2 ); // 高斯模糊矩阵,提供3x3的和4x4的 float GaussianFilter4[16]; }; #endif
#include "GaussianBlur.h" #include <math.h> #include <float.h> static const int N_FilterLength3 = 3; static const int N_FilterLength4 = 4; bool CGaussianBlur::FEqual(float fValue1, float fValue2 ) { if( fabs(fValue1 - fValue2) < FLT_EPSILON ) { return true; } else { return false; } } float CGaussianBlur::GetGaussianDistribution( float x, float y, float rho ) { float g = 1.0f / sqrt( 2.0f * 3.141592654f * rho * rho ); return g * exp( -(x * x + y * y) / (2 * rho * rho) ); } void CGaussianBlur::CalculateGaussianFilter(int nLength, float rho) { int nSideLength = (int)floor(nLength * 0.5f); int nIndex = 0; float fTotalWeight = 0; for( int j = -nSideLength; j <= nSideLength ; j++ ) { for( int i = -nSideLength; i <= nSideLength; i++ ) { if( nLength == N_FilterLength3 ) { GaussianFilter3[nIndex] = GetGaussianDistribution(i, j, rho); fTotalWeight += GaussianFilter3[nIndex]; } else if( nLength == N_FilterLength4 ) { GaussianFilter4[nIndex] = GetGaussianDistribution(i, j, rho); fTotalWeight += GaussianFilter4[nIndex]; } else { // ERROR Log return; } nIndex++; } } // 避免除0 if( FEqual( fTotalWeight, 0.0f) ) { // ERROR Log return; } nIndex = 0; // 归一化一下 for( int i = 0; i < nLength; i++ ) { for( int j = 0; j < nLength; j++ ) { if( nLength == N_FilterLength3 ) { GaussianFilter3[nIndex] = GaussianFilter3[nIndex] / fTotalWeight; } else if( nLength == N_FilterLength4 ) { GaussianFilter4[nIndex] = GaussianFilter4[nIndex] / fTotalWeight; } nIndex++; } } } float* CGaussianBlur::GetFilter3() { return GaussianFilter3; } float* CGaussianBlur::GetFilter4() { return GaussianFilter4; }
#include "d3dUtility.h" #include "GaussianBlur.h" LPDIRECT3DDEVICE9 Device = NULL; LPD3DXEFFECT BlurTexEffect = NULL; LPDIRECT3DVERTEXDECLARATION9 VT_DECL = NULL; LPDIRECT3DVERTEXBUFFER9 VB_Pos = NULL; LPDIRECT3DVERTEXBUFFER9 VB_UV = NULL; LPDIRECT3DINDEXBUFFER9 IB = NULL; D3DXHANDLE WorldViewProjectHandle = NULL; D3DXHANDLE BlurTechHandle = NULL; CGaussianBlur g_BlurFilter; LPDIRECT3DTEXTURE9 TexObj = NULL; const int Width = 640; const int Height = 480; // 模糊的顶点数和索引缓存数 static const int N_Blur_Vertex_Count = 4; static const int N_Blur_Index_Count = 6; static bool g_bChangeFilter = false; // 顶点声明的数据流索引 enum BlurVertexDeclType { eBlurDT_Pos, eBlurDT_UV }; //struct tagTextureVertex //{ // float x, y, z; // float u, v; // // tagTextureVertex(float ax, float ay, float az, float au, float av ) // { // x = ax; y = ay; z = az; // u = au; v = av; // } // static const DWORD FVF; //}; // //const DWORD tagTextureVertex::FVF = D3DFVF_XYZ | D3DFVF_TEX1; bool Setup() { // 顶点声明 D3DVERTEXELEMENT9 Decl_Element [] = { {eBlurDT_Pos, 0, D3DDECLTYPE_FLOAT4,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_POSITION, 0}, {eBlurDT_UV, 0, D3DDECLTYPE_FLOAT2,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END() }; if( FAILED(Device->CreateVertexDeclaration(Decl_Element,&VT_DECL) ) ) { return false; } /* Device->CreateVertexBuffer( 4 * sizeof( tagTextureVertex ), D3DUSAGE_WRITEONLY, tagTextureVertex::FVF, D3DPOOL_MANAGED, &VB_Pos, 0 );*/ // 顶点位置 if( FAILED( Device->CreateVertexBuffer(4 * sizeof(D3DXVECTOR4), D3DUSAGE_WRITEONLY, 0, D3DPOOL_MANAGED, &VB_Pos, 0) ) ) { return false; } D3DXVECTOR4 *pPos = NULL; if( FAILED (VB_Pos->Lock(0, 0, (void**)&pPos, 0) ) ) { return false; } //tagTextureVertex *pPos = (tagTextureVertex*)VertexData; float fHalfWidth = Width * 0.5f; float fHalfHeight = Height * 0.5f; pPos[0] = D3DXVECTOR4(-1.0f, -1.0f, 1.0f, 1.0f); pPos[1] = D3DXVECTOR4(-1.0f, 1.0f, 1.0f, 1.0f); pPos[2] = D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f); pPos[3] = D3DXVECTOR4(1.0f, -1.0f, 1.0f, 1.0f); /*pPos[0] = tagTextureVertex(-1.0f, -1.0f,1.0f, 0.0f, 1.0f); pPos[1] = tagTextureVertex(-1.0f, 1.0f, 1.0f, 0.0f, 0.0f); pPos[2] = tagTextureVertex( 1.0f, 1.0f, 1.0f,1.0f, 0.0f); pPos[3] = tagTextureVertex( 1.0f, -1.0f, 1.0f, 1.0f, 1.0f);*/ VB_Pos->Unlock(); //// 顶点UV if( FAILED( Device->CreateVertexBuffer(4 * sizeof(D3DXVECTOR2), D3DUSAGE_WRITEONLY, 0, D3DPOOL_MANAGED, &VB_UV, 0) ) ) { return false; } D3DXVECTOR2 *UV_Data = NULL; if( FAILED( VB_UV->Lock(0,0,(void**)&UV_Data, 0)) ) { return false; } UV_Data[0] = D3DXVECTOR2(0.0f, 1.0f); UV_Data[1] = D3DXVECTOR2(0.0f, 0.0f); UV_Data[2] = D3DXVECTOR2(1.0f, 0.0f); UV_Data[3] = D3DXVECTOR2(1.0f, 1.0f); VB_UV->Unlock(); // 索引缓存 if( FAILED( Device->CreateIndexBuffer( 6 * sizeof( WORD ), D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &IB, 0) ) ) { return false; } WORD *IB_Buffer = NULL; if( FAILED( IB->Lock(0,0, (void**)&IB_Buffer, 0) ) ) { return false; } IB_Buffer[0] = 0;IB_Buffer[1] = 1;IB_Buffer[2] = 2; IB_Buffer[3] = 0;IB_Buffer[4] = 2;IB_Buffer[5] = 3; IB->Unlock(); // 纹理对象设置进去就好了 D3DXIMAGE_INFO imageInfo; D3DXCreateTextureFromFileEx( Device, "crate.png", D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, &imageInfo, NULL, &TexObj); /*Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); Device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);*/ ID3DXBuffer* errorBuffer = 0; if( FAILED( D3DXCreateEffectFromFile( Device, "blur.fx", 0, // no preprocessor definitions 0, // no ID3DXInclude interface D3DXSHADER_DEBUG, // compile flags 0, // don't share parameters &BlurTexEffect, &errorBuffer) ) ) { if( errorBuffer ) { ::MessageBox(0, (char*)errorBuffer->GetBufferPointer(), 0, 0); d3d::Release<ID3DXBuffer*>(errorBuffer); } return false; } // output any error messages //D3DXHANDLE TextureHandle = BlurTexEffect->GetParameterByName(0, "BlurTex"); BlurTexEffect->SetTexture(/*TextureHandle*/"BlurTex", TexObj); if ( TexObj != NULL ) { TexObj->Release(); TexObj = NULL; } FLOAT texSize[2] = {imageInfo.Width * 1.0f, imageInfo.Height * 1.0f}; D3DXHANDLE TextureSizeHandle = BlurTexEffect->GetParameterByName(0, "TexSize"); BlurTexEffect->SetFloatArray(/*TextureSizeHandle*/"TexSize", texSize, 2); D3DXMATRIX W, P; D3DXMatrixIdentity(&W); //Device->SetTransform(D3DTS_WORLD, &W); D3DXVECTOR3 position( 0.0f, 0.0f, -2.0f ); D3DXVECTOR3 target(0.0f, 0.0f, 0.0f); D3DXVECTOR3 up(0.0f, 1.0f, 0.0f); D3DXMATRIX V; D3DXMatrixLookAtLH(&V, &position, &target, &up); //Device->SetTransform(D3DTS_VIEW, &V); /*D3DXMatrixLookAtLH(&V, &position, &target, &up); Device->SetTransform(D3DTS_PROJECTION, &V);*/ Device->SetRenderState( D3DRS_LIGHTING, FALSE); D3DXMatrixPerspectiveFovLH( &P, D3DX_PI * 0.25f, // 45 - degree (float)Width / (float)Height, 1.0f, 1000.0f); //D3DXMatrixOrthoLH(&P, float(Width), float(Height), 1.0f, 1000.0f); //Device->SetTransform(D3DTS_PROJECTION, &P); D3DXMATRIX worldViewProj = W * V * P; D3DXHANDLE MatrixHandle = BlurTexEffect->GetParameterByName(0, "WorldViewProj"); BlurTexEffect->SetMatrix(/*MatrixHandle*/"WorldViewProj", &worldViewProj); if( !g_bChangeFilter ) { g_BlurFilter.CalculateGaussianFilter(3, 8.5f); } //float* fArray9 = g_BlurFilter.GetFilter3(); D3DXHANDLE filterHandle = BlurTexEffect->GetParameterByName(0, "ArrayGaussianFilter"); BlurTexEffect->SetFloatArray(/*filterHandle*/"ArrayGaussianFilter", g_BlurFilter.GaussianFilter3, 9); BlurTechHandle = BlurTexEffect->GetTechniqueByName("BurTechnique"); return true; } void Cleanup() { d3d::Release<LPD3DXEFFECT>(BlurTexEffect); d3d::Release<LPDIRECT3DVERTEXBUFFER9>(VB_Pos); d3d::Release<LPDIRECT3DVERTEXBUFFER9>(VB_UV); d3d::Release<LPDIRECT3DINDEXBUFFER9>(IB); d3d::Release<LPDIRECT3DDEVICE9>(Device); } bool Display(float timeDelta) { if( Device == NULL || VB_Pos == NULL || VB_UV == NULL || IB == NULL ) { return false; } Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0); Device->BeginScene(); Device->SetVertexDeclaration(VT_DECL); Device->SetStreamSource(eBlurDT_Pos, VB_Pos, 0, sizeof(D3DXVECTOR4)); Device->SetStreamSource(eBlurDT_UV, VB_UV, 0, sizeof(D3DXVECTOR2)); Device->SetIndices(IB); /*Device->SetFVF(tagTextureVertex::FVF); Device->SetStreamSource(0, VB_Pos, 0, sizeof( tagTextureVertex ));*/ //Device->SetTexture(0, TexObj); BlurTexEffect->SetTechnique("BurTechnique"/*BlurTechHandle*/); UINT numPasses = 0; BlurTexEffect->Begin(&numPasses, 0); for( int i = 0; i < numPasses; i++ ) { BlurTexEffect->BeginPass(i); BlurTexEffect->CommitChanges(); // 绘制 Device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 4,0, 2); BlurTexEffect->EndPass(); } //Device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 4,0, 2); BlurTexEffect->End(); Device->EndScene(); Device->Present(0, 0, 0, 0); return true; } // // WndProc // LRESULT CALLBACK d3d::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch( msg ) { case WM_DESTROY: ::PostQuitMessage(0); break; case WM_KEYDOWN: if( wParam == VK_ESCAPE ) ::DestroyWindow(hwnd); break; } return ::DefWindowProc(hwnd, msg, wParam, lParam); } // // WinMain // int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE prevInstance, PSTR cmdLine, int showCmd) { if(!d3d::InitD3D(hinstance, Width, Height, true, D3DDEVTYPE_HAL, &Device)) { ::MessageBox(0, "InitD3D() - FAILED", 0, 0); return 0; } if(!Setup()) { ::MessageBox(0, "Setup() - FAILED", 0, 0); return 0; } d3d::EnterMsgLoop( Display ); Cleanup(); Device->Release(); return 0; }