📄 depthoffield.cpp
字号:
m_pD3DDev->SetTextureStageState(i, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
}
m_pD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
m_pD3DDev->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
m_pD3DDev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
m_pD3DDev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
m_pD3DDev->SetRenderState(D3DRS_ZENABLE, FALSE);
m_pD3DDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
m_pD3DDev->SetStreamSource(0, mpQuadVertexBuffer, sizeof(tQuadVertex));
// turn on our special filtering pixel shader
m_pD3DDev->SetVertexShader(m_dwBlurVertexShader);
m_pD3DDev->SetPixelShader(m_dwBlurPixelShader);
return S_OK;
}
HRESULT CDepthOfField::SetMatrices(D3DXMATRIX const &matWorld)
{
// set up vertex shading constants to contain proper
// transformation matrices etc.
D3DXMATRIX matLookRotations;
D3DXMatrixTranspose(&matLookRotations, &(mpMouseUI->GetRotationMatrix()));
mCamLookDirection = D3DXVECTOR3( 0.0f, 0.0f, 1.0f );
D3DXVec3TransformNormal(&mCamLookDirection, &mCamLookDirection, &matLookRotations);
D3DXVECTOR3 const vLookatPt = mCamPosition + mCamLookDirection;
D3DXVECTOR3 const vUp = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
float const fieldOfView = 2.0f * atanf(.5f*kFilmDimension/mFocalLength);
D3DXMATRIX matView;
D3DXMATRIX matProj;
D3DXMatrixLookAtLH(&matView, &mCamPosition, &vLookatPt, &vUp);
D3DXMatrixPerspectiveFovLH( &matProj, fieldOfView, 1.0f, kCloseClip, kFarClip );
D3DXMATRIX matWorldView;
D3DXMATRIX matWorldViewIT;
D3DXMATRIX matWorldViewProj;
D3DXMatrixMultiply(&matWorldView, &matWorld, &matView);
D3DXMatrixMultiply(&matWorldViewProj, &matWorldView, &matProj);
// Write Projection to clip space matrix to constant memory
D3DXMatrixTranspose(&matWorldViewProj, &matWorldViewProj);
m_pD3DDev->SetVertexShaderConstant(CV_WORLDVIEWPROJ_0, &matWorldViewProj(0, 0), 4);
// Create a 3x3 inverse of the world matrix for the normal transformation
// (we transpose it as we load it into the constant store)
D3DXMatrixInverse(&matWorldViewIT, NULL, &matWorldView);
m_pD3DDev->SetVertexShaderConstant(CV_WORLDVIEWIT_0, &matWorldViewIT(0, 0), 3);
// finally write the worldView matrix: it takes vertices to view-space
D3DXMatrixTranspose(&matWorldView, &matWorldView);
m_pD3DDev->SetVertexShaderConstant(CV_WORLDVIEW_0, &matWorldView(0, 0), 4);
// Create a directional light and transform it to eye-space
// Shader math requires that the vector is to the light
D3DXVECTOR3 vLight( 0.0f, 1.0f, 0.25f);
// Transform direction vector into eye space
D3DXVec3Normalize( &vLight, &vLight);
D3DXVec3TransformNormal(&vLight, &vLight, &matView);
D3DXVec3Normalize( &vLight, &vLight);
m_pD3DDev->SetVertexShaderConstant(CV_LIGHT_DIRECTION, &vLight, 1);
// color of the light
D3DXVECTOR4 lightDiffuse(0.9f, 0.9f, 1.0f, 0.0f);
m_pD3DDev->SetVertexShaderConstant(CV_LIGHT_DIFFUSE, &lightDiffuse, 1);
return S_OK;
}
HRESULT CDepthOfField::Free()
{
SAFE_RELEASE(mpTetrahedronVertices);
SAFE_RELEASE(mpTetrahedronIndices);
SAFE_RELEASE(mpQuadVertexBuffer);
SAFE_RELEASE(mpWorldBoxVertices);
SAFE_RELEASE(mpWorldBoxIndices);
SAFE_DELETE(m_pNVDevice);
if (m_pD3DDev)
{
// reset buffers properly
if ((mpBackbufferColor) != NULL && (mpBackbufferDepth != NULL))
{
HRESULT hr = m_pD3DDev->SetRenderTarget(mpBackbufferColor, mpBackbufferDepth);
_ASSERT(hr == S_OK);
}
SAFE_RELEASE(mpBackbufferColor);
SAFE_RELEASE(mpBackbufferDepth);
m_pD3DDev->DeletePixelShader (m_dwShowBlurrinessShader);
m_pD3DDev->DeleteVertexShader(m_dwBlurVertexShader);
m_pD3DDev->DeletePixelShader (m_dwBlurPixelShader );
m_pD3DDev->DeletePixelShader (m_dwDepthOfFieldPixelShader);
m_pD3DDev->DeleteVertexShader(m_dwWorldVertexShader);
m_pD3DDev->DeletePixelShader (m_dwWorldNoDoFPixelShader );
m_pD3DDev->DeletePixelShader (m_dwWorldPixelShader );
m_pD3DDev->DeleteVertexShader(m_dwTetraVertexShader);
m_pD3DDev->DeletePixelShader (m_dwTetraNoDoFPixelShader );
m_pD3DDev->DeletePixelShader (m_dwTetraPixelShader );
for (int i = 0; i < 3; ++i)
{
SAFE_RELEASE(mpFilterTarget[i]);
SAFE_RELEASE(mpTextureFiltered[i]);
}
for (i = 0; i < 2; ++i)
{
SAFE_RELEASE(mpTempTexture[i]);
SAFE_RELEASE(mpTempTarget [i]);
}
for (i = 0; i < 6; i++)
SAFE_DELETE(mpWorldTextures[i]);
SAFE_DELETE(mpObjectTexture);
SAFE_RELEASE(mpDepthTarget);
SAFE_RELEASE(mpCircleOfConfusionLookup);
SAFE_RELEASE(mpVolCircleOfConfusionLookup);
SAFE_RELEASE(m_pD3DDev);
}
SAFE_DELETE(mpMouseUI);
return S_OK;
}
HRESULT CDepthOfField::Start()
{
return S_OK;
}
HRESULT CDepthOfField::Tick(EBTimer* pTimer)
{
HRESULT hr;
int i, j, k;
// update view-state from the keyboard
SetViewFromKeyboardInput(pTimer);
// set a bunch of render-state for rendering the world
m_pD3DDev->SetRenderState(D3DRS_FILLMODE, (mbWireFrame) ? D3DFILL_WIREFRAME : D3DFILL_SOLID);
m_pD3DDev->SetTexture(0, mpObjectTexture->GetTexture());
m_pD3DDev->SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
m_pD3DDev->SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
m_pD3DDev->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR );
m_pD3DDev->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
m_pD3DDev->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
if (mbUsesVolumes)
m_pD3DDev->SetTexture(1, mpVolCircleOfConfusionLookup);
else
m_pD3DDev->SetTexture(1, mpCircleOfConfusionLookup);
m_pD3DDev->SetTextureStageState(1, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
m_pD3DDev->SetTextureStageState(1, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
m_pD3DDev->SetTextureStageState(1, D3DTSS_MIPFILTER, D3DTEXF_NONE);
m_pD3DDev->SetTextureStageState(1, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
m_pD3DDev->SetTextureStageState(1, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
m_pD3DDev->SetTextureStageState(1, D3DTSS_ADDRESSW, D3DTADDRESS_CLAMP);
m_pD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
m_pD3DDev->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
m_pD3DDev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
m_pD3DDev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
m_pD3DDev->SetRenderState(D3DRS_ZENABLE, TRUE);
m_pD3DDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
// first render the world "normally" but into a texture
hr = m_pD3DDev->SetRenderTarget(mpFilterTarget[0], mpDepthTarget);
hr = m_pD3DDev->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB( 0x0, 0x0, 0x0, 0x60 ), 1.0, 0);
// draw lots of tetrahedra here
D3DXVECTOR4 ambientLight(0.3f, 0.3f, 0.15f, 1.0f);
m_pD3DDev->SetVertexShaderConstant(CV_AMBIENT_LIGHT, &ambientLight, 1);
m_pD3DDev->SetVertexShader(m_dwTetraVertexShader);
if (meDisplayOption != SHOW_DEPTH)
m_pD3DDev->SetPixelShader (m_dwTetraPixelShader);
else
m_pD3DDev->SetPixelShader (m_dwTetraNoDoFPixelShader);
m_pD3DDev->SetStreamSource(0, mpTetrahedronVertices, sizeof(tTetrahedronVertex));
m_pD3DDev->SetIndices(mpTetrahedronIndices, 0);
D3DXVECTOR3 const vUp = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
D3DXMATRIX matWorld;
D3DXMATRIX matTemp;
float x, z, s, r;
float cr, cg, cb;
float const kRandMax = static_cast<float>(RAND_MAX);
// init random number generator (we need to get the same sequence every frame)
srand( 3 );
for (i = 0; i < kNumTetrahedra; ++i)
{
s = 1.0f + 0.5f * static_cast<float>(rand())/kRandMax;
r = 2.0f * D3DX_PI * static_cast<float>(rand())/kRandMax;
x = mWorldBoxDimensions.x * (0.5f - static_cast<float>(rand())/kRandMax);
z = mWorldBoxDimensions.z * (0.5f - static_cast<float>(rand())/kRandMax);
D3DXMatrixScaling (&matWorld, s, s, s);
D3DXMatrixRotationAxis(&matTemp, &vUp, r);
D3DXMatrixMultiply (&matWorld, &matWorld, &matTemp);
D3DXMatrixTranslation (&matTemp, x, 0.0f, z);
D3DXMatrixMultiply (&matWorld, &matWorld, &matTemp);
hr = SetMatrices( matWorld );
cr = 0.7f + 0.5f * static_cast<float>(rand())/kRandMax;
cg = 0.7f + 0.5f * static_cast<float>(rand())/kRandMax;
cb = 0.7f + 0.5f * static_cast<float>(rand())/kRandMax;
D3DXVECTOR4 materialColor(cr, cg, cb, 1.0f);
m_pD3DDev->SetVertexShaderConstant(CV_MATERIAL, &materialColor, 1);
m_pD3DDev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 12, 0, 4);
}
// draw the floor next
// Scale the world box and put it outside the world
D3DXVECTOR3 const vecScale = mWorldBoxDimensions;
D3DXMatrixScaling(&matWorld, vecScale.x, vecScale.y, vecScale.z);
hr = SetMatrices( matWorld );
m_pD3DDev->SetVertexShader(m_dwWorldVertexShader);
if (meDisplayOption != SHOW_DEPTH)
m_pD3DDev->SetPixelShader (m_dwWorldPixelShader);
else
m_pD3DDev->SetPixelShader (m_dwWorldNoDoFPixelShader);
m_pD3DDev->SetStreamSource(0, mpWorldBoxVertices, sizeof(tQuadVertex));
m_pD3DDev->SetIndices(mpWorldBoxIndices, 0);
// change the color texture, but all other stages and settings stay the same
m_pD3DDev->SetTexture(0, mpWorldTextures[1]->GetTexture());
m_pD3DDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
// draw the floor a bit different
for (j = 0; j < kNumQuadsPerSide; ++j) // for each strip
m_pD3DDev->DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP, 0, kNumVertices,
kNumIndicesPerFace + j*2*(kNumQuadsPerSide+1),
kNumTrisPerStrip);
// draw the walls and ceiling
m_pD3DDev->SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
m_pD3DDev->SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
m_pD3DDev->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR );
m_pD3DDev->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
m_pD3DDev->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
for (i = 0; i < 6; ++i) // for each cube face, except the floor
if (i != 1)
{
m_pD3DDev->SetTexture(0, mpWorldTextures[i]->GetTexture());
for (j = 0; j < kNumQuadsPerSide; ++j) // for each strip
m_pD3DDev->DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP, 0, kNumVertices,
i*kNumIndicesPerFace + j*2*(kNumQuadsPerSide+1),
kNumTrisPerStrip);
}
// then take the just rendered texture and generate blurred versions
D3DXMATRIX matView;
D3DXMATRIX matProj;
D3DXMATRIX matViewProj;
D3DXMATRIX matWorldViewProj;
hr = SetBlurRenderState();
D3DXVECTOR3 const vEyePt = D3DXVECTOR3( 0.0f, 0.0f, -5.0f );
D3DXVECTOR3 const vLookatPt = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );
// Set World, View, Projection, and combination matrices.
D3DXMatrixLookAtLH(&matView, &vEyePt, &vLookatPt, &vUp);
D3DXMatrixOrthoLH(&matProj, 4.0f, 4.0f, 0.2f, 20.0f);
D3DXMatrixMultiply(&matViewProj, &matView, &matProj);
// draw a single quad to texture: the quad covers the whole "screen" exactly
D3DXMatrixScaling(&matWorld, 2.0f, 2.0f, 1.0f);
D3DXMatrixMultiply(&matWorldViewProj, &matWorld, &matViewProj);
D3DXMatrixTranspose(&matWorldViewProj, &matWorldViewProj);
m_pD3DDev->SetVertexShaderConstant(CV_WORLDVIEWPROJ_0, &matWorldViewProj(0, 0), 4);
// write to constant memory to use the box9-filter
D3DXVECTOR4 offset(1.0f, 0.0f, 0.0f, 0.0f);
m_pD3DDev->SetVertexShaderConstant(CV_UV_OFFSET_TO_USE, &offset, 1);
// mpFilterTarget[0] is the full-res texture
// make mpFilterTarget[1] = blur^kNumOfFilterSteps( mpFilterTarget[0] )
// make mpFilterTarget[2] = blur^kNumOfFilterSteps( mpFilterTarget[1] )
IDirect3DTexture8 *pSource;
IDirect3DSurface8 *pDestination;
for (i = 1; i < 3; ++i) // this loop is for generating mpFilterTarget[i]
{
for (j = 0; j < kNumOfFilterSteps; ++j) // this loop does several blur passes
{
// alternate source and destination
pSource = mpTempTexture[ j %2];
pDestination = mpTempTarget [(j+1)%2];
if (j == 0) // first time thru
pSource = mpTextureFiltered[i-1];
else if (j == kNumOfFilterSteps-1) // last time thru
pDestination = mpFilterTarget[i];
// using the source and destination pointers set-up the render-state
hr = m_pD3DDev->SetRenderTarget(pDestination, NULL);
for (k = 0; k < 4; ++k)
m_pD3DDev->SetTexture(k, pSource);
// no need to clear the buffer: z-test is off: thus everything is overwritten
// now just draw the quad with displaced texture coordinates
hr = m_pD3DDev->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
}
}
// then render a single quad to the back-buffer.
// this quad uses a special depth of field blend pixel filter
hr = m_pD3DDev->SetRenderTarget(mpBackbufferColor, NULL);
// again, z-test is still off, so all is overwritten -- no need to clear
m_pD3DDev->SetVertexShader(m_dwBlurVertexShader);
if (meDisplayOption == SHOW_COLORS)
m_pD3DDev->SetPixelShader(m_dwDepthOfFieldPixelShader);
else
m_pD3DDev->SetPixelShader(m_dwShowBlurrinessShader);
m_pD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
// use the original and blurred textures
for (i = 0; i < 3; ++i)
{
m_pD3DDev->SetTexture(i, mpTextureFiltered[i]);
m_pD3DDev->SetTextureStageState(i, D3DTSS_MIPFILTER, D3DTEXF_NONE );
m_pD3DDev->SetTextureStageState(i, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
m_pD3DDev->SetTextureStageState(i, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
}
m_pD3DDev->SetTexture(3, NULL);
D3DXMatrixScaling(&matWorld, 2.0f, 2.0f, 1.0f);
D3DXMatrixMultiply(&matWorldViewProj, &matWorld, &matViewProj);
D3DXMatrixTranspose(&matWorldViewProj, &matWorldViewProj);
m_pD3DDev->SetVertexShaderConstant(CV_WORLDVIEWPROJ_0, &matWorldViewProj(0, 0), 4);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -