介绍
Texture 类用于管理 Direct3D 中的纹理资源。它提供了一系列方法来加载、设置和管理纹理。通过封装这些操作,Texture 类可以提高代码的可维护性和可扩展性。
类的定义
#pragma once #include <d3d9.h> #include <d3dx9.h> #include <string> #include <vector> class Texture { private: LPDIRECT3DDEVICE9 d3dDevice; // Direct3D设备对象 std::vector<LPDIRECT3DTEXTURE9> textures; // 纹理对象集合 public: Texture(LPDIRECT3DDEVICE9 device); ~Texture(); HRESULT LoadTextureFromFile(const std::wstring& fileName); HRESULT LoadCubeTextureFromFile(const std::wstring& fileName); void SetTexture(DWORD stage = 0) const; void SetTextureFilter(DWORD stage = 0, D3DTEXTUREFILTERTYPE minFilter = D3DTEXF_LINEAR, D3DTEXTUREFILTERTYPE magFilter = D3DTEXF_LINEAR, D3DTEXTUREFILTERTYPE mipFilter = D3DTEXF_LINEAR) const; LPDIRECT3DTEXTURE9 GetTexture(size_t index = 0) const; size_t GetTextureCount() const; };
d3dDevice:指向 Direct3D 设备对象的指针。用于与 Direct3D 设备进行交互。
textures:存储多个纹理对象的集合。
构造函数与析构函数
构造函数和析构函数负责初始化和清理资源:
Texture::Texture(LPDIRECT3DDEVICE9 device) : d3dDevice(device) {} Texture::~Texture() { for (auto texture : textures) { if (texture) { texture->Release(); } } textures.clear(); }
构造函数:初始化 d3dDevice 指针。
析构函数:释放所有加载的纹理资源
主要函数
加载纹理文件
HRESULT Texture::LoadTextureFromFile(const std::wstring& fileName) { LPDIRECT3DTEXTURE9 texture = nullptr; //第一个参数:指定要与纹理关联的设备 //第二个:纹理文件的地址。 第三个:表示创建的纹理对象 if (FAILED(D3DXCreateTextureFromFile(d3dDevice, fileName.c_str(), &texture))) { MessageBox(NULL, L"Failed to create texture", L"Error", MB_OK); return E_FAIL; } //将texture压入vector中 textures.push_back(texture); return S_OK; }
作用:从文件加载纹理,并将其存储在 textures 向量中。
参数:fileName 是纹理文件的路径。
返回值:成功时返回 S_OK,否则返回 E_FAIL。
加载立方体纹理文件
HRESULT Texture::LoadCubeTextureFromFile(const std::wstring& fileName) { LPDIRECT3DCUBETEXTURE9 cubeTexture = nullptr; if (FAILED(D3DXCreateCubeTextureFromFile(d3dDevice, fileName.c_str(), &cubeTexture))) { MessageBox(NULL, L"Failed to create cube texture", L"Error", MB_OK); return E_FAIL; } //reinterpret_cast:通过重新解释底层位模式在类型间转换。 textures.push_back(reinterpret_cast<LPDIRECT3DTEXTURE9>(cubeTexture)); return S_OK; }
作用:从文件加载立方体纹理,并将其存储在 textures 向量中。
参数:fileName 是立方体纹理文件的路径。
返回值:成功时返回 S_OK,否则返回 E_FAIL。
设置纹理过滤模式
void Texture::SetTextureFilter(DWORD stage, D3DTEXTUREFILTERTYPE minFilter, D3DTEXTUREFILTERTYPE magFilter, D3DTEXTUREFILTERTYPE mipFilter) const { d3dDevice->SetSamplerState(stage, D3DSAMP_MINFILTER, minFilter); d3dDevice->SetSamplerState(stage, D3DSAMP_MAGFILTER, magFilter); d3dDevice->SetSamplerState(stage, D3DSAMP_MIPFILTER, mipFilter); }
作用:设置纹理的过滤模式。
参数:
stage:纹理阶段。
minFilter:缩小过滤器类型。
magFilter:放大过滤器类型。
mipFilter:多级纹理过滤器类型。
获取纹理对象
LPDIRECT3DTEXTURE9 Texture::GetTexture(size_t index) const { if (index < textures.size()) { return textures[index]; } return nullptr; }
作用:获取指定索引的纹理对象。
参数:index 表示纹理对象的索引。
返回值:返回指定索引的纹理对象指针。
获取纹理的数量
size_t Texture::GetTextureCount() const { return textures.size(); }
作用:获取纹理对象的数量。
返回值:返回纹理对象的数量。
示例代码
以下是如何使用 Texture 类的示例代码
#include "Texture.h" int main() { // 初始化 Direct3D 设备 (省略实际初始化代码) LPDIRECT3DDEVICE9 d3dDevice = ...; // 创建 Texture 对象 Texture* texture = new Texture(d3dDevice); // 加载纹理文件 if (SUCCEEDED(texture->LoadTextureFromFile(L"example.jpg"))) { // 设置纹理过滤模式 texture->SetTextureFilter(); // 使用纹理 texture->SetTexture(); } // 清理 delete texture; return 0; }
这个示例展示了如何创建 Texture 对象、加载纹理文件、设置纹理过滤模式以及使用纹理。
完整源码
Texture 类
#pragma once #include <d3d9.h> #include <d3dx9.h> #include <string> #include <vector> class Texture { private: LPDIRECT3DDEVICE9 d3dDevice; // Direct3D设备对象 std::vector<LPDIRECT3DTEXTURE9> textures; // 纹理对象集合 public: Texture(LPDIRECT3DDEVICE9 device); ~Texture(); HRESULT LoadTextureFromFile(const std::wstring& fileName); HRESULT LoadCubeTextureFromFile(const std::wstring& fileName); void SetTexture(DWORD stage = 0) const; void SetTextureFilter(DWORD stage = 0, D3DTEXTUREFILTERTYPE minFilter = D3DTEXF_LINEAR, D3DTEXTUREFILTERTYPE magFilter = D3DTEXF_LINEAR, D3DTEXTUREFILTERTYPE mipFilter = D3DTEXF_LINEAR) const; LPDIRECT3DTEXTURE9 GetTexture(size_t index = 0) const; size_t GetTextureCount() const; }; Texture::Texture(LPDIRECT3DDEVICE9 device) : d3dDevice(device) {} Texture::~Texture() { for (auto texture : textures) { if (texture) { texture->Release(); } } textures.clear(); } HRESULT Texture::LoadTextureFromFile(const std::wstring& fileName) { LPDIRECT3DTEXTURE9 texture = nullptr; if (FAILED(D3DXCreateTextureFromFile(d3dDevice, fileName.c_str(), &texture))) { MessageBox(NULL, L"Failed to create texture", L"Error", MB_OK); return E_FAIL; } textures.push_back(texture); return S_OK; } HRESULT Texture::LoadCubeTextureFromFile(const std::wstring& fileName) { LPDIRECT3DCUBETEXTURE9 cubeTexture = nullptr; if (FAILED(D3DXCreateCubeTextureFromFile(d3dDevice, fileName.c_str(), &cubeTexture))) { MessageBox(NULL, L"Failed to create cube texture", L"Error", MB_OK); return E_FAIL; } textures.push_back(reinterpret_cast<LPDIRECT3DTEXTURE9>(cubeTexture)); return S_OK; } void Texture::SetTexture(DWORD stage) const { if (!textures.empty()) { d3dDevice->SetTexture(stage, textures[0]); } } void Texture::SetTextureFilter(DWORD stage, D3DTEXTUREFILTERTYPE minFilter, D3DTEXTUREFILTERTYPE magFilter, D3DTEXTUREFILTERTYPE mipFilter) const { d3dDevice->SetSamplerState(stage, D3DSAMP_MINFILTER, minFilter); d3dDevice->SetSamplerState(stage, D3DSAMP_MAGFILTER, magFilter); d3dDevice->SetSamplerState(stage, D3DSAMP_MIPFILTER, mipFilter); } LPDIRECT3DTEXTURE9 Texture::GetTexture(size_t index) const { if (index < textures.size()) { return textures[index]; } return nullptr; } size_t Texture::GetTextureCount() const { return textures.size(); }
Lighting类
#pragma once #include <d3d9.h> #include <d3dx9.h> #include <vector> class Lighting { private: LPDIRECT3DDEVICE9 d3dDevice; std::vector<D3DLIGHT9> lights; // 存储多个光源 public: Lighting(LPDIRECT3DDEVICE9 device); ~Lighting(); void Initialize(); void EnableLighting(bool enable); void CreatePointLight(D3DXVECTOR3 position, D3DXCOLOR color); void CreateDirectionalLight(D3DXVECTOR3 direction, D3DXCOLOR color); void CreateSpotLight(D3DXVECTOR3 position, D3DXVECTOR3 direction, D3DXCOLOR color); void SetAmbientLight(D3DXCOLOR color); void UpdateLightPosition(int lightIndex, D3DXVECTOR3 newPos); }; Lighting::Lighting(LPDIRECT3DDEVICE9 device) : d3dDevice(device) {} Lighting::~Lighting() { // 清理代码,如果需要的话 } void Lighting::Initialize() { EnableLighting(true); SetAmbientLight(D3DXCOLOR(0.5f, 0.5f, 0.5f, 1.0f)); } void Lighting::EnableLighting(bool enable) { d3dDevice->SetRenderState(D3DRS_LIGHTING, enable); } void Lighting::CreatePointLight(D3DXVECTOR3 position, D3DXCOLOR color) { D3DLIGHT9 light; ZeroMemory(&light, sizeof(light)); light.Type = D3DLIGHT_POINT; light.Diffuse = color; light.Position = position; light.Range = 1000.0f; light.Attenuation0 = 0.0f; light.Attenuation1 = 0.125f; light.Attenuation2 = 0.0f; lights.push_back(light); d3dDevice->SetLight(lights.size() - 1, &light); d3dDevice->LightEnable(lights.size() - 1, TRUE); } void Lighting::CreateDirectionalLight(D3DXVECTOR3 direction, D3DXCOLOR color) { D3DLIGHT9 light; ZeroMemory(&light, sizeof(light)); light.Type = D3DLIGHT_DIRECTIONAL; light.Diffuse = color; light.Direction = direction; lights.push_back(light); d3dDevice->SetLight(lights.size() - 1, &light); d3dDevice->LightEnable(lights.size() - 1, TRUE); } void Lighting::CreateSpotLight(D3DXVECTOR3 position, D3DXVECTOR3 direction, D3DXCOLOR color) { D3DLIGHT9 light; ZeroMemory(&light, sizeof(light)); light.Type = D3DLIGHT_SPOT; light.Diffuse = color; light.Position = position; light.Direction = direction; light.Range = 1000.0f; light.Theta = 0.5f; // 内锥角 light.Phi = 1.0f; // 外锥角 light.Falloff = 1.0f; lights.push_back(light); d3dDevice->SetLight(lights.size() - 1, &light); d3dDevice->LightEnable(lights.size() - 1, TRUE); } void Lighting::SetAmbientLight(D3DXCOLOR color) { d3dDevice->SetRenderState(D3DRS_AMBIENT, color); } void Lighting::UpdateLightPosition(int lightIndex, D3DXVECTOR3 newPos) { if (lightIndex < 0 || lightIndex >= lights.size()) return; lights[lightIndex].Position = newPos; d3dDevice->SetLight(lightIndex, &lights[lightIndex]); }
Camera类
#pragma once #include <windows.h> #include <d3dx9.h> class Camera { private: D3DXMATRIX m_View; // 视图变换矩阵 D3DXMATRIX m_Project; // 投影变换矩阵 D3DXVECTOR3 m_Pos; // 位置 D3DXVECTOR3 m_LookAt; // 视点 D3DXVECTOR3 m_Up; // 正方向 D3DXVECTOR3 m_Right; // 右向量 D3DXVECTOR3 m_Direction;// 朝向 float m_fNear; // 近平面 float m_fFar; // 远平面 float m_fFOV; // FOV夹角 float m_fAspect; // 纵横比 bool m_bIsRot; // 是否发生旋转 float m_fYaw; // 偏航角 float m_fPitch; // 俯仰角 POINT m_LastPoint; // 上一次的鼠标位置 D3DXVECTOR3 upVector; D3DXVECTOR3 directionVector; public: Camera(); void SetViewParam(D3DXVECTOR3& vPos, D3DXVECTOR3& vLookAt, D3DXVECTOR3& vUp); void SetProjMatrix(float fFov, float fAspect, float fNear, float fFar); D3DXMATRIX* GetViewMatrix(); D3DXMATRIX* GetProjMatrix(); void Update(float deltaTime); LRESULT HandleMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); }; Camera::Camera() : m_fYaw(0), m_fPitch(0), m_bIsRot(false), upVector(0, 1, 0), directionVector(0, 0, 1) { ZeroMemory(&m_LastPoint, sizeof(POINT)); } void Camera::SetViewParam(D3DXVECTOR3& vPos, D3DXVECTOR3& vLookAt, D3DXVECTOR3& vUp) { m_Pos = vPos; m_LookAt = vLookAt; m_Up = vUp; m_Direction = vLookAt - vPos; D3DXVec3Normalize(&m_Direction, &m_Direction); D3DXVec3Cross(&m_Right, &vUp, &m_Direction); D3DXMatrixLookAtLH(&m_View, &m_Pos, &m_LookAt, &m_Up); } void Camera::SetProjMatrix(float fFov, float fAspect, float fNear, float fFar) { m_fFOV = fFov; m_fAspect = fAspect; m_fNear = fNear; m_fFar = fFar; D3DXMatrixPerspectiveFovLH(&m_Project, fFov, fAspect, fNear, fFar); } D3DXMATRIX* Camera::GetViewMatrix() { return &m_View } D3DXMATRIX* Camera::GetProjMatrix() { return &m_Project; } void Camera::Update(float deltaTime) { if (m_bIsRot) { D3DXVECTOR3 vUp, vDirection; D3DXMATRIX matCamera; D3DXMatrixRotationYawPitchRoll(&matCamera, m_fYaw, m_fPitch, 0); D3DXVec3TransformCoord(&vUp, &upVector, &matCamera); D3DXVec3TransformCoord(&vDirection, &directionVector, &matCamera); m_LookAt = m_Pos + vDirection; D3DXMatrixLookAtLH(&m_View, &m_Pos, &m_LookAt, &vUp); m_Direction = m_LookAt - m_Pos; D3DXVec3Normalize(&m_Direction, &m_Direction); m_Up = vUp; D3DXVec3Cross(&m_Right, &m_Up, &m_Direction); } D3DXVECTOR3 forward = m_LookAt - m_Pos; D3DXVec3Normalize(&forward, &forward); D3DXVECTOR3 right; D3DXVec3Cross(&right, &m_Up, &forward); D3DXVec3Normalize(&right, &right); float speed = 5.0f * deltaTime; if (GetAsyncKeyState('W') & 0x8000) m_Pos += forward * speed; if (GetAsyncKeyState('S') & 0x8000) m_Pos -= forward * speed; if (GetAsyncKeyState('A') & 0x8000) m_Pos -= right * speed; if (GetAsyncKeyState('D') & 0x8000) m_Pos += right * speed; m_LookAt = m_Pos + forward; // 重新计算 LookAt 点 D3DXMatrixLookAtLH(&m_View, &m_Pos, &m_LookAt, &m_Up); } LRESULT Camera::HandleMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_LBUTTONDOWN: m_bIsRot = true; SetCapture(hWnd); GetCursorPos(&m_LastPoint); break; case WM_LBUTTONUP: m_bIsRot = false ReleaseCapture(); break; case WM_MOUSEMOVE: if (m_bIsRot) { POINT currentPos; GetCursorPos(¤tPos); m_fYaw += (currentPos.x - m_LastPoint.x) * 0.01f; m_fPitch += (currentPos.y - m_LastPoint.y) * 0.01f; m_fPitch = max(-D3DX_PI / 2, min(D3DX_PI / 2, m_fPitch)); // Limit pitch m_LastPoint = currentPos; } break; } return 0; }
Render类
#pragma once #include <windows.h> #include <d3d9.h> #include <d3dx9.h> #include <vector> #include "Camera.h" #include "Lighting.h" #include "Texture.h" struct CUSTOMVERTEX { FLOAT X, Y, Z; D3DCOLOR COLOR; FLOAT NX, NY, NZ; // 顶点法线 FLOAT TU, TV; // 纹理坐标 }; #define CUSTOMFVF (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_NORMAL | D3DFVF_TEX1) class Renderer { private: LPDIRECT3DDEVICE9 d3dDevice; LPDIRECT3DVERTEXBUFFER9 v_buffer; LPDIRECT3DINDEXBUFFER9 i_buffer; float angle; Camera camera; Lighting* lighting; Texture* texture; LPD3DXMESH sphereMesh; public: Renderer(LPDIRECT3DDEVICE9 dev); ~Renderer(); void initGraphics(); void update(float deltaTime); void render(); void setupCamera(); void setupProjection(); void renderSphereAtLightPosition(D3DXVECTOR3 lightPos); Camera* getCamera() { return &camera; } void setLighting(Lighting* light) { lighting = light; } void setTexture(Texture* tex) { texture = tex; } }; Renderer::Renderer(LPDIRECT3DDEVICE9 dev) : d3dDevice(dev), v_buffer(nullptr), i_buffer(nullptr), angle(0.0f), camera(), lighting(nullptr), texture(nullptr), sphereMesh(nullptr) { initGraphics(); } Renderer::~Renderer() { if (v_buffer) v_buffer->Release(); if (i_buffer) i_buffer->Release(); if (sphereMesh) sphereMesh->Release(); } void Renderer::setupCamera() { D3DXVECTOR3 vCamera(0.0f, 0.0f, -10.0f); D3DXVECTOR3 vLookat(0.0f, 0.0f, 5.0f); D3DXVECTOR3 vUpVec(0.0f, 1.0f, 0.0f); camera.SetViewParam(vCamera, vLookat, vUpVec); camera.SetProjMatrix(D3DX_PI / 4, (FLOAT)800 / (FLOAT)600, 1.0f, 100.0f); } void Renderer::setupProjection() { D3DXMATRIX matProj; D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI / 4, (FLOAT)800 / (FLOAT)600, 1.0f, 100.0f); d3dDevice->SetTransform(D3DTS_PROJECTION, &matProj); } void Renderer::initGraphics() { setupCamera(); setupProjection(); d3dDevice->SetRenderState(D3DRS_LIGHTING, TRUE); D3DMATERIAL9 mat; ZeroMemory(&mat, sizeof(mat)); mat.Diffuse = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f); // 白色散射光 mat.Ambient = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f); // 白色环境光 mat.Specular = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f); // 高光颜色 mat.Emissive = D3DXCOLOR(0.0f, 0.0f, 0.0f, 1.0f); // 没有自发光 mat.Power = 20.0f; // 高光强度 d3dDevice->SetMaterial(&mat); CUSTOMVERTEX vertices[] = { // Front face {-1.0f, -1.0f, -1.0f, D3DCOLOR_XRGB(255, 0, 0), 0.0f, 0.0f, -1.0f, 0.0f, 1.0f}, {1.0f, -1.0f, -1.0f, D3DCOLOR_XRGB(0, 255, 0), 0.0f, 0.0f, -1.0f, 1.0f, 1.0f}, {1.0f, 1.0f, -1.0f, D3DCOLOR_XRGB(0, 0, 255), 0.0f, 0.0f, -1.0f, 1.0f, 0.0f}, {-1.0f, 1.0f, -1.0f, D3DCOLOR_XRGB(255, 255, 0), 0.0f, 0.0f, -1.0f, 0.0f, 0.0f}, // Back face {-1.0f, -1.0f, 1.0f, D3DCOLOR_XRGB(255, 255, 255), 0.0f, 0.0f, 1.0f, 1.0f, 1.0f}, {1.0f, -1.0f, 1.0f, D3DCOLOR_XRGB(0, 255, 255), 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, {1.0f, 1.0f, 1.0f, D3DCOLOR_XRGB(255, 0, 255), 0.0f, 0.0f, 1.0f, 0.0f, 0.0f}, {-1.0f, 1.0f, 1.0f, D3DCOLOR_XRGB(255, 0, 0), 0.0f, 0.0f, 1.0f, 1.0f, 0.0f}, // Top face {-1.0f, 1.0f, -1.0f, D3DCOLOR_XRGB(0, 255, 0), 0.0f, 1.0f, 0.0f, 0.0f, 0.0f}, {1.0f, 1.0f, -1.0f, D3DCOLOR_XRGB(0, 0, 255), 0.0f, 1.0f, 0.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 1.0f, D3DCOLOR_XRGB(255, 255, 0), 0.0f, 1.0f, 0.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f, D3DCOLOR_XRGB(255, 255, 255), 0.0f, 1.0f, 0.0f, 0.0f, 1.0f}, // Bottom face {-1.0f, -1.0f, -1.0f, D3DCOLOR_XRGB(255, 0, 255), 0.0f, -1.0f, 0.0f, 0.0f, 1.0f}, {1.0f, -1.0f, -1.0f, D3DCOLOR_XRGB(255, 0, 0), 0.0f, -1.0f, 0.0f, 1.0f, 1.0f}, {1.0f, -1.0f, 1.0f, D3DCOLOR_XRGB(0, 255, 0), 0.0f, -1.0f, 0.0f, 1.0f, 0.0f}, {-1.0f, -1.0f, 1.0f, D3DCOLOR_XRGB(0, 0, 255), 0.0f, -1.0f, 0.0f, 0.0f, 0.0f}, // Left face {-1.0f, -1.0f, 1.0f, D3DCOLOR_XRGB(0, 255, 255), -1.0f, 0.0f, 0.0f, 0.0f, 1.0f}, {-1.0f, 1.0f, 1.0f, D3DCOLOR_XRGB(255, 255, 255), -1.0f, 0.0f, 0.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, -1.0f, D3DCOLOR_XRGB(255, 0, 0), -1.0f, 0.0f, 0.0f, 1.0f, 0.0f}, {-1.0f, -1.0f, -1.0f, D3DCOLOR_XRGB(255, 255, 0), -1.0f, 0.0f, 0.0f, 0.0f, 0.0f}, // Right face {1.0f, -1.0f, 1.0f, D3DCOLOR_XRGB(0, 0, 255), 1.0f, 0.0f, 0.0f, 1.0f, 1.0f}, {1.0f, 1.0f, 1.0f, D3DCOLOR_XRGB(255, 0, 255), 1.0f, 0.0f, 0.0f, 0.0f, 1.0f}, {1.0f, 1.0f, -1.0f, D3DCOLOR_XRGB(0, 255, 0), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f}, {1.0f, -1.0f, -1.0f, D3DCOLOR_XRGB(255, 255, 255), 1.0f, 0.0f, 0.0f, 1.0f, 0.0f}, }; short indices[] = { 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 8, 9, 10, 8, 10, 11, 12, 13, 14, 12, 14, 15, 16, 17, 18, 16, 18, 19, 20, 21, 22, 20, 22, 23 }; d3dDevice->CreateVertexBuffer(24 * sizeof(CUSTOMVERTEX), 0, CUSTOMFVF, D3DPOOL_MANAGED, &v_buffer, NULL); VOID* pVoid; v_buffer->Lock(0, 0, (void**)&pVoid, 0); memcpy(pVoid, vertices, sizeof(vertices)); v_buffer->Unlock(); void* pIndices; if (FAILED(d3dDevice->CreateIndexBuffer(36 * sizeof(short), 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &i_buffer, NULL))) { MessageBox(NULL, L"Failed to create index buffer.", L"Graphics Initialization Error", MB_OK); return; } if (FAILED(i_buffer->Lock(0, sizeof(indices), (void**)&pIndices, 0))) { MessageBox(NULL, L"Failed to lock index buffer.", L"Graphics Initialization Error", MB_OK); return; } memcpy(pIndices, indices, sizeof(indices)); i_buffer->Unlock(); D3DXCreateSphere(d3dDevice, 2.5f, 20, 20, &sphereMesh, NULL); } void Renderer::render() { d3dDevice->SetTransform(D3DTS_VIEW, camera.GetViewMatrix()); d3dDevice->SetTransform(D3DTS_PROJECTION, camera.GetProjMatrix()); d3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 40, 100), 1.0f, 0); if (lighting) { lighting->EnableLighting(true); } d3dDevice->BeginScene(); d3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); update(0.016f); d3dDevice->SetFVF(CUSTOMFVF); d3dDevice->SetStreamSource(0, v_buffer, 0, sizeof(CUSTOMVERTEX)); d3dDevice->SetIndices(i_buffer); if (texture) { texture->SetTexture(); } d3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 24, 0, 12); d3dDevice->EndScene(); d3dDevice->Present(NULL, NULL, NULL, NULL); } void Renderer::update(float deltaTime) { static float angle = 0.0f; angle += deltaTime; float radius = 5.0f; D3DXVECTOR3 lightPos(cos(angle) * radius, sin(angle) * radius, 0.0f); if (lighting) { lighting->UpdateLightPosition(0, lightPos); } renderSphereAtLightPosition(lightPos); D3DXMATRIX matRotateY; D3DXMatrixRotationY(&matRotateY, angle); d3dDevice->SetTransform(D3DTS_WORLD, &matRotateY); } void Renderer::renderSphereAtLightPosition(D3DXVECTOR3 lightPos) { D3DXMATRIX matTranslate; D3DXMatrixTranslation(&matTranslate, lightPos.x, lightPos.y, lightPos.z); d3dDevice->SetTransform(D3DTS_WORLD, &matTranslate); sphereMesh->DrawSubset(0); }
DirectX9Manager类
#pragma once #include "Renderer.h" #include <mmsystem.h> #pragma comment(lib, "winmm.lib") class DirectX9Manager { private: LPDIRECT3D9 d3d; LPDIRECT3DDEVICE9 d3ddev; Renderer* renderer; Lighting* lighting; Texture* texture; public: DirectX9Manager(); ~DirectX9Manager(); bool initD3D(HWND hWnd); void cleanup(); void render(float deltaTime); Camera* getCamera(); }; DirectX9Manager::DirectX9Manager() : d3d(nullptr), d3ddev(nullptr), renderer(nullptr), lighting(nullptr), texture(nullptr) {} DirectX9Manager::~DirectX9Manager() { cleanup(); } bool DirectX9Manager::initD3D(HWND hWnd) { d3d = Direct3DCreate9(D3D_SDK_VERSION); if (!d3d) return false; D3DPRESENT_PARAMETERS d3dpp; ZeroMemory(&d3dpp, sizeof(d3dpp)); d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.hDeviceWindow = hWnd; d3dpp.EnableAutoDepthStencil = TRUE; d3dpp.AutoDepthStencilFormat = D3DFMT_D16; if (FAILED(d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3ddev))) { d3d->Release(); return false; } renderer = new Renderer(d3ddev); lighting = new Lighting(d3ddev) lighting->Initialize(); texture = new Texture(d3ddev); texture->LoadTextureFromFile(L"texture.jpg"); renderer->setLighting(lighting); renderer->setTexture(texture); return true; } void DirectX9Manager::cleanup() { if (texture) delete texture; if (lighting) delete lighting; if (renderer) delete renderer; if (d3ddev) d3ddev->Release(); if (d3d) d3d->Release(); } void DirectX9Manager::render(float deltaTime) { if (renderer) { renderer->update(deltaTime); renderer->render(); } } Camera* DirectX9Manager::getCamera() { return renderer ? renderer->getCamera() : nullptr; }
Main.cpp
#include "DirectX9Manager.h" // 窗口过程函数原型 LRESULT CALLBACK WindowProcedure(HWND, UINT, WPARAM, LPARAM); DirectX9Manager dxManager; // WinMain: 应用程序入口点 int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR args, int nCmdShow) { WNDCLASSW wc = { 0 }; wc.hbrBackground = (HBRUSH)COLOR_WINDOW; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hInstance = hInst; wc.lpszClassName = L"MyWindowClass"; wc.lpfnWndProc = WindowProcedure; if (!RegisterClassW(&wc)) return -1; HWND hWnd = CreateWindowW(L"MyWindowClass", L"我的窗口", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 800, 600, NULL, NULL, NULL, NULL); if (!dxManager.initD3D(hWnd)) { MessageBox(hWnd, L"Failed to initialize Direct3D.", L"Error", MB_OK); return -1; } MSG msg = { 0 }; float lastTime = (float)timeGetTime(); while (TRUE) { float currentTime = (float)timeGetTime(); float deltaTime = (currentTime - lastTime) * 0.001f; if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); if (msg.message == WM_QUIT) break; } else { dxManager.render(deltaTime); lastTime = currentTime; } } dxManager.cleanup(); return (int)msg.wParam; } // 窗口过程函数 LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_DESTROY: PostQuitMessage(0); break; case WM_LBUTTONDOWN: case WM_LBUTTONUP: case WM_MOUSEMOVE: if (dxManager.getCamera()) { return dxManager.getCamera()->HandleMessage(hWnd, message, wParam, lParam); } break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }