main.h main.cpp 无变化
define.h
#ifndef _UGP_DEFINES_H_ #define _UGP_DEFINES_H_ #include// 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#include #include #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;
}