Game client codebase including: - CharacterActionControl: Character and creature management - GlobalScript: Network, items, skills, quests, utilities - RYLClient: Main client application with GUI and event handlers - Engine: 3D rendering engine (RYLGL) - MemoryManager: Custom memory allocation - Library: Third-party dependencies (DirectX, boost, etc.) - Tools: Development utilities 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1144 lines
39 KiB
C++
1144 lines
39 KiB
C++
//-----------------------------------------------------------------------------
|
|
// File: main.cpp
|
|
//
|
|
// Desc: Example code showing a technique for rendering volumetric fog in D3D.
|
|
//
|
|
// Copyright (c) 1999-2001 Microsoft Corporation. All rights reserved.
|
|
//-----------------------------------------------------------------------------
|
|
#define STRICT
|
|
#include <tchar.h>
|
|
#include <math.h>
|
|
#include <stdio.h>
|
|
#include <d3dx8.h>
|
|
#include "d3dapp.h"
|
|
#include "d3dfont.h"
|
|
#include "dxutil.h"
|
|
|
|
#define RENDERTARGSIZE 512
|
|
|
|
|
|
// Maintains a set of triangles - its vertices and indices
|
|
struct TRIANGLESET
|
|
{
|
|
LPDIRECT3DINDEXBUFFER8 pIndexBuffer;
|
|
LPDIRECT3DVERTEXBUFFER8 pVertexBuffer;
|
|
DWORD dwNumVertices;
|
|
DWORD dwNumTriangles;
|
|
D3DXVECTOR3 Center;
|
|
FLOAT fRadius;
|
|
};
|
|
|
|
struct FILEVERTEX
|
|
{
|
|
FLOAT x,y,z;
|
|
FLOAT nx,ny,nz;
|
|
};
|
|
|
|
#define D3DFVF_FILEVERTEX (D3DFVF_XYZ | D3DFVF_NORMAL)
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: class CMyD3DApplication
|
|
// Desc: Application class. The base class (CD3DApplication) provides the
|
|
// generic functionality needed in all Direct3D samples. CMyD3DApplication
|
|
// adds functionality specific to this sample program.
|
|
//-----------------------------------------------------------------------------
|
|
class CMyD3DApplication : public CD3DApplication
|
|
{
|
|
protected:
|
|
D3DXMATRIX m_matObject;
|
|
D3DXMATRIX m_matView;
|
|
D3DXMATRIX m_matProj;
|
|
D3DXMATRIX m_matShadObject;
|
|
|
|
BOOL m_bInsideFog;
|
|
BOOL m_bUsePicShader;
|
|
BOOL m_bDrawHelp;
|
|
|
|
LPDIRECT3DVERTEXBUFFER8 m_pScreenVertBuf;
|
|
LPDIRECT3DVERTEXBUFFER8 m_pScreenVertBuf2;
|
|
LPDIRECT3DSURFACE8 m_pOldRenderTarget;
|
|
LPDIRECT3DSURFACE8 m_pOldStencilZ;
|
|
LPDIRECT3DSURFACE8 m_pTargetZ;
|
|
|
|
TRIANGLESET m_FogVolume;
|
|
TRIANGLESET m_MeshShaderObject;
|
|
|
|
BYTE m_bKey[256];
|
|
D3DXVECTOR3 m_vVelocity;
|
|
FLOAT m_fYawVelocity;
|
|
FLOAT m_fPitchVelocity;
|
|
D3DXMATRIX m_matOrientation;
|
|
D3DXVECTOR3 m_vPosition;
|
|
FLOAT m_fYaw;
|
|
FLOAT m_fPitch;
|
|
|
|
LPDIRECT3DTEXTURE8 m_pBackFogDist;
|
|
LPDIRECT3DTEXTURE8 m_pFrontFogDist;
|
|
LPDIRECT3DTEXTURE8 m_pSceneDist;
|
|
LPDIRECT3DTEXTURE8 m_pTempDist;
|
|
|
|
LPDIRECT3DTEXTURE8 m_pStepTexture;
|
|
|
|
LPD3DXBUFFER m_pCodeFogShader;
|
|
LPD3DXBUFFER m_pCodeFogShader2;
|
|
LPD3DXBUFFER m_pCodeSubPicShader;
|
|
|
|
DWORD m_dwFogShader;
|
|
DWORD m_dwFogShader2;
|
|
DWORD m_dwSubPicShader;
|
|
|
|
LPD3DXMESH m_pMeshObject;
|
|
|
|
CD3DFont* m_pFont;
|
|
CD3DFont* m_pFontSmall;
|
|
|
|
public:
|
|
CMyD3DApplication();
|
|
virtual HRESULT InitDeviceObjects();
|
|
virtual HRESULT RestoreDeviceObjects();
|
|
virtual HRESULT InvalidateDeviceObjects();
|
|
virtual HRESULT DeleteDeviceObjects();
|
|
virtual HRESULT FrameMove();
|
|
virtual HRESULT Render();
|
|
virtual LRESULT MsgProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
|
|
virtual HRESULT ConfirmDevice( D3DCAPS8*, DWORD, D3DFORMAT );
|
|
HRESULT SetFogMatrices();
|
|
HRESULT SetObjMatrices();
|
|
HRESULT LoadXFile(TCHAR*, TRIANGLESET *);
|
|
HRESULT ComputeStepTexture();
|
|
};
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: WinMain()
|
|
// Desc: Entry point to the program. Initializes everything, and goes into a
|
|
// message-processing loop. Idle time is used to render the scene.
|
|
//-----------------------------------------------------------------------------
|
|
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
|
|
{
|
|
CMyD3DApplication d3dApp;
|
|
|
|
if( FAILED( d3dApp.Create( hInst ) ) )
|
|
return 0;
|
|
|
|
return d3dApp.Run();
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: CMyD3DApplication()
|
|
// Desc: Application constructor. Sets attributes for the app.
|
|
//-----------------------------------------------------------------------------
|
|
CMyD3DApplication::CMyD3DApplication()
|
|
{
|
|
m_bUseDepthBuffer = TRUE;
|
|
|
|
m_strWindowTitle = _T("VolumeFog");
|
|
|
|
m_pFont = new CD3DFont( _T("Arial"), 12, D3DFONT_BOLD );
|
|
m_pFontSmall = new CD3DFont( _T("Arial"), 9, D3DFONT_BOLD );
|
|
|
|
for(int i=0;i<256;i++)
|
|
m_bKey[i] = FALSE;
|
|
|
|
D3DXMatrixIdentity(&m_matObject);
|
|
D3DXMatrixIdentity(&m_matView);
|
|
D3DXMatrixIdentity(&m_matProj);
|
|
D3DXMatrixIdentity(&m_matShadObject);
|
|
|
|
m_vPosition = D3DXVECTOR3( 0.0f, 0.0f,-4.0f );
|
|
m_vVelocity = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );
|
|
m_fYaw = 0.0f;
|
|
m_fYawVelocity = 0.0f;
|
|
m_fPitch = 0.0f;
|
|
m_fPitchVelocity = 0.0f;
|
|
m_bDrawHelp = FALSE;
|
|
|
|
m_pOldRenderTarget = NULL;
|
|
m_pOldStencilZ = NULL;
|
|
m_pScreenVertBuf = NULL;
|
|
m_pBackFogDist = NULL;
|
|
m_pSceneDist = NULL;
|
|
m_pTempDist = NULL;
|
|
m_pFrontFogDist = NULL;
|
|
m_pTargetZ = NULL;
|
|
m_pMeshObject = NULL;
|
|
m_pStepTexture = NULL;
|
|
m_pCodeFogShader = NULL;
|
|
m_pCodeFogShader2 = NULL;
|
|
m_pCodeSubPicShader= NULL;
|
|
m_pScreenVertBuf = NULL;
|
|
m_pScreenVertBuf2 = NULL;
|
|
m_dwFogShader = 0;
|
|
m_dwFogShader2 = 0;
|
|
m_dwSubPicShader = 0;
|
|
|
|
memset(&m_MeshShaderObject,0,sizeof(m_MeshShaderObject));
|
|
memset(&m_FogVolume,0,sizeof(m_FogVolume));
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: ConfirmDevice()
|
|
// Desc: Called during device intialization, this code checks the device
|
|
// for some minimum set of capabilities
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT CMyD3DApplication::ConfirmDevice( D3DCAPS8* pCaps, DWORD dwBehavior,
|
|
D3DFORMAT Format )
|
|
{
|
|
if( (dwBehavior & D3DCREATE_HARDWARE_VERTEXPROCESSING ) ||
|
|
(dwBehavior & D3DCREATE_MIXED_VERTEXPROCESSING ) )
|
|
{
|
|
if( pCaps->VertexShaderVersion < D3DVS_VERSION(1,0) )
|
|
return E_FAIL;
|
|
}
|
|
|
|
if( pCaps->PixelShaderVersion < D3DPS_VERSION(1,1) )
|
|
return E_FAIL;
|
|
|
|
if( dwBehavior & D3DCREATE_PUREDEVICE)
|
|
return E_FAIL;
|
|
|
|
if( Format != D3DFMT_A8R8G8B8 && Format != D3DFMT_X8R8G8B8 && Format != D3DFMT_R8G8B8 )
|
|
return E_FAIL;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: MsgProc()
|
|
// Desc: Process windows messages.
|
|
//-----------------------------------------------------------------------------
|
|
LRESULT CMyD3DApplication::MsgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch(uMsg)
|
|
{
|
|
case WM_KEYUP:
|
|
m_bKey[wParam] = FALSE;
|
|
if( wParam == VK_F1 )
|
|
m_bDrawHelp = !m_bDrawHelp;
|
|
break;
|
|
|
|
case WM_KEYDOWN:
|
|
m_bKey[wParam] = TRUE;
|
|
break;
|
|
}
|
|
|
|
return CD3DApplication::MsgProc( hwnd, uMsg, wParam, lParam );
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: ComputeStepTexture()
|
|
// Desc: This computes a step texture - used for high precision fogging. The
|
|
// step texture is a 4096 texture which incrementes from 0 to 4095. This
|
|
// is used because on a triangle basis - the texture interpolaters are
|
|
// much higher precision then the color interpolaters. Since we need a
|
|
// higher precision then 8 bits, we need a way to load in more bits into
|
|
// every pixel. This is only way to do it on an 8 bit card.
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT CMyD3DApplication::ComputeStepTexture()
|
|
{
|
|
D3DLOCKED_RECT Lock;
|
|
HRESULT hr;
|
|
unsigned int Width = 4096;
|
|
unsigned int Height = 8;
|
|
unsigned char *pLine,*pBase;
|
|
unsigned int x,y;
|
|
float widthRatio = 1.0f;
|
|
unsigned int scaledX;
|
|
|
|
if( FAILED( hr = D3DXCreateTexture( m_pd3dDevice, Width, Height, 1, 0, D3DFMT_A8R8G8B8,
|
|
D3DPOOL_MANAGED, &m_pStepTexture ) ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
// Adjust Width if D3DXCreateTexture had to pick a different texture
|
|
// width. Texture contents will still go up to 4096, though.
|
|
D3DSURFACE_DESC desc;
|
|
m_pStepTexture->GetLevelDesc( 0, &desc );
|
|
if( desc.Width != Width)
|
|
{
|
|
widthRatio = (float)Width / (float)desc.Width;
|
|
Width = desc.Width;
|
|
}
|
|
|
|
if( FAILED( hr = m_pStepTexture->LockRect( 0, &Lock, NULL, 0 ) ) )
|
|
{
|
|
m_pStepTexture->Release();
|
|
return hr;
|
|
}
|
|
|
|
pBase = (unsigned char *)Lock.pBits;
|
|
|
|
for( y = 0; y < Height; y++ )
|
|
{
|
|
pLine = &pBase[y*Lock.Pitch];
|
|
for( x = 0; x < Width; x++ )
|
|
{
|
|
scaledX = (unsigned int)( widthRatio * (float)x );
|
|
pLine[0] = scaledX & 0xF; // red, lower 4 bits
|
|
pLine[2] = (scaledX & 0xFF0) >> 4; // blue, upper 8 bits
|
|
pLine[1] = 0; // green
|
|
pLine[3] = 255; // alpha
|
|
pLine += 4;
|
|
}
|
|
}
|
|
|
|
m_pStepTexture->UnlockRect(0);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: LoadXFile()
|
|
// Desc: This loads an xfile into the TRIANGLESET structure. It is not enough
|
|
// to render an X-File blindly since the the data must be fed into our
|
|
// vertex shader.
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT CMyD3DApplication::LoadXFile(TCHAR *pModel,TRIANGLESET *pTriSet)
|
|
{
|
|
LPD3DXBUFFER pbufMaterials = NULL;
|
|
LPD3DXBUFFER pbufAdjacency = NULL;
|
|
LPDIRECT3DVERTEXBUFFER8 pVertexBuffer = NULL;
|
|
LPDIRECT3DINDEXBUFFER8 pIndexBuffer = NULL;
|
|
D3DINDEXBUFFER_DESC IndexDesc;
|
|
DWORD cMaterials;
|
|
DWORD dwDecl[100];
|
|
BYTE* pSourceI;
|
|
BYTE* pDestI;
|
|
LPD3DXMESH pMeshSysMem = NULL;
|
|
LPD3DXMESH pTempMesh = NULL;
|
|
HRESULT hr;
|
|
FILEVERTEX* pVert;
|
|
FILEVERTEX* pSource;
|
|
DWORD dwGetFVF;
|
|
|
|
pTriSet->pVertexBuffer = NULL;
|
|
pTriSet->pIndexBuffer = NULL;
|
|
pVertexBuffer = NULL;
|
|
|
|
//load the x file
|
|
if( FAILED( hr = D3DXLoadMeshFromX( pModel, D3DXMESH_SYSTEMMEM,
|
|
m_pd3dDevice, &pbufAdjacency, &pbufMaterials, &cMaterials, &pTempMesh ) ) )
|
|
{
|
|
goto FAIL;
|
|
}
|
|
|
|
dwGetFVF = pTempMesh->GetFVF();
|
|
|
|
// Change it to a mesh that has this vertex format if it is not that way
|
|
if(dwGetFVF != D3DFVF_FILEVERTEX)
|
|
{
|
|
D3DXDeclaratorFromFVF(D3DFVF_FILEVERTEX, dwDecl);
|
|
|
|
hr = pTempMesh->CloneMesh(0,dwDecl,m_pd3dDevice,&pMeshSysMem);
|
|
pTempMesh->Release();
|
|
if( FAILED( hr ) )
|
|
goto FAIL;
|
|
}
|
|
else
|
|
{
|
|
pMeshSysMem = pTempMesh;
|
|
}
|
|
|
|
pTriSet->dwNumTriangles = pMeshSysMem->GetNumFaces();
|
|
pTriSet->dwNumVertices = pMeshSysMem->GetNumVertices();
|
|
|
|
// Now copy the vertex buffers and index buffers into new ones that
|
|
// have things set the way we want
|
|
|
|
if( FAILED( hr = pMeshSysMem->GetVertexBuffer( &pVertexBuffer ) ) )
|
|
goto FAIL;
|
|
|
|
hr = m_pd3dDevice->CreateVertexBuffer( sizeof(FILEVERTEX) * pTriSet->dwNumVertices,
|
|
D3DUSAGE_WRITEONLY, D3DFVF_FILEVERTEX, D3DPOOL_MANAGED,
|
|
&(pTriSet->pVertexBuffer ) );
|
|
if( FAILED( hr ) )
|
|
goto FAIL;
|
|
|
|
hr = pTriSet->pVertexBuffer->Lock( 0, sizeof(FILEVERTEX)*pTriSet->dwNumVertices, (BYTE**)(&pVert), 0 );
|
|
if( FAILED( hr ) )
|
|
goto FAIL;
|
|
|
|
hr = pVertexBuffer->Lock(0, sizeof(FILEVERTEX)*pTriSet->dwNumVertices, (BYTE**)&pSource, 0);
|
|
if( FAILED( hr ) )
|
|
goto FAIL;
|
|
|
|
memcpy( pVert, pSource, sizeof(FILEVERTEX) * pTriSet->dwNumVertices );
|
|
|
|
D3DXComputeBoundingSphere( pVert, pTriSet->dwNumVertices, D3DFVF_FILEVERTEX,
|
|
&(pTriSet->Center), &(pTriSet->fRadius) );
|
|
|
|
pVertexBuffer->Unlock();
|
|
pTriSet->pVertexBuffer->Unlock();
|
|
|
|
if( FAILED( hr = pMeshSysMem->GetIndexBuffer( &pIndexBuffer ) ) )
|
|
goto FAIL;
|
|
|
|
pIndexBuffer->GetDesc(&IndexDesc);
|
|
|
|
if( FAILED( hr = m_pd3dDevice->CreateIndexBuffer(IndexDesc.Size, D3DUSAGE_WRITEONLY,
|
|
IndexDesc.Format, D3DPOOL_MANAGED, &(pTriSet->pIndexBuffer) ) ) )
|
|
{
|
|
goto FAIL;
|
|
}
|
|
|
|
pIndexBuffer->Lock(0, IndexDesc.Size, &pSourceI, 0);
|
|
pTriSet->pIndexBuffer->Lock(0, IndexDesc.Size, &pDestI, 0);
|
|
memcpy(pDestI, pSourceI, IndexDesc.Size);
|
|
|
|
pIndexBuffer->Unlock();
|
|
pTriSet->pIndexBuffer->Unlock();
|
|
|
|
//cleanup
|
|
SAFE_RELEASE(pbufMaterials);
|
|
SAFE_RELEASE(pbufAdjacency);
|
|
SAFE_RELEASE(pMeshSysMem);
|
|
SAFE_RELEASE(pVertexBuffer);
|
|
SAFE_RELEASE(pIndexBuffer);
|
|
|
|
return S_OK;
|
|
|
|
FAIL:
|
|
SAFE_RELEASE(pMeshSysMem);
|
|
SAFE_RELEASE(pVertexBuffer);
|
|
SAFE_RELEASE(pTriSet->pVertexBuffer);
|
|
SAFE_RELEASE(pTriSet->pIndexBuffer);
|
|
SAFE_RELEASE(pIndexBuffer);
|
|
SAFE_RELEASE(pbufMaterials);
|
|
SAFE_RELEASE(pbufAdjacency);
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: FrameMove()
|
|
// Desc: Called once per frame, the call is the entry point for animating
|
|
// the scene.
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT CMyD3DApplication::FrameMove()
|
|
{
|
|
FLOAT fElapsedTime;
|
|
|
|
if( m_fElapsedTime > 0.0f )
|
|
fElapsedTime = m_fElapsedTime;
|
|
else
|
|
fElapsedTime = 0.05f;
|
|
|
|
FLOAT fSpeed = 3.0f*fElapsedTime;
|
|
FLOAT fAngularSpeed = 1.0f*fElapsedTime;
|
|
|
|
// De-accelerate the camera movement (for smooth motion)
|
|
m_vVelocity *= 0.9f;
|
|
m_fYawVelocity *= 0.9f;
|
|
m_fPitchVelocity *= 0.9f;
|
|
|
|
// Process keyboard input
|
|
if( m_bKey[VK_RIGHT] ) m_vVelocity.x += fSpeed; // Slide Right
|
|
if( m_bKey[VK_LEFT] ) m_vVelocity.x -= fSpeed; // Slide Left
|
|
if( m_bKey[VK_UP] ) m_vVelocity.y += fSpeed; // Slide Up
|
|
if( m_bKey[VK_DOWN] ) m_vVelocity.y -= fSpeed; // Slide Down
|
|
if( m_bKey['W'] ) m_vVelocity.z += fSpeed; // Move Forward
|
|
if( m_bKey['S'] ) m_vVelocity.z -= fSpeed; // Move Backward
|
|
if( m_bKey['E'] ) m_fYawVelocity += fSpeed; // Turn Right
|
|
if( m_bKey['Q'] ) m_fYawVelocity -= fSpeed; // Turn Left
|
|
if( m_bKey['Z'] ) m_fPitchVelocity += fSpeed; // Turn Down
|
|
if( m_bKey['A'] ) m_fPitchVelocity -= fSpeed; // Turn Up
|
|
|
|
// Update the position vector
|
|
D3DXVECTOR3 vT = m_vVelocity * fSpeed;
|
|
D3DXVec3TransformNormal( &vT, &vT, &m_matOrientation );
|
|
m_vPosition += vT;
|
|
|
|
// Update the yaw-pitch-rotation vector
|
|
m_fYaw += fAngularSpeed * m_fYawVelocity;
|
|
m_fPitch += fAngularSpeed * m_fPitchVelocity;
|
|
|
|
// Set the view matrix
|
|
D3DXQUATERNION qR;
|
|
D3DXQuaternionRotationYawPitchRoll( &qR, m_fYaw, m_fPitch, 0.0f );
|
|
D3DXMatrixAffineTransformation( &m_matOrientation, 1.25f, NULL, &qR, &m_vPosition );
|
|
D3DXMatrixInverse( &m_matView, NULL, &m_matOrientation );
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: SetFogMatrices()
|
|
// Desc: Sets up the fog matrices, the matrices which represnet the fog volume's
|
|
// position. These have to be loaded into the right places in the vertex
|
|
// shader:
|
|
// 0-3 = object transformat matrix
|
|
// 16-19 = ObjectView
|
|
// 8-11 = Total matrix
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT CMyD3DApplication::SetFogMatrices()
|
|
{
|
|
D3DXMATRIX temp,tObject,m_matTot;
|
|
|
|
D3DXMatrixMultiply(&m_matTot, &m_matObject,&m_matView);
|
|
D3DXMatrixTranspose(&temp,&m_matTot);
|
|
m_pd3dDevice->SetVertexShaderConstant( 16,&temp, 4 );
|
|
|
|
D3DXMatrixMultiply(&m_matTot,&m_matTot,&m_matProj);
|
|
|
|
D3DXMatrixTranspose(&m_matTot,&m_matTot);
|
|
D3DXMatrixTranspose(&tObject,&m_matObject);
|
|
|
|
//these need to be tranposes
|
|
m_pd3dDevice->SetVertexShaderConstant( 0, &tObject, 4 );
|
|
m_pd3dDevice->SetVertexShaderConstant( 8, &m_matTot, 4 );
|
|
|
|
//the w clip distance
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: SetObjMatrices()
|
|
// Desc: Sets up the objects matrices, the matrices which represent the object
|
|
// (or the world) volume's position. These have to be loaded into the
|
|
// right places in the vertex shader:
|
|
// 0-3 = object transformation matrix
|
|
// 16-19 = ObjectView
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT CMyD3DApplication::SetObjMatrices()
|
|
{
|
|
D3DXMATRIX temp,tObject,m_matTot;
|
|
|
|
D3DXMatrixTranspose(&tObject,&m_matShadObject);
|
|
m_pd3dDevice->SetVertexShaderConstant( 0, &tObject, 4 );
|
|
|
|
D3DXMatrixMultiply(&m_matTot, &m_matShadObject,&m_matView);
|
|
D3DXMatrixTranspose(&temp,&m_matTot);
|
|
m_pd3dDevice->SetVertexShaderConstant( 16, &temp, 4 );
|
|
|
|
D3DXMatrixMultiply(&m_matTot,&m_matTot,&m_matProj);
|
|
|
|
D3DXMatrixTranspose(&m_matTot,&m_matTot);
|
|
m_pd3dDevice->SetVertexShaderConstant( 8, &m_matTot, 4 );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: Render()
|
|
// Desc: Called once per frame, the call is the entry point for 3d
|
|
// rendering. This function sets up render states, clears the
|
|
// viewport, and renders the scene.
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT CMyD3DApplication::Render()
|
|
{
|
|
D3DXVECTOR3 lightDir(1,0,0);
|
|
D3DXVECTOR3 sub;
|
|
D3DXVECTOR4 WClip;
|
|
|
|
HRESULT hr;
|
|
D3DXMATRIX temp,tObject,m_matTot;
|
|
LPDIRECT3DSURFACE8 pSurface;
|
|
D3DMATERIAL8 Mat;
|
|
|
|
D3DVIEWPORT8 ViewPort,OldPort;
|
|
VOID* pVerts;
|
|
D3DLIGHT8 myLight;
|
|
|
|
//WClip represents our near and far fog 'clipping' (the y index is the inverse of the rear
|
|
//clipping plane)
|
|
//planes. The higher precision one has a further clipping plane
|
|
|
|
WClip = D3DXVECTOR4(1,.015f,1,1);
|
|
|
|
// Compute the current viewport
|
|
// Since we might be on a pure device, we can't query it from the driver
|
|
OldPort.X = 0;
|
|
OldPort.Y = 0;
|
|
OldPort.Width = m_d3dsdBackBuffer.Width;
|
|
OldPort.Height = m_d3dsdBackBuffer.Height;
|
|
OldPort.MaxZ = 1;
|
|
OldPort.MinZ = 0;
|
|
|
|
FLOAT fAspectRatio = (FLOAT)OldPort.Width / (FLOAT) OldPort.Height;
|
|
|
|
D3DXMATRIX mat1,mat2;
|
|
|
|
// Update projection matrix for a changed aspect ratio
|
|
D3DXMatrixPerspectiveFovLH(&m_matProj, 0.75f, fAspectRatio, 1.0f, 100);
|
|
|
|
lightDir = D3DXVECTOR3(2.5f, 2.25f, -2.55f);
|
|
|
|
// Set up a set of points which represents the screen
|
|
static struct { FLOAT x,y,z,w; DWORD color; FLOAT u,v; } s_Verts[] =
|
|
{
|
|
{1.0f, 1.0f, 0.5f, 1.0f , D3DCOLOR_XRGB( 0xff, 0xff, 0x8f ), 1,0 },
|
|
{1.0f, -1.0f, 0.5f, 1.0f, D3DCOLOR_XRGB( 0xff, 0xff, 0x8f), 1,1},
|
|
{ -1.0f, 1.0f, 0.5f, 1.0f, D3DCOLOR_XRGB( 0xff, 0xff, 0x8f), 0,0},
|
|
{ -1.0f, -1.0f, 0.5f, 1.0f, D3DCOLOR_XRGB( 0xff, 0xff, 0x8f), 0,1},
|
|
};
|
|
|
|
if( FAILED( hr = m_pScreenVertBuf->Lock( 0, sizeof(s_Verts), (BYTE **)(&pVerts), 0 ) ) )
|
|
goto FAIL;
|
|
|
|
memcpy( (void*)pVerts, (void*)s_Verts, sizeof(s_Verts) );
|
|
|
|
if( FAILED( hr = m_pScreenVertBuf->Unlock() ) )
|
|
goto FAIL;
|
|
|
|
//set the fog clipping into the vertex shader's constant register #12
|
|
m_pd3dDevice->SetVertexShaderConstant( 12, &WClip, 1 );
|
|
|
|
m_pd3dDevice->BeginScene();
|
|
|
|
//now we render the first half of the fog scene - or rather, the back side of the
|
|
//fog. what will be left in the buffer after we are done is the w depth of the
|
|
//back fog volume
|
|
|
|
ViewPort.X = 0;
|
|
ViewPort.Y = 0;
|
|
ViewPort.Height = RENDERTARGSIZE;
|
|
ViewPort.Width = RENDERTARGSIZE;
|
|
ViewPort.MaxZ = 1;
|
|
ViewPort.MinZ = 0;
|
|
|
|
if( FAILED( hr = m_pScreenVertBuf2->Lock( 0, sizeof(s_Verts), (BYTE **)(&pVerts), 0 ) ) )
|
|
goto FAIL;
|
|
|
|
memcpy( (void*)pVerts, (void*)s_Verts, sizeof(s_Verts) );
|
|
|
|
if (FAILED(hr = m_pScreenVertBuf2->Unlock()) )
|
|
goto FAIL;
|
|
|
|
m_pd3dDevice->SetTexture(0,NULL);
|
|
m_pd3dDevice->SetTexture(1,NULL);
|
|
m_pd3dDevice->SetTexture(2,NULL);
|
|
m_pd3dDevice->SetTexture(3,NULL);
|
|
|
|
m_pd3dDevice->SetPixelShader(0);
|
|
|
|
//we will just use a special vertex shader to fill the color and alpha as our w depth using the
|
|
//step texture
|
|
m_pd3dDevice->SetRenderState(D3DRS_WRAP0, 0 );
|
|
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0 );
|
|
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
|
|
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
|
|
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
|
|
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
|
|
m_pd3dDevice->SetRenderState(D3DRS_TEXTUREFACTOR,0x01010101);
|
|
|
|
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_POINT );
|
|
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_POINT );
|
|
|
|
//use our step texture to get higher precision interpolating
|
|
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_NONE);
|
|
|
|
m_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
|
m_pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
|
|
|
|
m_pd3dDevice->SetTextureStageState(0,D3DTSS_ADDRESSU,D3DTADDRESS_CLAMP);
|
|
m_pd3dDevice->SetTextureStageState(0,D3DTSS_ADDRESSV,D3DTADDRESS_CLAMP);
|
|
|
|
m_pd3dDevice->SetTexture(0,m_pStepTexture);
|
|
m_pd3dDevice->SetTexture(1,NULL);
|
|
|
|
//set up tranform matrices for the fixed pipe.
|
|
//this only used for the rendering of the object
|
|
m_pd3dDevice->SetTransform(D3DTS_VIEW,&m_matView);
|
|
m_pd3dDevice->SetTransform(D3DTS_PROJECTION,&m_matProj );
|
|
m_pd3dDevice->SetTransform(D3DTS_WORLD,&m_matObject);
|
|
|
|
//Now we need to draw the scene, happens first to also set the Z
|
|
hr = m_pSceneDist->GetSurfaceLevel(0, &pSurface);
|
|
|
|
//first, render the scene with the depth encoding
|
|
hr = m_pd3dDevice->SetRenderTarget(pSurface, m_pTargetZ);
|
|
m_pd3dDevice->SetViewport(&ViewPort);
|
|
hr = m_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER ,
|
|
D3DCOLOR_ARGB( 0x00, 0x00, 0x00, 0x00), 1.0,0);
|
|
|
|
m_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
|
|
|
|
SetObjMatrices();
|
|
m_pd3dDevice->SetRenderState(D3DRS_TEXTUREFACTOR, 0x00000000);
|
|
m_pd3dDevice->SetIndices(m_MeshShaderObject.pIndexBuffer, 0);
|
|
m_pd3dDevice->SetStreamSource( 0,m_MeshShaderObject.pVertexBuffer, sizeof(FILEVERTEX) );
|
|
m_pd3dDevice->SetVertexShader(m_dwFogShader);
|
|
|
|
//no alpha blending since geometry is opaque
|
|
m_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
|
|
m_pd3dDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
|
|
m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE);
|
|
hr = m_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0,
|
|
m_MeshShaderObject.dwNumVertices, 0, m_MeshShaderObject.dwNumTriangles);
|
|
|
|
//Now Render the back side of the fog, the
|
|
//z buffer is the same as the one set by the geometry
|
|
//since elements of the fog behind the scene should not be rendered (sine they are not visible)
|
|
pSurface->Release();
|
|
hr = m_pBackFogDist->GetSurfaceLevel(0,&pSurface);
|
|
hr = m_pd3dDevice->SetRenderTarget(pSurface,m_pTargetZ);
|
|
hr = m_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB( 0x00, 0x00, 0x00, 0x00), 1.0,0);
|
|
|
|
SetFogMatrices();
|
|
|
|
//reverse the culling order to get the back side
|
|
m_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
|
|
|
|
//add up all the backsides, this is volumetric rendering so
|
|
//everythin is totally transparent, want to check Z Buffer,
|
|
//but not write to it.
|
|
m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE);
|
|
m_pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE, FALSE);
|
|
m_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
|
|
m_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
|
|
m_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
|
|
|
|
//the tfactor adds in the alpha so that we can keep track the number
|
|
//of times a pixel is in and out of a fog
|
|
m_pd3dDevice->SetRenderState(D3DRS_TEXTUREFACTOR, 0x10101010);
|
|
m_pd3dDevice->SetIndices(m_FogVolume.pIndexBuffer, 0);
|
|
m_pd3dDevice->SetStreamSource( 0, m_FogVolume.pVertexBuffer, sizeof(FILEVERTEX) );
|
|
m_pd3dDevice->SetVertexShader(m_dwFogShader);
|
|
hr = m_pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0,
|
|
m_FogVolume.dwNumVertices, 0, m_FogVolume.dwNumTriangles );
|
|
pSurface->Release();
|
|
|
|
//Now we need to draw the front end of the fog
|
|
//same concept as above, but htis time the front haves of the
|
|
//fog get drawned
|
|
hr = m_pFrontFogDist->GetSurfaceLevel(0, &pSurface);
|
|
hr = m_pd3dDevice->SetRenderTarget(pSurface, m_pTargetZ);
|
|
m_pd3dDevice->SetViewport(&ViewPort);
|
|
hr = m_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET ,
|
|
D3DCOLOR_ARGB( 0x00, 0x00, 0x00, 0x00), 1.0,0);
|
|
|
|
m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE);
|
|
m_pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE,FALSE);
|
|
m_pd3dDevice->SetRenderState(D3DRS_TEXTUREFACTOR, 0x10101010);
|
|
m_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);//DESTALPHA);
|
|
m_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
|
|
m_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
|
|
m_pd3dDevice->SetVertexShaderConstant(0, &tObject, 4);
|
|
m_pd3dDevice->SetVertexShaderConstant(8, &m_matTot, 4);
|
|
m_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
|
|
|
|
SetFogMatrices();
|
|
m_pd3dDevice->SetIndices(m_FogVolume.pIndexBuffer, 0);
|
|
m_pd3dDevice->SetStreamSource( 0, m_FogVolume.pVertexBuffer, sizeof(FILEVERTEX) );
|
|
m_pd3dDevice->SetVertexShader(m_dwFogShader);
|
|
hr = m_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0,
|
|
m_FogVolume.dwNumVertices, 0, m_FogVolume.dwNumTriangles);
|
|
pSurface->Release();
|
|
|
|
//first we render the object, or whatever solid objects
|
|
//we have in the scene. This will act as the back side of our
|
|
//fog if it happens to be in the fog volume
|
|
|
|
m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE);
|
|
m_pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE, FALSE);
|
|
|
|
m_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
|
|
m_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
|
|
m_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
|
|
|
|
//now we are ready to actually draw the scene
|
|
m_pd3dDevice->SetRenderTarget(m_pOldRenderTarget, m_pOldStencilZ);
|
|
m_pd3dDevice->SetViewport(&OldPort);
|
|
|
|
hr = m_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER ,
|
|
D3DCOLOR_ARGB( 0x00, 0x00, 0x00, 0x00), 1.0,0);
|
|
|
|
//first draw the scene as it is.
|
|
m_pd3dDevice->SetTransform(D3DTS_VIEW, &m_matView);
|
|
m_pd3dDevice->SetTransform(D3DTS_PROJECTION, &m_matProj );
|
|
m_pd3dDevice->SetTransform(D3DTS_WORLD, &m_matShadObject);
|
|
m_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
|
|
|
|
memset(&Mat,0,sizeof(Mat));
|
|
|
|
//generic light and generic scene.
|
|
myLight.Type = D3DLIGHT_DIRECTIONAL;
|
|
myLight.Diffuse.r = 0;
|
|
myLight.Diffuse.g = 1;
|
|
myLight.Diffuse.b = 0;
|
|
myLight.Diffuse.a = 1;
|
|
myLight.Range = 1000000;
|
|
myLight.Direction = D3DXVECTOR3(1,1,1);
|
|
|
|
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
|
|
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
|
|
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
|
|
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
|
|
|
|
m_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
|
|
m_pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
|
|
|
|
m_pd3dDevice->SetRenderState(D3DRS_LIGHTING, TRUE);
|
|
m_pd3dDevice->LightEnable(0, TRUE);
|
|
|
|
m_pd3dDevice->SetLight(0, &myLight);
|
|
|
|
Mat.Diffuse.r = 1;
|
|
Mat.Diffuse.b = 1;
|
|
Mat.Diffuse.g = 1;
|
|
Mat.Diffuse.a = 1;
|
|
|
|
m_pd3dDevice->SetMaterial(&Mat);
|
|
|
|
m_pd3dDevice->SetTexture(0, NULL);
|
|
m_pd3dDevice->SetTexture(1, NULL);
|
|
|
|
D3DVERTEXBUFFER_DESC vDesc;
|
|
m_MeshShaderObject.pVertexBuffer->GetDesc(&vDesc);
|
|
m_pd3dDevice->SetStreamSource( 0,m_MeshShaderObject.pVertexBuffer, sizeof(FILEVERTEX) );
|
|
m_pd3dDevice->SetIndices(m_MeshShaderObject.pIndexBuffer, 0);
|
|
m_pd3dDevice->SetVertexShader(D3DFVF_FILEVERTEX);
|
|
hr = m_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0,
|
|
m_MeshShaderObject.dwNumVertices, 0, m_MeshShaderObject.dwNumTriangles);
|
|
|
|
m_pd3dDevice->SetTexture(0, NULL);
|
|
m_pd3dDevice->SetTexture(1, NULL);
|
|
m_pd3dDevice->SetTexture(2, NULL);
|
|
m_pd3dDevice->SetTexture(3, NULL);
|
|
|
|
//draw the fog
|
|
//this uses a complex pixel shader which is fully commented
|
|
//this computes the amount of fog at every pixel on the screen
|
|
|
|
m_pd3dDevice->SetRenderTarget(m_pOldRenderTarget, m_pOldStencilZ);
|
|
m_pd3dDevice->SetViewport(&OldPort);
|
|
|
|
m_pd3dDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
|
|
m_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
|
|
|
|
m_pd3dDevice->SetRenderState(D3DRS_WRAP0, 0);
|
|
m_pd3dDevice->SetRenderState(D3DRS_WRAP1, 0);
|
|
m_pd3dDevice->SetRenderState(D3DRS_WRAP2, 0);
|
|
|
|
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_POINT );
|
|
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_POINT );
|
|
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_NONE);
|
|
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ADDRESSU,D3DTADDRESS_CLAMP);
|
|
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ADDRESSV,D3DTADDRESS_CLAMP);
|
|
|
|
m_pd3dDevice->SetTextureStageState( 1, D3DTSS_MINFILTER, D3DTEXF_POINT );
|
|
m_pd3dDevice->SetTextureStageState( 1, D3DTSS_MAGFILTER, D3DTEXF_POINT );
|
|
m_pd3dDevice->SetTextureStageState( 1, D3DTSS_MIPFILTER, D3DTEXF_NONE);
|
|
m_pd3dDevice->SetTextureStageState( 1, D3DTSS_ADDRESSU,D3DTADDRESS_CLAMP);
|
|
m_pd3dDevice->SetTextureStageState( 1, D3DTSS_ADDRESSV,D3DTADDRESS_CLAMP);
|
|
|
|
m_pd3dDevice->SetTextureStageState( 2, D3DTSS_MINFILTER, D3DTEXF_POINT );
|
|
m_pd3dDevice->SetTextureStageState( 2, D3DTSS_MAGFILTER, D3DTEXF_POINT );
|
|
m_pd3dDevice->SetTextureStageState( 2, D3DTSS_MIPFILTER, D3DTEXF_NONE);
|
|
m_pd3dDevice->SetTextureStageState( 2, D3DTSS_ADDRESSU,D3DTADDRESS_CLAMP);
|
|
m_pd3dDevice->SetTextureStageState( 2, D3DTSS_ADDRESSV,D3DTADDRESS_CLAMP);
|
|
|
|
m_pd3dDevice->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 0 );
|
|
m_pd3dDevice->SetTextureStageState( 2, D3DTSS_TEXCOORDINDEX, 0 );
|
|
|
|
m_pd3dDevice->SetPixelShader(m_dwSubPicShader);
|
|
m_pd3dDevice->SetTexture(0,m_pFrontFogDist);
|
|
m_pd3dDevice->SetTexture(1,m_pBackFogDist);
|
|
m_pd3dDevice->SetTexture(2,m_pSceneDist);
|
|
|
|
//alpha blend on. If we want to do volumetric light, we use an additive rather
|
|
//then blended mode
|
|
m_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
|
m_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
|
m_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
|
|
|
|
|
|
m_pd3dDevice->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 1 );
|
|
m_pd3dDevice->SetTextureStageState( 2, D3DTSS_TEXCOORDINDEX, 2 );
|
|
|
|
//simple vertex shader, just copies coordinates and stuff.
|
|
m_pd3dDevice->SetVertexShader(m_dwFogShader2);
|
|
m_pd3dDevice->SetStreamSource( 0, m_pScreenVertBuf, 7 * sizeof(FLOAT) );
|
|
m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );
|
|
|
|
m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE);
|
|
|
|
// Output statistics
|
|
m_pFont->DrawText( 2, 0, D3DCOLOR_ARGB(255,255,255,0), m_strFrameStats );
|
|
m_pFont->DrawText( 2, 20, D3DCOLOR_ARGB(255,255,255,0), m_strDeviceStats );
|
|
|
|
// Draw help
|
|
if( m_bDrawHelp )
|
|
{
|
|
m_pFontSmall->DrawText( 2, 40, 0xffffff00,
|
|
_T("Keyboard controls:") );
|
|
m_pFontSmall->DrawText( 20, 60, 0xffffff00,
|
|
_T("Move\nTurn\nPitch\nSlide\n\nHelp\n"
|
|
"Change device\n"
|
|
"Exit") );
|
|
m_pFontSmall->DrawText( 160, 60, 0xffffff00,
|
|
_T("W,S\nE,Q\nA,Z\nArrow keys\n\n"
|
|
"F1\nF2\nEsc") );
|
|
}
|
|
else
|
|
{
|
|
m_pFontSmall->DrawText( 2, 40, 0xffffff00, _T("Press F1 for help") );
|
|
}
|
|
|
|
m_pd3dDevice->EndScene();
|
|
|
|
return S_OK;
|
|
|
|
FAIL:
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: InitDeviceObjects()
|
|
// Desc: Initialize scene objects.
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT CMyD3DApplication::InitDeviceObjects()
|
|
{
|
|
TCHAR model[160];
|
|
TCHAR model2[160];
|
|
HRESULT hr;
|
|
|
|
m_pFont->InitDeviceObjects( m_pd3dDevice );
|
|
m_pFontSmall->InitDeviceObjects( m_pd3dDevice );
|
|
|
|
if( FAILED( hr = DXUtil_FindMediaFile( model, _T("fog2.x") ) ) )
|
|
return D3DAPPERR_MEDIANOTFOUND;
|
|
if( FAILED( hr = DXUtil_FindMediaFile( model2, _T("room2.x") ) ) )
|
|
return D3DAPPERR_MEDIANOTFOUND;
|
|
|
|
if( D3DSHADER_VERSION_MAJOR( m_d3dCaps.PixelShaderVersion ) >= 1 )
|
|
m_bUsePicShader = TRUE;
|
|
else
|
|
m_bUsePicShader = FALSE;
|
|
|
|
if( FAILED( hr = LoadXFile( model, &m_FogVolume ) ) )
|
|
return hr;
|
|
|
|
if( FAILED( hr = LoadXFile( model2, &m_MeshShaderObject ) ) )
|
|
return hr;
|
|
|
|
if( FAILED( hr = D3DXLoadMeshFromX( model2, D3DXMESH_SYSTEMMEM, m_pd3dDevice,
|
|
NULL, NULL, NULL, &m_pMeshObject ) ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
if( FAILED( hr = m_pd3dDevice->CreateVertexBuffer( 7 * sizeof(FLOAT) * 4, 0,
|
|
D3DFVF_XYZRHW | D3DFVF_TEX1 | D3DFVF_DIFFUSE, D3DPOOL_MANAGED, &m_pScreenVertBuf ) ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
if( FAILED( hr = m_pd3dDevice->CreateVertexBuffer( 7 * sizeof(FLOAT) * 4, 0,
|
|
D3DFVF_XYZRHW | D3DFVF_TEX1 | D3DFVF_DIFFUSE, D3DPOOL_MANAGED, &m_pScreenVertBuf2 ) ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
if( FAILED( hr = ComputeStepTexture() ) )
|
|
return hr;
|
|
|
|
TCHAR FogShader1[160];
|
|
TCHAR SubtractShader[160];
|
|
if( FAILED( hr = DXUtil_FindMediaFile( FogShader1, _T("fogshader.vsh") ) ) )
|
|
return D3DAPPERR_MEDIANOTFOUND;
|
|
if( FAILED( hr = DXUtil_FindMediaFile( SubtractShader, _T("FogPixShader.psh") ) ) )
|
|
return D3DAPPERR_MEDIANOTFOUND;
|
|
|
|
if( FAILED( hr = D3DXAssembleShaderFromFile(FogShader1, 0, NULL, &m_pCodeFogShader, NULL ) ) )
|
|
return hr;
|
|
|
|
if( FAILED( hr = DXUtil_FindMediaFile( FogShader1, _T("fogshader2.vsh") ) ) )
|
|
return D3DAPPERR_MEDIANOTFOUND;
|
|
if( FAILED( hr = D3DXAssembleShaderFromFile(FogShader1, 0, NULL, &m_pCodeFogShader2, NULL ) ) )
|
|
return hr;
|
|
|
|
if( FAILED( hr = DXUtil_FindMediaFile( SubtractShader, _T("FogPixShader.psh") ) ) )
|
|
return D3DAPPERR_MEDIANOTFOUND;
|
|
if( FAILED( hr = D3DXAssembleShaderFromFile(SubtractShader, 0, NULL, &m_pCodeSubPicShader, NULL ) ) )
|
|
return hr;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: RestoreDeviceObjects()
|
|
// Desc: Initialize scene objects.
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT CMyD3DApplication::RestoreDeviceObjects()
|
|
{
|
|
HRESULT hr;
|
|
|
|
m_pFont->RestoreDeviceObjects();
|
|
m_pFontSmall->RestoreDeviceObjects();
|
|
|
|
DWORD dwDecl[] =
|
|
{
|
|
D3DVSD_STREAM(0),
|
|
D3DVSD_REG(0, D3DVSDT_FLOAT3),
|
|
D3DVSD_REG(1, D3DVSDT_FLOAT3),
|
|
D3DVSD_END()
|
|
};
|
|
|
|
DWORD dwDecl2[] =
|
|
{
|
|
D3DVSD_STREAM(0),
|
|
D3DVSD_REG(0, D3DVSDT_FLOAT4),
|
|
D3DVSD_REG(5, D3DVSDT_D3DCOLOR),
|
|
D3DVSD_REG(7, D3DVSDT_FLOAT2),
|
|
D3DVSD_END()
|
|
};
|
|
|
|
if( FAILED( hr = m_pd3dDevice->CreateTexture( RENDERTARGSIZE, RENDERTARGSIZE, 0,
|
|
D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &m_pBackFogDist ) ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
if( FAILED( hr = m_pd3dDevice->CreateTexture( RENDERTARGSIZE, RENDERTARGSIZE, 0,
|
|
D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &m_pFrontFogDist ) ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
if( FAILED( hr = m_pd3dDevice->CreateTexture( RENDERTARGSIZE, RENDERTARGSIZE, 0,
|
|
D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &m_pSceneDist ) ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
if( FAILED( hr = m_pd3dDevice->CreateTexture( RENDERTARGSIZE, RENDERTARGSIZE, 0,
|
|
D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &m_pTempDist ) ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
if( FAILED( hr = m_pd3dDevice->CreateDepthStencilSurface( RENDERTARGSIZE,RENDERTARGSIZE,
|
|
D3DFMT_D16, D3DMULTISAMPLE_NONE, &m_pTargetZ ) ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
m_dwFogShader = 0;
|
|
if (FAILED( hr = m_pd3dDevice->CreateVertexShader( dwDecl,
|
|
(DWORD*)m_pCodeFogShader->GetBufferPointer(), &m_dwFogShader, 0 ) ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
m_dwFogShader2 = 0;
|
|
if (FAILED( hr = m_pd3dDevice->CreateVertexShader( dwDecl2,
|
|
(DWORD*)m_pCodeFogShader2->GetBufferPointer(), &m_dwFogShader2, 0 ) ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
m_dwSubPicShader = 0;
|
|
if (FAILED( hr = m_pd3dDevice->CreatePixelShader( (DWORD*)m_pCodeSubPicShader->GetBufferPointer(),
|
|
&m_dwSubPicShader ) ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
if( FAILED( hr = m_pd3dDevice->GetRenderTarget( &m_pOldRenderTarget ) ) )
|
|
return hr;
|
|
|
|
if( FAILED( hr = m_pd3dDevice->GetDepthStencilSurface( &m_pOldStencilZ ) ) )
|
|
return hr;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: InvalidateDeviceObjects()
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT CMyD3DApplication::InvalidateDeviceObjects()
|
|
{
|
|
m_pFont->InvalidateDeviceObjects();
|
|
m_pFontSmall->InvalidateDeviceObjects();
|
|
|
|
SAFE_RELEASE(m_pOldRenderTarget);
|
|
SAFE_RELEASE(m_pOldStencilZ);
|
|
SAFE_RELEASE(m_pFrontFogDist);
|
|
SAFE_RELEASE(m_pBackFogDist);
|
|
SAFE_RELEASE(m_pSceneDist);
|
|
SAFE_RELEASE(m_pTempDist);
|
|
SAFE_RELEASE(m_pTargetZ);
|
|
if( m_dwSubPicShader != 0 )
|
|
{
|
|
m_pd3dDevice->DeletePixelShader(m_dwSubPicShader);
|
|
m_dwSubPicShader = 0;
|
|
}
|
|
if( m_dwFogShader != 0 )
|
|
{
|
|
m_pd3dDevice->DeleteVertexShader(m_dwFogShader);
|
|
m_dwFogShader = 0;
|
|
}
|
|
if( m_dwFogShader2 != 0 )
|
|
{
|
|
m_pd3dDevice->DeleteVertexShader(m_dwFogShader2);
|
|
m_dwFogShader2 = 0;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: DeleteDeviceObjects()
|
|
// Desc: Called when the app is exiting, or the device is being changed,
|
|
// this function deletes any device dependent objects.
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT CMyD3DApplication::DeleteDeviceObjects()
|
|
{
|
|
m_pFont->DeleteDeviceObjects();
|
|
m_pFontSmall->DeleteDeviceObjects();
|
|
SAFE_RELEASE(m_pScreenVertBuf);
|
|
SAFE_RELEASE(m_pScreenVertBuf2);
|
|
SAFE_RELEASE(m_FogVolume.pVertexBuffer);
|
|
SAFE_RELEASE(m_FogVolume.pIndexBuffer);
|
|
SAFE_RELEASE(m_MeshShaderObject.pVertexBuffer);
|
|
SAFE_RELEASE(m_MeshShaderObject.pIndexBuffer);
|
|
SAFE_RELEASE(m_pMeshObject);
|
|
SAFE_RELEASE(m_pStepTexture);
|
|
SAFE_RELEASE(m_pCodeFogShader);
|
|
SAFE_RELEASE(m_pCodeSubPicShader);
|
|
SAFE_RELEASE(m_pCodeFogShader2);
|
|
|
|
return S_OK;
|
|
}
|