📄 rain.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)
#define VK_1 0x31 // 按键 “1”的值0x31
#define VK_2 0x32
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
inline DWORD FtoDW( FLOAT f ) { return *((DWORD*)&f); }
struct PLAYER
{
D3DXVECTOR3 LookAt[3];
};
struct POINTVERTEX
{
D3DXVECTOR3 p;
D3DCOLOR color;
};
// 定义雨效果的结构
struct RAIN
{
LPDIRECT3DVERTEXBUFFER8 m_pRainVB;
LONG m_lRainCount;
D3DXVECTOR3 m_vPosition;
DWORD m_Width;
DWORD m_Lenth;
DWORD m_Hight;
float m_offset;
};
// 定义个表示顶点的结构
struct FOGVERTEX
{
D3DXVECTOR3 p;
D3DXVECTOR3 n;
FLOAT tu, tv;
};
struct CUSTOMVERTEX01
{
D3DXVECTOR3 position;
D3DXVECTOR3 normal;
};
struct CUSTOMVERTEX02
{
D3DXVECTOR3 position;
D3DCOLOR color;
FLOAT tu, tv;
};
struct CUSTOMVERTEX
{
FLOAT x, y, z; // x,y,z表示点的三维坐标值,
DWORD color; // 顶点颜色
};
// 自定义的顶点格式
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)
#define D3DFVF_FOGVERTEX (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1)
#define D3DFVF_CUSTOMVERTEX01 (D3DFVF_XYZ|D3DFVF_NORMAL)
#define D3DFVF_CUSTOMVERTEX02 (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)
#define D3DFVF_POINTVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)
// 定义全局变量
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;
LPDIRECT3DVERTEXBUFFER8 g_pTerrainVB = NULL;
RAIN g_Rain;
// 定义用于墙面渲染的纹理指针变量
LPDIRECT3DTEXTURE8 g_pTextureWall = NULL;
// 定义用于地面渲染的纹理指针变量
LPDIRECT3DTEXTURE8 g_pTextureLand = NULL;
D3DXVECTOR3 g_lightPosition;
BOOL g_TextureFilter = TRUE;
DWORD g_dwNumTerrainVertices = 0;
PLAYER g_Player;
float g_Angle = 0;
#define LINE_VECTOR_NUM 20
#define GRID_WIDTH 20.0f
#define NUM_GRID 20
#define ELLIPSE_RINGS 20
#define ELLIPSE_SEGMENTS 20
//-----------------------------------------------------------------------------
// 名称: 3DEn_Rain_Init()
// 功能: 初始化雨
//-----------------------------------------------------------------------------
HRESULT En_Rain_Delete(RAIN *pRain)
{
if(pRain->m_pRainVB)
pRain->m_pRainVB->Release();
return D3D_OK;
}
HRESULT En_Rain_Init(LPDIRECT3DDEVICE8 pd3dDevice,
RAIN *pRain,
LONG density)
{
HRESULT hr;
DWORD width = pRain->m_Width;
DWORD lenth = pRain->m_Lenth;
LONG lRainCount = width*lenth*density*density;
pRain->m_lRainCount = lRainCount;
// 生成雨滴的顶点
hr = pd3dDevice->CreateVertexBuffer( lRainCount*sizeof(POINTVERTEX),
D3DUSAGE_WRITEONLY, D3DFVF_POINTVERTEX,
D3DPOOL_MANAGED, &pRain->m_pRainVB );
if( FAILED(hr) )
return hr;
POINTVERTEX* pVertices = NULL;
LPDIRECT3DVERTEXBUFFER8 pVB = pRain->m_pRainVB;
hr = pVB->Lock( 0, lRainCount*sizeof(POINTVERTEX),
(BYTE**)&pVertices, 0 );
for( DWORD line = 0; line < (DWORD)(width*density) ; line++ )
{
float offwidth = (float)line*width/density;
for( DWORD seg=0; seg < (DWORD)(lenth*density); seg++ )
{
FLOAT fRandx = ((FLOAT)rand()/(FLOAT)RAND_MAX) * 0.1f;
FLOAT fRandy = ((FLOAT)rand()/(FLOAT)RAND_MAX) * 5.0f;
FLOAT fRandz = ((FLOAT)rand()/(FLOAT)RAND_MAX) * 0.1f;
float offlenth = (float)seg*lenth/density;
pVertices->p.x = 8 - (float)width*density/2 + offwidth + fRandx;
pVertices->p.y = (float)pRain->m_Hight + fRandy;
pVertices->p.z = 8 - (float)lenth*density/2 + offlenth + fRandz;
pVertices->color = 0x00bbbbbb;
pVertices++;
}
}
pVB->Unlock();
return S_OK;
}
HRESULT En_Rain_Move( RAIN *pRain, float offset )
{
HRESULT hr;
DWORD lRainCount = pRain->m_lRainCount;
// 移动雨滴的顶点
POINTVERTEX* pVertices = NULL;
LPDIRECT3DVERTEXBUFFER8 pVB = pRain->m_pRainVB;
hr = pVB->Lock( 0, lRainCount*sizeof(POINTVERTEX),
(BYTE**)&pVertices, 0 );
for( DWORD seg=0; seg < lRainCount; seg++ )
{
if(pVertices->p.y < 0)
pVertices->p.y = (float)pRain->m_Hight;
else
pVertices->p.y -= offset;
pVertices++;
}
pVB->Unlock();
return S_OK;
}
HRESULT En_Rain_Draw( LPDIRECT3DDEVICE8 pd3dDevice, RAIN *pRain )
{
D3DXMATRIX matWorld;
float offset = 0.01f;
DWORD lRainCount = pRain->m_lRainCount;
D3DXMatrixTranslation( &matWorld, g_Player.LookAt[0].x , 0, g_Player.LookAt[0].z );
g_pMyd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
// 渲染雨滴的顶点
POINTVERTEX* pVertices = NULL;
LPDIRECT3DVERTEXBUFFER8 pVB = pRain->m_pRainVB;
pd3dDevice->SetRenderState( D3DRS_POINTSPRITEENABLE, TRUE );
pd3dDevice->SetRenderState( D3DRS_POINTSCALEENABLE, TRUE );
pd3dDevice->SetRenderState( D3DRS_POINTSIZE, FtoDW(0.01f) );
pd3dDevice->SetRenderState( D3DRS_POINTSIZE_MIN, FtoDW(0.00f) );
pd3dDevice->SetRenderState( D3DRS_POINTSCALE_A, FtoDW(1.00f) );
pd3dDevice->SetRenderState( D3DRS_POINTSCALE_B, FtoDW(1.00f) );
pd3dDevice->SetRenderState( D3DRS_POINTSCALE_C, FtoDW(1.00f) );
pd3dDevice->SetVertexShader( D3DFVF_POINTVERTEX );
pd3dDevice->SetStreamSource( 0, pVB, sizeof(POINTVERTEX) );
pd3dDevice->DrawPrimitive( D3DPT_POINTLIST,
0, lRainCount);
for(DWORD i = 0; i< 6; i ++)
{
En_Rain_Move(pRain,0.01f);
pd3dDevice->SetVertexShader( D3DFVF_POINTVERTEX );
pd3dDevice->SetStreamSource( 0, pVB, sizeof(POINTVERTEX) );
pd3dDevice->DrawPrimitive( D3DPT_POINTLIST,
0, lRainCount);
En_Rain_Move(pRain, 0.01f);
pd3dDevice->SetVertexShader( D3DFVF_POINTVERTEX );
pd3dDevice->SetStreamSource( 0, pVB, sizeof(POINTVERTEX) );
pd3dDevice->DrawPrimitive( D3DPT_POINTLIST,
0, lRainCount);
En_Rain_Move(pRain, 0.01f);
pd3dDevice->SetVertexShader( D3DFVF_POINTVERTEX );
pd3dDevice->SetStreamSource( 0, pVB, sizeof(POINTVERTEX) );
pd3dDevice->DrawPrimitive( D3DPT_POINTLIST,
0, lRainCount);
En_Rain_Move(pRain, 0.01f);
pd3dDevice->SetVertexShader( D3DFVF_POINTVERTEX );
pd3dDevice->SetStreamSource( 0, pVB, sizeof(POINTVERTEX) );
pd3dDevice->DrawPrimitive( D3DPT_POINTLIST,
0, lRainCount);
}
En_Rain_Move(pRain, pRain->m_offset);
return S_OK;
}
//-----------------------------------------------------------------------------
// 名称: GenerateTerrain()
// 功能: 初始化用于地面的顶点
//
//-----------------------------------------------------------------------------
HRESULT GenerateTerrain( LPDIRECT3DDEVICE8 pd3dDevice, DWORD dwNumSegments,
FLOAT fScale )
{
HRESULT hr;
g_dwNumTerrainVertices = 2 * dwNumSegments * (dwNumSegments);
// Destroy the old vertex buffer, if any
SAFE_RELEASE( g_pTerrainVB );
// Create a vertex buffer
hr = pd3dDevice->CreateVertexBuffer( g_dwNumTerrainVertices*sizeof(FOGVERTEX),
D3DUSAGE_WRITEONLY, D3DFVF_FOGVERTEX,
D3DPOOL_MANAGED, &g_pTerrainVB );
if( FAILED(hr) )
return hr;
FOGVERTEX* pVertices = NULL;
hr = g_pTerrainVB->Lock( 0, g_dwNumTerrainVertices*sizeof(FOGVERTEX),
(BYTE**)&pVertices, 0 );
if( FAILED(hr) )
return hr;
// Generate a spiralized trianglestrip
for( DWORD ring = 0; ring < dwNumSegments; ring++ )
{
for( DWORD seg=0; seg < dwNumSegments; seg++ )
{
FLOAT fTheta = (seg*2*D3DX_PI) / dwNumSegments;
FLOAT r0 = (ring + fTheta/(2*D3DX_PI))*fScale/dwNumSegments;
FLOAT r1 = r0 + fScale/dwNumSegments;
FLOAT x = (FLOAT)sin( fTheta );
FLOAT z = (FLOAT)cos( fTheta );
FLOAT y0 = (FLOAT)sin(r0*z*z+r0*x*x);
FLOAT nx0 = -(FLOAT)cos(r0*z*z+r0*x*x)*r0*2*x;
FLOAT ny0 = 1.0f;
FLOAT nz0 = -(FLOAT)cos(r0*z*z+r0*x*x)*r0*2*z;
FLOAT y1 = (FLOAT)sin(r1*z*z+r1*x*x);
FLOAT nx1 = -(FLOAT)cos(r1*z*z+r1*x*x)*r1*2*x;
FLOAT ny1 = 1.0f;
FLOAT nz1 = -(FLOAT)cos(r1*z*z+r1*x*x)*r1*2*z;
// Add two vertices to the strip at each step
pVertices->p.x = r0*x;
pVertices->p.y = y0;
pVertices->p.z = r0*z;
pVertices->n.x = nx0;
pVertices->n.y = ny0;
pVertices->n.z = nz0;
pVertices->tu = (r0*x)/fScale;
pVertices->tv = (r0*z)/fScale;
pVertices++;
pVertices->p.x = r1*x;
pVertices->p.y = y1;
pVertices->p.z = r1*z;
pVertices->n.x = nx1;
pVertices->n.y = ny1;
pVertices->n.z = nz1;
pVertices->tu = (r1*x)/fScale;
pVertices->tv = (r1*z)/fScale;
pVertices++;
}
}
g_pTerrainVB->Unlock();
return S_OK;
}
//-----------------------------------------------------------------------------
// 名称: SetupPointLights()
// 功能: 建立一个点灯光
//-----------------------------------------------------------------------------
VOID SetupPointLights(D3DXVECTOR3 Position, ULONG ulIndex, D3DCOLORVALUE Color)
{
D3DXVECTOR3 vecDir;
D3DLIGHT8 light;
ZeroMemory( &light, sizeof(D3DLIGHT8) );
light.Type = D3DLIGHT_POINT ;
light.Diffuse.r = Color.r;
light.Diffuse.g = Color.g;
light.Diffuse.b = Color.b;
light.Position = Position;
light.Range = 200.0f;
light.Attenuation0 = 1.1f;
g_pMyd3dDevice->SetLight( ulIndex, &light );
g_pMyd3dDevice->LightEnable( 0, TRUE );
g_pMyd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE );
return;
}
//-----------------------------------------------------------------------------
// 名称: 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -