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

📄 light.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

struct PLAYER
{
    D3DXVECTOR3    LookAt[3];
};

// 定义个表示顶点的结构
struct ELLIPSE_VERTEX
{
        D3DXVECTOR3 p;
        D3DXVECTOR3 n;
        FLOAT       tu, tv;
};

struct CUSTOMVERTEX01
{
    D3DXVECTOR3 position; 
    D3DXVECTOR3 normal;   
};

struct CUSTOMVERTEX02
{
    D3DXVECTOR3 position; 
    D3DCOLOR    color;  
    FLOAT       tu, tv;   
};

#define FILL_WALLVERTEX( v, ax, ay, az, acolor, atu, atv )  \
{   v.position.x = ax; v.position.y = ay; v.position.z = az; v.color  = acolor; \
    v.tu = atu; v.tv = atv; \
}

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)
#define D3DFVF_CUSTOMVERTEX02 (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)

// 定义全局变量
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_pVBWalls = NULL;

// 定义用于墙面渲染的纹理指针变量
LPDIRECT3DTEXTURE8      g_pTextureWall   = NULL; 

// 定义用于地面渲染的纹理指针变量
LPDIRECT3DTEXTURE8      g_pTextureLand   = NULL;
 
// 定义用于天空渲染的纹理指针变量
LPDIRECT3DTEXTURE8      g_pTextureSky   = NULL; 

D3DXVECTOR3             g_lightPosition;

BOOL                    g_TextureFilter = TRUE;

PLAYER  g_Player;


float g_time = 0;

float   g_Angle = 0;

#define LINE_VECTOR_NUM 20


#define GRID_WIDTH       20.0f
#define NUM_GRID         20

#define WALL_VERT_NUM 10

#define ELLIPSE_RINGS     20
#define ELLIPSE_SEGMENTS  20

VOID GenerateEllipse( DWORD dwNumRings, DWORD dwNumSegments,
                      FLOAT fXScale, FLOAT fYScale, FLOAT fZScale,
                      CUSTOMVERTEX02** Vertices, DWORD* pdwNumVertices );
