C++之(6)DirectX 9.0C 编程——Texture类

介绍

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(&currentPos);
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;
}
如果这篇文章对您有所帮助,不妨打赏一下作者吧~
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