2013-07-25 77 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與實例...