【寒江雪】Alpha通道混合技术
2016-12-24 03:51
381 查看
Alpha通道与混合技术
Alpha通道是计算机中存储一张图片的透明和半透明信息的通道。它是一个8位的灰度通道,用256级灰度来记录图像中的透明度信息,定义透明,不透明和半透明区域,其中黑色表示全透明,白色表示不透明,灰表示半透明。混合的英文术语为Blending,是计算机图形学中常用的一种技术,即混合像素。我们通常用已经光栅化的像素光栅化同一位置的像素,或者说是在某图元上混合图元。
Direct3D中的融合因子
在Direct3D中,使用Alpha通道来实现多个像素颜色值的融合。每个像素都包含四个分量:Alpha,红色分量,绿色分量和蓝色分量。其中,Alpha分量用于指定像素的透明度,在0~255之间取值。根据不同的颜色宏的区别,也有可能是在0.0~1.0之间在Direct3D中,融合这一领域有一个权威,那便是Alpha融合公式。Alpha融合公式如下:
OutPutColor=(RGBsrc×Ksrc)op(RGBdst×Kdst);
其中,RGBsrc和RGBdst分别表示源像素和目标像素的颜色值,为包含四个颜色分量的颜色值。Ksrc和Kdst分别表示源融合因子和目标融合因子。它们指定了源像素和目标像素的颜色值在融合过程中所占的比例,在[0,1]之间取值。通过源融合因子和目标融合因子,我们能够以多种方式来修改源像素和目标像素的颜色值,从而获得我们满意的最终融合后的颜色值。
OP表示源和目标的融合运算方式,由D3DBLENDOP枚举体来指定,需要注意的是,它的默认值是源计算结果和目标计算结果相加。
融合运算方式的取法
我们在SetRenderState中设置参数,第二个参数在D3DBLENDOP枚举体中取值,而第一个参数取D3DRS_BLENDOPD3DBLENDOP枚举体的定义如下:
typedef enum D3DBLENDOP{ D3DBLENDOP_ADD = 1, D3DBLENDOP_SUB = 2, D3DBLENDOP_REVSUBTRACT = 3, D3DBLENDOP_MIN = 4, D3DBLENDOP_MAX = 5, D3DBLENDOP_FORCE_DWORD = 0x7fffffff }D3DBLENDOP,*LPD3DBLENDOP;
D3DBLENDOP_ADD:源像素计算结果与目标像素计算结果相加。即【最终结果】=【源】+【目标】
D3DBLENDOP_SUBTRACT:源像素计算结果与目标像素计算结果相减。即【最终结果】=【源】-【目标】
D3DBLENDOP_REVSUBTRACT:目标像素的计算结果与源像素计算结果相减。即【最终结果】=【目标】-【源】
D3DBLENDOP_MIN:在源像素计算结果和目标像素计算结果之间取小者。即【最终结果】=MIN(【源】,【目标】)
D3DBLENDOP_MAX:在源像素计算结果和目标像素计算结果之间取大者。即【最终结果】=MAX(【源】,【目标】)
融合因子取法
源融合因子和目标融合因子可以在SetRenderState方法中第一个参数取D3DRS_SRCBLEND和D3DRS_DESTBLEND分别进行设置,而第二个参数都是在一个D3DBLEND枚举体中进行的取值,它的原型如下:typedef enum D3DBLEND { D3DBLEND_ZERO = 1, D3DBLEND_ONE = 2, D3DBLEND_SRCCOLOR = 3, D3DBLEND_INVSRCCOLOR = 4, D3DBLEND_SRCALPHA = 5, D3DBLEND_INVSRCALPHA = 6, D3DBLEND_DESTALPHA = 7, D3DBLEND_INVDESTALPHA = 8, D3DBLEND_DESTCOLOR = 9, D3DBLEND_INVDESTCOLOR = 10, D3DBLEND_SRCALPHASAT = 11, D3DBLEND_BOTHSRCALPHA = 12, D3DBLEND_BOTHINVSRCALPHA = 13, D3DBLEND_BLENDFACTOR = 14, D3DBLEND_INVBLENDFACTOR = 15, D3DBLEND_SRCCOLOR2 = 16, D3DBLEND_INVSRCCOLOR2 = 17, D3DBLEND_FORCE_DWORD = 0x7fffffff } D3DBLEND, *LPD3DBLEND;
下面通过一个表格来叙述融合因子的含义
* D3DBLEND_ZERO:融合因子(0,0,0,0)
* D3DBLEND_ONE:融合因子(1,1,1,1)
* D3DBLEND_SRCCOLOR:融合因子(Rsrc,Gsrc,Bsrc,Asrc)
* D3DBLEND_INVSRCCOLOR:融合因子(1-Rsrc,1-Gsrc,1-Bsrc,1-Asrc)
* D3DBLEND_SRCALPHASAT:融合因子(1-Asrc,Asrc,Asrc,Asrc)
* D3DBLEND_INVSRCALPHA:融合因子(1-Asrc,1-Asrc,1-Asrc,1-Asrc)
* D3DBLEND_DESTALPHA:融合因子(Adst,Adst,Adst,Adst)
* D3DBLEND_INVDESTALPHA:融合因子(1-Adst,1-Adst,1-Adst,1-Adst)
* D3DBLEND_DESTCOLOR:融合因子(Rdst,Gdst,Bdst,Adst)
* D3DBLEND_INVDESTCOLOR:融合因子(1-Rdst,1-Gdst,1-Bdst,1-Adst)
* D3DBLEND_SRCALPHASAT:融合因子(f,f,f,1),其中f=min(Asrc,1-Asrc)
Alpha的三处来源
源像素和目标像素颜色值的Alpha分量分别来自顶点颜色的Alpha值,材质的Alpha值,纹理的Alpha值。我们通常在这三处源取一处就可以了。它们的优先级如下纹理>材质>顶点颜色
我们可以通过IDirect3DDevice9::SetTextureStageState方法指定Alpha值的来源,它的原型如下
HRESULT SetTextureStageState( [in] DWORD Stage, [in] D3DTEXTURESTAGESTATETYPE Type, [in] DWORD Value );
DWORD Stage:指定当前设置的纹理层为第几层(0~7)
D3DTEXTURESTAGESTATETYPE Type:填将要设置的纹理渲染状态,在枚举类型D3DTEXTURESTAGESTATETYPE中任意取值。
DWORD Value:表示所设置的状态值,它是根据第二个参数来决定具体取什么值的。
顶点的Alpha分量
如果在程序中指定每个顶点的颜色,那么可以直接给出每个顶点颜色的Alpha值,并且这些顶点的Alpha值是可以在程序运行过程中动态修改的。对于顶点Alpha分量,我们就这样写:
g_pd3dDevice->SetTextureStageState(0,D3DTSS_ALPHAARG1,D3DTA_DIFFUSE); g_pd3dDevice->SetTextureStageState(0,D3DTSS_ALPHAOP,D3DTOP_SELECTARG1);
材质的Alpha分量
场景中物体没有指定纹理的时候,才会启用材质的Alpha分量。在这种情况下,顶点的Alpha值取决于材质属性中漫反射颜色的Alpha系数以及灯光颜色中的Alpha系数,通过材质和光照中的Alpha系数相互作用,计算得到。我们可以这样来设定某材质的Alpha分量值,这句代码中,我们把这种材质的漫反射颜色值的Alpha分量设为了0.2g_pMaterials.Diffuse.a=0.2f;
纹理的Alpha分量
作为不可一世的“高富帅”——纹理,既然它在物体表面上使用了,就必须首先满足它的要求,那么,像素的Alpha值就是纹理Alpha混合之后的值了。所以这时候混合后的像素就取决于纹理的Alpha混合方式。而纹理Alpha混合方式决定了纹理Alpha混合之后的Alpha值是取自材质,还是取自纹理,抑或是取自这两者的某种运算。若是取自纹理,我们就这样写:
g_pd3dDevice->SetTextureStageState(0,D3DTSS_ALPHAARG1,D3DTA_TEXTURE);//Alpha提取自纹理 g_pd3dDevice->SetTextureStageState(0,D3DTSS_ALPHAOP,D3DTOP_SELECTARG1);//将纹理颜色混合的第一个参数的Alpha值用于输出
Alpha融合使用方法
启用Alpha融合要启用Alpha融合,我们可以通过设置D3DRS_ALPHABLENDENABLE渲染状态为true,即写上这句代码:
g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,true);
设置融合因子
启用了Alpha融合,第二步便是设置源融合因子和目标融合因子。源融合因子和目标融合因子可以分别在SetRenderState方法中第一个参数取D3DRS_SRCBLEND和D3DRS_DESTBLEND分别进行设置,第二个参数是在一个D3DBLEND枚举体中取值
g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA); g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA);
设置Alpha融合运算方式
g_pd3dDevice->SetRenderState(D3DRS_BLENDOP,D3DBLENDOP_SUBTRACT);
示例代码
#include<Windows.h> #include<d3dx9.h> #include<d3d9.h> #include<time.h> #include"DirectInput.h" #pragma comment(lib,"d3dx9.lib") #pragma comment(lib,"winmm.lib") #pragma comment(lib,"dxerr.lib") #pragma comment(lib,"dxguid.lib") #pragma comment(lib,"d3dx10.lib") #pragma comment(lib,"d3d9.lib") #pragma comment(lib,"comctl32.lib") #define SAFE_RELEASE(p) {if((p)){(p)->Release();(p)=NULL;}} struct CUSTOMVERTEX { FLOAT _x, _y, _z; FLOAT _u, _v; CUSTOMVERTEX(FLOAT x, FLOAT y, FLOAT z, FLOAT u, FLOAT v) :_x(x),_y(y),_z(z),_u(u),_v(v) { } }; #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_TEX1) //全局变量声明区 const int WINDOW_WIDTH = 800; const int WINDOW_HEIGHT = 600; IDirect3DDevice9 *g_pd3dDevice = NULL; LPD3DXFONT g_pTextFPS = NULL; //字体COM接口 LPD3DXFONT g_pTextAdapterName = NULL; //显卡信息的2D文本 LPD3DXFONT g_pTextHelper = NULL; //帮助信息的2D文本 LPD3DXFONT g_pTextInfo = NULL; //绘制信息的2D文本 float g_FPS = 0.0f; //一个浮点数,表示帧率 wchar_t g_strFPS[50] = { 0 }; //包含帧速率的字符数组 wchar_t g_strAdapterName[60] = { 0 };//包含显卡名称的字符数组 D3DXMATRIX g_matWorld; //世界矩阵 LPDIRECT3DVERTEXBUFFER9 g_pVertexBuffer = NULL; //顶点缓存数组 LPDIRECT3DINDEXBUFFER9 g_pIndexBuffer = NULL; //索引缓存数组 D3DMATERIAL9 *g_pMaterials=NULL; LPDIRECT3DTEXTURE9 *g_pTextures = NULL; DWORD g_dwNumMtrls; LPD3DXMESH g_pMesh = NULL; LPDIRECT3DTEXTURE9 g_pMipTexture = NULL; //纹理接口对象 DInputClass *g_pDInput = NULL; //一个DInputClass对象 HRESULT Direct3D_Init(HWND hwnd); HRESULT Object_Init(); VOID Direct3D_Update(HWND hwnd); VOID Direct3D_Render(HWND hwnd); VOID Direct3D_CleanUp(HWND hwnd); VOID Matrix_Set(); float GET_FPS(); LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow) { WNDCLASSEX wc = { 0 }; wc.cbClsExtra = 0; wc.cbSize = sizeof(WNDCLASSEX); wc.cbWndExtra = 0; wc.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hIcon = NULL; wc.hIconSm = NULL; wc.hInstance = hInstance; wc.lpfnWndProc = WndProc; wc.lpszClassName = L"MainWindow"; wc.lpszMenuName = NULL; wc.style = CS_HREDRAW | CS_VREDRAW; RegisterClassEx(&wc); HWND hwnd = CreateWindow(L"MainWindow", L"寒江雪", WS_OVERLAPPED, CW_USEDEFAULT, CW_USEDEFAULT, WINDOW_WIDTH, WINDOW_HEIGHT, NULL, NULL, hInstance, NULL); if (S_OK == Direct3D_Init(hwnd)) { MessageBox(hwnd, L"DirectX3D 初始化完成", L"寒江雪消息窗口", 0); } g_pDInput = new DInputClass(); g_pDInput->Init(hwnd, hInstance, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE); PlaySound(L"Through the Arbor.wav", NULL, SND_FILENAME | SND_ASYNC | SND_LOOP); //循环播放背景音乐 ShowWindow(hwnd, SW_SHOW); UpdateWindow(hwnd); MSG msg = { 0 }; while (msg.message != WM_QUIT) { if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { Direct3D_Update(hwnd); Direct3D_Render(hwnd); } } UnregisterClass(L"MainWindow", hInstance); return 0; } HRESULT Direct3D_Init(HWND hwnd) { LPDIRECT3D9 d3d9 = NULL; d3d9 = Direct3DCreate9(D3D_SDK_VERSION); if (d3d9 == NULL) return E_FAIL; D3DCAPS9 caps; int vp = 0; if (FAILED(d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps))) return E_FAIL; if (caps.DevCaps&D3DDEVCAPS_HWTRANSFORMANDLIGHT) vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;//支持顶点运算 else vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING; D3DPRESENT_PARAMETERS d3dpp; ZeroMemory(&d3dpp, sizeof d3dpp); d3dpp.BackBufferWidth = WINDOW_WIDTH; d3dpp.BackBufferHeight = WINDOW_HEIGHT; d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8; d3dpp.BackBufferCount = 2; d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE; d3dpp.MultiSampleQuality = 0; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.hDeviceWindow = hwnd; d3dpp.Windowed = true; d3dpp.EnableAutoDepthStencil = true; d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8; d3dpp.Flags = 0; d3dpp.FullScreen_RefreshRateInHz = 0; d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; if (FAILED(d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,vp, &d3dpp, &g_pd3dDevice))) return E_FAIL; ////////////////////////////////// //获取显卡信息 wchar_t TempName[60] = L"当前显卡号:"; D3DADAPTER_IDENTIFIER9 Adapter;//定义一个D3DADAPTER_IDENTIFIER9结构体,用于存储显卡信息 d3d9->GetAdapterIdentifier(D3DADAPTER_DEFAULT, 0, &Adapter);//调用GetAdapterIdentifier,获取显卡信息 int len = MultiByteToWideChar(CP_ACP, 0, Adapter.Description, -1, NULL, 0); MultiByteToWideChar(CP_ACP, 0, Adapter.Description, -1, g_strAdapterName, len); wcscat_s(TempName, g_strAdapterName); wcscpy_s(g_strAdapterName, TempName); SAFE_RELEASE(d3d9); if (FAILED(Object_Init())) return E_FAIL; return S_OK; } #include<tchar.h> HRESULT Object_Init() { D3DXCreateFont(g_pd3dDevice, 36, 0, 0, 1000, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, 0, _T("Calibri"), &g_pTextFPS); D3DXCreateFont(g_pd3dDevice, 20, 0, 1000, 0, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, 0, L"楷体", &g_pTextAdapterName); D3DXCreateFont(g_pd3dDevice, 23, 0, 1000, 0, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, 0, L"楷体", &g_pTextHelper); D3DXCreateFont(g_pd3dDevice, 26, 0, 1000, 0, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, 0, L"楷体", &g_pTextInfo); //从X文件中加载网格数据 LPD3DXBUFFER pAdjBuffer = NULL; LPD3DXBUFFER pMtrlBuffer = NULL; D3DXLoadMeshFromX(L"miki.X", D3DXMESH_MANAGED, g_pd3dDevice, &pAdjBuffer, &pMtrlBuffer, NULL,&g_dwNumMtrls,&g_pMesh); //读取材质和纹理数据 D3DXMATERIAL *pMtrls = (D3DXMATERIAL*)pMtrlBuffer->GetBufferPointer(); g_pMaterials = new D3DMATERIAL9[g_dwNumMtrls]; g_pTextures = new LPDIRECT3DTEXTURE9[g_dwNumMtrls]; for (DWORD i = 0; i < g_dwNumMtrls; i++) { g_pMaterials[i] = pMtrls[i].MatD3D; //g_pMaterials[i].Ambient = g_pMaterials[i].Diffuse; g_pMaterials[i].Specular = g_pMaterials[i].Diffuse; //创建下一纹理 g_pTextures[i] = NULL; //D3DXCreateTextureFromFileA(g_pd3dDevice, pMtrls[i].pTextureFilename, &g_pTextures[i]); } SAFE_RELEASE(pAdjBuffer); SAFE_RELEASE(pMtrlBuffer); D3DLIGHT9 light; ::ZeroMemory(&light, sizeof(D3DLIGHT9)); light.Type = D3DLIGHT_DIRECTIONAL; light.Ambient= D3DXCOLOR(0.5f, 0.5f, 0.5f, 1.0f); light.Diffuse= D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f); light.Specular= D3DXCOLOR(1.0f,1.0f,1.0f,1.0f ); light.Direction = D3DXVECTOR3(0,0, 1.0f); g_pd3dDevice->SetLight(0, &light); g_pd3dDevice->LightEnable(0, true); g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); g_pd3dDevice->SetRenderState(D3DRS_NORMALIZENORMALS, true);//初始化顶点法向量 g_pd3dDevice->SetRenderState(D3DRS_SPECULARENABLE, true); g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);//开启背面消隐 g_pd3dDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESS);//将深度测试函数设为D3DCMP_LESS g_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, true);//深度测试成功后,更新深度缓存 //g_pd3dDevice->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_XRGB(36, 36, 36));//设置环境光 //开启Alpha融合 g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true); //设置融合因子 g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); //设置融合运算方式 g_pd3dDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); //各项异性过滤 g_pd3dDevice->SetSamplerState(0, D3DSAMP_MAXANISOTROPY, 3); g_pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_ANISOTROPIC); g_pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC); return S_OK; } VOID Direct3D_Update(HWND hwnd) { g_pDInput->GetInput(); static FLOAT fPosX = 0.0f; static FLOAT fPosY = 0.0f; static FLOAT fPosZ = 0.0f; if (g_pDInput->GetKeyDown(DIK_1)) { for (DWORD i = 0; i < g_dwNumMtrls; i++) { g_pMaterials[i].Diffuse.a += 0.001; } } if (g_pDInput->GetKeyDown(DIK_2)) { for (DWORD i = 0; i < g_dwNumMtrls; i++) { g_pMaterials[i].Diffuse.a -= 0.001; } } if (g_pDInput->GetMouseButtonDown(0)) { fPosX += (g_pDInput->MouseX())*0.08f; fPosY += (g_pDInput->MouseY())*-0.08f; } //鼠标滚轮,为观察点收缩操作 fPosZ += (g_pDInput->MouseZ())*0.02f; //键盘按键控制物体的平移 if (g_pDInput->GetKeyDown(DIK_A))fPosX -= 0.005f; if (g_pDInput->GetKeyDown(DIK_D))fPosX += 0.005; if (g_pDInput->GetKeyDown(DIK_W))fPosY += 0.005f; if (g_pDInput->GetKeyDown(DIK_S))fPosY -= 0.005; D3DXMatrixTranslation(&g_matWorld, fPosX, fPosY, fPosZ); //按住鼠标右键并拖动,为旋转操作 static FLOAT fAngleX = D3DX_PI/6, fAngleY = D3DX_PI / 6; if (g_pDInput->GetMouseButtonDown(1)) { fAngleX += (g_pDInput->MouseX())*-0.01f; fAngleY += (g_pDInput->MouseY())*0.01f; } //键盘按键旋转物体 if (g_pDInput->GetKeyDown(DIK_UP))fAngleX += 0.005f; if (g_pDInput->GetKeyDown(DIK_DOWN))fAngleX -= 0.005f; if (g_pDInput->GetKeyDown(DIK_LEFT))fAngleY += 0.005f; if (g_pDInput->GetKeyDown(DIK_RIGHT))fAngleY -= 0.005f; D3DXMATRIX Rx, Ry; D3DXMatrixRotationX(&Rx, fAngleX); D3DXMatrixRotationY(&Ry, fAngleY); g_matWorld = Rx*Ry*g_matWorld; g_pd3dDevice->SetTransform(D3DTS_WORLD, &g_matWorld); Matrix_Set(); return VOID(); } VOID Direct3D_Render(HWND hwnd) { g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,D3DCOLOR_XRGB(100,100,100),1.0f,0.0f); RECT formatrect; GetClientRect(hwnd,&formatrect); //开始绘制 g_pd3dDevice->BeginScene(); for (DWORD i = 0; i < g_dwNumMtrls; i++) { g_pd3dDevice->SetMaterial(&g_pMaterials[i]); g_pd3dDevice->SetTexture(0,g_pTextures[i]); g_pMesh->DrawSubset(i); } //在窗口右上角处,显示每秒帧数 int charCount = swprintf(g_strFPS, 20, _T("FPS:%0.3f"), GET_FPS()); g_pTextFPS->DrawText(NULL, g_strFPS, charCount, &formatrect, DT_TOP | DT_RIGHT, D3DCOLOR_XRGB(0, 239, 136, 255)); //显示显卡类型名 g_pTextAdapterName->DrawText(NULL, g_strAdapterName, -1, &formatrect, DT_TOP | DT_LEFT, D3DXCOLOR(1.0f,0.5f,0.0f,1.0f)); //输出绘制信息 formatrect.top = 30; static wchar_t strInfo[256] = { 0 }; swprintf_s(strInfo, -1, L"模型横坐标:(%.2f,%.2f,%.2f)", g_matWorld._41, g_matWorld._42, g_matWorld._43); g_pTextInfo->DrawText(NULL, strInfo, -1, &formatrect, DT_SINGLELINE | DT_NOCLIP | DT_LEFT, D3DXCOLOR(135, 239, 136, 255)); formatrect.left = 0; formatrect.top = 380; g_pTextHelper->DrawText(NULL, L"控制说明:", -1, &formatrect, DT_SINGLELINE | DT_NOCLIP | DT_LEFT, D3DCOLOR_RGBA(235, 123, 230, 255)); formatrect.top += 25; g_pTextHelper->DrawText(NULL, L"按住鼠标左键并拖动,平移模型", -1, &formatrect, DT_SINGLELINE | DT_NOCLIP | DT_LEFT, D3DCOLOR_RGBA(235, 123, 230, 255)); formatrect.top += 25; g_pTextHelper->DrawText(NULL, L"按住鼠标右键并拖动,旋转模型", -1, &formatrect, DT_SINGLELINE | DT_NOCLIP | DT_LEFT, D3DCOLOR_RGBA(235, 123, 230, 255)); formatrect.top += 25; g_pTextHelper->DrawText(NULL, L"滑动鼠标滚轮:拉伸模型", -1, &formatrect, DT_SINGLELINE | DT_NOCLIP | DT_LEFT, D3DCOLOR_RGBA(235, 123, 230, 255)); formatrect.top += 25; g_pTextHelper->DrawText(NULL, L"W,S,A,D键:平移模型", -1, &formatrect, DT_SINGLELINE | DT_NOCLIP | DT_LEFT, D3DCOLOR_RGBA(235, 123, 230, 255)); formatrect.top += 25; g_pTextHelper->DrawText(NULL, L"上下左右方向键:旋转模型", -1, &formatrect, DT_SINGLELINE | DT_NOCLIP | DT_LEFT, D3DCOLOR_RGBA(235, 123, 230, 255)); formatrect.top += 25; g_pTextHelper->DrawText(NULL, L"键盘上1,2,3,4数字键:在四种寻址模式之间切换", -1, &formatrect, DT_SINGLELINE | DT_NOCLIP | DT_LEFT, D3DCOLOR_RGBA(235, 123, 230, 255)); formatrect.top += 25; g_pTextHelper->DrawText(NULL, L"ESC 键盘:退出程序", -1, &formatrect, DT_SINGLELINE | DT_NOCLIP | DT_LEFT, D3DCOLOR_RGBA(235, 123, 230, 255)); g_pd3dDevice->EndScene(); g_pd3dDevice->Present(NULL, NULL, NULL, NULL); return VOID(); } VOID Direct3D_CleanUp(HWND hwnd) { if (g_pDInput)delete g_pDInput; SAFE_RELEASE(g_pIndexBuffer); SAFE_RELEASE(g_pVertexBuffer); SAFE_RELEASE(g_pTextAdapterName); SAFE_RELEASE(g_pTextHelper); SAFE_RELEASE(g_pTextInfo); SAFE_RELEASE(g_pTextFPS); SAFE_RELEASE(g_pd3dDevice); return VOID(); } VOID Matrix_Set() { D3DXMATRIX view;//取景变换矩阵 D3DXMATRIX projection;//投影变换矩阵 D3DVIEWPORT9 vp;//视口变换 D3DXVECTOR3 vEye(0.0f, 0.0f, -50.0f);//摄像机的位置 D3DXVECTOR3 vAt(0.0f, 0.0f, 0.0f);//观察点的位置 D3DXVECTOR3 vUp(0.0f, 1.0f, 0.0f);//向上的向量 //取景变换矩阵的设置 D3DXMatrixLookAtLH(&view,&vEye,&vAt,&vUp); g_pd3dDevice->SetTransform(D3DTS_VIEW, &view); //投影变换矩阵 D3DXMatrixPerspectiveFovLH(&projection, D3DX_PI / 4.0f, (float)((double)WINDOW_WIDTH / WINDOW_HEIGHT), 1.0f, 1000.0f); g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &projection); //设置视口变换 vp.Width = WINDOW_WIDTH; vp.Height = WINDOW_HEIGHT; vp.X = 0; vp.Y = 0; vp.MinZ = 0; vp.MaxZ = 1; g_pd3dDevice->SetViewport(&vp); return VOID(); } float GET_FPS() { static float fps = 0; //我们需要计算的FPS值 static int frameCount = 0;//帧数 static float currentTime = 0.0f;//当前时间 static float lastTime = 0.0f;//持续时间 frameCount++; currentTime = timeGetTime()*0.001f; if (currentTime - lastTime > 1.0f) { fps = (float)frameCount / (currentTime - lastTime); lastTime = currentTime; frameCount = 0; } return fps; return 0.0f; } LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_PAINT: Direct3D_Render(hwnd); ValidateRect(hwnd, NULL); break; case WM_DESTROY: Direct3D_CleanUp(hwnd); PostQuitMessage(0); break; case WM_KEYDOWN: if (wParam == VK_ESCAPE) DestroyWindow(hwnd); break; default: return DefWindowProc(hwnd, message, wParam, lParam); } //return LRESULT(); }
Copyright© by 寒江雪
Date:2016.12.23
相关文章推荐
- 【Visual C++】游戏开发五十五 浅墨DirectX教程二十二 水乳交融的美学:alpha混合技术
- Alpha混合技术——unity
- 【Visual C++】游戏开发五十五 浅墨DirectX教程二十二 水乳交融的美学:alpha混合技术
- DirectX 3D_基础之融合技术 融合因子 透明度 Alpha通道 模板缓存 模板缓存的使用 模板测试
- 关于携带完整alpha通道图标的技术研究
- 关于携带完整 alpha 通道图标的技术研究
- Windows的位图alpha混合技术
- 【Visual C++】游戏开发五十五 浅墨DirectX教程二十二 水乳交融的美学:alpha混合技术
- 《逐梦旅程 WINDOWS游戏编程之从零开始》笔记8——载入三维模型&Alpha混合技术&深度测试与Z缓存
- alpha混合技术
- alpha混合技术
- 【Unity Shaders】Transparency —— 使用alpha通道创建透明效果
- 水面Alpha混合与边界柔和
- 办公室的“技术达人” alpha geek
- unity游戏优化之ETC压缩和 Alpha通道处理
- 关于Unity中混合模式、Alpha测试、深度测试、通道遮罩、面剔除的使用----渲染通道通用指令(二)
- Alpha混合
- 转载-Alpha通道实现
- 学习@浅墨_毛星云【OpenCV入门教程之五】 分离颜色通道&多通道图像混合
- 关于 cvSlite 和cvMerge 实现图像的通道分离和混合的说明