📄 shader_fog.cpp
字号:
GetFilePath("sunol_right_mipmap.dds").c_str(),
D3DX_DEFAULT,
D3DX_DEFAULT,
0,
0,
D3DFMT_UNKNOWN,
D3DPOOL_MANAGED,
D3DX_FILTER_LINEAR,
D3DX_FILTER_LINEAR,
0,
NULL,
NULL,
&m_pWorldTextures[D3DCUBEMAP_FACE_POSITIVE_X]);
if (FAILED(hr))
{
m_strLastError = "Could not create sunol_right_mipmap.dds";
return hr;
}
hr = D3DXCreateTextureFromFileEx(m_pD3DDev,
GetFilePath("sunol_left_mipmap.dds").c_str(),
D3DX_DEFAULT,
D3DX_DEFAULT,
0,
0,
D3DFMT_UNKNOWN,
D3DPOOL_MANAGED,
D3DX_FILTER_LINEAR,
D3DX_FILTER_LINEAR,
0,
NULL,
NULL,
&m_pWorldTextures[D3DCUBEMAP_FACE_NEGATIVE_X]);
if (FAILED(hr))
{
m_strLastError = "Could not create sunol_left_mipmap.dds";
return hr;
}
m_pWorldBoxVertices->Unlock();
m_pWorldBoxIndices->Unlock();
hr = m_pD3DDev->CreateTexture(m_dwFogMapWidth, m_dwFogMapHeight, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &m_pFogMap);
if (FAILED(hr))
return hr;
// Create a big square for rendering the fogmap
if( FAILED( m_pD3DDev->CreateVertexBuffer( 4*sizeof(TLVertex), D3DUSAGE_WRITEONLY, D3DFVF_TLVERTEX,
D3DPOOL_MANAGED, &m_pFogMapVB ) ) )
return E_FAIL;
// Create a quad for the final pass
TLVertex* v;
FLOAT sx = 100.0f;
FLOAT sy = 100.0f;
m_pFogMapVB->Lock( 0, 0, (BYTE**)&v, 0 );
v[0].Position = D3DXVECTOR4(0, sy, 0, 1);
v[0].Diffuse = 0x0;
v[0].Specular = 0;
v[0].Texture = D3DXVECTOR2(1, 1);
v[1].Position = D3DXVECTOR4(0, 0, 0, 1);
v[1].Diffuse = 0x0;
v[1].Specular = 0;
v[1].Texture = D3DXVECTOR2(1, 0);
v[2].Position = D3DXVECTOR4(sx, sy, 0, 1);
v[2].Diffuse = 0x0;
v[2].Specular = 0;
v[2].Texture = D3DXVECTOR2(0, 1);
v[3].Position = D3DXVECTOR4(sx, 0, 0, 1);
v[3].Diffuse = 0x0;
v[3].Specular = 0;
v[3].Texture = D3DXVECTOR2(0, 0);
m_pFogMapVB->Unlock();
// Load a ground object
m_pRoom = new NVFile();
if( FAILED( m_pRoom->Create(m_pNVDevice, GetFilePath("room.x") ) ) )
{
m_strLastError = "Could not load room.x";
return E_FAIL;
}
ZeroMemory(&m_RoomBounds, sizeof(NVBounds));
m_pRoom->GetBoundingInfo(&m_RoomBounds);
m_pChair = new NVFile();
if( FAILED( m_pChair->Create(m_pNVDevice, GetFilePath("chair.x") ) ) )
{
m_strLastError = "Could not load chair.x";
return E_FAIL;
}
ZeroMemory(&m_ChairBounds, sizeof(NVBounds));
m_pChair->GetBoundingInfo(&m_ChairBounds);
m_pTable = new NVFile();
if( FAILED( m_pTable->Create(m_pNVDevice, GetFilePath("table.x") ) ) )
{
m_strLastError = "Could not load table.x";
return E_FAIL;
}
ZeroMemory(&m_TableBounds, sizeof(NVBounds));
m_pTable->GetBoundingInfo(&m_TableBounds);
m_pChair->SetTexture(m_pFogMap);
m_pTable->SetTexture(m_pFogMap);
m_pNVDevice->SetProjectionTransform(&m_pCamera->GetProjectionMatrix());
for (DWORD i = 0; i < NUM_CHAIRS; i++)
{
m_vecChairs[i] = D3DXVECTOR4((2.5f * sin((i / (float)NUM_CHAIRS) * (D3DX_PI * 2.0f))),
-(m_vecRoomDimensions.y * 0.5f) + (m_vecChairDimensions.y * 0.5f),
(2.5f * cos((i / (float)NUM_CHAIRS) * (D3DX_PI * 2.0f))) ,
((i / (float)NUM_CHAIRS) * (D3DX_PI * 2.0f)) );
}
ZeroMemory(&m_bKey[0], sizeof(bool) * MAX_VKEY);
D3DXVECTOR4 vecFogScale = m_vecRoomDimensions;
// Height scale and shift
vecFogScale.y = 1.0f / (vecFogScale.y);
vecFogScale.x = (m_vecRoomDimensions.y * 0.5f);
// Distance scale
vecFogScale.z = (1.0f / (sqrt((vecFogScale.x * vecFogScale.x) + (vecFogScale.z * vecFogScale.z))));
m_pD3DDev->SetVertexShaderConstant(CV_FOG_SCALE, &vecFogScale.x, 1);
m_pRoom->SetFVF(m_pNVDevice, FOGVERTEX_FVF);
m_pTable->SetFVF(m_pNVDevice, FOGVERTEX_FVF);
m_pChair->SetFVF(m_pNVDevice, FOGVERTEX_FVF);
m_pRoom->RestoreDeviceObjects(m_pNVDevice);
m_pTable->RestoreDeviceObjects(m_pNVDevice);
m_pChair->RestoreDeviceObjects(m_pNVDevice);
return S_OK;
}
HRESULT CShaderFog::BuildFogMap()
{
LPDIRECT3DTEXTURE8 pTexture;
m_pFogMap->QueryInterface(IID_IDirect3DTexture8, (void**)&pTexture);
D3DLOCKED_RECT LockedRect;
pTexture->LockRect(0, &LockedRect, NULL, 0);
const float fHeightScale = m_vecRoomDimensions.y;
const float fRangeScale = sqrt((m_vecRoomDimensions.x * m_vecRoomDimensions.x) +
(m_vecRoomDimensions.z * m_vecRoomDimensions.z));
D3DXVECTOR3 CameraPosition = m_pCamera->GetCameraPosition();
const float fEyeHeight = (CameraPosition.y + (m_vecRoomDimensions.y * 0.5f));
const float fFogBottom = 0.0f;
const float fFogTop = ((m_vecChairDimensions.y) + fFogBottom);
const float fFogHeight = (fFogTop - fFogBottom);
float fDeltaD;
float fDeltaY;
DWORD dwColor = 0xFFFFFF;
float fDensityIntegral;
float fVertexHeight;
float fVertexRange;
float fFog;
for (int y = 0; y < m_dwFogMapHeight; y++)
{
fVertexHeight = ((float)y / (float)m_dwFogMapHeight) * fHeightScale;
for (int x = 0; x < m_dwFogMapWidth; x++)
{
fVertexRange = ((float)x / (float)m_dwFogMapWidth) * fRangeScale;
fDeltaD = fVertexRange;
// fVertexHeight = height above ground of vertex
// fVertexRange = distance from viewer to vertex
if (fEyeHeight > fFogTop)
{
if (fVertexHeight < fFogTop)
{
fDeltaY = fFogTop - fVertexHeight;
fDensityIntegral = (fDeltaY * fDeltaY * 0.5f);
dwColor = 0xFF;
}
else
{
fDeltaY = 0.0f;
fDensityIntegral = 0.0f;
}
}
else
{
if (fVertexHeight < fFogTop)
{
float fDeltaA = fFogTop - fEyeHeight;
float fDeltaB = fFogTop - fVertexHeight;
fDeltaY = fabs(fDeltaA - fDeltaB);
fDensityIntegral = fabs((fDeltaA * fDeltaA * 0.5f) - (fDeltaB * fDeltaB * 0.5f));
dwColor = 0xFF00;
}
else
{
fDeltaY = fabs(fFogTop - fEyeHeight);
fDensityIntegral = fabs(fDeltaY * fDeltaY * 0.5f);
dwColor = 0xFF0000;
}
}
dwColor = 0xFFFFFF;
assert(fDeltaD >= 0.0f);
assert(fDeltaY >= 0.0f);
assert(fDensityIntegral >= 0.0f);
fDensityIntegral*= 0.25f;
if (fDeltaY != 0.0f)
{
fFog = (sqrt(1.0f + ((fDeltaD / fDeltaY) * (fDeltaD / fDeltaY)))) * fDensityIntegral;
}
else
{
fFog = 0.0f;//fDeltaD * fEyeHeight;
}
fFog = 1.0f - exp(-fFog);
DWORD dwOutput = dwColor | (((DWORD)((fFog) * (float)0xFF)) << 24);
*(((DWORD*)LockedRect.pBits) + (y * m_dwFogMapHeight) + x) = m_bEnableFog ? dwOutput : 0;
}
}
pTexture->UnlockRect(0);
SAFE_RELEASE(pTexture);
return S_OK;
}
HRESULT CShaderFog::DrawFogMap()
{
// Draw the background
m_pD3DDev->SetTexture(0, m_pFogMap );
m_pD3DDev->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_BLENDTEXTUREALPHA);
m_pD3DDev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
m_pD3DDev->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
m_pD3DDev->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
m_pD3DDev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
m_pD3DDev->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
m_pD3DDev->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0);
m_pD3DDev->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
m_pD3DDev->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
m_pD3DDev->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_NONE);
m_pD3DDev->SetRenderState(D3DRS_ZENABLE, FALSE);
m_pD3DDev->SetStreamSource(0, m_pFogMapVB, sizeof(TLVertex));
m_pD3DDev->SetVertexShader(D3DFVF_TLVERTEX);
m_pD3DDev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2 );
// Restore render states
m_pD3DDev->SetRenderState(D3DRS_ZENABLE, TRUE);
return S_OK;
}
HRESULT CShaderFog::Free()
{
for (int i = 0; i < 6; i++)
{
SAFE_RELEASE(m_pWorldTextures[i]);
}
SAFE_RELEASE(m_pWorldBoxVertices);
SAFE_RELEASE(m_pWorldBoxIndices);
SAFE_RELEASE(m_pFogMapVB);
SAFE_RELEASE(m_pFogMap);
SAFE_DELETE(m_pRoom);
SAFE_DELETE(m_pChair);
SAFE_DELETE(m_pTable);
SAFE_DELETE(m_pNVDevice);
SAFE_DELETE(m_pCamera);
if (m_pD3DDev)
{
m_pD3DDev->DeleteVertexShader(m_dwWorldShader);
m_pD3DDev->DeleteVertexShader(m_dwFogShader);
SAFE_RELEASE(m_pD3DDev);
}
return S_OK;
}
HRESULT CShaderFog::Start()
{
return S_OK;
}
HRESULT CShaderFog::SetTransform()
{
D3DXMATRIX matTemp;
D3DXMATRIX matWorldViewProj;
D3DXMATRIX matWorldView;
D3DXMATRIX matWorldViewIT;
D3DXMATRIX matWorld = m_pNVDevice->GetWorldTransform();
D3DXMATRIX matView = m_pNVDevice->GetViewTransform();
D3DXMATRIX matProj = m_pNVDevice->GetProjectionTransform();
D3DXMatrixMultiply(&matTemp, &matWorld, &matView);
D3DXMatrixMultiply(&matWorldViewProj, &matTemp, &matProj);
D3DXMatrixMultiply(&matWorldView, &matWorld, &matView);
// Create a 3x3 invertse of the worldview for the normal transformation (we transpose it as we load it into
// the constant store)
D3DXMatrixInverse(&matWorldViewIT, NULL, &matWorldView);
// Projection to clip space
D3DXMatrixTranspose(&matWorldViewProj, &matWorldViewProj);
m_pD3DDev->SetVertexShaderConstant(CV_WORLDVIEWPROJ_0, &matWorldViewProj(0, 0), 4);
D3DXMatrixTranspose(&matWorldViewProj, &matWorldViewProj);
// Transform to eye space
D3DXMatrixTranspose(&matWorld, &matWorld);
m_pD3DDev->SetVertexShaderConstant(CV_WORLD_0, &matWorld(0, 0), 4);
D3DXMatrixTranspose(&matWorld, &matWorld);
// Transform to eye space
D3DXMatrixTranspose(&matWorldView, &matWorldView);
m_pD3DDev->SetVertexShaderConstant(CV_WORLDVIEW_0, &matWorldView(0, 0), 4);
D3DXMatrixTranspose(&matWorldView, &matWorldView);
// Transform from eye to projection
D3DXMatrixTranspose(&matProj, &matProj);
m_pD3DDev->SetVertexShaderConstant(CV_PROJ_0, &matProj(0, 0), 4);
D3DXMatrixTranspose(&matProj, &matProj);
// Transform for normals
m_pD3DDev->SetVertexShaderConstant(CV_WORLDVIEWIT_0, &matWorldViewIT(0, 0), 1);
m_pD3DDev->SetVertexShaderConstant(CV_WORLDVIEWIT_1, &matWorldViewIT(1, 0), 1);
m_pD3DDev->SetVertexShaderConstant(CV_WORLDVIEWIT_2, &matWorldViewIT(2, 0), 1);
// Sometimes we don't need the shader - just draw with the current world/view/projection matrices
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -