Direct3D_Init()函数—创建模板缓冲区
//--------------------------------------------------------------------------------------
// 【Direct3D初始化四步曲之三,填内容】:填充D3DPRESENT_PARAMETERS结构体
//--------------------------------------------------------------------------------------
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.BackBufferWidth = SCREEN_WIDTH;
d3dpp.BackBufferHeight = SCREEN_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;
Direct3D_Render()函数部分代码
//-----------------------------------【Direct3D_Render( )函数】-------------------------------
// 描述:使用Direct3D进行渲染
//--------------------------------------------------------------------------------------------------
void Direct3D_Render(HWND hwnd)
{
//1. 清空模板缓存
//--------------------------------------------------------------------------------------
// 【Direct3D渲染五步曲之一】:清屏操作
//--------------------------------------------------------------------------------------
//0: 下一个参数所指向的矩形数组中的矩形数量
//NULL: 要清空的目标矩形区域
//D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL:要清空的缓冲区组合---模板缓冲区|深度缓冲区|颜色缓冲区
//D3DCOLOR_XRGB(100, 150, 0): 清空颜色缓冲区后每个像素对应的颜色值
//1.0f: 清空深度缓冲区后每个像素对应的深度值
//0: 清空模板缓冲区后每个像素对应的模板值
g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL, D3DCOLOR_XRGB(100, 150, 0), 1.0f, 0);
//定义一个矩形,用于获取主窗口矩形
RECT formatRect;
GetClientRect(hwnd, &formatRect);
//2. 进行常规物体的绘制
//--------------------------------------------------------------------------------------
// 【Direct3D渲染五步曲之二】:开始绘制
//--------------------------------------------------------------------------------------
g_pd3dDevice->BeginScene(); // 开始绘制
//--------------------------------------------------------------------------------------
// 【Direct3D渲染五步曲之三】:正式绘制
//--------------------------------------------------------------------------------------
D3DXMATRIX matHero,matWorld,matRotation; //定义一些矩阵
//绘制3D模型
D3DXMatrixTranslation(&matHero, -20.0f, 0.0f, -25.0f);
matHero=matHero*g_matWorld;
g_pd3dDevice->SetTransform(D3DTS_WORLD, &matHero);//设置模型的世界矩阵,为绘制做准备
// 用一个for循环,进行模型的网格各个部分的绘制
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); //绘制此部分
}
// 绘制出墙面
D3DXMatrixTranslation(&matWorld, 0.0f,0.0f,0.0f); //给墙面的世界矩阵初始化
g_pd3dDevice->SetTransform(D3DTS_WORLD, &matWorld); //设置墙面的世界矩阵
g_pd3dDevice->SetMaterial(&g_MaterialsWall); //设置材质
g_pMeshWall->DrawSubset(0); //绘制墙面
//3. 启用模板缓存,以及对相关的绘制状态进行设置。
g_pd3dDevice->SetRenderState(D3DRS_STENCILENABLE, true); //启用模板处理
g_pd3dDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS); //模板测试的比较函数,总是返回TRUE
g_pd3dDevice->SetRenderState(D3DRS_STENCILREF, 0x1); //模板参考值
g_pd3dDevice->SetRenderState(D3DRS_STENCILMASK, 0xffffffff); //模板掩码
g_pd3dDevice->SetRenderState(D3DRS_STENCILWRITEMASK, 0xffffffff); //写入到模板缓冲区中的数值的掩码
//目标测试通过时进行的模板操,用模板参考值替换模板缓冲区中对应的值
g_pd3dDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
// 4.进行融合操作,以及禁止向深度缓存和后台缓存写数据
g_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, false); //关闭向深度缓存中写操作
g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true); //启用融合操作
g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO); //源融合因子,将模板缓冲区中的值设为0,(0, 0, 0, 0)
g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); //目标融合因子,(1, 1, 1, 1)
// 5.绘制出作为镜面的区域
D3DXMatrixTranslation(&matWorld, 0.0f, 0.0f, 0.0f); //镜面区域的世界矩阵初始化
g_pd3dDevice->SetTransform(D3DTS_WORLD, &matWorld); //设置镜面的世界矩阵
g_pd3dDevice->SetMaterial(&g_MaterialsWall); //设置材质
g_pMeshWall->DrawSubset(0); //绘制镜面
// 6.重新设置一系列渲染状态,将镜像与镜面进行融合运算,并清理一下Z缓存
g_pd3dDevice->Clear(0, 0, D3DCLEAR_ZBUFFER, 0, 1.0f, 0); //清空Z缓存,因为接下来所绘制镜像的深度值大于镜面
g_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, true); //打开深度缓存的写操作
g_pd3dDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_EQUAL); //设置比较函数
g_pd3dDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP); //当模板测试通过时,保留目标缓冲中原来的值
g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_DESTCOLOR); //源融合因子,(Rs, Gs, Bs, As)
g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO); //目标融合因子,(0, 0, 0, 0)
g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW); //关闭背面消隐
//7. 计算镜像变换矩阵
D3DXMATRIX matReflect;
D3DXPLANE planeXY(0.0f, 0.0f, 1.0f, 0.0f); // xy平面 0*x + 0*y + 0*z = 0
D3DXMatrixReflect(&matReflect, &planeXY); // 计算xy平面的镜像变换矩阵
matWorld = matReflect * matHero; // 镜中人物的世界矩阵
//8.绘制镜子中的3D模型
g_pd3dDevice->SetTransform(D3DTS_WORLD, &matWorld);//设置模型的世界矩阵,为绘制做准备
// 用一个for循环,进行模型的网格各个部分的绘制
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); //绘制此部分
}
// 9.恢复渲染状态,以免下一次调用Direct3D_Render()时渲染受到影响
g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
g_pd3dDevice->SetRenderState( D3DRS_STENCILENABLE, false);
g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);