Direct3D轮回:游戏场景之陆地
2011-07-23 13:32
337 查看
继天空效果之后,这一节简单阐述一点地形生成的基本原理和方法~ 如果哪里说的不对,还望园子的前辈们多多拍砖 ^ ^
首先,我们准备两张图:
D3DGame.cpp
/*-------------------------------------
代码清单:D3DGame.cpp
来自:http://www.cnblogs.com/kenkao
-------------------------------------*/
#include "StdAfx.h"
#include "D3DGame.h"
#include "D3DCamera.h"
#include "D3DEffect.h"
#include "CoordCross.h"
#include "SimpleXMesh.h"
#include "Texture2D.h"
#include "D3DSprite.h"
#include "Skybox.h"
#include "SpriteBatch.h"
#include "BaseTerrain.h"
#include <stdio.h>
//---通用全局变量
HINSTANCE g_hInst;
HWND g_hWnd;
D3DXMATRIX g_matProjection;
//---D3D全局变量
IDirect3D9 *g_pD3D = NULL;
IDirect3DDevice9 *g_pD3DDevice = NULL;
CMouseInput *g_pMouseInput = NULL;
CKeyboardInput *g_pKeyboardInput = NULL;
CD3DCamera *g_pD3DCamera = NULL;
CCoordCross *g_pCoordCross = NULL;
CSimpleXMesh *g_pSimpleXMesh = NULL;
CD3DEffect *g_pD3DEffect = NULL;
CD3DSprite *g_pD3DSprite = NULL;
CTexture2D *g_pTexture2D = NULL;
CSpriteBatch *g_SpriteBatch = NULL;
CTexture2D *g_pTexture2D2 = NULL;
CD3DEffect *g_pD3DEffect2 = NULL;
CSkybox *g_pSkybox = NULL;
CBaseTerrain *g_pBaseTerrain = NULL;
//---HLSL全局变量句柄
D3DXHANDLE g_CurrentTechHandle = NULL;
D3DXHANDLE g_matWorldViewProj = NULL;
D3DXHANDLE g_matWorld = NULL;
D3DXHANDLE g_vecEye = NULL;
D3DXHANDLE g_vecLightDir = NULL;
D3DXHANDLE g_vDiffuseColor = NULL;
D3DXHANDLE g_vSpecularColor = NULL;
D3DXHANDLE g_vAmbient = NULL;
D3DXHANDLE g_CurrentTechHandle2 = NULL;
D3DXHANDLE g_Scale = NULL;
// HLSL特效参数设置
void GetParameters();
void SetParameters();
void Initialize(HINSTANCE hInst, HWND hWnd)
{
g_hInst = hInst;
g_hWnd = hWnd;
InitD3D(&g_pD3D, &g_pD3DDevice, g_matProjection, hWnd);
g_pMouseInput = new CMouseInput;
g_pMouseInput->Initialize(hInst,hWnd);
g_pKeyboardInput = new CKeyboardInput;
g_pKeyboardInput->Initialize(hInst,hWnd);
g_pD3DCamera = new CD3DCamera;
}
void LoadContent()
{
g_pCoordCross = new CCoordCross;
g_pD3DCamera->SetCameraPos(D3DXVECTOR3(0.0f,0.0f,0.0f));
g_pSimpleXMesh = new CSimpleXMesh;
g_pSimpleXMesh->LoadXMesh("teapot.X");
g_pD3DEffect = new CD3DEffect;
g_pD3DEffect2 = new CD3DEffect;
g_pD3DEffect->LoadEffect("Light.fx");
g_pD3DEffect2->LoadEffect("Thunder.fx");
GetParameters();
g_pD3DSprite = new CD3DSprite(g_pD3DDevice);
g_SpriteBatch = new CSpriteBatch(g_pD3DDevice);
g_pTexture2D = new CTexture2D;
g_pTexture2D->LoadTexture("img.jpg");
g_pTexture2D2 = new CTexture2D;
g_pTexture2D2->LoadTexture("img2.jpg");
g_pSkybox = new CSkybox;
g_pSkybox->Create("Skybox_0.JPG","Skybox_1.JPG","Skybox_2.JPG"
,"Skybox_3.JPG","Skybox_4.JPG","Skybox_5.JPG");
g_pBaseTerrain = new CBaseTerrain;
g_pBaseTerrain->Create(128,128,10,"HeightData_128x128.raw","Grass.dds");
}
void Update()
{
g_pMouseInput->GetState();
g_pKeyboardInput->GetState();
// 更新摄影机高度
D3DXVECTOR3 CameraPos = g_pD3DCamera->GetCameraPos();
float roleHeight = 25.0f;
float Ty = g_pBaseTerrain->GetExactHeightAt(CameraPos.x,CameraPos.z) + roleHeight;
g_pD3DCamera->SetCameraPos(D3DXVECTOR3(
CameraPos.x,
Ty,
CameraPos.z));
g_pD3DCamera->Update();
// 更新g_pD3DEffect中的视点位置
D3DXVECTOR4 vecEye = D3DXVECTOR4(CameraPos.x,Ty,CameraPos.z,0.0f);
g_pD3DEffect -> GetEffect() -> SetVector(g_vecEye,&vecEye);
}
void Draw()
{
// 参数设定
SetParameters();
g_pD3DDevice->SetTransform(D3DTS_VIEW,&g_pD3DCamera->GetViewMatrix());
g_pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_RGBA(100,149,237,255), 1.0f, 0);
if(SUCCEEDED(g_pD3DDevice->BeginScene()))
{
// 天空处在无限远处,因此必须最先绘制天空盒
g_pSkybox->Draw();
UINT numPasses;
// 开启特效
g_pD3DEffect->BeginEffect(numPasses);
for(UINT i=0;i<numPasses;i++)
{
// 开启路径
g_pD3DEffect->GetEffect()->BeginPass(i);
// 绘制地形
g_pBaseTerrain->Draw();
// 路径结束
g_pD3DEffect->GetEffect()->EndPass();
}
// 特效结束
g_pD3DEffect->EndEffect();
g_pD3DDevice->EndScene();
}
g_pD3DDevice->Present(NULL, NULL, NULL, NULL);
}
void UnloadContent()
{
ReleaseCOM(g_pBaseTerrain);
ReleaseCOM(g_pSkybox);
ReleaseCOM(g_pTexture2D2);
ReleaseCOM(g_pTexture2D);
ReleaseCOM(g_SpriteBatch);
ReleaseCOM(g_pD3DSprite);
ReleaseCOM(g_pD3DEffect2);
ReleaseCOM(g_pD3DEffect);
ReleaseCOM(g_pSimpleXMesh);
ReleaseCOM(g_pCoordCross);
}
void Dispose()
{
ReleaseCOM(g_pD3DCamera);
ReleaseCOM(g_pKeyboardInput);
ReleaseCOM(g_pMouseInput);
ReleaseCOM(g_pD3DDevice);
ReleaseCOM(g_pD3D);
}
void GetParameters()
{
// 获得HLSL中各个全局变量句柄
g_CurrentTechHandle = g_pD3DEffect -> GetEffect() -> GetTechniqueByName("SpecularLight");
g_matWorldViewProj = g_pD3DEffect -> GetEffect() -> GetParameterByName(0, "matWorldViewProj");
g_matWorld = g_pD3DEffect -> GetEffect() -> GetParameterByName(0, "matWorld");
g_vecEye = g_pD3DEffect -> GetEffect() -> GetParameterByName(0, "vecEye");
g_vecLightDir = g_pD3DEffect -> GetEffect() -> GetParameterByName(0, "vecLightDir");
g_vDiffuseColor = g_pD3DEffect -> GetEffect() -> GetParameterByName(0, "vDiffuseColor");
g_vSpecularColor = g_pD3DEffect -> GetEffect() -> GetParameterByName(0, "vSpecularColor");
g_vAmbient = g_pD3DEffect -> GetEffect() -> GetParameterByName(0, "vAmbient");
g_CurrentTechHandle2 = g_pD3DEffect2 -> GetEffect() -> GetTechniqueByName("Technique1");
g_Scale = g_pD3DEffect2 -> GetEffect() -> GetParameterByName(0, "Scale");
}
void SetParameters()
{
// 设定当前技术
g_pD3DEffect -> GetEffect() -> SetTechnique(g_CurrentTechHandle);
// 设定HLSL中的各个参数
D3DXMATRIX worldMatrix;
D3DXMatrixTranslation(&worldMatrix,0.0f,0.0f,0.0f);
g_pD3DEffect -> GetEffect() -> SetMatrix(g_matWorldViewProj,&(worldMatrix*g_pD3DCamera->GetViewMatrix()*g_matProjection));
g_pD3DEffect -> GetEffect() -> SetMatrix(g_matWorld,&worldMatrix);
D3DXVECTOR4 vLightDirection = D3DXVECTOR4(-5.0f, -1.0f, 2.0f, 1.0f);
g_pD3DEffect -> GetEffect() -> SetVector(g_vecLightDir,&vLightDirection);
D3DXVECTOR4 vColorDiffuse = D3DXVECTOR4(0.0f, 0.0f, 0.0f, 1.0f);
D3DXVECTOR4 vColorSpecular = D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f);
D3DXVECTOR4 vColorAmbient = D3DXVECTOR4(0.0f, 0.0f, 0.0f, 1.0f);
g_pD3DEffect -> GetEffect() -> SetVector(g_vDiffuseColor,&vColorDiffuse);
// g_pD3DEffect -> GetEffect() -> SetVector(g_vSpecularColor,&vColorSpecular); //暂时不加入镜面高光 ^ ^
g_pD3DEffect -> GetEffect() -> SetVector(g_vAmbient,&vColorAmbient);
g_pD3DEffect2 -> GetEffect() -> SetTechnique(g_CurrentTechHandle2);
g_pD3DEffect2 -> GetEffect() -> SetFloat(g_Scale,0.8f);
}
我们使用light.fx为新生成的地形添加光照效果。这里我在其原有基础上作了改动。
首先添加一个纹理采样器:
sampler2D TextureSampler = sampler_state
{
magfilter=LINEAR;
minfilter=LINEAR;
mipfilter=LINEAR;
};
然后让像素着色器最终的输出结果累计地形纹理原有的颜色:
return vAmbient + vDiffuseColor * Diff + vSpecularColor * Specular + tex2D(TextureSampler, vtop.uv); //---最后的颜色 = 环境光 + 漫射光 + 镜面高光 + 本来颜色(纹理)
我们来看看效果:
山地跟沟壑~ 都是高度图的功劳,呵呵~
主体代码中我注释掉了镜面光的颜色赋值,因为按理说草地是不会反射阳光的。我们不妨换一张冷峻的岩石地表,然后再打开镜面光,试试看效果如何~
怎么样,很耀眼吧?呵呵 ^ ^
到此,以上阐述了地形生成方法中的诸多基本原理,但如果要用于生成大型的地形或者无边界地形的话,仅仅靠这样简单的方法是不堪重负的。不过大家无需担心,地形生成的基本原理大致都是相同的,只不过复杂的大地形在此基础上加入了一些特殊的算法和机制,以动态数据的方法减轻了CPU和显卡的负担。如果后续有机会深度研究这些,我会尽我所能,为大家一一道来~
谢谢~ ^ ^
首先,我们准备两张图:
D3DGame.cpp
/*-------------------------------------
代码清单:D3DGame.cpp
来自:http://www.cnblogs.com/kenkao
-------------------------------------*/
#include "StdAfx.h"
#include "D3DGame.h"
#include "D3DCamera.h"
#include "D3DEffect.h"
#include "CoordCross.h"
#include "SimpleXMesh.h"
#include "Texture2D.h"
#include "D3DSprite.h"
#include "Skybox.h"
#include "SpriteBatch.h"
#include "BaseTerrain.h"
#include <stdio.h>
//---通用全局变量
HINSTANCE g_hInst;
HWND g_hWnd;
D3DXMATRIX g_matProjection;
//---D3D全局变量
IDirect3D9 *g_pD3D = NULL;
IDirect3DDevice9 *g_pD3DDevice = NULL;
CMouseInput *g_pMouseInput = NULL;
CKeyboardInput *g_pKeyboardInput = NULL;
CD3DCamera *g_pD3DCamera = NULL;
CCoordCross *g_pCoordCross = NULL;
CSimpleXMesh *g_pSimpleXMesh = NULL;
CD3DEffect *g_pD3DEffect = NULL;
CD3DSprite *g_pD3DSprite = NULL;
CTexture2D *g_pTexture2D = NULL;
CSpriteBatch *g_SpriteBatch = NULL;
CTexture2D *g_pTexture2D2 = NULL;
CD3DEffect *g_pD3DEffect2 = NULL;
CSkybox *g_pSkybox = NULL;
CBaseTerrain *g_pBaseTerrain = NULL;
//---HLSL全局变量句柄
D3DXHANDLE g_CurrentTechHandle = NULL;
D3DXHANDLE g_matWorldViewProj = NULL;
D3DXHANDLE g_matWorld = NULL;
D3DXHANDLE g_vecEye = NULL;
D3DXHANDLE g_vecLightDir = NULL;
D3DXHANDLE g_vDiffuseColor = NULL;
D3DXHANDLE g_vSpecularColor = NULL;
D3DXHANDLE g_vAmbient = NULL;
D3DXHANDLE g_CurrentTechHandle2 = NULL;
D3DXHANDLE g_Scale = NULL;
// HLSL特效参数设置
void GetParameters();
void SetParameters();
void Initialize(HINSTANCE hInst, HWND hWnd)
{
g_hInst = hInst;
g_hWnd = hWnd;
InitD3D(&g_pD3D, &g_pD3DDevice, g_matProjection, hWnd);
g_pMouseInput = new CMouseInput;
g_pMouseInput->Initialize(hInst,hWnd);
g_pKeyboardInput = new CKeyboardInput;
g_pKeyboardInput->Initialize(hInst,hWnd);
g_pD3DCamera = new CD3DCamera;
}
void LoadContent()
{
g_pCoordCross = new CCoordCross;
g_pD3DCamera->SetCameraPos(D3DXVECTOR3(0.0f,0.0f,0.0f));
g_pSimpleXMesh = new CSimpleXMesh;
g_pSimpleXMesh->LoadXMesh("teapot.X");
g_pD3DEffect = new CD3DEffect;
g_pD3DEffect2 = new CD3DEffect;
g_pD3DEffect->LoadEffect("Light.fx");
g_pD3DEffect2->LoadEffect("Thunder.fx");
GetParameters();
g_pD3DSprite = new CD3DSprite(g_pD3DDevice);
g_SpriteBatch = new CSpriteBatch(g_pD3DDevice);
g_pTexture2D = new CTexture2D;
g_pTexture2D->LoadTexture("img.jpg");
g_pTexture2D2 = new CTexture2D;
g_pTexture2D2->LoadTexture("img2.jpg");
g_pSkybox = new CSkybox;
g_pSkybox->Create("Skybox_0.JPG","Skybox_1.JPG","Skybox_2.JPG"
,"Skybox_3.JPG","Skybox_4.JPG","Skybox_5.JPG");
g_pBaseTerrain = new CBaseTerrain;
g_pBaseTerrain->Create(128,128,10,"HeightData_128x128.raw","Grass.dds");
}
void Update()
{
g_pMouseInput->GetState();
g_pKeyboardInput->GetState();
// 更新摄影机高度
D3DXVECTOR3 CameraPos = g_pD3DCamera->GetCameraPos();
float roleHeight = 25.0f;
float Ty = g_pBaseTerrain->GetExactHeightAt(CameraPos.x,CameraPos.z) + roleHeight;
g_pD3DCamera->SetCameraPos(D3DXVECTOR3(
CameraPos.x,
Ty,
CameraPos.z));
g_pD3DCamera->Update();
// 更新g_pD3DEffect中的视点位置
D3DXVECTOR4 vecEye = D3DXVECTOR4(CameraPos.x,Ty,CameraPos.z,0.0f);
g_pD3DEffect -> GetEffect() -> SetVector(g_vecEye,&vecEye);
}
void Draw()
{
// 参数设定
SetParameters();
g_pD3DDevice->SetTransform(D3DTS_VIEW,&g_pD3DCamera->GetViewMatrix());
g_pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_RGBA(100,149,237,255), 1.0f, 0);
if(SUCCEEDED(g_pD3DDevice->BeginScene()))
{
// 天空处在无限远处,因此必须最先绘制天空盒
g_pSkybox->Draw();
UINT numPasses;
// 开启特效
g_pD3DEffect->BeginEffect(numPasses);
for(UINT i=0;i<numPasses;i++)
{
// 开启路径
g_pD3DEffect->GetEffect()->BeginPass(i);
// 绘制地形
g_pBaseTerrain->Draw();
// 路径结束
g_pD3DEffect->GetEffect()->EndPass();
}
// 特效结束
g_pD3DEffect->EndEffect();
g_pD3DDevice->EndScene();
}
g_pD3DDevice->Present(NULL, NULL, NULL, NULL);
}
void UnloadContent()
{
ReleaseCOM(g_pBaseTerrain);
ReleaseCOM(g_pSkybox);
ReleaseCOM(g_pTexture2D2);
ReleaseCOM(g_pTexture2D);
ReleaseCOM(g_SpriteBatch);
ReleaseCOM(g_pD3DSprite);
ReleaseCOM(g_pD3DEffect2);
ReleaseCOM(g_pD3DEffect);
ReleaseCOM(g_pSimpleXMesh);
ReleaseCOM(g_pCoordCross);
}
void Dispose()
{
ReleaseCOM(g_pD3DCamera);
ReleaseCOM(g_pKeyboardInput);
ReleaseCOM(g_pMouseInput);
ReleaseCOM(g_pD3DDevice);
ReleaseCOM(g_pD3D);
}
void GetParameters()
{
// 获得HLSL中各个全局变量句柄
g_CurrentTechHandle = g_pD3DEffect -> GetEffect() -> GetTechniqueByName("SpecularLight");
g_matWorldViewProj = g_pD3DEffect -> GetEffect() -> GetParameterByName(0, "matWorldViewProj");
g_matWorld = g_pD3DEffect -> GetEffect() -> GetParameterByName(0, "matWorld");
g_vecEye = g_pD3DEffect -> GetEffect() -> GetParameterByName(0, "vecEye");
g_vecLightDir = g_pD3DEffect -> GetEffect() -> GetParameterByName(0, "vecLightDir");
g_vDiffuseColor = g_pD3DEffect -> GetEffect() -> GetParameterByName(0, "vDiffuseColor");
g_vSpecularColor = g_pD3DEffect -> GetEffect() -> GetParameterByName(0, "vSpecularColor");
g_vAmbient = g_pD3DEffect -> GetEffect() -> GetParameterByName(0, "vAmbient");
g_CurrentTechHandle2 = g_pD3DEffect2 -> GetEffect() -> GetTechniqueByName("Technique1");
g_Scale = g_pD3DEffect2 -> GetEffect() -> GetParameterByName(0, "Scale");
}
void SetParameters()
{
// 设定当前技术
g_pD3DEffect -> GetEffect() -> SetTechnique(g_CurrentTechHandle);
// 设定HLSL中的各个参数
D3DXMATRIX worldMatrix;
D3DXMatrixTranslation(&worldMatrix,0.0f,0.0f,0.0f);
g_pD3DEffect -> GetEffect() -> SetMatrix(g_matWorldViewProj,&(worldMatrix*g_pD3DCamera->GetViewMatrix()*g_matProjection));
g_pD3DEffect -> GetEffect() -> SetMatrix(g_matWorld,&worldMatrix);
D3DXVECTOR4 vLightDirection = D3DXVECTOR4(-5.0f, -1.0f, 2.0f, 1.0f);
g_pD3DEffect -> GetEffect() -> SetVector(g_vecLightDir,&vLightDirection);
D3DXVECTOR4 vColorDiffuse = D3DXVECTOR4(0.0f, 0.0f, 0.0f, 1.0f);
D3DXVECTOR4 vColorSpecular = D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f);
D3DXVECTOR4 vColorAmbient = D3DXVECTOR4(0.0f, 0.0f, 0.0f, 1.0f);
g_pD3DEffect -> GetEffect() -> SetVector(g_vDiffuseColor,&vColorDiffuse);
// g_pD3DEffect -> GetEffect() -> SetVector(g_vSpecularColor,&vColorSpecular); //暂时不加入镜面高光 ^ ^
g_pD3DEffect -> GetEffect() -> SetVector(g_vAmbient,&vColorAmbient);
g_pD3DEffect2 -> GetEffect() -> SetTechnique(g_CurrentTechHandle2);
g_pD3DEffect2 -> GetEffect() -> SetFloat(g_Scale,0.8f);
}
我们使用light.fx为新生成的地形添加光照效果。这里我在其原有基础上作了改动。
首先添加一个纹理采样器:
sampler2D TextureSampler = sampler_state
{
magfilter=LINEAR;
minfilter=LINEAR;
mipfilter=LINEAR;
};
然后让像素着色器最终的输出结果累计地形纹理原有的颜色:
return vAmbient + vDiffuseColor * Diff + vSpecularColor * Specular + tex2D(TextureSampler, vtop.uv); //---最后的颜色 = 环境光 + 漫射光 + 镜面高光 + 本来颜色(纹理)
我们来看看效果:
山地跟沟壑~ 都是高度图的功劳,呵呵~
主体代码中我注释掉了镜面光的颜色赋值,因为按理说草地是不会反射阳光的。我们不妨换一张冷峻的岩石地表,然后再打开镜面光,试试看效果如何~
怎么样,很耀眼吧?呵呵 ^ ^
到此,以上阐述了地形生成方法中的诸多基本原理,但如果要用于生成大型的地形或者无边界地形的话,仅仅靠这样简单的方法是不堪重负的。不过大家无需担心,地形生成的基本原理大致都是相同的,只不过复杂的大地形在此基础上加入了一些特殊的算法和机制,以动态数据的方法减轻了CPU和显卡的负担。如果后续有机会深度研究这些,我会尽我所能,为大家一一道来~
谢谢~ ^ ^
相关文章推荐
- Direct3D轮回:游戏场景之天空
- Direct3D轮回:游戏场景之植被
- Direct3D轮回:游戏场景之河流
- Direct3D轮回:游戏场景之河流
- Direct3D轮回:快速构建基于win32工程的Direct3D游戏框架
- Direct3D轮回:游戏特效之晴天光晕
- Direct3D轮回:游戏特效之风动、雾化
- *Direct3D轮回:游戏场景之河流
- Direct3D轮回:游戏特效之全屏泛光(Bloom)
- 守卫者游戏开发教程之cocos2d-iphone2.0第一部分(菜单场景)
- 【Cocos2d游戏开发之二】CCScene场景切换的特效
- 游戏中的跨场景寻路
- 【Unity3D】学习笔记(第3记) 2D游戏开发基本技巧之场景切换(Javascript)
- 【Cocos2D-X游戏开发笔记2】自定义场景及场景切换效果
- C#实现游戏 场景的保存和加载(利用序列化)
- Unity3D游戏制作(一)——3D横版场景的角色移动控制
- Unity游戏开发使用Assetbundle加载场景实战
- (转)Android游戏开发之切换游戏场景特效的实现 (十九)
- cocos2d-lua消除游戏实战(一)主场景和游戏场景设计
- 网络游戏服务器构架设计(三):刀剑Online - 总控服务器、场景服务器