//-----------------------------------------------------------------------------
// 名称: 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, FALSE );
    g_pMyd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );

	// 创建墙面使用的纹理
    if( FAILED( D3DXCreateTextureFromFile( g_pMyd3dDevice, "tree01S.tga",
                                           &g_pTextureWall ) ) )
        return E_FAIL;

	// 创建地面使用的纹理
    if( FAILED( D3DXCreateTextureFromFile( g_pMyd3dDevice, "land.bmp",
                                           &g_pTextureLand ) ) )
        return E_FAIL;

	// 创建天空使用的纹理
    if( FAILED( D3DXCreateTextureFromFile( g_pMyd3dDevice, "Sky.bmp",
                                           &g_pTextureSky ) ) )
        return E_FAIL;
	// 创建表示墙面的顶点缓冲区
    if( FAILED( g_pMyd3dDevice->CreateVertexBuffer( 4*sizeof(CUSTOMVERTEX02),
                                                  0, D3DFVF_CUSTOMVERTEX02,
                                                  D3DPOOL_DEFAULT, &g_pMyVxBufferRec ) ) )
    {
        return E_FAIL;
    } 
	CUSTOMVERTEX02* pVertices1;
	// 获得顶点缓冲区的内存指针,并锁定顶点缓冲区
    if( FAILED( g_pMyVxBufferRec->Lock( 0, 4*sizeof(CUSTOMVERTEX02), (BYTE**)&pVertices1, 0 ) ) )
	{
        return E_FAIL;
	}

	// 初始化顶点数据到顶点缓冲区中
    pVertices1->position = D3DXVECTOR3(-1.5f, 0.0f, 0.0f);
	pVertices1->color =  0xffffffff;
	pVertices1->tu = 0.0f;
	pVertices1->tv = 1.0f;
	pVertices1++;
    pVertices1->position = D3DXVECTOR3(-1.5f, 3.0f, 0.0f);
	pVertices1->color =  0xffffffff;
	pVertices1->tu = 0.0f;
	pVertices1->tv = 0.0f;

	pVertices1++;
	pVertices1->position = D3DXVECTOR3( 1.5f, 0.0f, 0.0f);
	pVertices1->color =  0xffffffff;
	pVertices1->tu = 1.0f;
	pVertices1->tv = 1.0f;

	pVertices1++;
	pVertices1->position = D3DXVECTOR3( 1.5f, 3.0f, 0.0f);
	pVertices1->color =  0xffffffff;
	pVertices1->tu = 1.0f;
	pVertices1->tv = 0.0f;

	// 顶点缓冲区的解锁操作
    g_pMyVxBufferRec->Unlock();
	

	// 创建顶点缓冲区
    if( FAILED( g_pMyd3dDevice->CreateVertexBuffer( 4*sizeof(CUSTOMVERTEX02),
                                                  0, D3DFVF_CUSTOMVERTEX02,
                                                  D3DPOOL_DEFAULT, &g_pMyVxBufferLine ) ) )
    {
        return E_FAIL;
    } 

	// 获得顶点缓冲区的内存指针,并锁定顶点缓冲区
    if( FAILED( g_pMyVxBufferLine->Lock( 0, 4*sizeof(CUSTOMVERTEX02), (BYTE**)&pVertices1, 0 ) ) )
	{
        return E_FAIL;
	}

	// 初始化顶点数据到顶点缓冲区中
    pVertices1->position = D3DXVECTOR3(-12.0f, 0.0f, -12.0f);
	pVertices1->color =  0xffffffff;
	pVertices1->tu = 0.0f;
	pVertices1->tv = 1.0f;
	pVertices1++;
    pVertices1->position = D3DXVECTOR3(-12.0f, 0.0f, 12.0f);
	pVertices1->color =  0xffffffff;
	pVertices1->tu = 0.0f;
	pVertices1->tv = 0.0f;

	pVertices1++;
	pVertices1->position = D3DXVECTOR3( 12.0f, 0.0f, -12.0f);
	pVertices1->color =  0xffffffff;
	pVertices1->tu = 1.0f;
	pVertices1->tv = 1.0f;

	pVertices1++;
	pVertices1->position = D3DXVECTOR3( 12.0f, 0.0f, 12.0f);
	pVertices1->color =  0xffffffff;
	pVertices1->tu = 1.0f;
	pVertices1->tv = 0.0f;

	// 顶点缓冲区的解锁操作
    g_pMyVxBufferLine->Unlock();

	//************************************************************
	// 创建球形
	//************************************************************
	DWORD dwNumVertices;
	CUSTOMVERTEX02  *pVerticesEllipse;
	CUSTOMVERTEX02  *pVertices;

	GenerateEllipse( ELLIPSE_RINGS, ELLIPSE_SEGMENTS,
                      20.0f, 20.0f, 20.0f,
                      (CUSTOMVERTEX02**)&pVerticesEllipse, &dwNumVertices );

    if( FAILED( g_pMyd3dDevice->CreateVertexBuffer( dwNumVertices*sizeof(CUSTOMVERTEX02),
                                                  0, D3DFVF_CUSTOMVERTEX02,
                                                  D3DPOOL_DEFAULT, &g_pMyVxBufferEllipse ) ) )
        return E_FAIL;

	// 获得顶点缓冲区的内存指针,并锁定顶点缓冲区
    if( FAILED( g_pMyVxBufferEllipse->Lock( 0, dwNumVertices*sizeof(CUSTOMVERTEX02), 
		                                 (BYTE**)&pVertices, 0 ) ) )
        return E_FAIL;

    memcpy( pVertices, pVerticesEllipse, dwNumVertices*sizeof(CUSTOMVERTEX02) );
	
	// 顶点缓冲区的解锁操作
    g_pMyVxBufferEllipse->Unlock();
	delete pVerticesEllipse;


	//************************************************************
	// 创建天空的BOX
	//************************************************************
    if( FAILED( g_pMyd3dDevice->CreateVertexBuffer( WALL_VERT_NUM * sizeof(CUSTOMVERTEX02),
        0, D3DFVF_CUSTOMVERTEX02, D3DPOOL_DEFAULT, &g_pVBWalls ) ) )
    {
        return E_FAIL;
    }
    if(FAILED(g_pVBWalls->Lock( 0, WALL_VERT_NUM*sizeof(CUSTOMVERTEX02),
								(BYTE**)&pVertices, 0 )))
		return E_FAIL;
 
    FILL_WALLVERTEX( pVertices[ 0], -50.0f,-20.0f, 50.0f, 0xfffffff, 0.00f, 1.0f );
    FILL_WALLVERTEX( pVertices[ 1], -50.0f, 100.0f, 50.0f, 0xfffffff, 0.00f, 0.0f );
    FILL_WALLVERTEX( pVertices[ 2],  50.0f,-20.0f, 50.0f, 0xfffffff, 1.00f, 1.0f );
    FILL_WALLVERTEX( pVertices[ 3],  50.0f, 100.0f, 50.0f, 0xfffffff, 1.00f, 0.0f );
    FILL_WALLVERTEX( pVertices[ 4],  50.0f,-20.0f,-50.0f, 0xfffffff, 2.00f, 1.0f );
    FILL_WALLVERTEX( pVertices[ 5],  50.0f, 100.0f,-50.0f, 0xfffffff, 2.00f, 0.0f );
    FILL_WALLVERTEX( pVertices[ 6], -50.0f,-20.0f,-50.0f, 0xfffffff, 3.00f, 1.0f );
    FILL_WALLVERTEX( pVertices[ 7], -50.0f, 100.0f,-50.0f, 0xfffffff, 3.00f, 0.0f );
    FILL_WALLVERTEX( pVertices[ 8], -50.0f,-20.0f, 50.0f, 0xfffffff, 4.00f, 1.0f );
    FILL_WALLVERTEX( pVertices[ 9], -50.0f, 100.0f, 50.0f, 0xfffffff, 4.00f, 0.0f );

    g_pVBWalls->Unlock();

	g_Player.LookAt[0] = D3DXVECTOR3( 0.0f, 1.0f,-4.0f );
	g_Player.LookAt[1] = D3DXVECTOR3( 0.0f, 1.0f,-3.0f );
	g_Player.LookAt[2] = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
    g_lightPosition = D3DXVECTOR3( 0.0f, 1.0f,-4.0f );

	g_time = timeGetTime();
	
	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       = 20.0f;
	light.Attenuation0 = 1.0f;
    g_pMyd3dDevice->SetLight( ulIndex, &light );
    g_pMyd3dDevice->LightEnable( 0, TRUE );
    g_pMyd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE );
	return;

}

VOID GenerateEllipse( DWORD dwNumRings, DWORD dwNumSegments,
                      FLOAT fXScale, FLOAT fYScale, FLOAT fZScale,
                      CUSTOMVERTEX02** ppVertices, DWORD* pdwNumVertices )
{
    // Allocate space for the sphere
    CUSTOMVERTEX02* v    = new CUSTOMVERTEX02[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 );

⌨️ 快捷键说明

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