⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rain.cpp

📁 是《3D游戏编程》的代码 买了这本书
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//-----------------------------------------------------------------------------
// 名称: 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 SNOW
{
        LPDIRECT3DVERTEXBUFFER8      m_pSnowVB;   
		LPDIRECT3DTEXTURE8      m_pTextureSnow;
		LONG		m_lSnowCount;
        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;

SNOW 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_Snow_Delete(SNOW *pSnow)
{
    if(pSnow->m_pSnowVB)
	       pSnow->m_pSnowVB->Release();

    if(pSnow->m_pTextureSnow != NULL )
        pSnow->m_pTextureSnow->Release();

	return D3D_OK;

}

HRESULT En_Snow_Init(LPDIRECT3DDEVICE8 pd3dDevice,
					   SNOW *pSnow,	   
					   LONG density)
{
    
	HRESULT hr;
    
	DWORD width = pSnow->m_Width;
	DWORD lenth = pSnow->m_Lenth;

	LONG lRainCount = width*lenth*density*density;
	pSnow->m_lSnowCount = lRainCount;
 
	// 创建渲染雪花的纹理
    if( FAILED( D3DXCreateTextureFromFile( pd3dDevice, "snow.tga",
                                           &pSnow->m_pTextureSnow ) ) )
        return E_FAIL;

    // 生成雪花的顶点
    hr = pd3dDevice->CreateVertexBuffer( lRainCount*sizeof(POINTVERTEX),
                                         D3DUSAGE_WRITEONLY, D3DFVF_POINTVERTEX,
                                         D3DPOOL_MANAGED, &pSnow->m_pSnowVB );
    if( FAILED(hr) )
        return hr;
	POINTVERTEX* pVertices = NULL;
	LPDIRECT3DVERTEXBUFFER8      pVB = pSnow->m_pSnowVB;

    hr = pVB->Lock( 0, lRainCount*sizeof(POINTVERTEX),
                             (BYTE**)&pVertices, 0 );

    for( DWORD line = 0; line < (DWORD)(width*density) ; line++ )
    {
		float offwidth = (float)1/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)1/density;
            pVertices->p.x =  -(float)width/2 + seg * (offwidth + fRandx);
            pVertices->p.y = (float)pSnow->m_Hight + fRandy;
            pVertices->p.z =  -(float)lenth/2 + line *(offlenth + fRandz);
			pVertices->color = 0xffffffff;
            pVertices++;
		}
	}

    pVB->Unlock();

	return S_OK;
}

HRESULT En_Snow_Move( SNOW *pSnow, float offset )
{
    
	HRESULT hr;

	DWORD lRainCount = pSnow->m_lSnowCount;

    // 移动雪花的顶点
	POINTVERTEX* pVertices = NULL;
	LPDIRECT3DVERTEXBUFFER8      pVB = pSnow->m_pSnowVB;

    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)pSnow->m_Hight;
		else
			pVertices->p.y -= offset;

        pVertices++;
	}



    pVB->Unlock();

	return S_OK;
}


HRESULT En_Snow_Draw( LPDIRECT3DDEVICE8 pd3dDevice, SNOW *pSnow )
{
   	D3DXMATRIX matWorld;
	DWORD lRainCount = pSnow->m_lSnowCount;

	D3DXMatrixTranslation( &matWorld, g_Player.LookAt[0].x , 0, g_Player.LookAt[0].z );
	g_pMyd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );

    // 渲染雪花的顶点
	POINTVERTEX* pVertices = NULL;
	LPDIRECT3DVERTEXBUFFER8      pVB = pSnow->m_pSnowVB;

    pd3dDevice->SetTexture( 0, pSnow->m_pTextureSnow );

    pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE,   TRUE );
    pd3dDevice->SetRenderState( D3DRS_SRCBLEND,  D3DBLEND_SRCALPHA );
    pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);

    pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE, TRUE );
    pd3dDevice->SetRenderState( D3DRS_ALPHAREF,        0x0f);
    pd3dDevice->SetRenderState( D3DRS_ALPHAFUNC,D3DCMP_GREATEREQUAL );

    pd3dDevice->SetRenderState( D3DRS_POINTSPRITEENABLE, TRUE );
    pd3dDevice->SetRenderState( D3DRS_POINTSCALEENABLE,  TRUE );
    pd3dDevice->SetRenderState( D3DRS_POINTSIZE,     FtoDW(0.04f) );
    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);

	En_Snow_Move(pSnow,0.01f);

	pd3dDevice->SetVertexShader( D3DFVF_POINTVERTEX );
    pd3dDevice->SetStreamSource( 0, pVB, sizeof(POINTVERTEX) );
    pd3dDevice->DrawPrimitive( D3DPT_POINTLIST,
                                   0, lRainCount);

	pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE, FALSE );
    pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );

	En_Snow_Move(pSnow, pSnow->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
	// 4. 指定设备的对于顶点的处理能力为软件处理顶点,这是为了能够让所有
	//    的显卡支持,参数D3DCREATE_SOFTWARE_VERTEXPROCESSING
    if( FAILED( g_pMyD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -