⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 shader_fog.cpp

📁 游戏编程精华02-含有几十个游戏编程例子
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		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 + -