2013-07-25 31 views
0

我使用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在后缓冲器上,并在那个事件中,承认光的像素颜色。这表示存在以下两个问题之一:

  1. 在'Instanced Geometry Pass'期间绘制场景(对象)时...后缓冲区在绘制对象时没有存储对象的深度(所以模板测试具有“0”值进行比较 或
  2. 当绘制模版卷(灯)的后备缓冲区是不存储的卷的深度,因为它们被绘制...

这是由于我的实例化方法?是由于Shader Versions(vs3,ps3)还是DX的版本?

+0

“*这种照明方法要求我为场景中的每个灯渲染模板体积(掩模)。*”一般而言,延迟渲染和*模板阴影*不起作用一起。就像*一样*。您需要切换到阴影贴图。 –

+0

谁对阴影说什么?没有阴影......我正在实施使用模板卷的延迟照明技术(后期处理)。所有通过斯蒂尔测试并且不能进行深度测试的像素对于给定体积(光点使用球体,光点使用锥体)表现为“点亮”... –

+0

那么什么是“模板体积”模板体积是?如果它不是一个影子,那么你的场景中应该做什么? –

回答

0

问题是我用vs_3_0编译了顶点着色器(用于模板卷掩码)...我将其更改为vs_2_0,现在它工作正常......我不明白,因为我认为有必要使用顶点着色器模型3.0与实例...