所以我为一些旧的开源游戏写了一篇Post Processing课程,
我有一个开始场景功能,一个结束场景功能,一个渲染功能和一个用于创建屏幕小队和资源的功能。
bool CPostProcessingChain::BeginScene()
{
if (!m_lpSourceTexture || !m_lpLastPass || !m_lpTarget || !m_lpDepthStencilSurface)
{
if (!CreateResources())
{
return false;
}
}
STATEMANAGER.GetDevice()->GetRenderTarget(0, &m_lpBackupTargetSurface);
STATEMANAGER.GetDevice()->SetRenderTarget(0, m_lpSourceTextureSurface);
STATEMANAGER.GetDevice()->GetDepthStencilSurface(&m_lpDepthStencilBackup);
STATEMANAGER.GetDevice()->SetDepthStencilSurface(m_lpDepthStencilSurface);
return true;
}
bool CPostProcessingChain::EndScene()
{
STATEMANAGER.GetDevice()->SetRenderTarget(0, m_lpBackupTargetSurface);
STATEMANAGER.GetDevice()->SetDepthStencilSurface(m_lpDepthStencilBackup);
m_lpDepthStencilBackup->Release();
m_lpDepthStencilBackup = nullptr;
m_lpBackupTargetSurface->Release();
m_lpBackupTargetSurface = nullptr;
D3DXMATRIX mWorld, mView, mProj, mIdentity;
D3DXMatrixIdentity(&mIdentity);
STATEMANAGER.GetDevice()->GetTransform(D3DTS_WORLD, &mWorld);
STATEMANAGER.GetDevice()->GetTransform(D3DTS_VIEW, &mView);
STATEMANAGER.GetDevice()->GetTransform(D3DTS_PROJECTION, &mProj);
STATEMANAGER.GetDevice()->SetTransform(D3DTS_WORLD, &mIdentity);
STATEMANAGER.GetDevice()->SetTransform(D3DTS_VIEW, &mIdentity);
STATEMANAGER.GetDevice()->SetTransform(D3DTS_PROJECTION, &mIdentity);
STATEMANAGER.SaveRenderState(D3DRS_ZENABLE, FALSE);
STATEMANAGER.SaveRenderState(D3DRS_MULTISAMPLEANTIALIAS, FALSE);
STATEMANAGER.GetDevice()->Clear(0, nullptr, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0.0f);
STATEMANAGER.GetDevice()->SetTexture(0, m_lpTarget);
STATEMANAGER.GetDevice()->SetPixelShader(nullptr);
STATEMANAGER.GetDevice()->SetVertexShader(nullptr);
STATEMANAGER.GetDevice()->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
STATEMANAGER.GetDevice()->SetStreamSource(0, m_lpScreenQuad, 0, sizeof(TRTTVertex));
STATEMANAGER.GetDevice()->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);
STATEMANAGER.RestoreRenderState(D3DRS_MULTISAMPLEANTIALIAS);
STATEMANAGER.RestoreRenderState(D3DRS_ZENABLE);
STATEMANAGER.GetDevice()->SetTransform(D3DTS_WORLD, &mWorld);
STATEMANAGER.GetDevice()->SetTransform(D3DTS_VIEW, &mView);
STATEMANAGER.GetDevice()->SetTransform(D3DTS_PROJECTION, &mProj);
return true;
}
bool CPostProcessingChain::Render()
{
D3DXMATRIX mWorld, mView, mProj, mIdentity;
D3DXMatrixIdentity(&mIdentity);
STATEMANAGER.GetDevice()->GetTransform(D3DTS_WORLD, &mWorld);
STATEMANAGER.GetDevice()->GetTransform(D3DTS_VIEW, &mView);
STATEMANAGER.GetDevice()->GetTransform(D3DTS_PROJECTION, &mProj);
STATEMANAGER.GetDevice()->SetTransform(D3DTS_WORLD, &mIdentity);
STATEMANAGER.GetDevice()->SetTransform(D3DTS_VIEW, &mIdentity);
STATEMANAGER.GetDevice()->SetTransform(D3DTS_PROJECTION, &mIdentity);
STATEMANAGER.GetDevice()->SetRenderTarget(0, m_lpLastPassSurface);
STATEMANAGER.SaveRenderState(D3DRS_ZENABLE, FALSE);
STATEMANAGER.SaveRenderState(D3DRS_MULTISAMPLEANTIALIAS, FALSE);
STATEMANAGER.GetDevice()->Clear(0, nullptr, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0.0f);
STATEMANAGER.GetDevice()->SetTexture(0, m_lpSourceTexture);
STATEMANAGER.GetDevice()->SetPixelShader(nullptr);
STATEMANAGER.GetDevice()->SetVertexShader(nullptr);
STATEMANAGER.GetDevice()->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
STATEMANAGER.GetDevice()->SetStreamSource(0, m_lpScreenQuad, 0, sizeof(TRTTVertex));
STATEMANAGER.GetDevice()->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);
IDirect3DSurface9* pCurrentTarget = m_lpTargetSurface;
STATEMANAGER.GetDevice()->SetTexture(1, m_lpSourceTexture);
for (std::list<CPostProcessingEffect>::iterator it = m_kEffects.begin(); it != m_kEffects.end(); ++it)
{
D3DSURFACE_DESC kDesc;
pCurrentTarget->GetDesc(&kDesc);
D3DXVECTOR4 vScreenSize = D3DXVECTOR4(kDesc.Width, kDesc.Height, 0.0f, 0.0f);
(*it).GetConstants()->SetFloatArray(STATEMANAGER.GetDevice(), "ScreenSize", reinterpret_cast<float*>(&vScreenSize), 4);
if ((*it).Apply())
{
STATEMANAGER.GetDevice()->SetRenderTarget(0, pCurrentTarget);
STATEMANAGER.GetDevice()->Clear(0, nullptr, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0.0f);
STATEMANAGER.GetDevice()->SetTexture(0, pCurrentTarget == m_lpLastPassSurface ? m_lpTarget : m_lpLastPass);
STATEMANAGER.GetDevice()->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
STATEMANAGER.GetDevice()->SetStreamSource(0, m_lpScreenQuad, 0, sizeof(TRTTVertex));
STATEMANAGER.GetDevice()->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);
pCurrentTarget = pCurrentTarget == m_lpLastPassSurface ? m_lpTargetSurface : m_lpLastPassSurface;
}
}
STATEMANAGER.GetDevice()->SetTexture(1, nullptr);
if (pCurrentTarget == m_lpTargetSurface)
{
STATEMANAGER.GetDevice()->SetRenderTarget(0, m_lpTargetSurface);
STATEMANAGER.GetDevice()->Clear(0, nullptr, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0.0f);
STATEMANAGER.GetDevice()->SetTexture(0, m_lpLastPass);
STATEMANAGER.GetDevice()->SetPixelShader(nullptr);
STATEMANAGER.GetDevice()->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
STATEMANAGER.GetDevice()->SetStreamSource(0, m_lpScreenQuad, 0, sizeof(TRTTVertex));
STATEMANAGER.GetDevice()->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);
}
STATEMANAGER.RestoreRenderState(D3DRS_MULTISAMPLEANTIALIAS);
STATEMANAGER.RestoreRenderState(D3DRS_ZENABLE);
STATEMANAGER.GetDevice()->SetTransform(D3DTS_WORLD, &mWorld);
STATEMANAGER.GetDevice()->SetTransform(D3DTS_VIEW, &mView);
STATEMANAGER.GetDevice()->SetTransform(D3DTS_PROJECTION, &mProj);
return true;
}
bool CPostProcessingChain::CreateResources()
{
ReleaseResources();
D3DSURFACE_DESC kDesc;
IDirect3DSurface9* pSurface;
STATEMANAGER.GetDevice()->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pSurface);
pSurface->GetDesc(&kDesc);
pSurface->Release();
if (FAILED(STATEMANAGER.GetDevice()->CreateTexture(kDesc.Width, kDesc.Width, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A32B32G32R32F, D3DPOOL_DEFAULT, &m_lpSourceTexture, nullptr)))
{
TraceError("CPostProcessingChain unable to create render target");
return false;
}
m_lpSourceTexture->GetSurfaceLevel(0, &m_lpSourceTextureSurface);
if (FAILED(STATEMANAGER.GetDevice()->CreateTexture(kDesc.Width, kDesc.Width, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A32B32G32R32F, D3DPOOL_DEFAULT, &m_lpLastPass, nullptr)))
{
TraceError("CPostProcessingChain unable to create pass render target");
return false;
}
m_lpLastPass->GetSurfaceLevel(0, &m_lpLastPassSurface);
if (FAILED(STATEMANAGER.GetDevice()->CreateTexture(kDesc.Width, kDesc.Width, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A32B32G32R32F, D3DPOOL_DEFAULT, &m_lpTarget, nullptr)))
{
TraceError("CPostProcessingChain unable to create final render target");
return false;
}
m_lpTarget->GetSurfaceLevel(0, &m_lpTargetSurface);
STATEMANAGER.GetDevice()->GetDepthStencilSurface(&pSurface);
pSurface->GetDesc(&kDesc);
pSurface->Release();
if (FAILED(STATEMANAGER.GetDevice()->CreateDepthStencilSurface(kDesc.Width, kDesc.Width, D3DFMT_D16, kDesc.MultiSampleType, kDesc.MultiSampleQuality, FALSE, &m_lpDepthStencilSurface, nullptr)))
{
TraceError("CPostProcessingChain unable to create depth surface");
return false;
}
if (FAILED(STATEMANAGER.GetDevice()->CreateVertexBuffer(sizeof(TRTTVertex)* 6, 0, D3DFVF_XYZRHW | D3DFVF_TEX1, D3DPOOL_MANAGED, &m_lpScreenQuad, nullptr)))
{
TraceError("CPostProcessingChain unable to create screen quad");
return false;
}
float fWidth = static_cast<float>(kDesc.Width) - 0.5f;
float fHeight = static_cast<float>(kDesc.Height) - 0.5f;
float fTexPos = fHeight / fWidth;
TRTTVertex* pVertices;
m_lpScreenQuad->Lock(0, 0, reinterpret_cast<void**>(&pVertices), 0);
pVertices[0].p = D3DXVECTOR4(-0.5f, -0.5f, 0.0f, 1.0f);
pVertices[0].t = D3DXVECTOR2(0.0f, 0.0f);
pVertices[1].p = D3DXVECTOR4(-0.5f, fHeight, 0.0f, 1.0f);
pVertices[1].t = D3DXVECTOR2(0.0f, 1.0f);
pVertices[2].p = D3DXVECTOR4(fWidth, fHeight, 0.0f, 1.0f);
pVertices[2].t = D3DXVECTOR2(1.0f, 1.0f);
pVertices[3].p = D3DXVECTOR4(-0.5f, -0.5f, 0.0f, 1.0f);
pVertices[3].t = D3DXVECTOR2(0.0f, 0.0f);
pVertices[4].p = D3DXVECTOR4(fWidth, fHeight, 0.0f, 1.0f);
pVertices[4].t = D3DXVECTOR2(1.0f, 1.0f);
pVertices[5].p = D3DXVECTOR4(fWidth, -0.5f, 0.0f, 1.0f);
pVertices[5].t = D3DXVECTOR2(1.0f, 0.0f);
m_lpScreenQuad->Unlock();
/*0, 0 | up left
0, height | down left
width, height | down right
0, 0 | up left
width, height | down right
width, 0 | up right*/
AddEffect("shaders/testshader.xml");
return true;
}
此代码适用于AMD显卡,但不适用于NVida显卡, 我已经尝试使用cl2p clamp纹理,但这没有用,所以目前我一点也不知道为什么它在AMD上运行而不在Nvidia卡上
它不会在Nvidia上崩溃,但屏幕是黑色的
如果您有任何想法,请回复, 提前致谢