📄 techniqueapplication.cpp
字号:
/***************************************************************
* TechniqueApplication.cpp *
* *
* This file contains the implementation of the *
* TechniqueApplication class. *
* To compile correctly, this file must be linked with: *
* kernel32.lib *
* user32.lib *
* d3dx8dt.lib *
* d3d8.lib *
* *
***************************************************************/
#include "TechniqueApplication.h"
#define D3DFVF_MESHVERTEX (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE)
#define D3DFVF_STENCILVERTEX (D3DFVF_XYZRHW | D3DFVF_TEX1)
struct MESH_VERTEX
{
float x, y, z;
float nx, ny, nz;
DWORD color;
};
struct STENCIL_VERTEX
{
float x, y, z, rhw;
float u, v;
};
#define CIRCLE_RES 15
#define NUM_VERTICES 29
CTechniqueApplication::CTechniqueApplication()
{
m_pStencilVertexBuffer = NULL;
m_pMeshVertexBuffer = NULL;
m_pMeshIndexBuffer = NULL;
m_pMesh = NULL;
m_pMeshMaterials = NULL;
m_pCrossHairTexture = NULL;
m_NumMaterials = 0;
m_BasicShader = 0;
}
CTechniqueApplication::~CTechniqueApplication()
{
}
BOOL CTechniqueApplication::PostInitialize()
{
D3DCAPS8 Caps;
m_pD3D->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &Caps);
if (Caps.VertexShaderVersion == D3DVS_VERSION(1,1))
{
if (FAILED(EasyCreateWindowed(m_hWnd, D3DDEVTYPE_HAL,
D3DCREATE_HARDWARE_VERTEXPROCESSING)))
return FALSE;
}
else
{
if (FAILED(EasyCreateWindowed(m_hWnd, D3DDEVTYPE_HAL,
D3DCREATE_SOFTWARE_VERTEXPROCESSING)))
return FALSE;
}
//Do the basic camera positioning, etc.
SetupDevice();
//Load the mesh object
LoadMesh();
//Create the buffers we're actually going to use
ExtractBuffers();
if (FAILED(CreateStencilVertexBuffer()))
return FALSE;
//Create the shader
if (FAILED(CreateShaders()))
return FALSE;
if (FAILED(D3DXCreateTextureFromFile(m_pD3DDevice,
"..\\media\\CrossHair.dds",
&m_pCrossHairTexture)))
return FALSE;
return TRUE;
}
void CTechniqueApplication::Render()
{
//Set the eye position
D3DXVECTOR4 EyePos(0.0, 60.0f, -60.0f, 0.0f);
//Set the view matrix based on the position above.
D3DXMatrixLookAtLH(&m_ViewMatrix, &(D3DXVECTOR3)EyePos,
&D3DXVECTOR3(0.0f, 0.0f, 0.0f),
&D3DXVECTOR3(0.0f, 1.0f, 0.0f));
//Set the current light shader
m_pD3DDevice->SetVertexShader(m_BasicShader);
//The following matrix operations will transform the mesh
D3DXMATRIX Rotation;
D3DXMATRIX Translation;
//These matrices will rotate and translate the mesh
D3DXMatrixRotationY(&Rotation, (float)GetTickCount() / 1000.0f);
D3DXMatrixTranslation(&Translation, 0.0f, 5.0f, 0.0f);
m_WorldMatrix = Rotation * Translation;
//Set some lighting constants
D3DXVECTOR4 Ambient (0.1, 0.1f, 0.1f, 0.0f);
m_pD3DDevice->SetVertexShaderConstant(5, &Ambient, 1);
//The light is moving side to side over the model.
float Time = (float)GetTickCount() / 1000.0f;
D3DXVECTOR4 LightPosition(150.0f * sin(Time), 70.0f, 0.0f, 1.0f);
//Set the light direction based on what was computed for the shadow
D3DXVECTOR4 LightDir = D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f) - LightPosition;
D3DXMATRIX InverseWorld;
D3DXMatrixInverse(&InverseWorld, NULL, &m_WorldMatrix);
D3DXVec4Transform(&LightDir, &LightDir, &InverseWorld);
D3DXVec4Normalize(&LightDir, &LightDir);
m_pD3DDevice->SetVertexShaderConstant(4, &LightDir, 1);
//Create the concatenated transformation matrix
D3DXMATRIX ShaderMatrix = m_WorldMatrix * m_ViewMatrix *
m_ProjectionMatrix;
//Get the transpose
D3DXMatrixTranspose(&ShaderMatrix, &ShaderMatrix);
//Pass the transposed matrix to the shader
m_pD3DDevice->SetVertexShaderConstant(0, &ShaderMatrix, 4);
m_pD3DDevice->SetStreamSource(0, m_pMeshVertexBuffer, sizeof(MESH_VERTEX));
m_pD3DDevice->SetIndices(m_pMeshIndexBuffer, 0);
//The code above has set everything up for the rendering. First, render
//the usual scene with the usual stuff.
m_pD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0,
m_pMesh->GetNumVertices(), 0,
m_pMesh->GetNumFaces());
//Now, change the viewport and do it again...
m_pD3DDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
//First, save the viewport.
D3DVIEWPORT8 NormalViewport;
m_pD3DDevice->GetViewport(&NormalViewport);
//Create a new viewport in the lower right
D3DVIEWPORT8 ZoomViewport;
ZoomViewport.X = 400;
ZoomViewport.Y = 300;
ZoomViewport.Width = 200;
ZoomViewport.Height = 150;
ZoomViewport.MinZ = 0.0f;
ZoomViewport.MaxZ = 1.0f;
m_pD3DDevice->SetViewport(&ZoomViewport);
//Change the projection matrix and reset the shader matrix accordingly.
//The new projection matrix has a much smaller field of view than the
//original matrix. This creates the zoom effect.
D3DXMATRIX ZoomProjection;
D3DXMatrixPerspectiveFovLH(&ZoomProjection,
D3DX_PI / 32, 1.5f, 1.0f, 1000.0f);
ShaderMatrix = m_WorldMatrix * m_ViewMatrix * ZoomProjection;
D3DXMatrixTranspose(&ShaderMatrix, &ShaderMatrix);
m_pD3DDevice->SetVertexShaderConstant(0, &ShaderMatrix, 4);
//Draw the stencil circle. Set it up so that everything passes and
//the new pixels increment the stencil buffer
m_pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
m_pD3DDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
m_pD3DDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE);
m_pD3DDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
m_pD3DDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_INCR);
//Set it up so that nothing is drawn to the color buffer
m_pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
m_pD3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
m_pD3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
//Draw the actual circle
m_pD3DDevice->SetVertexShader(D3DFVF_STENCILVERTEX);
m_pD3DDevice->SetStreamSource(0, m_pStencilVertexBuffer, sizeof(STENCIL_VERTEX));
m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, CIRCLE_RES - 2);
//Set most things back to normal
m_pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
m_pD3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
m_pD3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
m_pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
m_pD3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
//Only draw if the value is greater than the ref value (zero)
m_pD3DDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_LESS);
m_pD3DDevice->SetRenderState(D3DRS_STENCILREF, 0);
m_pD3DDevice->SetVertexShader(m_BasicShader);
m_pD3DDevice->SetStreamSource(0, m_pMeshVertexBuffer, sizeof(MESH_VERTEX));
m_pD3DDevice->SetIndices(m_pMeshIndexBuffer, 0);
m_pD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0,
m_pMesh->GetNumVertices(), 0,
m_pMesh->GetNumFaces());
//disable stenciling
m_pD3DDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
//Draw the crosshairs
m_pD3DDevice->SetTexture(0, m_pCrossHairTexture);
m_pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
m_pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
m_pD3DDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
m_pD3DDevice->SetVertexShader(D3DFVF_STENCILVERTEX);
m_pD3DDevice->SetStreamSource(0, m_pStencilVertexBuffer, sizeof(STENCIL_VERTEX));
m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, CIRCLE_RES, 2);
m_pD3DDevice->SetTexture(0, NULL);
//Restore modes
m_pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
m_pD3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
m_pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
//Restore the old viewport
m_pD3DDevice->SetViewport(&NormalViewport);
}
HRESULT CTechniqueApplication::LoadMesh()
{
LPD3DXBUFFER pD3DXMtrlBuffer;
LPD3DXMESH pOriginalMesh;
//Load and initialize the mesh. This is a repeat of the code
//from Chapter 10.
if(FAILED(D3DXLoadMeshFromX("..\\media\\fattorus.x",
D3DXMESH_MANAGED,
m_pD3DDevice, NULL, &pD3DXMtrlBuffer,
&m_NumMaterials, &pOriginalMesh)))
return FALSE;
D3DXMATERIAL* d3dxMaterials =
(D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer();
m_pMeshMaterials = new D3DMATERIAL8[m_NumMaterials];
for(long MatCount = 0; MatCount < m_NumMaterials; MatCount++)
{
m_pMeshMaterials[MatCount] = d3dxMaterials[MatCount].MatD3D;
m_pMeshMaterials[MatCount].Ambient =
m_pMeshMaterials[MatCount].Diffuse;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -