Directx11教程(49) stencil的应用-镜面反射
???? 本教程中,我們利用stencil來(lái)實(shí)現(xiàn)一個(gè)鏡面反射效果。
1、首先我們要在D3DClass中增加幾個(gè)成員變量及函數(shù)。
ID3D11DepthStencilState* m_depthStencilStateMirror;
ID3D11DepthStencilState* m_depthStencilStateReflect;
m_depthStencilStateMirror是渲染鏡子時(shí)候,使用的depth stencil 狀態(tài),我們?cè)O(shè)置stencil 函數(shù)為D3D11_COMPARISON_ALWAYS,這樣,stencil測(cè)試總能pass,然后pass的操作為D3D11_STENCIL_OP_REPLACE,這樣,會(huì)用設(shè)置的ref值填充stencil buffer。
depthStencilDesc.DepthEnable = true;
depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL
depthStencilDesc.DepthFunc = D3D11_COMPARISON_LESS;
depthStencilDesc.StencilEnable = true;
depthStencilDesc.StencilReadMask = 0xFF;
depthStencilDesc.StencilWriteMask = 0xFF;
// 對(duì)于front face 像素使用的模版操作操作.
depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE;
depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
// 對(duì)于back face像素使用的模版操作模式.
depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE;
depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
// 創(chuàng)建深度模版狀態(tài),使其生效
result = m_device->CreateDepthStencilState(&depthStencilDesc, &m_depthStencilStateMirror);
if(FAILED(result))
??? {
??? HR(result);
??? return false;
??? }
m_depthStencilStateReflect用來(lái)渲染鏡子中反射的物體,此時(shí)禁止depth test,使depth test總是pass,stencil函數(shù)用等于比較,及當(dāng)前的stencil ref值和stencil buffer中的值比較,等于則pass stencil test。
// 設(shè)置reflect object深度模版狀態(tài)描述.
depthStencilDesc.DepthEnable = true;
depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO;//D3D11_DEPTH_WRITE_MASK_ZERO禁止寫深度緩沖
depthStencilDesc.DepthFunc = D3D11_COMPARISON_ALWAYS;
// 對(duì)于front face 像素使用的模版操作操作.
depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_EQUAL;
// 創(chuàng)建深度模版狀態(tài),使其生效
result = m_device->CreateDepthStencilState(&depthStencilDesc, &m_depthStencilStateReflect);
if(FAILED(result))
??? {
??? HR(result);
??? return false;
??? }
m_alphaEnableBlendingState狀態(tài)變量創(chuàng)建一個(gè)alpha blend狀態(tài),這個(gè)狀態(tài)主要在渲染鏡子中物體時(shí)候使用,因?yàn)槲覀兊溺R面是一個(gè)紋理表示,alpha blend會(huì)把鏡面紋理和渲染物體進(jìn)行混合操作。
// 創(chuàng)建一個(gè)alpha blend狀態(tài).
blendStateDescription.RenderTarget[0].BlendEnable = TRUE;
//blendStateDescription.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
blendStateDescription.RenderTarget[0].SrcBlend = D3D11_BLEND_BLEND_FACTOR;
blendStateDescription.RenderTarget[0].DestBlend = D3D11_BLEND_INV_BLEND_FACTOR;
blendStateDescription.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
blendStateDescription.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
blendStateDescription.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
blendStateDescription.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
blendStateDescription.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;//0x0f;
// 用描述符創(chuàng)建一個(gè)alpha blend狀態(tài)
result = m_device->CreateBlendState(&blendStateDescription, &m_alphaEnableBlendingState);
if(FAILED(result))
??? {
??? return false;
??? }
另外還有一個(gè)函數(shù)ChangeBackCullMode(bool b),用來(lái)改變渲染狀態(tài),設(shè)置front face 為順時(shí)針渲染。因?yàn)樵阡秩剧R子中物體時(shí)候,鏡子中物體正面其實(shí)對(duì)應(yīng)物體的反面,這是需要改變渲染次序。
下面的幾個(gè)函數(shù)用來(lái)改變這幾個(gè)新增加的狀態(tài)。
void TurnOnAlphaBlending();
void TurnOffAlphaBlending();
void ChangeBackCullMode(bool b);
void EnableDefaultDepthStencil();
void EnableMirrorDepthStencil();
void EnableReflectDepthStencil();
2、D3Dclass中的BeginSence函數(shù)小改動(dòng),每幀渲染之前清除stencil值為0
void D3DClass::BeginScene(float red, float green, float blue, float alpha)
??? {
…
? ? //清除深度緩沖.
??? m_deviceContext->ClearDepthStencilView(m_depthStencilView, D3D11_CLEAR_DEPTH|D3D11_CLEAR_STENCIL, 1.0f, 0);
??? return;
??? }
3、增加了一個(gè)MirrorModelClass類用來(lái)表示鏡子的mesh。
4、在graphicsClass類中依次渲染物體
??? 首先渲染地面,墻以及box
??? m_D3D->EnableMirrorDepthStencil();
??? 渲染鏡子
???? m_D3D->EnableDefaultDepthStencil();
???? 定義鏡子反射平面,計(jì)算反射矩陣,注意D3DXMatrixReflect計(jì)算反射矩陣時(shí)候,對(duì)平面進(jìn)行了歸一化,所以我加了一個(gè)平移操作。
D3DXPLANE mirrorPlane(0.0, 0.0, 10.99, 0.0);
D3DXMATRIX R;
//得到基于mirrorPlane平面的反射矩陣
D3DXMatrixReflect(&R, &mirrorPlane);
//box在原點(diǎn)位置,沒有變化,它的世界坐標(biāo)矩陣為worldMatrix
D3DXMATRIX W = worldMatrix * R;
D3DXMatrixTranslation(&worldMatrix1, 0.0, 0.0, -18.0);
W = worldMatrix1*W;
???? 接下來(lái),設(shè)置狀態(tài)
m_D3D->EnableReflectDepthStencil();
m_D3D->TurnOnAlphaBlending();
m_D3D->ChangeBackCullMode(true);
渲染鏡子中box
m_D3D->EnableDefaultDepthStencil();
m_D3D->TurnOffAlphaBlending();
m_D3D->ChangeBackCullMode(false);
程序最終的效果如下:
完整的代碼請(qǐng)參考:
工程文件myTutorialD3D11_43
代碼下載:
http://files.cnblogs.com/mikewolf2002/d3d1139-49.zip
http://files.cnblogs.com/mikewolf2002/pictures.zip
總結(jié)
以上是生活随笔為你收集整理的Directx11教程(49) stencil的应用-镜面反射的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 10万镜子反射月光,组成3.6平方公里巨
- 下一篇: 初中计算机应用基础知识,初中乐理基础知识