Direct3D---模板测试之镜面特效

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);

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值