25. GameProject3
main.h main.cpp 无变化
define.h
#ifndef _UGP_DEFINES_H_
#define _UGP_DEFINES_H_
#include<windows.h>
// Boolean values.
#define UGP_INVALID -1
#define UGP_OK 1
#define UGP_FAIL 0
// Light type defines.
#define LIGHT_POINT 1
#define LIGHT_DIRECTIONAL 2
#define LIGHT_SPOT 3
// Window handle (need new way if porting to Mac and OpenGL).
#define WinHWND HWND
// Typedefs and enumerations.
typedef long VertexType;
enum PrimType
{
NULL_TYPE,
POINT_LIST,
TRIANGLE_LIST,
TRIANGLE_STRIP,
TRIANGLE_FAN,
LINE_LIST,
LINE_STRIP
};
// 一些渲染状态
enum RenderState
{
CULL_NONE,
CULL_CW,
CULL_CCW,
DEPTH_NONE,
DEPTH_READONLY,
DEPTH_READWRITE,
SHADE_POINTS,
SHADE_SOLIDTRI,
SHADE_WIRETRI,
SHADE_WIREPOLY,
TRANSPARENCY_NONE, // 禁用透明度
TRANSPARENCY_ENABLE // 启用透明度
};
// 透明度渲染状态值
enum TransState
{
TRANS_ZERO = 1,
TRANS_ONE,
TRANS_SRCCOLOR,
TRANS_INVSRCCOLOR,
TRANS_SRCALPHA,
TRANS_INVSRCALPHA,
TRANS_DSTALPHA,
TRANS_INVDSTALPHA,
TRANS_DSTCOLOR,
TRANS_INVDSTCOLOR,
TRANS_SRCALPHASAT,
TRANS_BOTHSRCALPHA,
TRANS_INVBOTHSRCALPHA,
TRANS_BLENDFACTOR,
TRANS_INVBLENDFACTOR
};
// 纹理过滤器的过滤模式
enum TextureState
{
MIN_FILTER, // 缩小率
MAG_FILTER, // 放大率
MIP_FILTER // mipmap纹理级别
};
// 纹理过滤器类型
enum FilterType
{
POINT_TYPE, // 最近点采样
LINEAR_TYPE, // 线性纹理过滤
ANISOTROPIC_TYPE // 各向异性纹理过滤
};
// Color defines.
#define UGPCOLOR_ARGB(a,r,g,b) ((unsigned long)((((a)&0xff)<<24)|\
(((r)&0xff)<<16)|(((g)&0xff)<<8)|\
((b)&0xff)))
#endif
RenderInterface.h
#ifndef _UGP_RENDERINTERFACE_H_
#define _UGP_RENDERINTERFACE_H_
#include"defines.h"
#include"material.h"
#include"light.h"
class CRenderInterface
{
public:
CRenderInterface() : m_screenWidth(0), m_screenHeight(0), m_near(0), m_far(0) { }
virtual ~CRenderInterface() {}
// 初始化D3D
// @w 窗口的宽度
// @h 窗口的高度
// @mainWin 初始化D3D用到的窗口句柄
// @fullScreen 是否全屏
virtual bool Initialize(int w, int h, WinHWND mainWin, bool fullScreen) = 0;
// 一些可以一次性的设置的D3D渲染状态的初始化操作
virtual void OneTimeInit() = 0;
// 关闭引擎释放资源
virtual void Shutdown() = 0;
// 设置清屏幕用的颜色
virtual void SetClearCol(float r, float g, float b) = 0;
// 开始渲染之前的一些必须操作
// @bColor D3D的Clear是否清空目标缓存
// @bDepth D3D的Clear是否清空深度缓存
// @bStencil D3D的Clear是否清空模板缓存
virtual void StartRender(bool bColor, bool bDepth, bool bStencil) = 0;
// 结束渲染的之前的一些必须操作
// @bColor D3D的Clear是否清空目标缓存
// @bDepth D3D的Clear是否清空深度缓存
// @bStencil D3D的Clear是否清空模板缓存
virtual void ClearBuffers(bool bColor, bool bDepth, bool bStencil) = 0;
// 结束渲染并将渲染结果输出到屏幕
virtual void EndRendering() = 0;
// 应用材质
// @mat 被应用的材质对象指针
virtual void SetMaterial(stMaterial *mat) = 0;
// 开启光照
// @light 被应用的光源对象指针
// @index 指定需要激活的光源的序号值0-7
virtual void SetLight(stLight *light, int index) = 0;
// 禁止光照
virtual void DisableLight(int index) = 0;
// 设置深度测试
virtual void SetDepthTesting(RenderState state) = 0;
// 设置透明度
// @state 正在设置的渲染状态
// @src 源混合操作(源融合因子)
// @dst 目的混合操作(目标融合因子)
virtual void SetTransparency(RenderState state, TransState src, TransState dst) = 0;
// 添加2D纹理
// @file 图像文件名
// @texId 新创建纹理对象的id
virtual int AddTexture2D(char *file, int *texId) = 0;
// 设置纹理过滤器
// @index 纹理采样属性的纹理层ID(0~7)
// @filter 滤波器模式
// @val 滤波器值
virtual void SetTextureFilter(int index, int filter, int val) = 0;
// 设置多纹理贴图
virtual void SetMultiTexture() = 0;
// 应用纹理
// @index 纹理层id 0-7
// @texId 纹理的计数器id
virtual void ApplyTexture(int index, int texId) = 0;
// 保存屏幕截图
virtual void SaveScreenShot(char *file) = 0;
// 启用点状sprite
// @size sprite的尺寸
// @min 最小尺寸
// @a 参数a
// @b 参数b
// @c 参数c
virtual void EnablePointSprites(float size, float min, float a, float b, float c) = 0;
// 禁用点状sprite
virtual void DisablePointSprites() = 0;
// 计算并设置透视投影矩阵
// @fov 摄像机镜头的夹角(在Y轴上的成像角度)
// @n 近平截面的距离
// @f 远平截面的距离
virtual void CalculateProjMatrix(float fov, float n, float f) = 0;
// 计算并设置正交投影矩阵
// @n 近平截面的距离
// @f 远平截面的距离
virtual void CalculateOrthoMatrix(float n, float f) = 0;
// 创建要绘制的静态顶点缓存
// @VertexType
// @PrimType 渲染静态缓存时要用的图元类型
// @totalVerts 顶点个数
// @totalIndices 索引个数
// @stride 单个顶点的尺寸
// @data 存储顶点数据的缓冲区指针
// @indices 存储顶点索引数据的缓冲区指针
// @staticId 返回刚刚创建的顶点缓存的索引id
virtual int CreateStaticBuffer(VertexType, PrimType,
int totalVerts, int totalIndices,
int stride, void **data, unsigned int *indices,
int *staticId) = 0;
// 渲染
// @staticId 渲染函数要使用的顶点缓存的索引id
virtual int Render(int staticId) = 0;
protected:
int m_screenWidth; // 屏幕宽度
int m_screenHeight; // 屏幕高度
bool m_fullscreen; // 是否渲染整个屏幕
WinHWND m_mainHandle; // D3D初始化函数所需要的窗口句柄
float m_near; // 投影矩阵所需的近距离值
float m_far; // 投影矩阵所需的远距离值
};
#endif
D3DRenderer.h
#ifndef _D3D_RENDERER_H_
#define _D3D_RENDERER_H_
#include<windows.h>
#include<d3d9.h>
#include<d3dx9.h>
#include"RenderInterface.h"
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")
struct stD3DStaticBuffer
{
stD3DStaticBuffer() : vbPtr(0), ibPtr(0), numVerts(0),
numIndices(0), stride(0), fvf(0),
primType(NULL_TYPE) {}
LPDIRECT3DVERTEXBUFFER9 vbPtr; // 顶点缓存
LPDIRECT3DINDEXBUFFER9 ibPtr; // 索引缓存
int numVerts; //定点计数器
int numIndices; // 索引计数器
int stride; // 单个顶点的尺寸幅度值
unsigned long fvf; // Direct3D顶点FVF
PrimType primType; // 在渲染静态缓存时要用的图元类型
};
// 纹理信息结构
struct stD3DTexture
{
stD3DTexture() : fileName(0), image(0), width(0), height(0) {}
char *fileName;
int width, height;
LPDIRECT3DTEXTURE9 image;
};
class CD3DRenderer : public CRenderInterface
{
public:
CD3DRenderer();
~CD3DRenderer();
bool Initialize(int w, int h, WinHWND mainWin,
bool fullScreen);
void Shutdown();
void SetClearCol(float r, float g, float b);
void StartRender(bool bColor, bool bDepth, bool bStencil);
void ClearBuffers(bool bColor, bool bDepth, bool bStencil);
void EndRendering();
void SetMaterial(stMaterial *mat);
void SetLight(stLight *light, int index);
void DisableLight(int index);
void SetDepthTesting(RenderState state);
void SetTransparency(RenderState state, TransState src, TransState dst);
int AddTexture2D(char *file, int *texId);
void SetTextureFilter(int index, int filter, int val);
void SetMultiTexture();
void ApplyTexture(int index, int texId);
void SaveScreenShot(char *file);
void EnablePointSprites(float size, float min, float a, float b, float c);
void DisablePointSprites();
void CalculateProjMatrix(float fov, float n, float f);
void CalculateOrthoMatrix(float n, float f);
int CreateStaticBuffer(VertexType, PrimType,
int totalVerts, int totalIndices,
int stride, void **data, unsigned int *indices,
int *staticId);
int Render(int staticId);
private:
void OneTimeInit();
private:
D3DCOLOR m_Color;
LPDIRECT3D9 m_Direct3D;
LPDIRECT3DDEVICE9 m_Device;
bool m_renderingScene;
stD3DStaticBuffer *m_staticBufferList; // 静态顶点缓存列表的头指针
int m_numStaticBuffers; // 顶点缓存个数
int m_activeStaticBuffer; // 当前活动的顶点缓存的索引id
stD3DTexture *m_textureList; //纹理对象列表,这里将存储所有的纹理对象,并使用ID访问它们
int m_numTextures; // 纹理对象计数器
};
bool CreateD3DRenderer(CRenderInterface **pObj);
#endif
D3DRenderer.cpp
#include"D3DRenderer.h"
inline unsigned long FtoDW(float val)
{
return *((unsigned long*)&val);
}
bool CreateD3DRenderer(CRenderInterface **pObj)
{
if(!*pObj) *pObj = new CD3DRenderer;
else return false;
return true;
}
unsigned long CreateD3DFVF(int flags)
{
unsigned long fvf = 0;
return fvf;
}
CD3DRenderer::CD3DRenderer()
{
m_Direct3D = NULL;
m_Device = NULL;
m_renderingScene = false;
m_numStaticBuffers = 0;
m_activeStaticBuffer = UGP_INVALID;
m_staticBufferList = NULL;
m_textureList = NULL;
m_numTextures = 0;
}
CD3DRenderer::~CD3DRenderer()
{
Shutdown();
}
bool CD3DRenderer::Initialize(int w, int h, WinHWND mainWin,
bool fullScreen)
{
Shutdown();
m_mainHandle = mainWin;
if(!m_mainHandle) return false;
m_fullscreen = fullScreen;
D3DDISPLAYMODE mode;
D3DCAPS9 caps;
D3DPRESENT_PARAMETERS Params;
ZeroMemory(&Params, sizeof(Params));
m_Direct3D = Direct3DCreate9(D3D_SDK_VERSION);
if(!m_Direct3D) return false;
if(FAILED(m_Direct3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,
&mode))) return false;
if(FAILED(m_Direct3D->GetDeviceCaps(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL, &caps))) return false;
DWORD processing = 0;
if(caps.VertexProcessingCaps != 0)
processing = D3DCREATE_HARDWARE_VERTEXPROCESSING |
D3DCREATE_PUREDEVICE;
else
processing = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
if(m_fullscreen)
{
Params.FullScreen_RefreshRateInHz = mode.RefreshRate;
Params.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
}
else
Params.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
Params.Windowed = !m_fullscreen;
Params.BackBufferWidth = w;
Params.BackBufferHeight = h;
Params.hDeviceWindow = m_mainHandle;
Params.SwapEffect = D3DSWAPEFFECT_DISCARD;
Params.BackBufferFormat = mode.Format;
Params.BackBufferCount = 1;
Params.EnableAutoDepthStencil = TRUE;
Params.AutoDepthStencilFormat = D3DFMT_D16;
m_screenWidth = w;
m_screenHeight = h;
if(FAILED(m_Direct3D->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL, m_mainHandle, processing,
&Params, &m_Device))) return false;
if(m_Device == NULL) return false;
OneTimeInit();
return true;
}
void CD3DRenderer::OneTimeInit()
{
if(!m_Device) return;
m_Device->SetRenderState(D3DRS_LIGHTING, FALSE);
m_Device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
SetTextureFilter(0, MAG_FILTER, ANISOTROPIC_TYPE);
SetTextureFilter(0, MIN_FILTER, ANISOTROPIC_TYPE);
SetTextureFilter(0, MIP_FILTER, ANISOTROPIC_TYPE);
CalculateProjMatrix(D3DX_PI / 4, 0.1f, 1000);
}
void CD3DRenderer::Shutdown()
{
for(int s = 0; s < m_numStaticBuffers; s++)
{
if(m_staticBufferList[s].vbPtr)
{
m_staticBufferList[s].vbPtr->Release();
m_staticBufferList[s].vbPtr = NULL;
}
if(m_staticBufferList[s].ibPtr)
{
m_staticBufferList[s].ibPtr->Release();
m_staticBufferList[s].ibPtr = NULL;
}
}
m_numStaticBuffers = 0;
if(m_staticBufferList) delete[] m_staticBufferList;
m_staticBufferList = NULL;
for(int s = 0; s < m_numTextures; s++)
{
if(m_textureList[s].fileName)
{
delete[] m_textureList[s].fileName;
m_textureList[s].fileName = NULL;
}
if(m_textureList[s].image)
{
m_textureList[s].image->Release();
m_textureList[s].image = NULL;
}
}
m_numTextures = 0;
if(m_textureList) delete[] m_textureList;
m_textureList = NULL;
if(m_Device) m_Device->Release();
if(m_Direct3D) m_Direct3D->Release();
m_Device = NULL;
m_Direct3D = NULL;
}
void CD3DRenderer::SetClearCol(float r, float g, float b)
{
m_Color = D3DCOLOR_COLORVALUE(r, g, b, 1.0f);
}
void CD3DRenderer::StartRender(bool bColor, bool bDepth,
bool bStencil)
{
if(!m_Device) return;
unsigned int buffers = 0;
if(bColor) buffers |= D3DCLEAR_TARGET;
if(bDepth) buffers |= D3DCLEAR_ZBUFFER;
if(bStencil) buffers |= D3DCLEAR_STENCIL;
if(FAILED(m_Device->Clear(0, NULL, buffers, m_Color, 1, 0)))
return;
if(FAILED(m_Device->BeginScene())) return;
m_renderingScene = true;
}
void CD3DRenderer::ClearBuffers(bool bColor, bool bDepth,
bool bStencil)
{
if(!m_Device) return;
unsigned int buffers = 0;
if(bColor) buffers |= D3DCLEAR_TARGET;
if(bDepth) buffers |= D3DCLEAR_ZBUFFER;
if(bStencil) buffers |= D3DCLEAR_STENCIL;
if(m_renderingScene) m_Device->EndScene();
if(FAILED(m_Device->Clear(0, NULL, buffers, m_Color, 1, 0)))
return;
if(m_renderingScene)
if(FAILED(m_Device->BeginScene())) return;
}
void CD3DRenderer::EndRendering()
{
if(!m_Device) return;
m_Device->EndScene();
m_Device->Present(NULL, NULL, NULL, NULL);
m_renderingScene = false;
}
void CD3DRenderer::SetMaterial(stMaterial *mat)
{
if(!mat || !m_Device) return;
D3DMATERIAL9 m = { mat->diffuseR, mat->diffuseG,
mat->diffuseB, mat->diffuseA,
mat->ambientR, mat->ambientG,
mat->ambientB, mat->ambientA,
mat->specularR, mat->specularG,
mat->specularB, mat->specularA,
mat->emissiveR, mat->emissiveG,
mat->emissiveB, mat->emissiveA,
mat->power
};
m_Device->SetMaterial(&m);
}
void CD3DRenderer::SetLight(stLight *light, int index)
{
if(!light || !m_Device || index < 0) return;
D3DLIGHT9 l;
l.Ambient.a = light->ambientA;
l.Ambient.r = light->ambientR;
l.Ambient.g = light->ambientG;
l.Ambient.b = light->ambientB;
l.Attenuation0 = light->attenuation0;
l.Attenuation1 = light->attenuation1;
l.Attenuation2 = light->attenuation2;
l.Diffuse.a = light->diffuseA;
l.Diffuse.r = light->diffuseR;
l.Diffuse.g = light->diffuseG;
l.Diffuse.b = light->diffuseB;
l.Direction.x = light->dirX;
l.Direction.y = light->dirY;
l.Direction.z = light->dirZ;
l.Falloff = light->falloff;
l.Phi = light->phi;
l.Position.x = light->posX;
l.Position.y = light->posY;
l.Position.z = light->posZ;
l.Range = light->range;
l.Specular.a = light->specularA;
l.Specular.r = light->specularR;
l.Specular.g = light->specularG;
l.Specular.b = light->specularB;
l.Theta = light->theta;
if(light->type == LIGHT_POINT) l.Type = D3DLIGHT_POINT;
else if (light->type == LIGHT_SPOT) l.Type = D3DLIGHT_SPOT;
else l.Type = D3DLIGHT_DIRECTIONAL;
m_Device->SetLight(index, &l);
m_Device->LightEnable(index, TRUE);
}
void CD3DRenderer::DisableLight(int index)
{
if(!m_Device) return;
m_Device->LightEnable(index, FALSE);
}
void CD3DRenderer::SetDepthTesting(RenderState state)
{
if(!m_Device) return;
if(state == DEPTH_NONE)
{
m_Device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
m_Device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
}
else if(state == DEPTH_READONLY)
{
m_Device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
m_Device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
}
else if(state == DEPTH_READWRITE)
{
m_Device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
m_Device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
}
}
void CD3DRenderer::SetTransparency(RenderState state, TransState src, TransState dst)
{
if(!m_Device) return;
// 若状态标识符相符,则禁用透明度
if(state == TRANSPARENCY_NONE)
{
m_Device->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
return;
}
// 若状态标识符相符,启用透明度
if(state == TRANSPARENCY_ENABLE)
{
m_Device->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
switch(src)
{
case TRANS_ZERO:
m_Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
break;
case TRANS_ONE:
m_Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
break;
case TRANS_SRCCOLOR:
m_Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCCOLOR);
break;
case TRANS_INVSRCCOLOR:
m_Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_INVSRCCOLOR);
break;
case TRANS_SRCALPHA:
m_Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
break;
case TRANS_INVSRCALPHA:
m_Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_INVSRCALPHA);
break;
case TRANS_DSTALPHA:
m_Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_DESTALPHA);
break;
case TRANS_INVDSTALPHA:
m_Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_INVDESTALPHA);
break;
case TRANS_DSTCOLOR:
m_Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_DESTCOLOR);
break;
case TRANS_INVDSTCOLOR:
m_Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_INVDESTCOLOR);
break;
case TRANS_SRCALPHASAT:
m_Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHASAT);
break;
case TRANS_BOTHSRCALPHA:
m_Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_BOTHSRCALPHA);
break;
case TRANS_INVBOTHSRCALPHA:
m_Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_BOTHINVSRCALPHA);
break;
case TRANS_BLENDFACTOR:
m_Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_BLENDFACTOR);
break;
case TRANS_INVBLENDFACTOR:
m_Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_INVBLENDFACTOR);
break;
default:
m_Device->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
return;
break;
}
switch(dst)
{
case TRANS_ZERO:
m_Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
break;
case TRANS_ONE:
m_Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
break;
case TRANS_SRCCOLOR:
m_Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_SRCCOLOR);
break;
case TRANS_INVSRCCOLOR:
m_Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCCOLOR);
break;
case TRANS_SRCALPHA:
m_Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_SRCALPHA);
break;
case TRANS_INVSRCALPHA:
m_Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
break;
case TRANS_DSTALPHA:
m_Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_DESTALPHA);
break;
case TRANS_INVDSTALPHA:
m_Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVDESTALPHA);
break;
case TRANS_DSTCOLOR:
m_Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_DESTCOLOR);
break;
case TRANS_INVDSTCOLOR:
m_Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVDESTCOLOR);
break;
case TRANS_SRCALPHASAT:
m_Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_SRCALPHASAT);
break;
case TRANS_BOTHSRCALPHA:
m_Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_BOTHSRCALPHA);
break;
case TRANS_INVBOTHSRCALPHA:
m_Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_BOTHINVSRCALPHA);
break;
case TRANS_BLENDFACTOR:
m_Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_BLENDFACTOR);
break;
case TRANS_INVBLENDFACTOR:
m_Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVBLENDFACTOR);
break;
default:
m_Device->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
break;
}
}
}
int CD3DRenderer::AddTexture2D(char *file, int *texId)
{
if(!file || !m_Device) return UGP_FAIL;
int len = strlen(file);
if(!len) return UGP_FAIL;
int index = m_numTextures;
if(!m_textureList)
{
m_textureList = new stD3DTexture[1];
if(!m_textureList) return UGP_FAIL;
}
else
{
stD3DTexture *temp;
temp = new stD3DTexture[m_numTextures + 1];
memcpy(temp, m_textureList, sizeof(stD3DTexture) * m_numTextures);
delete[] m_textureList;
m_textureList = temp;
}
m_textureList[index].fileName = new char[len];
memcpy(m_textureList[index].fileName, file, len);
D3DCOLOR colorkey = 0xff000000;
D3DXIMAGE_INFO info;
if(D3DXCreateTextureFromFileEx(m_Device, file, 0, 0, 0, 0,
D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT,
D3DX_DEFAULT, colorkey, &info, NULL,
&m_textureList[index].image) != D3D_OK) return false;
m_textureList[index].image->SetAutoGenFilterType(D3DTEXF_LINEAR);
m_textureList[index].image->GenerateMipSubLevels();
m_textureList[index].width = info.Width;
m_textureList[index].height = info.Height;
*texId = m_numTextures;
m_numTextures++;
return UGP_OK;
}
void CD3DRenderer::SetTextureFilter(int index, int filter, int val)
{
if(!m_Device || index < 0) return;
D3DSAMPLERSTATETYPE fil = D3DSAMP_MINFILTER;
int v = D3DTEXF_POINT;
if(filter == MIN_FILTER) fil = D3DSAMP_MINFILTER;
if(filter == MAG_FILTER) fil = D3DSAMP_MAGFILTER;
if(filter == MIP_FILTER) fil = D3DSAMP_MIPFILTER;
if(val == POINT_TYPE) v = D3DTEXF_POINT;
if(val == LINEAR_TYPE) v = D3DTEXF_LINEAR;
if(val == ANISOTROPIC_TYPE) v = D3DTEXF_ANISOTROPIC;
m_Device->SetSamplerState(index, fil, v);
}
void CD3DRenderer::SetMultiTexture()
{
if(!m_Device) return;
/* 设置纹理的渲染状态
HRESULT SetTextureStageState(
DWORD Stage, //当前设置的多级纹理的索引
D3DTEXTURESTAGESTATETYPE Type, //纹理渲染状态的类型
DWORD Value //纹理渲染状态的值,与类型相对应
);
*/
m_Device->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0);
m_Device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
m_Device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
m_Device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
m_Device->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);
m_Device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE);
m_Device->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
m_Device->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
}
void CD3DRenderer::ApplyTexture(int index, int texId)
{
if(!m_Device) return;
if(index < 0 || texId < 0)
m_Device->SetTexture(0, NULL);
else
m_Device->SetTexture(0, m_textureList[texId].image);
}
void CD3DRenderer::SaveScreenShot(char *file)
{
if(!file) return;
LPDIRECT3DSURFACE9 surface = NULL;
D3DDISPLAYMODE disp;
m_Device->GetDisplayMode(0, &disp);
m_Device->CreateOffscreenPlainSurface(disp.Width, disp.Height,
D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface, NULL);
m_Device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
D3DXSaveSurfaceToFile(file, D3DXIFF_JPG, surface, NULL, NULL);
if(surface != NULL)
surface->Release();
surface = NULL;
}
void CD3DRenderer::EnablePointSprites(float size, float min,
float a, float b, float c)
{
if(!m_Device) return;
m_Device->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);
m_Device->SetRenderState(D3DRS_POINTSCALEENABLE, TRUE);
m_Device->SetRenderState(D3DRS_POINTSIZE, FtoDW(size));
m_Device->SetRenderState(D3DRS_POINTSIZE_MIN, FtoDW(min));
m_Device->SetRenderState(D3DRS_POINTSCALE_A, FtoDW(a));
m_Device->SetRenderState(D3DRS_POINTSCALE_B, FtoDW(b));
m_Device->SetRenderState(D3DRS_POINTSCALE_C, FtoDW(c));
}
void CD3DRenderer::DisablePointSprites()
{
m_Device->SetRenderState(D3DRS_POINTSPRITEENABLE, FALSE);
m_Device->SetRenderState(D3DRS_POINTSCALEENABLE, FALSE);
}
void CD3DRenderer::CalculateProjMatrix(float fov, float n, float f)
{
if(!m_Device) return;
D3DXMATRIX projection;
D3DXMatrixPerspectiveFovLH(&projection, fov,
(float)m_screenWidth/(float)m_screenHeight, n, f);
m_Device->SetTransform(D3DTS_PROJECTION, &projection);
}
void CD3DRenderer::CalculateOrthoMatrix(float n, float f)
{
if(!m_Device) return;
D3DXMATRIX ortho;
D3DXMatrixOrthoLH(&ortho, (float)m_screenWidth,
(float)m_screenHeight, n, f);
m_Device->SetTransform(D3DTS_PROJECTION, &ortho);
}
int CD3DRenderer::CreateStaticBuffer(VertexType vType,
PrimType primType, int totalVerts,
int totalIndices, int stride, void **data,
unsigned int *indices, int *staticId)
{
void *ptr;
int index = m_numStaticBuffers;
if(!m_staticBufferList)
{
m_staticBufferList = new stD3DStaticBuffer[1];
if(!m_staticBufferList) return UGP_FAIL;
}
else
{
stD3DStaticBuffer *temp;
temp = new stD3DStaticBuffer[m_numStaticBuffers + 1];
memcpy(temp, m_staticBufferList,
sizeof(stD3DStaticBuffer) * m_numStaticBuffers);
delete[] m_staticBufferList;
m_staticBufferList = temp;
}
m_staticBufferList[index].numVerts = totalVerts;
m_staticBufferList[index].numIndices = totalIndices;
m_staticBufferList[index].primType = primType;
m_staticBufferList[index].stride = stride;
m_staticBufferList[index].fvf = CreateD3DFVF(vType);
if(totalIndices > 0)
{
if(FAILED(m_Device->CreateIndexBuffer(sizeof(unsigned int) *
totalIndices, D3DUSAGE_WRITEONLY, D3DFMT_INDEX16,
D3DPOOL_DEFAULT,
&m_staticBufferList[index].ibPtr,
NULL))) return UGP_FAIL;
if(FAILED(m_staticBufferList[index].ibPtr->Lock(0, 0,
(void**)&ptr, 0))) return UGP_FAIL;
memcpy(ptr, indices, sizeof(unsigned int) * totalIndices);
m_staticBufferList[index].ibPtr->Unlock();
}
else
{
m_staticBufferList[index].ibPtr = NULL;
}
if(FAILED(m_Device->CreateVertexBuffer(totalVerts * stride,
D3DUSAGE_WRITEONLY, m_staticBufferList[index].fvf,
D3DPOOL_DEFAULT, &m_staticBufferList[index].vbPtr,
NULL))) return UGP_FAIL;
if(FAILED(m_staticBufferList[index].vbPtr->Lock(0, 0,
(void**)&ptr, 0))) return UGP_FAIL;
memcpy(ptr, data, totalVerts * stride);
m_staticBufferList[index].vbPtr->Unlock();
*staticId = m_numStaticBuffers;
m_numStaticBuffers++;
return UGP_OK;
}
int CD3DRenderer::Render(int staticId)
{
if(staticId >= m_numStaticBuffers) return UGP_FAIL;
if(m_activeStaticBuffer != staticId)
{
if(m_staticBufferList[staticId].ibPtr != NULL)
m_Device->SetIndices(m_staticBufferList[staticId].ibPtr); //使用的索引缓冲区指针
m_Device->SetStreamSource(0,
m_staticBufferList[staticId].vbPtr, 0,
m_staticBufferList[staticId].stride);
m_Device->SetFVF(m_staticBufferList[staticId].fvf);
m_activeStaticBuffer = staticId;
}
if(m_staticBufferList[staticId].ibPtr != NULL)
{
switch(m_staticBufferList[staticId].primType)
{
case POINT_LIST:
if(FAILED(m_Device->DrawPrimitive(D3DPT_POINTLIST,
0, m_staticBufferList[staticId].numVerts)))
return UGP_FAIL;
break;
case TRIANGLE_LIST:
if(FAILED(m_Device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0,
0, m_staticBufferList[staticId].numVerts / 3,
0, m_staticBufferList[staticId].numIndices)))
return UGP_FAIL;
break;
case TRIANGLE_STRIP:
if(FAILED(m_Device->DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP, 0,
0, m_staticBufferList[staticId].numVerts / 2,
0, m_staticBufferList[staticId].numIndices)))
return UGP_FAIL;
break;
case TRIANGLE_FAN:
if(FAILED(m_Device->DrawIndexedPrimitive(D3DPT_TRIANGLEFAN, 0,
0, m_staticBufferList[staticId].numVerts / 2,
0, m_staticBufferList[staticId].numIndices)))
return UGP_FAIL;
break;
case LINE_LIST:
if(FAILED(m_Device->DrawIndexedPrimitive(D3DPT_LINELIST, 0,
0, m_staticBufferList[staticId].numVerts / 2,
0, m_staticBufferList[staticId].numIndices)))
return UGP_FAIL;
break;
case LINE_STRIP:
if(FAILED(m_Device->DrawIndexedPrimitive(D3DPT_LINESTRIP, 0,
0, m_staticBufferList[staticId].numVerts,
0, m_staticBufferList[staticId].numIndices)))
return UGP_FAIL;
break;
default:
return UGP_FAIL;
}
}
else
{
switch(m_staticBufferList[staticId].primType)
{
case POINT_LIST:
if(FAILED(m_Device->DrawPrimitive(D3DPT_POINTLIST,
0, m_staticBufferList[staticId].numVerts)))
return UGP_FAIL;
break;
case TRIANGLE_LIST:
if(FAILED(m_Device->DrawPrimitive(D3DPT_TRIANGLELIST, 0,
(int)(m_staticBufferList[staticId].numVerts / 3))))
return UGP_FAIL;
break;
case TRIANGLE_STRIP:
if(FAILED(m_Device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0,
(int)(m_staticBufferList[staticId].numVerts / 2))))
return UGP_FAIL;
break;
case TRIANGLE_FAN:
if(FAILED(m_Device->DrawPrimitive(D3DPT_TRIANGLEFAN, 0,
(int)(m_staticBufferList[staticId].numVerts / 2))))
return UGP_FAIL;
break;
case LINE_LIST:
if(FAILED(m_Device->DrawPrimitive(D3DPT_LINELIST, 0,
m_staticBufferList[staticId].numVerts / 2)))
return UGP_FAIL;
break;
case LINE_STRIP:
if(FAILED(m_Device->DrawPrimitive(D3DPT_LINESTRIP, 0,
m_staticBufferList[staticId].numVerts)))
return UGP_FAIL;
break;
default:
return UGP_FAIL;
}
}
return UGP_OK;
}