zoukankan      html  css  js  c++  java
  • D3D 模板缓存的创建过程

    下面是我对模板缓存创建的理解:

    1. 模板缓存是和深度缓存一起被创建的,将深度缓存的一部分作为模板缓存使用。

    深度缓存和模板缓存是在Direct3D初始化时创建的,D3DPRESENT_PARAMETERS结构便包含了深度缓存和模板缓存的格式

    typedef struct D3DPRESENT_PARAMETERS {
     UINT               BackBufferWidth;
     UINT               BackBufferHeight;
     D3DFORMAT          BackBufferFormat;
     UINT               BackBufferCount;
     D3DMULTISAMPLE_TYPE MultiSampleType;
     DWORD               MultiSampleQuality;
     D3DSWAPEFFECT       SwapEffect;
     HWND                hDeviceWindow;
     BOOL                Windowed;
     BOOL               EnableAutoDepthStencil;
     D3DFORMAT          AutoDepthStencilFormat;
     DWORD               Flags;
     UINT                FullScreen_RefreshRateInHz;
     UINT               PresentationInterval;
    } D3DPRESENT_PARAMETERS,*LPD3DPRESENT_PARAMETERS;

    D3DFORMAT          AutoDepthStencilFormat;

    可以有以下取值:

    D3DFMT_D24S8    创建一个32位深度/模版缓存,其中24位为深度缓存,8位为模版缓存。

    D3DFMT_D24X4S4    创建一个32位深度/模版缓存,其中24位为深度缓存,4位为模版缓存,还有4位留着不用。

    D3DFMT_D15S1    创建一个16位深度/模版缓存,其中15位为深度缓存,1位为模版缓存。

    2. 使用模板缓存前需要启用模板缓存

    下面是启用和关闭模板缓存代码

    Device->SetRenderState(D3DRS_STENCILENABLE, true);
    ... // do stencil work
    Device->SetRenderState(D3DRS_STENCILENABLE, false);

    使用IDirect3DDevice9::Clear方法来清除模板缓存并让其拥有默认值。

    Device->Clear(0, 0,
        D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL,
        0xff000000, 1.0f, 0 );

    此时模板缓存中的模板值(Value)已被初始化为0

    3. 模板缓存是用来阻止像素被写入后台缓存中的,如果像素不能被写入后台缓存,那么它也不能被写入深度缓存。

    阻止像素被写入是通过模板测试来决定的,表达式为:

    (ref & mask) ComparisonOperation (value & mask)

    模版测试是对每个像素进行的,假设模版是被允许。将有两个操作:

    • 左手边操作数(LHS=ref&mask
    • 右手边操作数(RHS=value&mask

    模版测试比较LHS和RHS,通过比较运算来指定。全部的运算都得到一个布尔值(true/false)。假如测试的结果是true,那么我们把像素写入后缓存。假如测试的结果是false,我们就阻止像素被写入后缓存。
    设置渲染状态:

    Device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
        Device->SetRenderState(D3DRS_STENCILREF, 0x1);
        Device->SetRenderState(D3DRS_STENCILMASK, 0xffffffff);
        Device->SetRenderState(D3DRS_STENCILWRITEMASK,0xffffffff);
        Device->SetRenderState(D3DRS_STENCILZFAIL,D3DSTENCILOP_KEEP);
        Device->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP);
    Device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);

    设置模版比较运算为D3DCMP_ALWAYS,这就是说让所有模版测试都通过。

    假如深度测试失败了,我们指定D3DSTENCILOP_KEEP,它表明不更新模版缓存入口,保存当前值。这样做的原因是假如深度测试失败了,那么就意味着像素被“模糊”了。我们不想渲染被“模糊”的反射像素。

    同样假如模版测试失败了,我们也指定D3DSTENCILOP_KEEP。但是在这里这样做不是必须的,因为我们指定的是D3DCMP_ALWAYS,当然这样的测试也就永远不会失败。

    假如深度测试和模版测试都通过了,我们就指定D3DSTENCILOP_REPLACE,更新模版缓存入口,设置模版参考值为0x1。

     

    4. 更新模板缓存,因为测试总是通过,所以被渲染的部分替换为0x1,其他部分为0

    更新模板缓存前,先阻止向深度缓存写入

     // 禁用向模板 深度(Z)缓冲区进行写   
     Device->SetRenderState(D3DRS_ZWRITEENABLE, false);   
     Device->SetRenderState(D3DRS_ALPHABLENDENABLE, true);   

    将源融合因子和目标融合因子分别指定为D3DBLEND_ZERO和D3DBLEND_ONE防止对后台缓存进行更新,

        //设置 源融合因子和 目标融合因子   
        Device->SetRenderState(D3DRS_SRCBLEND,  D3DBLEND_ZERO);   
        Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);   

    将镜子写入模板缓存

    Device->SetStreamSource(0, VB, 0, sizeof(Vertex));
        Device->SetFVF(Vertex::FVF);
        Device->SetMaterial(&MirrorMtrl);
        Device->SetTexture(0, MirrorTex);
        D3DXMATRIX I;
        D3DXMatrixIdentity(&I);
        Device->SetTransform(D3DTS_WORLD, &I);
        Device->DrawPrimitive(D3DPT_TRIANGLELIST, 18, 2);

    在模版缓存中,符合镜子可视像素的为0x1,其他像素为0

    至此,模板缓存已创建完成。

    ......

  • 相关阅读:
    BZOJ 3505: [Cqoi2014]数三角形 数学
    BZOJ 3931: [CQOI2015]网络吞吐量 最大流
    BZOJ 4236: JOIOJI MAP
    BZOJ 4247 挂饰 背包DP
    hihocoder #1224 : 赛车 dfs
    hihocoder #1223 : 不等式 水题
    BZOJ 3224: Tyvj 1728 普通平衡树 treap
    uoj #31. 【UR #2】猪猪侠再战括号序列 贪心
    BZOJ 1005: [HNOI2008]明明的烦恼 Purfer序列 大数
    心跳回忆4 攻略
  • 原文地址:https://www.cnblogs.com/felove2013/p/3537076.html
Copyright © 2011-2022 走看看