我使用DXUT使用DirectX9創建圖形應用程序。在我的應用程序中,我想實現延期着色。這種照明方法要求我爲場景中的每個燈提供模板體積(掩模)。爲避免單獨渲染卷,我想使用DirectX的實例化功能。使用頂點着色器3.0和像素着色器3.0我已經成功繪製了任何給定模型的多個實例,但是,似乎當我嘗試繪製實例化模板卷時,沒有數據寫入後緩衝器的深度模板表面。DirectX - 具有實例化模板卷的延遲着色
我的延遲着色的實現是僞代碼如下:
耗損所有場景幾何(實例幾何通行證)後備緩衝區:
- 啓用Z(D3DRS_ZENABLE,TRUE)
- 啓用ZWrites (D3DRS_ZWRITEENABLE,TRUE)
- 禁用模具(D3DRS_STENCILENABLE,FALSE)
- 集CullMode(D3DRS_CULLMODE,D3DCULL_CCW) 個
- 禁用ColorWrites(D3DRS_COLORWRITEENABLE,0)
- 禁用Alphablending(D3DRS_ALPHABLENDENABLE,FALSE)
- RenderScene
得到一個指向後備緩衝:
- 的IDirect3DDevice9 :: GetRenderTarget(0, pBackbufferSurface)
Set 3 rendertargets( COLOR(0),NORMAL(1),位置(2)):
- 的IDirect3DDevice9 :: SetRenderTarget方法(0 - > 2,COLOR - > POSITION)
耗損所有場景幾何圖形到3渲染目標:
- 啓用ColorWrites(D3DRS_COLORWRITEENABLE,CW_RED,CW_GREEN, CW_BLUE,CW_ALPHA)
- 渲染場景
重置後備緩衝到設備的RenderTarget 0:
- 的IDirect3DDevice9 :: SetRenderTarget方法(0,pBackbufferSurface)
設置效果的紋理(SrcColor)到顏色渲染目標
- ID3DXEffect :: SetTexture(「g_TextureSrcColor」,pRTColor)
渲染從色彩渲染目標全屏四和樣品(油漆的場景)
模板所有場景燈光使用實例化技術(這裏是實際的代碼):
// set the instance buffer vertex declaration
hr = pd3dDevice->SetVertexDeclaration(CContentManager::GetInstanceBufferVertexDeclaration());
if(FAILED(hr))
{
DebugStringDX(ClassName, "Failed to IDirect3DDevice9::SetVertexDeclaration(instances)at RenderScene()", __LINE__, hr);
return hr;
}
// render instances of each light(sphere and cone)
for(UINT i = 0; i < 2; ++i)
{
// point to base model
CXModel *pXBase = (CXModel*)pCM->GetAppObject(i);
if(!pXBase)
{
DebugStringDX(ClassName,
"Failed to retrieve the base light model at index(" + ToString(i) + ") at Render()",
__LINE__,
E_POINTER);
continue;
}
// if the model has no instances
// there is no reason to try and draw
UINT ucInstances = pXBase->GetNumInstances();
if(ucInstances < 1)
continue;
// Set up the geometry data stream
hr = pd3dDevice->SetStreamSourceFreq(0,
(D3DSTREAMSOURCE_INDEXEDDATA | ucInstances));
if(FAILED(hr))
{
DebugStringDX(ClassName, "Failed to IDirect3DDevice9::SetStreamSourceFreq(source)(index - " + ToString(i) + ") at RenderScene()", __LINE__, hr);
continue;
}
// Set up the instance data stream
IDirect3DVertexBuffer9 *pVBInstances = pXBase->GetInstanceBuffer();
hr = pd3dDevice->SetStreamSource(1, pVBInstances, 0,
sizeof(CXModel::sInstanceEntry));
if(FAILED(hr))
{
DebugStringDX(ClassName, "Failed to IDirect3DDevice9::SetStreamSource(instances)(index - " + ToString(i) + ") at RenderScene()", __LINE__, hr);
continue;
}
hr = pd3dDevice->SetStreamSourceFreq(1,
(D3DSTREAMSOURCE_INSTANCEDATA | 1ul));
if(FAILED(hr))
{
DebugStringDX(ClassName, "Failed to IDirect3DDevice9::SetStreamSourceFreq(instances)(index - " + ToString(i) + ") at Render()", __LINE__, hr);
continue;
}
// get light model frame root
pFrame = pXBase->GetFrameRoot();
if(!pFrame)
{
DebugStringDX(ClassName, "Failed to CXModel::GetFrameRoot(Light Model) at Render()", __LINE__, hr);
continue;
}
//------------------------------------------------------------------------------------------------------------
// Stencil Volume Mask Pass
//------------------------------------------------------------------------------------------------------------
dev.SetRenderState(D3DRS_ZENABLE, TRUE);
dev.SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
dev.SetRenderState(D3DRS_STENCILENABLE, TRUE);
dev.SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
dev.SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP);
dev.SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_INCR);
dev.SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);
dev.SetRenderState(D3DRS_STENCILWRITEMASK, 0xffffffff);
dev.SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
dev.SetRenderState(D3DRS_COLORWRITEENABLE, 0);
hr = BeginPass(CFXDeferred::STENCIL);
if(FAILED(hr))
{
DebugStringDX(ClassName, "Failed to BeginPass(StencilVolumeMask) at Render()", __LINE__, hr);
continue;
}
// draw the light model
hr = DrawStaticModel(pd3dDevice, pFrame, &mWorld, pmView, pmProjection, true, bRenderStrips);
if(FAILED(hr))
{
DebugStringDX(ClassName, "Failed to DrawStaticModel(Light Model) at Render()", __LINE__, hr);
continue;
}
hr = pE->EndPass();
if(FAILED(hr))
{
DebugStringDX(ClassName, "Failed to ID3DXEffect::EndPass() at Render()", __LINE__, hr);
continue;
}
//------------------------------------------------------------------------------------------------------------
// Diffuse Light Pass
//------------------------------------------------------------------------------------------------------------
dev.SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
dev.SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
dev.SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
dev.SetRenderState(D3DRS_ZENABLE, FALSE);
dev.SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
dev.SetRenderState(D3DRS_COLORWRITEENABLE,
D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_ALPHA);
dev.SetRenderState(D3DRS_STENCILENABLE, TRUE);
dev.SetRenderState(D3DRS_STENCILFUNC, D3DCMP_EQUAL);
dev.SetRenderState(D3DRS_STENCILMASK, 0x1);
dev.SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_ZERO);
dev.SetRenderState(D3DRS_STENCILREF, 0x1);
dev.SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP);
dev.SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_ZERO);
hr = BeginPass(CFXDeferred::DIFFUSELIGHTSTENCIL);
if(FAILED(hr))
{
DebugStringDX(ClassName, "Failed to BeginPass(DiffuseSpecularLightStencilPass) at Render()", __LINE__, hr);
continue;
}
// draw light model
hr = DrawStaticModel(pd3dDevice, pFrame, &mWorld, pmView, pmProjection, true, bRenderStrips);
if(FAILED(hr))
{
DebugStringDX(ClassName, "Failed to DrawStaticModel(Light Model) at Render()", __LINE__, hr);
continue;
}
hr = pE->EndPass();
if(FAILED(hr))
{
DebugStringDX(ClassName, "Failed to ID3DXEffect::EndPass() at Render()", __LINE__, hr);
continue;
}
}
這裏是實例緩衝區頂點聲明:
// create instance vertex declaration
D3DVERTEXELEMENT9 pElements[] = {
{ 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
{ 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 },
{ 0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
{ 1, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1 },
{ 1, 16, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2 },
{ 1, 32, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 3 },
{ 1, 48, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 4 },
{ 1, 64, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 5 },
D3DDECL_END()
};
此方法工作正常,沒有實例化......實例是否阻止深度模板寫入?當我使用PIX進行調試時,它表示「Pixel未通過模板測試」。這裏是調用渲染之前清除後備緩衝:
pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, D3DCOLOR_ARGB(0, 0, 0, 0), 1.0f, 0));
在創建設備的,我修改了設置,使用AutoDepthStencilFormat D3DFMT_D24S8像這樣:
// check for D3DFMT_D24S8 AutoDepthStencilFormat
// if present set the AutoDepthStencilFormat to D3DFMT_D24S8
if(DXUTGetD3D9Enumeration()->GetPossibleDepthStencilFormatList()->Contains(D3DFMT_D24S8))
{
pDeviceSettings->d3d9.pp.AutoDepthStencilFormat = D3DFMT_D24S8;
}
如果我更改模板參數( IDirect3DDevice9 :: Clear()的最後一個參數設置爲1.模板體積通過模板測試...這是因爲我設置了模板操作,以便在模板的像素與像素相交時將模板值增加1在後緩衝器上,並在那個事件中,承認光的像素顏色。這表示存在以下兩個問題之一:
- 在'Instanced Geometry Pass'期間繪製場景(對象)時...後緩衝區在繪製對象時沒有存儲對象的深度(所以模板測試具有「0」值進行比較 或
- 當繪製模版卷(燈)的後備緩衝區是不存儲的卷的深度,因爲它們被繪製...
這是由於我的實例化方法?是由於Shader Versions(vs3,ps3)還是DX的版本?
「*這種照明方法要求我爲場景中的每個燈渲染模板體積(掩模)。*」一般而言,延遲渲染和*模板陰影*不起作用一起。就像*一樣*。您需要切換到陰影貼圖。 –
誰對陰影說什麼?沒有陰影......我正在實施使用模板卷的延遲照明技術(後期處理)。所有通過斯蒂爾測試並且不能進行深度測試的像素對於給定體積(光點使用球體,光點使用錐體)表現爲「點亮」... –
那麼什麼是「模板體積」模板體積是?如果它不是一個影子,那麼你的場景中應該做什麼? –