我使用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的版本?
“*这种照明方法要求我为场景中的每个灯渲染模板体积(掩模)。*”一般而言,延迟渲染和*模板阴影*不起作用一起。就像*一样*。您需要切换到阴影贴图。 –
谁对阴影说什么?没有阴影......我正在实施使用模板卷的延迟照明技术(后期处理)。所有通过斯蒂尔测试并且不能进行深度测试的像素对于给定体积(光点使用球体,光点使用锥体)表现为“点亮”... –
那么什么是“模板体积”模板体积是?如果它不是一个影子,那么你的场景中应该做什么? –