1.融合方程
首先绘制那些不需要融合的物体,然后将需要融合的物体按照相对于摄像机的深度进行排序。
融合后的颜色=源像素颜色值*源融合因子 + 目标像素颜色值*目标融合因子
Direct3D默认下是禁用融合运算的,以下方法可开启融合运算。
Device->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
2.通过设置绘制状态,可以设置源融合因子和目标融合因子。
Device->SetRenderState(D3DRS_SRCBLEND, value);
Device->SetRenderState(D3DRS_DESTBLEND, value);
3.透明度
Alpha分量主要用于指定像素的透明度。
默认情况下,如果当前设置的纹理拥有一个Alpha通道,Alpha值取自Alpha通道;如果没有Alpha通道,Alpha值取自顶点颜色。我们可以用绘制状态来指定Alpha的来源
Device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
Device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
如下:在后台缓存图片上显示一个半透明的三角形。
#include "d3dUtility.h" IDirect3DDevice9* Device = 0; //设备 //ID3DXMesh * teapot=0; //D3DMATERIAL9 teapotMaterial; const int Width = 640; const int Height = 480; IDirect3DVertexBuffer9* bkVb = 0; //后台顶点缓存 IDirect3DTexture9 * bkTex=0; //后台纹理 D3DMATERIAL9 bkMaterial; //后台材质 IDirect3DVertexBuffer9 * fnVb=0; //前置三角形 D3DMATERIAL9 fnMaterial; struct Vertex //顶点结构:位置、顶点法线和纹理 { Vertex(){} Vertex(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; } float _x, _y, _z; float _nx,_ny,_nz; float _u,_v; static const DWORD FVF; }; const DWORD Vertex::FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1; struct fnVertex { fnVertex(){} fnVertex(float x,float y,float z,D3DCOLOR c) { _x=x;_y=y;_z=z;_c=c; } float _x,_y,_z; D3DCOLOR _c; static const DWORD FVF; }; const DWORD fnVertex::FVF=D3DFVF_XYZ | D3DFVF_DIFFUSE; // // Framework Functions // bool Setup() { fnMaterial=d3d::Red_Mtrl; fnMaterial.Diffuse.a=0.5f; Device->CreateVertexBuffer( //创建顶点缓存 12 * sizeof(Vertex), // size in bytes D3DUSAGE_WRITEONLY, // flags Vertex::FVF, // vertex format D3DPOOL_MANAGED, // managed memory pool &bkVb, // return create vertex buffer 0); // not used - set to 0 Vertex* vertices; bkVb->Lock(0, 0, (void**)&vertices, 0); //获取指向顶点缓存内容的指针 vertices[0] = Vertex(-10.0f, -10.0f, 5.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f); vertices[1] = Vertex(-10.0f, 10.0f, 5.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f); vertices[2] = Vertex( 10.0f, 10.0f, 5.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f); vertices[3] = Vertex(-10.0f, -10.0f, 5.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f); vertices[4] = Vertex( 10.0f, 10.0f, 5.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f); vertices[5] = Vertex( 10.0f, -10.0f, 5.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f); bkVb->Unlock(); Device->CreateVertexBuffer(3*sizeof(fnVertex),D3DUSAGE_WRITEONLY,fnVertex::FVF,D3DPOOL_MANAGED,&fnVb,0); fnVertex* v; fnVb->Lock(0, 0, (void**)&v, 0); v[0] = fnVertex(-1.0f, 0.0f, 2.0f, D3DCOLOR_ARGB(128,255, 0, 0)); v[1] = fnVertex( 0.0f, 1.0f, 2.0f, D3DCOLOR_ARGB(128, 0, 255, 0)); v[2] = fnVertex( 1.0f, 0.0f, 2.0f, D3DCOLOR_ARGB(128, 0, 0, 255)); fnVb->Unlock(); Device->SetRenderState(D3DRS_LIGHTING, false); //---begin light D3DLIGHT9 light; memset(&light,0,sizeof(light)); light.Type = D3DLIGHT_DIRECTIONAL; light.Diffuse = d3d::WHITE; light.Specular = d3d::WHITE * 0.2f; light.Ambient = d3d::WHITE * 0.6f; light.Direction = D3DXVECTOR3(0.707f, 0.0f, 0.707f); Device->SetLight(0,&light); Device->LightEnable(0,true); Device->SetRenderState(D3DRS_NORMALIZENORMALS, true); Device->SetRenderState(D3DRS_SPECULARENABLE, true); //---end light //---begin texture D3DXCreateTextureFromFile(Device,"crate.jpg",&bkTex); //加载纹理图像, Device->SetTexture(0,bkTex); //设置当前纹理 Device->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR); //线性纹理过滤器设置为放大过滤器 Device->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_LINEAR); //线性纹理过滤器设置为缩小过滤器 Device->SetSamplerState(0,D3DSAMP_MIPFILTER,D3DTEXF_POINT); //多级渐进纹理过滤器,选择与屏幕尺寸最接近的那一级纹理 //---end texture // use alpha in material's diffuse component for alpha Device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); Device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); // set blending factors so that alpha component determines transparency Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); // // Set camera. // D3DXVECTOR3 pos(0.0f, 0.0f, -3.0f); D3DXVECTOR3 target(0.0f, 0.0f, 0.0f); D3DXVECTOR3 up(0.0f, 1.0f, 0.0f); D3DXMATRIX V; D3DXMatrixLookAtLH(&V, &pos, &target, &up); Device->SetTransform(D3DTS_VIEW, &V); D3DXMATRIX proj; D3DXMatrixPerspectiveFovLH( //投影矩阵 &proj, D3DX_PI * 0.5f, // 90 - degree (float)Width / (float)Height, 1.0f, 1000.0f); Device->SetTransform(D3DTS_PROJECTION, &proj); //投影 return true; } void Cleanup() { d3d::Release<IDirect3DVertexBuffer9*>(bkVb); d3d::Release<IDirect3DTexture9*>(bkTex); d3d::Release<IDirect3DVertexBuffer9*>(fnVb); } bool Display(float timeDelta) { if( Device ) { Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0); Device->BeginScene(); //draw 背景图 D3DXMATRIX w; D3DXMatrixIdentity(&w); Device->SetTransform(D3DTS_WORLD, &w); Device->SetFVF(Vertex::FVF); Device->SetStreamSource(0, bkVb, 0, sizeof(Vertex)); Device->SetMaterial(&bkMaterial); Device->SetTexture(0, bkTex); Device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2); //draw 三角形 Device->SetRenderState(D3DRS_ALPHABLENDENABLE, true); //D3DXMatrixScaling(&w, 105.0f,105.0f, 105.0f); Device->SetFVF(fnVertex::FVF); Device->SetStreamSource(0, fnVb, 0, sizeof(fnVertex)); Device->SetMaterial(&fnMaterial); Device->SetTexture(0, 0); Device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1); Device->SetRenderState(D3DRS_ALPHABLENDENABLE, false); 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; }