//=============================================================================
// Desc: 使用顶点缓冲区绘制三角形
//=============================================================================
#include <Windows.h>
#pragma comment(lib, "winmm.lib")
#include <d3dx9.h>
#include <d3dx9shader.h>
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9d.lib")
//-----------------------------------------------------------------------------
// Desc: 全局变量
//-----------------------------------------------------------------------------
LPDIRECT3D9 g_pD3D = NULL; //Direct3D对象
LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; //Direct3D设备对象
LPD3DXMESH g_pMesh = NULL; //网格模型
LPDIRECT3DTEXTURE9 g_pMeshTexture = NULL; //纹理
LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL;
LPD3DXEFFECT g_pEffect = NULL; //效果
D3DXMATRIX g_WorldMat;
D3DXMATRIX g_ViewMat;
D3DXMATRIX g_ProjMat;
D3DXMATRIX g_cmat;
D3DXMATRIX g_cmatWorld;
float g_MeshRadius = 0.0f;
//pos
D3DXVECTOR4 g_PointLightPos;
D3DXVECTOR4 g_EyePos;
//color
D3DXVECTOR4 g_MaterailAmbient;
D3DXVECTOR4 g_MaterailDiffuse;
D3DXVECTOR4 g_MaterailSpecular;
D3DXVECTOR4 g_lightAmbient;
D3DXVECTOR4 g_lightDiffuse;
D3DXVECTOR4 g_lightSpecular;
struct CUSTOMVERTEX
{
D3DXVECTOR3 pos;
DWORD color;
};
#define CUSTOMFVF (D3DFVF_XYZ | D3DFVF_DIFFUSE)
HRESULT LoadMesh( IDirect3DDevice9* pd3dDevice, char* strFileName, ID3DXMesh** ppMesh ) //自定义函数
{
ID3DXMesh* pMesh = NULL;
HRESULT hr;
//从文件加载网格模型
::D3DXLoadMeshFromX(strFileName, D3DXMESH_MANAGED, pd3dDevice, NULL, NULL, NULL, NULL, &pMesh);
//确保网格模型顶点包含法线信息,以满足光照计算的需要
if( !(pMesh->GetFVF() & D3DFVF_NORMAL) )
{
ID3DXMesh* pTempMesh;
pMesh->CloneMeshFVF( pMesh->GetOptions(),
pMesh->GetFVF() | D3DFVF_NORMAL,
pd3dDevice, &pTempMesh );
D3DXComputeNormals( pTempMesh, NULL ); //计算法线
if(NULL != pMesh)
{
pMesh->Release();
pMesh = NULL;
}
pMesh = pTempMesh;
}
//对网格模型进行优化,以提高程序运行性能
DWORD *rgdwAdjacency = NULL;
if(NULL == (rgdwAdjacency = new DWORD[pMesh->GetNumFaces() * 3]))
{
return E_FAIL;
}
pMesh->GenerateAdjacency(1e-6f,rgdwAdjacency);
pMesh->OptimizeInplace(D3DXMESHOPT_VERTEXCACHE, rgdwAdjacency, NULL, NULL, NULL); //优化
if(NULL != rgdwAdjacency)
{
delete []rgdwAdjacency;
rgdwAdjacency = NULL;
}
*ppMesh = pMesh;
return S_OK;
}
//-----------------------------------------------------------------------------
// Desc: 初始化Direct3D
//-----------------------------------------------------------------------------
HRESULT InitMesh()
{
if(E_FAIL == LoadMesh(g_pd3dDevice, "Media\\tiny\\tiny.x", &g_pMesh))
{
MessageBox(GetForegroundWindow(), "Shader_Error!" , "Shader", MB_OK);
abort();
}
//自动计算,不需要我们进行,它会根据模型返回中心球的半径和中心点
D3DXVECTOR3* pData;
D3DXVECTOR3 vCenter;
g_pMesh->LockVertexBuffer( 0, (LPVOID*) &pData );
::D3DXComputeBoundingSphere( pData, g_pMesh->GetNumVertices(),
D3DXGetFVFVertexSize( g_pMesh->GetFVF() ), &vCenter,
&g_MeshRadius);
g_pMesh->UnlockVertexBuffer();
::D3DXMatrixIdentity(&g_WorldMat);
::D3DXMatrixTranslation(&g_WorldMat, -vCenter.x, -vCenter.y, -vCenter.z);
//创建网格模型纹理
D3DXCreateTextureFromFileEx( g_pd3dDevice, "Media\\tiny\\tiny_skin.dds", D3DX_DEFAULT, D3DX_DEFAULT,
D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED,
D3DX_DEFAULT, D3DX_DEFAULT, 0,
NULL, NULL, &g_pMeshTexture );
return S_OK;
}
HRESULT InitD3D( HWND hWnd )
{
//创建Direct3D对象, 该对象用于创建Direct3D设备对象
if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
return E_FAIL;
//设置D3DPRESENT_PARAMETERS结构, 准备创建Direct3D设备对象
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( &d3dpp, sizeof(d3dpp) );
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
//创建Direct3D设备对象
if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, &g_pd3dDevice ) ) )
{
return E_FAIL;
}
//创建矩阵
::D3DXMatrixIdentity(&g_WorldMat);
::D3DXMatrixIdentity(&g_ViewMat);
::D3DXMatrixIdentity(&g_ProjMat);
D3DXVECTOR3 vEye(0.0, 0.0, -30.0);
D3DXVECTOR3 vAt(0.0, 0.0, 0.0);
D3DXVECTOR3 vUp(0.0, 1.0, 0.0);
::D3DXMatrixLookAtLH(&g_ViewMat, &vEye, &vAt, &vUp);
::D3DXMatrixPerspectiveFovLH(&g_ProjMat, D3DX_PI * 0.25, 1.0, 1.0, 300.0);
//加载模型
InitMesh();
g_EyePos = D3DXVECTOR4(vEye, 0.0);
g_PointLightPos = D3DXVECTOR4(-5.0, 0.0, 5.0, 0.0);
g_MaterailAmbient = D3DXVECTOR4(0.5, 0.5, 0.5, 1.0);
g_MaterailDiffuse = D3DXVECTOR4(0.0, 1.0, 0.0, 1.0);
g_MaterailSpecular = D3DXVECTOR4(1.0, 1.0, 1.0, 1.0); //镜面白色
g_lightAmbient = D3DXVECTOR4(1.0, 1.0, 1.0, 1.0);
g_lightDiffuse = D3DXVECTOR4(1.0, 1.0, 1.0, 1.0);
g_lightSpecular = D3DXVECTOR4(1.0, 1.0, 1.0, 1.0); //sun
//创建效果
if(E_FAIL == ::D3DXCreateEffectFromFile(g_pd3dDevice, "FX.h", NULL, NULL, D3DXSHADER_DEBUG, NULL, &g_pEffect, NULL))
{
MessageBox(GetForegroundWindow(), "Shader_Error!" , "Shader", MB_OK);
abort();
}
return S_OK;
}
//-----------------------------------------------------------------------------
// Desc: 创建并填充顶点缓冲区
//-----------------------------------------------------------------------------
HRESULT InitVB()
{
if(FAILED(g_pd3dDevice->CreateVertexBuffer(50*2*sizeof(CUSTOMVERTEX), 0,
CUSTOMFVF, D3DPOOL_MANAGED, &g_pVB, NULL)))
{
return E_FAIL;
}
CUSTOMVERTEX* lp;
g_pVB->Lock(0,50*2*sizeof(CUSTOMVERTEX), (void**)&lp, 0);
float theta = 0.0;
float TheDiv = 2 * D3DX_PI / 49.0;
float r = 1.0;
for(int i=0; i<50; i++)
{
theta = i * TheDiv;
lp[2*i+0].pos =r * D3DXVECTOR3(sinf(theta), -1.0, cosf(theta));
lp[2*i+0].color = 0xffff0000;
lp[2*i+1].pos = r * D3DXVECTOR3(sinf(theta), +1.0, cosf(theta));
lp[2*i+1].color = 0xff00ff00;
}
g_pVB->Unlock();
return S_OK;
}
//-----------------------------------------------------------------------------
// Desc: 释放创建的对象
//-----------------------------------------------------------------------------
VOID Cleanup()
{
if(NULL != g_pMesh)
{
g_pMesh->Release();
g_pMesh = NULL;
}
if(NULL != g_pMeshTexture)
{
g_pMeshTexture->Release();
g_pMeshTexture = NULL;
}
if(NULL != g_pEffect)
{
g_pEffect->Release();
g_pEffect = NULL;
}
//释放Direct3D设备对象
if( g_pd3dDevice != NULL )
g_pd3dDevice->Release();
//释放Direct3D对象
if( g_pD3D != NULL )
g_pD3D->Release();
}
void UpdateWorld()
{
DWORD CurTime = timeGetTime();
DWORD Velocity = 2000;
float ft = (CurTime % Velocity) * 1.0 / Velocity; //完全可以把时间传到顶点着色器中去进行算法计算
Velocity = 2000; //不同速率下的角度
float fTheda = (CurTime % Velocity) * 1.0 / Velocity * (2.0f * D3DX_PI);
Velocity = 3000; //不同速率下的角度
float fAlpha = (CurTime % Velocity) * 1.0 / Velocity * (2.0f * D3DX_PI);
D3DXMATRIX matScale;
D3DXMatrixIdentity( &matScale);
D3DXMatrixScaling(&matScale,0.02,0.02, 0.02);
D3DXMATRIX matRotateX;
D3DXMatrixIdentity( &matRotateX);
D3DXMatrixRotationX(&matRotateX,D3DX_PI*0.5);
D3DXMATRIX matRotateZ;
D3DXMatrixIdentity( &matRotateZ);
D3DXMatrixRotationZ(&matRotateZ,D3DX_PI);
D3DXMATRIX matRotateY;
D3DXMatrixIdentity( &matRotateY);
D3DXMatrixRotationZ(&matRotateY,fAlpha);
g_cmatWorld = g_WorldMat * matScale * matRotateY * matRotateX * matRotateZ;
g_cmat = g_cmatWorld * g_ViewMat * g_ProjMat;
g_pEffect->SetMatrix("mat", &g_cmat);
g_pEffect->SetMatrix("matWorld", &g_cmatWorld);
//Light