📄 shader_trees.cpp
字号:
/******************************************************************************
Copyright (C) 1999, 2000 NVIDIA Corporation
This file is provided without support, instruction, or implied warranty of any
kind. NVIDIA makes no guarantee of its fitness for a particular purpose and is
not liable under any circumstances for any damages or loss whatsoever arising
from the use or inability to use this file or items derived from it.
Comments:
******************************************************************************/
#include "eb_effect.h"
#include "nvmesh.h"
#include "nvdevice.h"
#include "shader_Trees.h"
#include "trees.h"
#include <algorithm>
using namespace nv_objects;
using namespace std;
DECLARE_EFFECT_MAIN()
extern "C"
{
__declspec(dllexport) unsigned int GetNumEffects() { return 1; }
__declspec(dllexport) EBEffect* CreateEffect(unsigned int EffectNum)
{
return new CShaderFishEye();
}
}
// Old-style D3D vertices
class Vertex
{
public:
Vertex(const D3DXVECTOR3& Pos, const D3DXVECTOR3& Norm, const D3DXVECTOR2& Tex)
: Position(Pos), Normal(Norm), Texture(Tex)
{}
Vertex()
{}
D3DXVECTOR3 Position;
D3DXVECTOR3 Normal;
D3DXVECTOR2 Texture;
};
class TLVertex
{
public:
D3DXVECTOR4 Position;
DWORD Diffuse;
DWORD Specular;
D3DXVECTOR2 Texture;
};
#define D3DFVF_VERTEX (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1)
#define D3DFVF_TLVERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1)
// Function to compare two trees relative to the eye.
class CompareToEye
{
private:
D3DXVECTOR3 m_EyePoint;
public:
CompareToEye(D3DXVECTOR3 EyePoint)
: m_EyePoint(EyePoint)
{}
bool operator()(const Tree& lhs, const Tree& rhs) const
{
D3DXVECTOR3 lPos = lhs.vPos;
lPos.y = 0.0f;
D3DXVECTOR3 rPos = rhs.vPos;
rPos.y = 0.0f;
D3DXVECTOR3 vEye = m_EyePoint;
vEye.y = 0.0f;
lPos -= vEye;
rPos -= vEye;
return D3DXVec3LengthSq(&lPos) < D3DXVec3LengthSq(&rPos);
}
};
CShaderTrees::CShaderTrees(TreeType Type)
: mbWireFrame(false),
m_TreeType(Type),
m_pTerrain(NULL),
m_pTreeTexture(NULL),
m_pFishViewVB(NULL),
m_pTreeVB(NULL),
m_pNVDevice(NULL),
m_pFishViewTexture(NULL),
m_dwTerrainShader(0),
m_dwTreeShader(0),
m_bPause(false),
m_fDuration(0.0f)
{
;
}
CShaderTrees::~CShaderTrees()
{
Free();
}
// Simple function to define "hilliness" for terrain
float CShaderTrees::HeightField( FLOAT x, FLOAT y )
{
return 9*(cosf(x/20+0.2f)*cosf(y/15-0.2f)+1.0f);
}
HRESULT CShaderTrees::Initialize(IDirect3DDevice8* pDev)
{
HRESULT hr;
vector<DWORD> Declaration;
D3DXMATRIX matWorld;
D3DXMATRIX matView;
D3DXMATRIX matProj;
m_pD3DDev = pDev;
pDev->AddRef();
m_pNVDevice = new NVTreeDevice(pDev, this);
DWORD dwVBFlags = D3DUSAGE_WRITEONLY;
// Create the shader
Declaration.clear();
Declaration.push_back(D3DVSD_STREAM(0));
Declaration.push_back(D3DVSD_REG(0, D3DVSDT_FLOAT3));
Declaration.push_back(D3DVSD_REG(1, D3DVSDT_D3DCOLOR));
Declaration.push_back(D3DVSD_REG(2, D3DVSDT_FLOAT2));
Declaration.push_back(D3DVSD_END());
hr = LoadAndCreateShader(GetFilePath("FishEye_Tree.vso"), &Declaration[0], 0, SHADERTYPE_VERTEX, &m_dwTreeShader);
if (FAILED(hr))
return hr;
Declaration.clear();
Declaration.push_back(D3DVSD_STREAM(0));
Declaration.push_back(D3DVSD_REG(0, D3DVSDT_FLOAT3));
Declaration.push_back(D3DVSD_REG(1, D3DVSDT_FLOAT3));
Declaration.push_back(D3DVSD_REG(2, D3DVSDT_FLOAT2));
Declaration.push_back(D3DVSD_END());
hr = LoadAndCreateShader(GetFilePath("FishEye_Terrain.vso"), &Declaration[0], 0, SHADERTYPE_VERTEX, &m_dwTerrainShader);
if (FAILED(hr))
return hr;
// Create the fisheye view
hr = D3DXCreateTextureFromFileEx(m_pD3DDev,
GetFilePath("FishView.dds").c_str(),
D3DX_DEFAULT,
D3DX_DEFAULT,
1,
0,
D3DFMT_UNKNOWN,
D3DPOOL_MANAGED,
D3DX_FILTER_LINEAR,
D3DX_FILTER_LINEAR,
0,
NULL,
NULL,
&m_pFishViewTexture);
if (FAILED(hr))
{
m_strLastError = "Could not load texture FishView.dds";
return hr;
}
hr = D3DXCreateTextureFromFileEx(m_pD3DDev,
GetFilePath("tree0.dds").c_str(),
D3DX_DEFAULT,
D3DX_DEFAULT,
0,
0,
D3DFMT_UNKNOWN,
D3DPOOL_MANAGED,
D3DX_FILTER_LINEAR,
D3DX_FILTER_LINEAR,
0,
NULL,
NULL,
&m_pTreeTexture);
if (FAILED(hr))
{
m_strLastError = "Could not load texture tree0.dds";
return hr;
}
// Load a ground object
m_pTerrain = new NVMesh();
if( FAILED( m_pTerrain->Create(m_pNVDevice, GetFilePath("seafloor.x") ) ) )
{
m_strLastError = "Could not load seafloor.x";
return E_FAIL;
}
DWORD dwFVF = m_pTerrain->GetSysMemMesh()->GetFVF();
m_pTerrain->SetFVF(m_pNVDevice, D3DFVF_TEX1 | D3DFVF_NORMAL | D3DFVF_XYZ);
// Add some "hilliness" to the terrain
LPDIRECT3DVERTEXBUFFER8 pVB;
if( SUCCEEDED( m_pTerrain->GetSysMemMesh()->GetVertexBuffer( &pVB ) ) )
{
Vertex* pVertices;
DWORD dwNumVertices = m_pTerrain->GetSysMemMesh()->GetNumVertices();
pVB->Lock( 0, 0, (BYTE**)&pVertices, 0 );
for( DWORD i=0; i<dwNumVertices; i++ )
pVertices[i].Position.y = HeightField( pVertices[i].Position.x, pVertices[i].Position.z );
pVB->Unlock();
pVB->Release();
}
m_vecTrees.resize(NUM_TREES);
// Initialize the tree data
for( WORD i=0; i<NUM_TREES; i++ )
{
// Position the trees randomly
FLOAT fTheta = 2.0f*D3DX_PI*(FLOAT)rand()/RAND_MAX;
FLOAT fRadius = 25.0f + 55.0f * (FLOAT)rand()/RAND_MAX;
m_vecTrees[i].vPos.x = fRadius * sinf(fTheta);
m_vecTrees[i].vPos.z = fRadius * cosf(fTheta);
m_vecTrees[i].vPos.y = HeightField( m_vecTrees[i].vPos.x, m_vecTrees[i].vPos.z );
// Size the trees randomly
FLOAT fWidth = 1.0f + 0.2f * (FLOAT)(rand()-rand())/RAND_MAX;
FLOAT fHeight = 1.4f + 0.4f * (FLOAT)(rand()-rand())/RAND_MAX;
// Each tree is a random color between red and green
DWORD r = (255-190) + (DWORD)(190*(FLOAT)(rand())/RAND_MAX);
DWORD g = (255-190) + (DWORD)(190*(FLOAT)(rand())/RAND_MAX);
DWORD b = 0;
DWORD dwColor = 0xff000000 + (r<<16) + (g<<8) + (b<<0);
m_vecTrees[i].v[0].p = D3DXVECTOR3(-fWidth, 0*fHeight, 0.0f );
m_vecTrees[i].v[0].color = dwColor;
m_vecTrees[i].v[0].tu = 0.0f; m_vecTrees[i].v[0].tv = 1.0f;
m_vecTrees[i].v[1].p = D3DXVECTOR3(-fWidth, 2*fHeight, 0.0f );
m_vecTrees[i].v[1].color = dwColor;
m_vecTrees[i].v[1].tu = 0.0f; m_vecTrees[i].v[1].tv = 0.0f;
m_vecTrees[i].v[2].p = D3DXVECTOR3( fWidth, 0*fHeight, 0.0f );
m_vecTrees[i].v[2].color = dwColor;
m_vecTrees[i].v[2].tu = 1.0f; m_vecTrees[i].v[2].tv = 1.0f;
m_vecTrees[i].v[3].p = D3DXVECTOR3( fWidth, 2*fHeight, 0.0f );
m_vecTrees[i].v[3].color = dwColor;
m_vecTrees[i].v[3].tu = 1.0f; m_vecTrees[i].v[3].tv = 0.0f;
}
// Check the alpha test caps of the device. (The alpha test offers a
// performance boost to not render pixels less than some alpha threshold.)
//m_bUseAlphaTest = ( m_d3dCaps.TriCaps.dwAlphaCmpCaps & D3DPCMPCAPS_GREATEREQUAL );
// Create a big square for rendering the fish view mask
if( FAILED( m_pD3DDev->CreateVertexBuffer( 4*sizeof(TLVertex),
D3DUSAGE_WRITEONLY, D3DFVF_TLVERTEX,
D3DPOOL_MANAGED, &m_pFishViewVB ) ) )
return E_FAIL;
// Create a square for rendering each tree. We modify, but only write
if( FAILED( m_pD3DDev->CreateVertexBuffer( NUM_TREES * 4*sizeof(TREEVERTEX),
D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, D3DFVF_TREEVERTEX,
D3DPOOL_DEFAULT, &m_pTreeVB ) ) )
return E_FAIL;
IDirect3DSurface8* pBackBuffer;
m_pD3DDev->GetRenderTarget(&pBackBuffer);
D3DSURFACE_DESC ddsd;
pBackBuffer->GetDesc(&ddsd);
m_dwWidth = ddsd.Width;
m_dwHeight = ddsd.Height;
SAFE_RELEASE(pBackBuffer);
// Create a quad for the final pass
TLVertex* v;
FLOAT sx = (FLOAT)m_dwWidth;
FLOAT sy = (FLOAT)m_dwHeight / 2;
m_pFishViewVB->Lock( 0, 0, (BYTE**)&v, 0 );
v[0].Position = D3DXVECTOR4(0, sy, 0, 1);
v[0].Diffuse = 0xffffffff;
v[0].Specular = 0;
v[0].Texture = D3DXVECTOR2(1, 1);
v[1].Position = D3DXVECTOR4(0, 0, 0, 1);
v[1].Diffuse = 0xffffffff;
v[1].Specular = 0;
v[1].Texture = D3DXVECTOR2(1, 0);
v[2].Position = D3DXVECTOR4(sx, sy, 0, 1);
v[2].Diffuse = 0xffffffff;
v[2].Specular = 0;
v[2].Texture = D3DXVECTOR2(0, 1);
v[3].Position = D3DXVECTOR4(sx, 0, 0, 1);
v[3].Diffuse = 0xffffffff;
v[3].Specular = 0;
v[3].Texture = D3DXVECTOR2(0, 0);
m_pFishViewVB->Unlock();
// Projection doesn't change
D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 0.3f, 100.0f );
m_pNVDevice->SetProjectionTransform(&matProj);
// Load values for the distortion shader
float fXZRatio = 2.5f;
float fkDistortion = 2.0f;
float fkp1Distortion = fkDistortion + 1.0f;
m_pD3DDev->SetVertexShaderConstant(CV_FISHEYEINFO, D3DXVECTOR4(fXZRatio, fkDistortion, 0.0f, 1.0f), 1);
m_pD3DDev->SetVertexShaderConstant(CV_CONSTANTS, D3DXVECTOR4(fkp1Distortion, 1.0f, 0.0f, 0.0f), 1);
m_pTerrain->RestoreDeviceObjects(m_pNVDevice);
return S_OK;
}
HRESULT CShaderTrees::Free()
{
SAFE_DELETE(m_pNVDevice);
SAFE_DELETE(m_pTerrain);
SAFE_RELEASE(m_pFishViewVB )
SAFE_RELEASE(m_pTreeVB )
SAFE_RELEASE(m_pTreeTexture);
SAFE_RELEASE(m_pFishViewTexture);
if (m_pD3DDev)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -