📄 multitex.cpp
字号:
/********************************************************************
* Advanced 3D Game Programming using DirectX 9.0 *
********************************************************************
* copyright (c) 2003 by Peter A Walsh and Adrian Perez *
* See license.txt for modification and distribution information *
********************************************************************/
#include "stdafx.h"
#include <string>
#include <vector>
using namespace std;
/**
* This is the type of vertex we'll be using
* location, normal, and 2 sets of uv coords.
*/
struct sMTVertex
{
point3 loc;
point3 norm;
// 2 sets of u,v coordinates
float tex[2][2];
};
class cMultiTexApp : public cApplication,
public iKeyboardReceiver
{
public:
float m_timeDelta;
matrix4 m_earthMat;
matrix4 m_cloudMat;
vector< sMTVertex > m_earthVerts;
vector< sMTVertex > m_cloudVerts;
cTexture* m_pTextures[8];
string m_helpText;
bool m_bDrawHelp;
/**
* Are we currently rendering a pass?
*/
bool m_bDoBasePass;
bool m_bDoGlowPass;
bool m_bDoGlossPass;
bool m_bDoDetailPass;
bool m_bDoEnvyPass;
bool m_bDoCloudPass;
/**
* Can we render a pass at all?
*/
bool m_bCanDoBasePass;
bool m_bCanDoGlowPass;
bool m_bCanDoGlossPass;
bool m_bCanDoDetailPass;
bool m_bCanDoEnvyPass;
bool m_bCanDoCloudPass;
//==========-------------------------- cApplication
virtual void DoFrame( float timeDelta );
virtual void SceneInit();
bool CheckCaps();
cMultiTexApp() :
cApplication()
{
m_title = string( "MultiTex - 6 passes of multitexture madness" );
m_glFlags &= ~GLF_ZBUFFER; // turn off Z
for( int i=0; i<8; i++ )
{
m_pTextures[i] = NULL;
}
}
virtual ~cMultiTexApp()
{
/**
* Delete all of the textures
*/
for( int i=0; i<8; i++ )
{
delete m_pTextures[i];
}
}
virtual void KeyUp( int key );
virtual void KeyDown( int key ){}
void CreateSphereVertices( float radius, vector<sMTVertex>* pVec, float* scales );
void InitLights();
void LoadTextures();
void DoBasePass();
void DoGlowPass();
void DoGlossPass();
void DoDetailPass();
void DoEnvyPass();
void DoCloudPass();
void DrawBackground();
};
cApplication* CreateApplication()
{
return new cMultiTexApp();
}
void DestroyApplication( cApplication* pApp )
{
delete pApp;
}
bool cMultiTexApp::CheckCaps()
{
// certain base functionality is assumed, like MODULATE
// and SELECTARGx
m_bCanDoBasePass = true; // lord help us if the card can't do the base pass.
m_bCanDoDetailPass = false;
m_bCanDoGlowPass = false;
m_bCanDoGlossPass = false;
m_bCanDoEnvyPass = false;
m_bCanDoCloudPass = false;
D3DCAPS9 DevCaps;
Graphics()->GetDevice()->GetDeviceCaps( &DevCaps );
bool bCanDoMultitexture = (DevCaps.MaxSimultaneousTextures >= 2);
bool bCanDoMod2x = (DevCaps.TextureOpCaps & D3DTEXOPCAPS_MODULATE2X)? true : false;
/**
* check detail mapping
*/
if( (DevCaps.SrcBlendCaps & D3DPBLENDCAPS_DESTCOLOR) &&
(DevCaps.DestBlendCaps & D3DPBLENDCAPS_SRCCOLOR) )
{
m_bCanDoDetailPass = true;
}
/**
* check glow mapping
*/
if( bCanDoMultitexture &&
(DevCaps.SrcBlendCaps & D3DPBLENDCAPS_ONE) &&
(DevCaps.DestBlendCaps & D3DPBLENDCAPS_ONE) )
{
m_bCanDoGlowPass = true;
}
/**
* check envy mapping
*/
if( (DevCaps.VertexProcessingCaps & D3DVTXPCAPS_TEXGEN ) &&
(DevCaps.SrcBlendCaps & D3DPBLENDCAPS_SRCCOLOR) &&
(DevCaps.DestBlendCaps & D3DPBLENDCAPS_ONE) )
{
m_bCanDoEnvyPass = true;
}
/**
* check gloss mapping
*/
if( bCanDoMod2x &&
(DevCaps.SrcBlendCaps & D3DPBLENDCAPS_ONE) &&
(DevCaps.DestBlendCaps & D3DPBLENDCAPS_ONE) )
{
m_bCanDoGlossPass = true;
}
/**
* check cloud mapping
*/
if( (DevCaps.SrcBlendCaps & D3DPBLENDCAPS_SRCCOLOR) &&
(DevCaps.DestBlendCaps & D3DPBLENDCAPS_INVSRCCOLOR) )
{
m_bCanDoCloudPass = true;
}
return true;
}
void cMultiTexApp::SceneInit()
{
/**
* We're making the FOV less than 90 degrees.
* this is so the object doesn't warp as much
* when we're close to it.
*/
CheckCaps();
Graphics()->SetProjectionData( PI/4.f, 1.f, 150.f );
Graphics()->MakeProjectionMatrix();
/**
* Request keyboard updates
*/
Input()->GetKeyboard()->SetReceiver( this );
/**
* initialize our scene
*/
LPDIRECT3DDEVICE9 pDevice = Graphics()->GetDevice();
pDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
pDevice->SetRenderState(D3DRS_LIGHTING, TRUE);
pDevice->SetRenderState(D3DRS_DITHERENABLE, TRUE);
pDevice->SetRenderState(D3DRS_SPECULARENABLE, TRUE);
pDevice->SetRenderState(D3DRS_AMBIENT, 0xFFFFFF );
/**
* Turn on bilinear filtering
*/
pDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
pDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
pDevice->SetSamplerState( 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT );
pDevice->SetSamplerState( 1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
pDevice->SetSamplerState( 1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
pDevice->SetSamplerState( 1, D3DSAMP_MIPFILTER, D3DTEXF_POINT );
/**
* initialize the camera
* the 'up' vector is tilted to make the earth appear off-axis
*/
Graphics()->SetViewMatrix(
matrix4::CameraLookAt(
point3(4, 10, -25 ),
point3(0,0,0) )
);
m_timeDelta = 0.03f; // a 30th of a second is a good first value
/**
* We're wasting a bit of space, since the cloud vertices
* only use one set of texture coordinates. Fixing that
* would introduce code complexity, which I'd rather avoid
*/
float scales[2] = {1.0f, 11.0f};
CreateSphereVertices( 10.f, &m_earthVerts, &scales[0] );
CreateSphereVertices( 10.2f, &m_cloudVerts, &scales[0] );
InitLights();
LoadTextures();
m_helpText = "Multitexture Sample Application\n" +
m_helpText += "Advanced 3D Game Programming using DirectX 8.0\n";
m_helpText += " available keys: (availability depends on device features)\n";
m_helpText += (( m_bCanDoBasePass ) ?
" [1]: Toggle base pass\n" :
" [1]: (Not available)\n");
m_helpText += (( m_bCanDoDetailPass ) ?
" [2]: Toggle detail pass\n" :
" [2]: (Not available)\n");
m_helpText += (( m_bCanDoGlowPass ) ?
" [3]: Toggle glow pass\n" :
" [3]: (Not available)\n");
m_helpText += (( m_bCanDoEnvyPass ) ?
" [4]: Toggle envy pass\n" :
" [4]: (Not available)\n");
m_helpText += (( m_bCanDoGlossPass ) ?
" [5]: Toggle gloss pass\n" :
" [5]: (Not available)\n");
m_helpText += (( m_bCanDoCloudPass ) ?
" [6]: Toggle cloud pass\n" :
" [6]: (Not available)\n");
/**
* Initially, don't draw help
*/
m_bDrawHelp = false;
/**
* Initially, just display the base map.
*/
m_bDoBasePass = true;
m_bDoGlowPass = false;
m_bDoGlossPass = false;
m_bDoDetailPass = false;
m_bDoEnvyPass = false;
m_bDoCloudPass = false;
}
void cMultiTexApp::DoFrame( float timeDelta )
{
/**
* update the time
*/
m_timeDelta = timeDelta;
static float rotAmt = 3*PI/4;
rotAmt += 0.75f * m_timeDelta;
/**
* then, draw the frame.
*/
LPDIRECT3DDEVICE9 pDevice = Graphics()->GetDevice();
if( pDevice )
{
pDevice->SetFVF(
D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX2 );
Graphics()->Clear( true, true, 0, 1.f );
Graphics()->BeginScene();
Graphics()->SetWorldMatrix( matrix4::Identity );
DrawBackground();
point3 from( 0, 1, 0 );
m_earthMat =
matrix4::AxisAngle( point3::j, rotAmt );
/**
* The cloud matrix rotates a tiny bit faster
* than the earth matrix
*/
m_cloudMat =
matrix4::AxisAngle( point3::j, rotAmt * 0.7f );
Graphics()->SetWorldMatrix( m_earthMat );
if( m_bCanDoBasePass && m_bDoBasePass )
{
DoBasePass();
}
if( m_bCanDoDetailPass && m_bDoDetailPass )
{
DoDetailPass();
}
if( m_bCanDoGlowPass && m_bDoGlowPass )
{
DoGlowPass();
}
if( m_bCanDoEnvyPass && m_bDoEnvyPass )
{
DoEnvyPass();
}
if( m_bCanDoGlossPass && m_bDoGlossPass )
{
DoGlossPass();
}
if( m_bCanDoCloudPass && m_bDoCloudPass )
{
Graphics()->SetWorldMatrix( m_cloudMat );
DoCloudPass();
}
if( m_bDrawHelp )
{
Graphics()->DrawTextString( 2, 2, D3DCOLOR_XRGB( 0, 255, 0 ),
(char*)m_helpText.c_str() );
}
else
{
Graphics()->DrawTextString( 2, 2, D3DCOLOR_XRGB( 0, 0, 255 ),
"Press [H] for help" );
}
Graphics()->EndScene();
/**
* flip the buffer.
*/
Graphics()->Flip();
}
}
void cMultiTexApp::KeyUp( int key )
{
if( key == DIK_1 )
{
m_bDoBasePass = !m_bDoBasePass;
}
if( key == DIK_2 )
{
m_bDoDetailPass = !m_bDoDetailPass;
}
if( key == DIK_3 )
{
m_bDoGlowPass = !m_bDoGlowPass;
}
if( key == DIK_4 )
{
m_bDoEnvyPass = !m_bDoEnvyPass;
}
if( key == DIK_5 )
{
m_bDoGlossPass = !m_bDoGlossPass;
}
if( key == DIK_6 )
{
m_bDoCloudPass = !m_bDoCloudPass;
}
if( key == DIK_H )
{
m_bDrawHelp = !m_bDrawHelp;
}
}
void cMultiTexApp::InitLights()
{
LPDIRECT3DDEVICE9 lpDevice = Graphics()->GetDevice();
sLight light;
// Light 0
light = sLight::Directional(
point3(8,-3,5).Normalized(),
0.9f * color3::White + 0.1f * color3::Yellow,
0.9f * color3::White + 0.1f * color3::Yellow );
// Set the light
lpDevice->SetLight( 0, &light );
lpDevice->LightEnable(0, TRUE);
// Light 1
light = sLight::Directional(
point3(8,-3,5).Normalized(),
color3::White );
// Set the light
lpDevice->SetLight( 1, &light );
}
/**
* Based off of InitSphereVertices from the
* BumpEarth D3D SDK application
*/
void cMultiTexApp::CreateSphereVertices( float radius, vector<sMTVertex>* pVec, float* scales )
{
int numSphereRings = 30;
int numSphereSegments = 30;
sMTVertex curr;
int i;
// Establish constants used in sphere generation
float fDeltaRingAngle = ( PI / numSphereRings );
float fDeltaSegAngle = ( 2.0f * PI / numSphereSegments );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -