📄 light.cpp
字号:
//-----------------------------------------------------------------------------
// 名称: RenderSene.cpp
//
// 功能: 进行3D场景的渲染——使用显示内存的顶点缓冲区。
//
//-----------------------------------------------------------------------------
// 包含Direct3D头文件
#include <d3d8.h>
#include <d3dx8.h>
// Windows类的名称宏定义
#define MY_WINCLASS_NAME "Direct3D"
#define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000)? 1 : 0)
#define KEYUP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000)? 0 : 1)
struct PLAYER
{
D3DXVECTOR3 LookAt[3];
};
// 定义个表示顶点的结构
struct ELLIPSE_VERTEX
{
D3DXVECTOR3 p;
D3DXVECTOR3 n;
FLOAT tu, tv;
};
struct CUSTOMVERTEX01
{
D3DXVECTOR3 position;
D3DXVECTOR3 normal;
};
struct CUSTOMVERTEX
{
FLOAT x, y, z; // x,y,z表示点的三维坐标值,
DWORD color; // 顶点颜色
};
// 自定义的顶点格式
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)
#define D3DFVF_CUSTOMVERTEX_ELLIPSE (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1)
#define D3DFVF_CUSTOMVERTEX01 (D3DFVF_XYZ|D3DFVF_NORMAL)
// 定义全局变量
LPDIRECT3D8 g_pMyD3D = NULL; // 定义Direct3D对象的指针
LPDIRECT3DDEVICE8 g_pMyd3dDevice = NULL; // 定义Direct3D设备指针
LPDIRECT3DVERTEXBUFFER8 g_pMyVxBufferRec = NULL; // 定义顶点缓冲区对象指针
LPDIRECT3DVERTEXBUFFER8 g_pMyVxBufferLine = NULL;
LPDIRECT3DVERTEXBUFFER8 g_pMyVxBufferEllipse = NULL;
LPDIRECT3DVERTEXBUFFER8 g_pVB = NULL;
D3DXVECTOR3 g_lightPosition;
PLAYER g_Player;
float g_Angle = 0;
#define LINE_VECTOR_NUM 20
// 定义包含4个顶点的顶点数组
/*CUSTOMVERTEX g_Vertices[] =
{
{ -1.5f, 0.0f, 0.0f, 0xffff0000, },
{ -1.5f, 2.0f, 0.0f, 0xffff0000, },
{ 1.5f, 0.0f, 0.0f, 0xffff0000, },
{ 1.5f, 2.0f, 0.0f, 0xffff0000, },
};*/
#define GRID_WIDTH 20.0f
#define NUM_GRID 20
#define ELLIPSE_RINGS 20
#define ELLIPSE_SEGMENTS 20
//----------------------------------------------------------------------------
// Name: GenerateEllipse()
// Desc: Generates the vertices for a ellipse
//----------------------------------------------------------------------------
VOID GenerateEllipse( DWORD dwNumRings, DWORD dwNumSegments,
FLOAT fXScale, FLOAT fYScale, FLOAT fZScale,
CUSTOMVERTEX** ppVertices, DWORD* pdwNumVertices )
{
// Allocate space for the sphere
CUSTOMVERTEX* v = new CUSTOMVERTEX[2 * dwNumRings * (dwNumSegments+1)];
*pdwNumVertices = 2 * dwNumRings * (dwNumSegments+1);
*ppVertices = v;
// Establish constants used in sphere generation
FLOAT fDeltaRingAngle = ( D3DX_PI / dwNumRings );
FLOAT fDeltaSegAngle = ( 2.0f * D3DX_PI / dwNumSegments );
// Generate the group of rings for the sphere
for( DWORD ring = 0; ring < dwNumRings; ring++ )
{
FLOAT r0 = (FLOAT)sin( (ring+0) * fDeltaRingAngle );
FLOAT r1 = (FLOAT)sin( (ring+1) * fDeltaRingAngle );
FLOAT y0 = (FLOAT)cos( (ring+0) * fDeltaRingAngle );
FLOAT y1 = (FLOAT)cos( (ring+1) * fDeltaRingAngle );
// Generate the group of segments for the current ring
for( DWORD seg = 0; seg < (dwNumSegments+1); seg++ )
{
FLOAT x0 = r0 * (FLOAT)sin( seg * fDeltaSegAngle );
FLOAT z0 = r0 * (FLOAT)cos( seg * fDeltaSegAngle );
FLOAT x1 = r1 * (FLOAT)sin( seg * fDeltaSegAngle );
FLOAT z1 = r1 * (FLOAT)cos( seg * fDeltaSegAngle );
// Add two vertices to the strip which makes up the sphere
v->x = fXScale*x0;
v->y = fYScale*y0;
v->z = fZScale*z0;
v->color = 0x0000ffff;
v++;
/*
*v++ = D3DVERTEX( D3DVECTOR(fXScale*x0,fYScale*y0,fZScale*z0),
D3DVECTOR(x0,y0,z0), -((FLOAT)seg)/dwNumSegments,
(ring+0) / (FLOAT)dwNumRings );
*/
v->x = fXScale*x1;
v->y = fYScale*y1;
v->z = fZScale*z1;
v->color = 0x0000ffff;
v++;
/*
*v++ = D3DVERTEX( D3DVECTOR(fXScale*x1,fYScale*y1,fZScale*z1),
D3DVECTOR(x1,y1,z1), -((FLOAT)seg)/dwNumSegments,
(ring+1) / (FLOAT)dwNumRings );
*/
}
}
}
HRESULT InitGeometry()
{
if( FAILED( g_pMyd3dDevice->CreateVertexBuffer( 100*2*sizeof(CUSTOMVERTEX01),
0, D3DFVF_CUSTOMVERTEX01,
D3DPOOL_DEFAULT, &g_pVB ) ) )
{
return E_FAIL;
}
CUSTOMVERTEX01* pVertices;
if( FAILED( g_pVB->Lock( 0, 0, (BYTE**)&pVertices, 0 ) ) )
return E_FAIL;
for( DWORD i=0; i<100; i++ )
{
FLOAT theta = (2*D3DX_PI*i)/(100-1);
pVertices[2*i+0].position = D3DXVECTOR3( sinf(theta),-1.0f, cosf(theta) );
pVertices[2*i+0].normal = D3DXVECTOR3( sinf(theta), 0.0f, cosf(theta) );
pVertices[2*i+1].position = D3DXVECTOR3( sinf(theta), 2.0f, cosf(theta) );
pVertices[2*i+1].normal = D3DXVECTOR3( sinf(theta), 0.0f, cosf(theta) );
}
g_pVB->Unlock();
return S_OK;
}
//-----------------------------------------------------------------------------
// 名称: InitD3D()
// 功能: 初始化3D环境的函数,函数中创建了Direct3D对象和Direct3D设备。
// 函数返回E_FAIL表示失败,返回E_OK表示成功。
//-----------------------------------------------------------------------------
HRESULT InitMy3D( HWND hWnd )
{
// 创建Direct3D对象,是使用Direct3D的第一步操作
if( NULL == ( g_pMyD3D = Direct3DCreate8( D3D_SDK_VERSION ) ) )
return E_FAIL;
// 获取当前Windows桌面的显示模式,保存到定义的d3ddm结构中
D3DDISPLAYMODE d3ddm;
if( FAILED( g_pMyD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm ) ) )
return E_FAIL;
// 定义Present结构
D3DPRESENT_PARAMETERS d3dpp;
// 把结构清零,创建设备时,结构中成员值为0表示使用缺省值
ZeroMemory( &d3dpp, sizeof(d3dpp) );
// 指定创建的Direct3D是支持窗口的设备
d3dpp.Windowed = TRUE;
// 指定交换效果为D3DSWAPEFFECT_DISCARD,即把后台表面显示到前台表面以后,
// 原来的后台表面包含的信息自动丢失
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
// 后台缓冲区的的点格式与当前显示模式的点格式一致
d3dpp.BackBufferFormat = d3ddm.Format;
// 创建Direct3D设备:
// 1. 使用主显卡创建设备,参数D3DADAPTER_DEFAULT
// 2. 设备类型为硬件抽象设备,使用硬件加速功能,参数D3DDEVTYPE_HAL
// 3. 使用前面创建的窗口用于目标表面的显示,参数hWnd
// 4. 指定设备的对于顶点的处理能力为软件处理顶点,这是为了能够让所有
// 的显卡支持,参数D3DCREATE_SOFTWARE_VERTEXPROCESSING
if( FAILED( g_pMyD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, &g_pMyd3dDevice ) ) )
{
return E_FAIL;
}
g_pMyd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
g_pMyd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE );
g_pMyd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
// 定义一个保存顶点缓冲区内存地址的指针
VOID* pVertices;
// 创建顶点缓冲区
if( FAILED( g_pMyd3dDevice->CreateVertexBuffer( 4*sizeof(CUSTOMVERTEX01),
0, D3DFVF_CUSTOMVERTEX01,
D3DPOOL_DEFAULT, &g_pMyVxBufferRec ) ) )
{
return E_FAIL;
}
CUSTOMVERTEX01* pVertices1;
// 获得顶点缓冲区的内存指针,并锁定顶点缓冲区
if( FAILED( g_pMyVxBufferRec->Lock( 0, 4*sizeof(CUSTOMVERTEX01), (BYTE**)&pVertices1, 0 ) ) )
{
return E_FAIL;
}
// 初始化顶点数据到顶点缓冲区中
pVertices1->position = D3DXVECTOR3(-1.5f, 0.0f, 0.0f);
pVertices1->normal = D3DXVECTOR3(0.0f, 0.0f, -1.0f);
pVertices1++;
pVertices1->position = D3DXVECTOR3(-1.5f, 2.0f, 0.0f);
pVertices1->normal = D3DXVECTOR3(0.0f, 0.0f, -1.0f);
pVertices1++;
pVertices1->position = D3DXVECTOR3( 1.5f, 0.0f, 0.0f);
pVertices1->normal = D3DXVECTOR3(0.0f, 0.0f, -1.0f);
pVertices1++;
pVertices1->position = D3DXVECTOR3( 1.5f, 2.0f, 0.0f);
pVertices1->normal = D3DXVECTOR3(0.0f, 0.0f, -1.0f);
pVertices1++;
// 顶点缓冲区的解锁操作
g_pMyVxBufferRec->Unlock();
// 创建顶点缓冲区
if( FAILED( g_pMyd3dDevice->CreateVertexBuffer( 2*NUM_GRID*NUM_GRID*sizeof(CUSTOMVERTEX),
0, D3DFVF_CUSTOMVERTEX,
D3DPOOL_DEFAULT, &g_pMyVxBufferLine ) ) )
{
return E_FAIL;
}
// 获得顶点缓冲区的内存指针,并锁定顶点缓冲区
if( FAILED( g_pMyVxBufferLine->Lock( 0, 2*NUM_GRID*NUM_GRID*sizeof(CUSTOMVERTEX), (BYTE**)&pVertices, 0 ) ) )
{
return E_FAIL;
}
CUSTOMVERTEX *pstCmVertex;
FLOAT fSize = GRID_WIDTH/(NUM_GRID-1.0f);
FLOAT fOffset = GRID_WIDTH/2.0f;
for(int i=0; i<NUM_GRID; i++ )
{
for( int j=0; j<NUM_GRID; j++ )
{
pstCmVertex = (CUSTOMVERTEX *)pVertices;
pstCmVertex->x = i*fSize-fOffset;
pstCmVertex->y = 0;
pstCmVertex->z = j*fSize-fOffset;
pstCmVertex->color = 0x000000ff;
pVertices = (CUSTOMVERTEX *)pVertices + 1;
}
}
for(i=0; i<NUM_GRID; i++ )
{
for(int j=0; j<NUM_GRID; j++ )
{
pstCmVertex = (CUSTOMVERTEX *)pVertices;
pstCmVertex->x = j*fSize-fOffset;
pstCmVertex->y = 0;
pstCmVertex->z = i*fSize-fOffset;
pstCmVertex->color = 0x000000ff;
pVertices = (CUSTOMVERTEX *)pVertices + 1;
}
}
// 顶点缓冲区的解锁操作
g_pMyVxBufferLine->Unlock();
//************************************************************
// 创建球形
//************************************************************
/* DWORD dwNumVertices;
CUSTOMVERTEX *pVerticesEllipse;
GenerateEllipse( ELLIPSE_RINGS, ELLIPSE_SEGMENTS,
1.0f, 1.0f, 1.0f,
(CUSTOMVERTEX**)&pVerticesEllipse, &dwNumVertices );
if( FAILED( g_pMyd3dDevice->CreateVertexBuffer( dwNumVertices*sizeof(CUSTOMVERTEX),
0, D3DFVF_CUSTOMVERTEX,
D3DPOOL_DEFAULT, &g_pMyVxBufferEllipse ) ) )
return E_FAIL;
// 获得顶点缓冲区的内存指针,并锁定顶点缓冲区
if( FAILED( g_pMyVxBufferEllipse->Lock( 0, dwNumVertices*sizeof(CUSTOMVERTEX),
(BYTE**)&pVertices, 0 ) ) )
return E_FAIL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -