1846 lines
52 KiB
Markdown
1846 lines
52 KiB
Markdown
# XCVolumeRenderer - 渲染引擎架构设计文档
|
||
|
||
> **基于 XCGameEngine 架构提取的渲染引擎子集**
|
||
> 版本: 1.0
|
||
> 日期: 2026-03-13
|
||
> 目标: 构建专业级实时体积渲染引擎
|
||
|
||
---
|
||
|
||
## 第一章 核心基础层
|
||
|
||
### 1.1 数学库 (Math Library)
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Math {
|
||
|
||
struct Vector2 {
|
||
float x, y;
|
||
|
||
static Vector2 Zero() { return Vector2{0, 0}; }
|
||
static Vector2 One() { return Vector2{1, 1}; }
|
||
static Vector2 Up() { return Vector2{0, 1}; }
|
||
static Vector2 Down() { return Vector2{0, -1}; }
|
||
static Vector2 Right() { return Vector2{1, 0}; }
|
||
static Vector2 Left() { return Vector2{-1, 0}; }
|
||
|
||
static float Dot(const Vector2& a, const Vector2& b);
|
||
static float Cross(const Vector2& a, const Vector2& b);
|
||
static Vector2 Normalize(const Vector2& v);
|
||
static float Magnitude(const Vector2& v);
|
||
static Vector2 Lerp(const Vector2& a, const Vector2& b, float t);
|
||
};
|
||
|
||
struct Vector3 {
|
||
float x, y, z;
|
||
|
||
static Vector3 Zero() { return Vector3{0, 0, 0}; }
|
||
static Vector3 One() { return Vector3{1, 1, 1}; }
|
||
static Vector3 Forward() { return Vector3{0, 0, 1}; }
|
||
static Vector3 Back() { return Vector3{0, 0, -1}; }
|
||
static Vector3 Up() { return Vector3{0, 1, 0}; }
|
||
static Vector3 Down() { return Vector3{0, -1, 0}; }
|
||
static Vector3 Right() { return Vector3{1, 0, 0}; }
|
||
static Vector3 Left() { return Vector3{-1, 0, 0}; }
|
||
|
||
static Vector3 Cross(const Vector3& a, const Vector3& b);
|
||
static float Dot(const Vector3& a, const Vector3& b);
|
||
static Vector3 Normalize(const Vector3& v);
|
||
static float Magnitude(const Vector3& v);
|
||
static float SqrMagnitude(const Vector3& v);
|
||
static Vector3 Lerp(const Vector3& a, const Vector3& b, float t);
|
||
static Vector3 MoveTowards(const Vector3& current, const Vector3& target, float maxDistance);
|
||
};
|
||
|
||
struct Vector4 { float x, y, z, w; };
|
||
|
||
struct Matrix3x3;
|
||
struct Matrix4x4;
|
||
|
||
struct Quaternion {
|
||
float x, y, z, w;
|
||
|
||
static Quaternion Identity() { return Quaternion{0, 0, 0, 1}; }
|
||
|
||
static Quaternion FromAxisAngle(const Vector3& axis, float radians);
|
||
static Quaternion FromEulerAngles(float pitch, float yaw, float roll);
|
||
static Quaternion FromRotationMatrix(const Matrix4x4& matrix);
|
||
static Quaternion Slerp(const Quaternion& a, const Quaternion& b, float t);
|
||
static Quaternion LookRotation(const Vector3& forward, const Vector3& up = Vector3::Up());
|
||
|
||
Vector3 ToEulerAngles() const;
|
||
Matrix4x4 ToMatrix4x4() const;
|
||
Vector3 operator*(const Vector3& v) const;
|
||
|
||
Quaternion operator*(const Quaternion& other) const;
|
||
Quaternion Inverse() const;
|
||
float Dot(const Quaternion& other) const;
|
||
};
|
||
|
||
struct Transform {
|
||
Vector3 position = Vector3::Zero();
|
||
Quaternion rotation = Quaternion::Identity();
|
||
Vector3 scale = Vector3::One();
|
||
|
||
Matrix4x4 ToMatrix() const;
|
||
Transform Inverse() const;
|
||
Transform operator*(const Transform& other) const;
|
||
Vector3 TransformPoint(const Vector3& point) const;
|
||
Vector3 TransformDirection(const Vector3& direction) const;
|
||
};
|
||
|
||
enum class Space {
|
||
Self,
|
||
World
|
||
};
|
||
|
||
struct Color {
|
||
float r, g, b, a;
|
||
|
||
static Color White() { return Color{1, 1, 1, 1}; }
|
||
static Color Black() { return Color{0, 0, 0, 1}; }
|
||
static Color Red() { return Color{1, 0, 0, 1}; }
|
||
static Color Green() { return Color{0, 1, 0, 1}; }
|
||
static Color Blue() { return Color{0, 0, 1, 1}; }
|
||
static Color Yellow() { return Color{1, 1, 0, 1}; }
|
||
static Color Cyan() { return Color{0, 1, 1, 1}; }
|
||
static Color Magenta() { return Color{1, 0, 1, 1}; }
|
||
static Color Clear() { return Color{0, 0, 0, 0}; }
|
||
|
||
static Color Lerp(const Color& a, const Color& b, float t);
|
||
};
|
||
|
||
struct Rect {
|
||
float x, y, width, height;
|
||
|
||
Rect() : x(0), y(0), width(0), height(0) {}
|
||
Rect(float x, float y, float w, float h) : x(x), y(y), width(w), height(h) {}
|
||
|
||
float GetLeft() const { return x; }
|
||
float GetRight() const { return x + width; }
|
||
float GetTop() const { return y; }
|
||
float GetBottom() const { return y + height; }
|
||
|
||
Vector2 GetPosition() const { return Vector2{x, y}; }
|
||
Vector2 GetSize() const { return Vector2{width, height}; }
|
||
|
||
bool Contains(float px, float py) const {
|
||
return px >= x && px < x + width && py >= y && py < y + height;
|
||
}
|
||
};
|
||
|
||
struct RectInt {
|
||
int32_t x, y, width, height;
|
||
|
||
RectInt() : x(0), y(0), width(0), height(0) {}
|
||
RectInt(int32_t x, int32_t y, int32_t w, int32_t h) : x(x), y(y), width(w), height(h) {}
|
||
};
|
||
|
||
struct Viewport {
|
||
float x, y, width, height;
|
||
float minDepth = 0.0f;
|
||
float maxDepth = 1.0f;
|
||
|
||
Viewport() : x(0), y(0), width(0), height(0) {}
|
||
Viewport(float x, float y, float w, float h) : x(x), y(y), width(w), height(h) {}
|
||
};
|
||
|
||
struct Ray {
|
||
Vector3 origin;
|
||
Vector3 direction;
|
||
|
||
Vector3 GetPoint(float t) const;
|
||
bool Intersects(const Sphere& sphere, float& t) const;
|
||
bool Intersects(const Box& box, float& t) const;
|
||
bool Intersects(const Plane& plane, float& t) const;
|
||
};
|
||
|
||
struct Sphere { Vector3 center; float radius; };
|
||
struct Box { Vector3 center; Vector3 extents; Matrix4x4 transform; };
|
||
struct Plane { Vector3 normal; float distance; };
|
||
struct Frustum;
|
||
struct OBB;
|
||
struct AABB;
|
||
|
||
} // namespace Math
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
### 1.2 内存管理 (Memory Management)
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Memory {
|
||
|
||
class IAllocator {
|
||
public:
|
||
virtual ~IAllocator() = default;
|
||
|
||
virtual void* Allocate(size_t size, size_t alignment = 0) = 0;
|
||
virtual void Free(void* ptr) = 0;
|
||
virtual void* Reallocate(void* ptr, size_t newSize) = 0;
|
||
|
||
virtual size_t GetTotalAllocated() const = 0;
|
||
virtual size_t GetTotalFreed() const = 0;
|
||
virtual size_t GetPeakAllocated() const = 0;
|
||
virtual size_t GetAllocationCount() const = 0;
|
||
|
||
virtual const char* GetName() const = 0;
|
||
};
|
||
|
||
class LinearAllocator : public IAllocator {
|
||
public:
|
||
explicit LinearAllocator(size_t size, IAllocator* parent = nullptr);
|
||
~LinearAllocator();
|
||
|
||
void* Allocate(size_t size, size_t alignment = 8) override;
|
||
void Free(void* ptr) override;
|
||
void Clear();
|
||
|
||
void* GetMarker() const;
|
||
void SetMarker(void* marker);
|
||
|
||
private:
|
||
byte* m_buffer = nullptr;
|
||
size_t m_capacity = 0;
|
||
size_t m_offset = 0;
|
||
IAllocator* m_parent = nullptr;
|
||
};
|
||
|
||
class PoolAllocator : public IAllocator {
|
||
public:
|
||
PoolAllocator(size_t blockSize, size_t poolSize, size_t alignment = 8);
|
||
~PoolAllocator();
|
||
|
||
void* Allocate(size_t size, size_t alignment = 0) override;
|
||
void Free(void* ptr) override;
|
||
|
||
bool Contains(void* ptr) const;
|
||
size_t GetBlockSize() const { return m_blockSize; }
|
||
size_t GetFreeBlockCount() const;
|
||
|
||
private:
|
||
struct FreeNode {
|
||
FreeNode* next;
|
||
};
|
||
|
||
size_t m_blockSize = 0;
|
||
size_t m_alignment = 0;
|
||
void* m_memory = nullptr;
|
||
FreeNode* m_freeList = nullptr;
|
||
size_t m_totalBlocks = 0;
|
||
size_t m_freeBlocks = 0;
|
||
};
|
||
|
||
class ProxyAllocator : public IAllocator {
|
||
public:
|
||
ProxyAllocator(IAllocator* underlying, const char* name);
|
||
|
||
void* Allocate(size_t size, size_t alignment = 0) override;
|
||
void Free(void* ptr) override;
|
||
void* Reallocate(void* ptr, size_t newSize) override;
|
||
|
||
struct Stats {
|
||
size_t totalAllocated;
|
||
size_t totalFreed;
|
||
size_t peakAllocated;
|
||
size_t allocationCount;
|
||
size_t memoryOverhead;
|
||
};
|
||
const Stats& GetStats() const;
|
||
|
||
private:
|
||
IAllocator* m_underlying;
|
||
const char* m_name;
|
||
Stats m_stats;
|
||
Mutex m_mutex;
|
||
};
|
||
|
||
class MemoryManager {
|
||
public:
|
||
static MemoryManager& Get();
|
||
|
||
void Initialize();
|
||
void Shutdown();
|
||
|
||
IAllocator* GetSystemAllocator();
|
||
|
||
std::unique_ptr<LinearAllocator> CreateLinearAllocator(size_t size);
|
||
std::unique_ptr<PoolAllocator> CreatePoolAllocator(size_t blockSize, size_t count);
|
||
std::unique_ptr<ProxyAllocator> CreateProxyAllocator(const char* name);
|
||
|
||
void SetTrackAllocations(bool track);
|
||
void DumpMemoryLeaks();
|
||
void GenerateMemoryReport();
|
||
};
|
||
|
||
#define XE_ALLOC(allocator, size, ...) allocator->Allocate(size, ##__VA_ARGS__)
|
||
#define XE_FREE(allocator, ptr) allocator->Free(ptr)
|
||
|
||
} // namespace Memory
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
### 1.3 容器库 (Containers)
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Containers {
|
||
|
||
template<typename T>
|
||
class Array {
|
||
public:
|
||
using Iterator = T*;
|
||
using ConstIterator = const T*;
|
||
|
||
Array() = default;
|
||
explicit Array(size_t capacity);
|
||
Array(size_t count, const T& value);
|
||
Array(std::initializer_list<T> init);
|
||
~Array();
|
||
|
||
Array(const Array& other);
|
||
Array(Array&& other) noexcept;
|
||
Array& operator=(const Array& other);
|
||
Array& operator=(Array&& other) noexcept;
|
||
|
||
T& operator[](size_t index);
|
||
const T& operator[](size_t index) const;
|
||
|
||
T* Data() { return m_data; }
|
||
const T* Data() const { return m_data; }
|
||
|
||
size_t Size() const { return m_size; }
|
||
size_t Capacity() const { return m_capacity; }
|
||
|
||
void Clear();
|
||
void PushBack(const T& value);
|
||
void PushBack(T&& value);
|
||
template<typename... Args>
|
||
T& EmplaceBack(Args&&... args);
|
||
void PopBack();
|
||
|
||
private:
|
||
T* m_data = nullptr;
|
||
size_t m_size = 0;
|
||
size_t m_capacity = 0;
|
||
IAllocator* m_allocator = nullptr;
|
||
};
|
||
|
||
class String {
|
||
public:
|
||
String();
|
||
String(const char* str);
|
||
String(const char* str, size_t len);
|
||
~String();
|
||
|
||
String& operator+=(const String& other);
|
||
String& operator+=(const char* str);
|
||
|
||
String Substring(size_t pos, size_t len = npos) const;
|
||
String Trim() const;
|
||
String ToLower() const;
|
||
String ToUpper() const;
|
||
|
||
size_t Find(const char* str, size_t pos = 0) const;
|
||
bool StartsWith(const String& prefix) const;
|
||
bool EndsWith(const String& suffix) const;
|
||
|
||
const char* CStr() const { return m_data; }
|
||
size_t Length() const { return m_length; }
|
||
|
||
private:
|
||
char* m_data = nullptr;
|
||
size_t m_length = 0;
|
||
size_t m_capacity = 0;
|
||
};
|
||
|
||
template<typename Key, typename Value>
|
||
class HashMap {
|
||
public:
|
||
struct Pair {
|
||
Key first;
|
||
Value second;
|
||
};
|
||
|
||
HashMap() = default;
|
||
explicit HashMap(size_t bucketCount, IAllocator* allocator = nullptr);
|
||
|
||
Value& operator[](const Key& key);
|
||
Value* Find(const Key& key);
|
||
const Value* Find(const Key& key) const;
|
||
bool Contains(const Key& key) const;
|
||
|
||
bool Insert(const Key& key, const Value& value);
|
||
bool Erase(const Key& key);
|
||
void Clear();
|
||
|
||
size_t Size() const { return m_size; }
|
||
|
||
private:
|
||
size_t GetBucketIndex(const Key& key) const;
|
||
void Resize();
|
||
|
||
struct Bucket {
|
||
Array<Pair> pairs;
|
||
};
|
||
Array<Bucket> m_buckets;
|
||
size_t m_bucketCount = 0;
|
||
size_t m_size = 0;
|
||
float m_loadFactor = 0.75f;
|
||
IAllocator* m_allocator = nullptr;
|
||
};
|
||
|
||
} // namespace Containers
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
### 1.4 线程系统 (Threading)
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Threading {
|
||
|
||
enum class TaskPriority : uint8_t {
|
||
Critical = 0,
|
||
High = 1,
|
||
Normal = 2,
|
||
Low = 3,
|
||
Idle = 4
|
||
};
|
||
|
||
enum class TaskStatus : uint8_t {
|
||
Pending,
|
||
Scheduled,
|
||
Running,
|
||
Completed,
|
||
Failed,
|
||
Canceled
|
||
};
|
||
|
||
template<typename T = void()>
|
||
using Func = std::function<T>;
|
||
|
||
class ITask {
|
||
public:
|
||
virtual ~ITask() = default;
|
||
|
||
virtual void Execute() = 0;
|
||
virtual void OnComplete() {}
|
||
virtual void OnCancel() {}
|
||
|
||
TaskPriority GetPriority() const { return m_priority; }
|
||
TaskStatus GetStatus() const { return m_status; }
|
||
uint64 GetId() const { return m_id; }
|
||
|
||
protected:
|
||
TaskPriority m_priority = TaskPriority::Normal;
|
||
TaskStatus m_status = TaskStatus::Pending;
|
||
uint64 m_id = 0;
|
||
std::atomic<uint32> m_refCount{1};
|
||
};
|
||
|
||
template<typename Func>
|
||
class LambdaTask : public ITask {
|
||
public:
|
||
explicit LambdaTask(Func&& func, TaskPriority priority = TaskPriority::Normal)
|
||
: m_func(std::move(func)), m_priority(priority) {}
|
||
|
||
void Execute() override {
|
||
m_func();
|
||
}
|
||
|
||
private:
|
||
Func m_func;
|
||
};
|
||
|
||
class TaskGroup {
|
||
public:
|
||
using Callback = std::function<void()>;
|
||
|
||
TaskGroup();
|
||
~TaskGroup();
|
||
|
||
uint64 AddTask(std::unique_ptr<ITask> task);
|
||
uint64 AddTask(Func&& func, TaskPriority priority = TaskPriority::Normal);
|
||
|
||
void AddDependency(uint64 taskId, uint64 dependsOn);
|
||
void Wait();
|
||
bool WaitFor(std::chrono::milliseconds timeout);
|
||
|
||
void SetCompleteCallback(Callback&& callback);
|
||
bool IsComplete() const;
|
||
float GetProgress() const;
|
||
};
|
||
|
||
class TaskSystem {
|
||
public:
|
||
static TaskSystem& Get();
|
||
|
||
void Initialize(const TaskSystemConfig& config);
|
||
void Shutdown();
|
||
|
||
uint64 Submit(std::unique_ptr<ITask> task);
|
||
uint64 Submit(Func&& func, TaskPriority priority = TaskPriority::Normal);
|
||
|
||
TaskGroup* CreateTaskGroup();
|
||
void DestroyTaskGroup(TaskGroup* group);
|
||
|
||
void Wait(uint64 taskId);
|
||
uint32 GetWorkerThreadCount() const;
|
||
|
||
void Update();
|
||
|
||
template<typename Func>
|
||
void ParallelFor(int32 start, int32 end, Func&& func);
|
||
|
||
void RunOnMainThread(Func&& func);
|
||
};
|
||
|
||
} // namespace Threading
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
### 1.5 日志与调试系统
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Core {
|
||
|
||
template<typename... Args>
|
||
class Event {
|
||
public:
|
||
using Callback = std::function<void(Args...)>;
|
||
using Listener = std::pair<uint64_t, Callback>;
|
||
using Iterator = typename std::vector<Listener>::iterator;
|
||
|
||
uint64_t Subscribe(Callback callback) {
|
||
std::lock_guard<std::mutex> lock(m_mutex);
|
||
uint64_t id = ++m_nextId;
|
||
m_listeners.emplace_back(id, std::move(callback));
|
||
return id;
|
||
}
|
||
|
||
void Unsubscribe(uint64_t id) {
|
||
std::lock_guard<std::mutex> lock(m_mutex);
|
||
m_pendingUnsubscribes.push_back(id);
|
||
}
|
||
|
||
void ProcessUnsubscribes() {
|
||
std::lock_guard<std::mutex> lock(m_mutex);
|
||
for (uint64_t id : m_pendingUnsubscribes) {
|
||
m_listeners.erase(
|
||
std::remove_if(m_listeners.begin(), m_listeners.end(),
|
||
[id](const auto& pair) { return pair.first == id; }),
|
||
m_listeners.end()
|
||
);
|
||
}
|
||
m_pendingUnsubscribes.clear();
|
||
}
|
||
|
||
void Invoke(Args... args) const {
|
||
if (!m_pendingUnsubscribes.empty()) {
|
||
std::vector<Listener> listenersCopy;
|
||
{
|
||
std::lock_guard<std::mutex> lock(m_mutex);
|
||
listenersCopy = m_listeners;
|
||
m_pendingUnsubscribes.clear();
|
||
}
|
||
for (const auto& [id, callback] : listenersCopy) {
|
||
callback(args...);
|
||
}
|
||
} else {
|
||
for (const auto& [id, callback] : m_listeners) {
|
||
callback(args...);
|
||
}
|
||
}
|
||
}
|
||
|
||
void Clear() {
|
||
std::lock_guard<std::mutex> lock(m_mutex);
|
||
m_listeners.clear();
|
||
}
|
||
|
||
Iterator begin() { return m_listeners.begin(); }
|
||
Iterator end() { return m_listeners.end(); }
|
||
|
||
private:
|
||
mutable std::mutex m_mutex;
|
||
std::vector<Listener> m_listeners;
|
||
std::vector<uint64_t> m_pendingUnsubscribes;
|
||
uint64_t m_nextId = 0;
|
||
};
|
||
|
||
using int8 = int8_t;
|
||
using int16 = int16_t;
|
||
using int32 = int32_t;
|
||
using int64 = int64_t;
|
||
using uint8 = uint8_t;
|
||
using uint16 = uint16_t;
|
||
using uint32 = uint32_t;
|
||
using uint64 = uint64_t;
|
||
using byte = uint8_t;
|
||
|
||
class RefCounted {
|
||
public:
|
||
RefCounted() : m_refCount(1) {}
|
||
virtual ~RefCounted() = default;
|
||
|
||
void AddRef() { ++m_refCount; }
|
||
void Release() {
|
||
if (--m_refCount == 0) {
|
||
delete this;
|
||
}
|
||
}
|
||
|
||
uint32_t GetRefCount() const { return m_refCount.load(); }
|
||
|
||
protected:
|
||
std::atomic<uint32_t> m_refCount;
|
||
};
|
||
|
||
template<typename T>
|
||
using Ref = std::shared_ptr<T>;
|
||
|
||
template<typename T>
|
||
using UniqueRef = std::unique_ptr<T>;
|
||
|
||
} // namespace Core
|
||
} // namespace XCEngine
|
||
|
||
namespace XCEngine {
|
||
namespace Debug {
|
||
|
||
enum class LogLevel : uint8_t {
|
||
Verbose = 0,
|
||
Debug = 1,
|
||
Info = 2,
|
||
Warning = 3,
|
||
Error = 4,
|
||
Fatal = 5
|
||
};
|
||
|
||
enum class LogCategory {
|
||
General,
|
||
Rendering,
|
||
Physics,
|
||
Audio,
|
||
Scripting,
|
||
Network,
|
||
Memory,
|
||
Threading,
|
||
FileSystem,
|
||
Custom
|
||
};
|
||
|
||
struct LogEntry {
|
||
LogLevel level;
|
||
LogCategory category;
|
||
String message;
|
||
String file;
|
||
int32 line;
|
||
String function;
|
||
uint64 timestamp;
|
||
uint32 threadId;
|
||
};
|
||
|
||
class ILogSink {
|
||
public:
|
||
virtual ~ILogSink() = default;
|
||
virtual void Log(const LogEntry& entry) = 0;
|
||
virtual void Flush() = 0;
|
||
};
|
||
|
||
class ConsoleLogSink : public ILogSink {
|
||
public:
|
||
void Log(const LogEntry& entry) override;
|
||
void Flush() override;
|
||
void SetColorOutput(bool enable);
|
||
void SetMinimumLevel(LogLevel level);
|
||
};
|
||
|
||
class FileLogSink : public ILogSink {
|
||
public:
|
||
explicit FileLogSink(const String& filePath);
|
||
~FileLogSink();
|
||
void Log(const LogEntry& entry) override;
|
||
void Flush() override;
|
||
private:
|
||
String m_filePath;
|
||
FileWriter m_writer;
|
||
};
|
||
|
||
class Logger {
|
||
public:
|
||
static Logger& Get();
|
||
|
||
void Initialize();
|
||
void Shutdown();
|
||
|
||
void AddSink(std::unique_ptr<ILogSink> sink);
|
||
void RemoveSink(ILogSink* sink);
|
||
|
||
void Log(LogLevel level, LogCategory category,
|
||
const String& message, const char* file = nullptr,
|
||
int32 line = 0, const char* function = nullptr);
|
||
|
||
void Verbose(LogCategory category, const String& message);
|
||
void Debug(LogCategory category, const String& message);
|
||
void Info(LogCategory category, const String& message);
|
||
void Warning(LogCategory category, const String& message);
|
||
void Error(LogCategory category, const String& message);
|
||
void Fatal(LogCategory category, const String& message);
|
||
|
||
void SetMinimumLevel(LogLevel level);
|
||
void SetCategoryEnabled(LogCategory category, bool enabled);
|
||
};
|
||
|
||
#define XE_LOG(category, level, message) \
|
||
XCEngine::Debug::Logger::Get().Log(level, category, message, __FILE__, __LINE__, __FUNCTION__)
|
||
|
||
#define XE_ASSERT(condition, message) \
|
||
if (!(condition)) { \
|
||
XCEngine::Debug::Logger::Get().Fatal(XCEngine::Debug::LogCategory::General, message); \
|
||
__debugbreak(); \
|
||
}
|
||
|
||
class Profiler {
|
||
public:
|
||
static Profiler& Get();
|
||
|
||
void Initialize();
|
||
void Shutdown();
|
||
|
||
void BeginProfile(const char* name);
|
||
void EndProfile();
|
||
|
||
void BeginFrame();
|
||
void EndFrame();
|
||
|
||
void MarkEvent(const char* name, uint64_t timestamp, uint32_t threadId);
|
||
void SetMarker(const char* name, uint32_t color);
|
||
|
||
void ExportChromeTracing(const String& filePath);
|
||
};
|
||
|
||
#define XE_PROFILE_BEGIN(name) XCEngine::Debug::Profiler::Get().BeginProfile(name)
|
||
#define XE_PROFILE_END() XCEngine::Debug::Profiler::Get().EndProfile()
|
||
#define XE_PROFILE_FUNCTION() XE_PROFILE_BEGIN(__FUNCTION__)
|
||
|
||
} // namespace Debug
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
---
|
||
|
||
## 第二章 组件系统
|
||
|
||
### 2.1 组件基类
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
|
||
class Scene;
|
||
class GameObject;
|
||
class TransformComponent;
|
||
|
||
// 组件类型注册(用于运行时类型识别)
|
||
class ComponentTypeRegistry {
|
||
public:
|
||
static ComponentTypeRegistry& Get();
|
||
|
||
template<typename T>
|
||
static uint32_t GetTypeId() {
|
||
static uint32_t id = Get().Register(typeid(T).name(), static_cast<uint32_t>(-1));
|
||
return id;
|
||
}
|
||
|
||
template<typename T>
|
||
static uint32_t GetTypeId(const char* typeName) {
|
||
static uint32_t id = Get().Register(typeName, static_cast<uint32_t>(-1));
|
||
return id;
|
||
}
|
||
|
||
static uint32_t GetTypeIdFromName(const char* typeName) {
|
||
return Get().GetIdByName(typeName);
|
||
}
|
||
|
||
static const char* GetTypeName(uint32_t typeId) {
|
||
return Get().GetNameById(typeId);
|
||
}
|
||
|
||
private:
|
||
uint32_t Register(const char* typeName, uint32_t suggestedId);
|
||
uint32_t GetIdByName(const char* typeName) const;
|
||
const char* GetNameById(uint32_t typeId) const;
|
||
|
||
std::atomic<uint32_t> m_nextTypeId{0};
|
||
std::unordered_map<uint32_t, String> m_idToName;
|
||
std::unordered_map<String, uint32_t> m_nameToId;
|
||
Mutex m_mutex;
|
||
};
|
||
|
||
// 组件基类(类Unity MonoBehaviour)
|
||
class Component {
|
||
public:
|
||
Component();
|
||
virtual ~Component();
|
||
|
||
GameObject* gameObject() const { return m_gameObject; }
|
||
TransformComponent& transform() const { return m_gameObject->GetTransform(); }
|
||
|
||
bool IsEnabled() const { return m_enabled; }
|
||
void SetEnabled(bool enabled) { m_enabled = enabled; }
|
||
|
||
Scene* GetScene() const;
|
||
|
||
template<typename T>
|
||
T* GetComponent() const { return m_gameObject->GetComponent<T>(); }
|
||
|
||
template<typename T>
|
||
std::vector<T*> GetComponents() const { return m_gameObject->GetComponents<T>(); }
|
||
|
||
virtual void Awake() {}
|
||
virtual void Start() {}
|
||
virtual void Update(float deltaTime) {}
|
||
virtual void FixedUpdate() {}
|
||
virtual void LateUpdate(float deltaTime) {}
|
||
virtual void OnDestroy() {}
|
||
virtual void OnEnable() {}
|
||
virtual void OnDisable() {}
|
||
|
||
protected:
|
||
GameObject* m_gameObject = nullptr;
|
||
bool m_enabled = true;
|
||
|
||
friend class GameObject;
|
||
};
|
||
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
### 2.2 Transform组件
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
|
||
class TransformComponent : public Component {
|
||
public:
|
||
Vector3 GetLocalPosition() const { return m_localPosition; }
|
||
void SetLocalPosition(const Vector3& position) { m_localPosition = position; SetDirty(); }
|
||
|
||
Quaternion GetLocalRotation() const { return m_localRotation; }
|
||
void SetLocalRotation(const Quaternion& rotation) { m_localRotation = rotation; SetDirty(); }
|
||
|
||
Vector3 GetLocalScale() const { return m_localScale; }
|
||
void SetLocalScale(const Vector3& scale) { m_localScale = scale; SetDirty(); }
|
||
|
||
Vector3 GetPosition() const;
|
||
void SetPosition(const Vector3& position);
|
||
|
||
Quaternion GetRotation() const;
|
||
void SetRotation(const Quaternion& rotation);
|
||
|
||
Vector3 GetScale() const;
|
||
void SetScale(const Vector3& scale);
|
||
|
||
Vector3 GetForward() const { return GetRotation() * Vector3::Forward(); }
|
||
Vector3 GetRight() const { return GetRotation() * Vector3::Right(); }
|
||
Vector3 GetUp() const { return GetRotation() * Vector3::Up(); }
|
||
|
||
const Matrix4x4& GetLocalToWorldMatrix() const;
|
||
Matrix4x4 GetWorldToLocalMatrix() const;
|
||
|
||
TransformComponent* GetParent() const { return m_parent; }
|
||
void SetParent(TransformComponent* parent, bool worldPositionStays = true);
|
||
|
||
int GetChildCount() const { return static_cast<int>(m_children.size()); }
|
||
TransformComponent* GetChild(int index) const;
|
||
TransformComponent* Find(const String& name) const;
|
||
|
||
void DetachChildren();
|
||
void SetAsFirstSibling();
|
||
void SetAsLastSibling();
|
||
void SetSiblingIndex(int index);
|
||
int GetSiblingIndex() const;
|
||
|
||
void LookAt(const Vector3& target);
|
||
void LookAt(const Vector3& target, const Vector3& up);
|
||
void Rotate(const Vector3& eulers);
|
||
void Rotate(const Vector3& axis, float angle);
|
||
void Translate(const Vector3& translation);
|
||
void Translate(const Vector3& translation, Math::Space relativeTo);
|
||
|
||
Vector3 TransformPoint(const Vector3& point) const;
|
||
Vector3 InverseTransformPoint(const Vector3& point) const;
|
||
Vector3 TransformDirection(const Vector3& direction) const;
|
||
Vector3 InverseTransformDirection(const Vector3& direction) const;
|
||
|
||
void SetDirty() { m_dirty = true; }
|
||
|
||
private:
|
||
Vector3 m_localPosition = Vector3::Zero();
|
||
Quaternion m_localRotation = Quaternion::Identity();
|
||
Vector3 m_localScale = Vector3::One();
|
||
|
||
TransformComponent* m_parent = nullptr;
|
||
std::vector<TransformComponent*> m_children;
|
||
|
||
mutable Matrix4x4 m_localToWorldMatrix;
|
||
mutable Matrix4x4 m_worldToLocalMatrix;
|
||
mutable Vector3 m_worldPosition;
|
||
mutable Quaternion m_worldRotation;
|
||
mutable Vector3 m_worldScale;
|
||
mutable bool m_dirty = true;
|
||
|
||
void UpdateWorldTransform() const;
|
||
|
||
friend class GameObject;
|
||
};
|
||
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
### 2.3 GameObject
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
|
||
class Scene;
|
||
|
||
class GameObject {
|
||
public:
|
||
GameObject();
|
||
~GameObject();
|
||
|
||
struct ConstructParams {
|
||
String name = "GameObject";
|
||
GameObject* parent = nullptr;
|
||
bool active = true;
|
||
};
|
||
|
||
static GameObject* Create(const ConstructParams& params = {});
|
||
static void Destroy(GameObject* obj);
|
||
|
||
String name;
|
||
bool active = true;
|
||
|
||
TransformComponent& GetTransform() { return m_transform; }
|
||
const TransformComponent& GetTransform() const { return m_transform; }
|
||
|
||
Scene* GetScene() const { return m_scene; }
|
||
|
||
template<typename T>
|
||
T* AddComponent();
|
||
|
||
template<typename T>
|
||
void RemoveComponent();
|
||
|
||
template<typename T>
|
||
T* GetComponent() const;
|
||
|
||
template<typename T>
|
||
std::vector<T*> GetComponents() const;
|
||
|
||
template<typename T>
|
||
T* GetComponentInChildren() const;
|
||
|
||
template<typename T>
|
||
std::vector<T*> GetComponentsInChildren() const;
|
||
|
||
template<typename T>
|
||
T* GetComponentInParent() const;
|
||
|
||
GameObject* GetParent() const;
|
||
void SetParent(GameObject* parent);
|
||
void SetParent(GameObject* parent, bool worldPositionStays);
|
||
const std::vector<GameObject*>& GetChildren() const;
|
||
GameObject* GetChild(int index) const;
|
||
int GetChildCount() const;
|
||
int GetSiblingIndex() const;
|
||
void SetSiblingIndex(int index);
|
||
|
||
void SetActive(bool active);
|
||
bool IsActive() const;
|
||
bool IsActiveInHierarchy() const;
|
||
|
||
static GameObject* Find(const String& name);
|
||
static std::vector<GameObject*> FindObjectsOfType();
|
||
static std::vector<GameObject*> FindGameObjectsWithTag(const String& tag);
|
||
|
||
void Destroy();
|
||
|
||
private:
|
||
void AddComponentInternal(Component* component);
|
||
void RemoveComponentInternal(Component* component);
|
||
|
||
std::vector<std::unique_ptr<Component>> m_components;
|
||
std::unordered_map<uint32_t, size_t> m_componentTypeIndex;
|
||
|
||
std::vector<GameObject*> m_children;
|
||
GameObject* m_parent = nullptr;
|
||
Scene* m_scene = nullptr;
|
||
|
||
TransformComponent m_transform;
|
||
|
||
void Initialize(const ConstructParams& params);
|
||
|
||
friend class Scene;
|
||
friend class TransformComponent;
|
||
};
|
||
|
||
inline GameObject::GameObject() {
|
||
}
|
||
|
||
inline GameObject::~GameObject() {
|
||
for (auto* child : m_children) {
|
||
delete child;
|
||
}
|
||
}
|
||
|
||
inline GameObject* GameObject::Create(const ConstructParams& params) {
|
||
GameObject* obj = new GameObject();
|
||
obj->Initialize(params);
|
||
return obj;
|
||
}
|
||
|
||
inline void GameObject::Destroy(GameObject* obj) {
|
||
delete obj;
|
||
}
|
||
|
||
inline void GameObject::Initialize(const ConstructParams& params) {
|
||
name = params.name;
|
||
active = params.active;
|
||
|
||
m_transform.m_gameObject = this;
|
||
|
||
if (params.parent) {
|
||
params.parent->m_children.push_back(this);
|
||
m_parent = params.parent;
|
||
}
|
||
}
|
||
|
||
inline void GameObject::Destroy() {
|
||
if (m_scene) {
|
||
m_scene->DestroyGameObject(this);
|
||
} else {
|
||
delete this;
|
||
}
|
||
}
|
||
|
||
inline GameObject* GameObject::Find(const String& name) {
|
||
return SceneManager::Get().GetActiveScene()->Find(name);
|
||
}
|
||
|
||
inline std::vector<GameObject*> GameObject::FindObjectsOfType() {
|
||
return SceneManager::Get().GetActiveScene()->FindObjectsOfType<GameObject>();
|
||
}
|
||
|
||
inline std::vector<GameObject*> GameObject::FindGameObjectsWithTag(const String& tag) {
|
||
return SceneManager::Get().GetActiveScene()->FindGameObjectsWithTag(tag);
|
||
}
|
||
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
---
|
||
|
||
## 第三章 场景系统
|
||
|
||
### 3.1 Scene
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
|
||
class Scene {
|
||
public:
|
||
Scene();
|
||
~Scene();
|
||
|
||
const String& GetName() const { return m_name; }
|
||
void SetName(const String& name) { m_name = name; }
|
||
|
||
GameObject* CreateGameObject(const String& name = "GameObject") {
|
||
GameObject::ConstructParams params;
|
||
params.name = name;
|
||
params.parent = nullptr;
|
||
params.active = true;
|
||
|
||
GameObject* obj = GameObject::Create(params);
|
||
obj->m_scene = this;
|
||
AddGameObject(obj);
|
||
return obj;
|
||
}
|
||
|
||
GameObject* CreateGameObject(const String& name, GameObject* parent) {
|
||
GameObject::ConstructParams params;
|
||
params.name = name;
|
||
params.parent = parent;
|
||
params.active = true;
|
||
|
||
GameObject* obj = GameObject::Create(params);
|
||
obj->m_scene = this;
|
||
AddGameObject(obj);
|
||
return obj;
|
||
}
|
||
|
||
void DestroyGameObject(GameObject* obj);
|
||
|
||
std::vector<GameObject*> GetRootGameObjects() const {
|
||
std::vector<GameObject*> roots;
|
||
roots.reserve(m_gameObjects.size() / 2);
|
||
for (auto& obj : m_gameObjects) {
|
||
if (obj->GetParent() == nullptr) {
|
||
roots.push_back(obj.get());
|
||
}
|
||
}
|
||
return roots;
|
||
}
|
||
|
||
GameObject* Find(const String& name) const;
|
||
GameObject* FindGameObjectWithTag(const String& tag) const;
|
||
std::vector<GameObject*> FindGameObjectsWithTag(const String& tag) const;
|
||
template<typename T>
|
||
std::vector<T*> FindObjectsOfType() const;
|
||
T* FindObjectOfType() const;
|
||
|
||
bool IsActive() const { return m_isActive; }
|
||
void SetActive(bool active);
|
||
|
||
void Load(const String& filePath);
|
||
void LoadAsync(const String& filePath, std::function<void()> callback);
|
||
void Save(const String& filePath);
|
||
|
||
void Update(float deltaTime);
|
||
void FixedUpdate(float fixedDeltaTime);
|
||
void LateUpdate(float deltaTime);
|
||
|
||
void DebugDraw();
|
||
int GetObjectCount() const { return m_gameObjects.size(); }
|
||
|
||
private:
|
||
void AddGameObject(GameObject* obj);
|
||
void RemoveGameObject(GameObject* obj);
|
||
|
||
String m_name;
|
||
std::vector<std::unique_ptr<GameObject>> m_gameObjects;
|
||
bool m_isActive = true;
|
||
|
||
friend class GameObject;
|
||
friend class SceneManager;
|
||
};
|
||
|
||
class SceneManager {
|
||
public:
|
||
static SceneManager& Get();
|
||
|
||
void Initialize();
|
||
void Shutdown();
|
||
|
||
Scene* CreateScene(const String& name);
|
||
void LoadScene(const String& filePath);
|
||
void LoadSceneAsync(const String& filePath, std::function<void(Scene*)> callback);
|
||
void UnloadScene(Scene* scene);
|
||
void UnloadScene(const String& sceneName);
|
||
|
||
void SetActiveScene(Scene* scene);
|
||
void SetActiveScene(const String& sceneName);
|
||
Scene* GetActiveScene() const;
|
||
|
||
Scene* GetScene(const String& name) const;
|
||
std::vector<Scene*> GetAllScenes() const;
|
||
|
||
void Update(float deltaTime);
|
||
void FixedUpdate(float fixedDeltaTime);
|
||
void LateUpdate(float deltaTime);
|
||
|
||
Event<Scene*> OnSceneLoaded;
|
||
Event<Scene*> OnSceneUnloaded;
|
||
Event<Scene*> OnActiveSceneChanged;
|
||
|
||
private:
|
||
SceneManager() = default;
|
||
|
||
std::vector<std::unique_ptr<Scene>> m_scenes;
|
||
Scene* m_activeScene = nullptr;
|
||
Scene* m_loadingScene = nullptr;
|
||
|
||
std::unordered_map<String, Scene*> m_sceneNameMap;
|
||
std::function<void(Scene*)> m_loadCallback;
|
||
bool m_loading = false;
|
||
};
|
||
|
||
// GameObject创建辅助类
|
||
class GameObjectBuilder {
|
||
public:
|
||
explicit GameObjectBuilder(const String& name = "GameObject");
|
||
~GameObjectBuilder() = default;
|
||
|
||
template<typename T, typename... Args>
|
||
GameObjectBuilder& AddComponent(Args&&... args);
|
||
|
||
GameObject* Build();
|
||
|
||
private:
|
||
String m_name;
|
||
std::vector<std::function<void(GameObject*)>> m_components;
|
||
};
|
||
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
---
|
||
|
||
## 第四章 渲染系统
|
||
|
||
### 4.1 渲染抽象层
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Rendering {
|
||
|
||
enum class ResourceState {
|
||
Undefined,
|
||
RenderTarget,
|
||
DepthStencil,
|
||
ShaderResource,
|
||
UnorderedAccess,
|
||
CopySrc,
|
||
CopyDst,
|
||
Present
|
||
};
|
||
|
||
struct ResourceDesc {
|
||
ResourceType type;
|
||
uint32_t width = 1;
|
||
uint32_t height = 1;
|
||
uint32_t depth = 1;
|
||
uint32_t mipLevels = 1;
|
||
uint32_t arraySize = 1;
|
||
Format format = Format::Unknown;
|
||
SampleCount sampleCount = SampleCount::Count1;
|
||
ResourceState initialState = ResourceState::Undefined;
|
||
bool cpuAccessible = false;
|
||
bool randomAccess = false;
|
||
|
||
MemoryUsage memoryUsage = MemoryUsage::Default;
|
||
|
||
String name;
|
||
};
|
||
|
||
class IRenderDevice {
|
||
public:
|
||
virtual ~IRenderDevice() = default;
|
||
|
||
virtual const char* GetApiName() const = 0;
|
||
virtual const char* GetDriverVersion() const = 0;
|
||
virtual uint64_t GetDeviceId() const = 0;
|
||
virtual uint64_t GetVendorId() const = 0;
|
||
|
||
virtual bool SupportsRaytracing() const = 0;
|
||
virtual bool SupportsMeshShaders() const = 0;
|
||
virtual bool SupportsVariableRateShading() const = 0;
|
||
virtual bool SupportsSamplerFeedback() const = 0;
|
||
virtual uint32_t GetMaxTextureSize() const = 0;
|
||
virtual uint32_t GetMaxUBOSize() const = 0;
|
||
virtual uint32_t GetMaxMSAA() const = 0;
|
||
|
||
virtual std::unique_ptr<RenderTexture> CreateTexture(const ResourceDesc& desc) = 0;
|
||
virtual std::unique_ptr<RenderBuffer> CreateBuffer(const ResourceDesc& desc, const void* initialData = nullptr) = 0;
|
||
virtual std::unique_ptr<Shader> CreateShader(const ShaderDesc& desc) = 0;
|
||
virtual std::unique_ptr<Pipeline> CreatePipeline(const PipelineDesc& desc) = 0;
|
||
virtual std::unique_ptr<RenderPass> CreateRenderPass(const RenderPassDesc& desc) = 0;
|
||
|
||
virtual ICommandQueue* GetGraphicsQueue() = 0;
|
||
virtual ICommandQueue* GetComputeQueue() = 0;
|
||
virtual ICommandQueue* GetCopyQueue() = 0;
|
||
|
||
virtual std::unique_ptr<IFence> CreateFence() = 0;
|
||
virtual IDescriptorHeap* CreateDescriptorHeap(const DescriptorHeapDesc& desc) = 0;
|
||
virtual std::unique_ptr<IQueryHeap> CreateQueryHeap(const QueryHeapDesc& desc) = 0;
|
||
};
|
||
|
||
class ICommandList {
|
||
public:
|
||
virtual ~ICommandList() = default;
|
||
|
||
virtual void TransitionBarrier(const IResource* resource, ResourceState newState) = 0;
|
||
virtual void UAVBarrier(const IResource* resource) = 0;
|
||
virtual void FlushBarriers() = 0;
|
||
|
||
virtual void SetPipeline(const IPipeline* pipeline) = 0;
|
||
virtual void SetVertexBuffer(uint32_t slot, const IBuffer* buffer, uint64_t offset = 0) = 0;
|
||
virtual void SetIndexBuffer(const IBuffer* buffer, IndexType indexType, uint64_t offset = 0) = 0;
|
||
virtual void SetConstantBuffer(uint32_t slot, const IBuffer* buffer, uint64_t offset = 0) = 0;
|
||
virtual void SetShaderResource(uint32_t slot, const IResource* resource) = 0;
|
||
virtual void SetSampler(uint32_t slot, const ISampler* sampler) = 0;
|
||
|
||
virtual void Draw(uint32_t vertexCount, uint32_t firstVertex = 0) = 0;
|
||
virtual void DrawIndexed(uint32_t indexCount, uint32_t firstIndex = 0, int32_t baseVertex = 0) = 0;
|
||
virtual void DrawInstanced(uint32_t vertexCountPerInstance, uint32_t instanceCount,
|
||
uint32_t firstVertex = 0, uint32_t firstInstance = 0) = 0;
|
||
virtual void DrawIndexedInstanced(uint32_t indexCountPerInstance, uint32_t instanceCount,
|
||
uint32_t firstIndex = 0, int32_t baseVertex = 0, uint32_t firstInstance = 0) = 0;
|
||
|
||
virtual void Dispatch(uint32_t threadGroupCountX, uint32_t threadGroupCountY, uint32_t threadGroupCountZ) = 0;
|
||
|
||
virtual void BuildAccelerationStructure(const RaytracingBuildDesc& desc) = 0;
|
||
virtual void SetRaytracingPipeline(const IPipeline* pipeline) = 0;
|
||
virtual void DispatchRays(const DispatchRaysDesc& desc) = 0;
|
||
|
||
virtual void BeginRenderPass(const RenderPassBeginDesc& desc) = 0;
|
||
virtual void EndRenderPass() = 0;
|
||
|
||
virtual void CopyResource(IResource* dst, const IResource* src) = 0;
|
||
virtual void CopyBuffer(IBuffer* dst, uint64_t dstOffset, const IBuffer* src, uint64_t srcOffset, uint64_t size) = 0;
|
||
|
||
virtual void BeginQuery(IQueryHeap* heap, uint32_t index) = 0;
|
||
virtual void EndQuery(IQueryHeap* heap, uint32_t index) = 0;
|
||
|
||
virtual void SetMarker(const char* name, uint32_t color) = 0;
|
||
virtual void BeginEvent(const char* name, uint32_t color) = 0;
|
||
virtual void EndEvent() = 0;
|
||
};
|
||
|
||
class RenderContext {
|
||
public:
|
||
class GBufferPass;
|
||
class LightingPass;
|
||
class ShadowPass;
|
||
class PostProcessPass;
|
||
|
||
static RenderContext* Create(const RenderContextDesc& desc);
|
||
static void Destroy(RenderContext* context);
|
||
|
||
static RenderContext* GetMain();
|
||
|
||
void Initialize(const RenderContextDesc& desc);
|
||
void Shutdown();
|
||
|
||
IRenderDevice* GetDevice() { return m_device.get(); }
|
||
|
||
void BeginFrame();
|
||
void EndFrame();
|
||
|
||
ICommandList* GetMainCommandList() { return m_mainCommandList.get(); }
|
||
|
||
void SetRenderTarget(const RenderTarget& target);
|
||
void SetViewport(const Viewport& viewport);
|
||
void SetScissorRect(const Rect& rect);
|
||
|
||
void RenderScene(const SceneRenderDesc& desc);
|
||
void ApplyPostProcessing(const PostProcessDesc& desc);
|
||
|
||
void CaptureFrame(const String& filePath);
|
||
void ToggleDebugView();
|
||
|
||
private:
|
||
std::unique_ptr<IRenderDevice> m_device;
|
||
std::unique_ptr<ICommandList> m_mainCommandList;
|
||
std::unique_ptr<ISwapChain> m_swapChain;
|
||
|
||
std::unique_ptr<GBufferPass> m_gBufferPass;
|
||
std::unique_ptr<LightingPass> m_lightingPass;
|
||
std::unique_ptr<ShadowPass> m_shadowPass;
|
||
std::unique_ptr<PostProcessPass> m_postProcessPass;
|
||
|
||
uint32_t m_frameIndex = 0;
|
||
uint64_t m_frameCount = 0;
|
||
|
||
static RenderContext* s_mainContext;
|
||
};
|
||
|
||
// 资源类型
|
||
enum class ResourceType {
|
||
Unknown,
|
||
Mesh,
|
||
Texture,
|
||
Material,
|
||
Shader,
|
||
Audio,
|
||
Animation,
|
||
Skeleton,
|
||
Font,
|
||
Prefab,
|
||
Scene,
|
||
Script,
|
||
PhysicsMaterial,
|
||
NavMesh,
|
||
Video,
|
||
Custom
|
||
};
|
||
|
||
// 资源GUID
|
||
struct ResourceGUID {
|
||
static constexpr uint64_t INVALID = 0;
|
||
|
||
uint64_t value = INVALID;
|
||
|
||
bool IsValid() const { return value != INVALID; }
|
||
bool operator==(const ResourceGUID& other) const { return value == other.value; }
|
||
bool operator!=(const ResourceGUID& other) const { return value != other.value; }
|
||
|
||
String ToString() const;
|
||
static ResourceGUID FromString(const String& str);
|
||
|
||
struct Hash {
|
||
size_t operator()(const ResourceGUID& guid) const {
|
||
return std::hash<uint64_t>{}(guid.value);
|
||
}
|
||
};
|
||
};
|
||
|
||
// 资源基类
|
||
class IResource {
|
||
public:
|
||
virtual ~IResource() = default;
|
||
|
||
virtual ResourceType GetType() const = 0;
|
||
virtual const String& GetName() const = 0;
|
||
virtual ResourceGUID GetGUID() const = 0;
|
||
|
||
virtual bool IsLoaded() const = 0;
|
||
virtual bool IsLoading() const = 0;
|
||
virtual float GetLoadingProgress() const = 0;
|
||
|
||
virtual void AddRef() = 0;
|
||
virtual void Release() = 0;
|
||
virtual uint32_t GetRefCount() const = 0;
|
||
|
||
virtual void Unload() = 0;
|
||
};
|
||
|
||
class RenderTexture : public IResource {
|
||
public:
|
||
uint32_t GetWidth() const { return m_width; }
|
||
uint32_t GetHeight() const { return m_height; }
|
||
uint32_t GetMipLevels() const { return m_mipLevels; }
|
||
Format GetFormat() const { return m_format; }
|
||
|
||
void* GetNativeHandle() const { return m_nativeHandle; }
|
||
|
||
IShaderResourceView* GetSRV() { return m_srv.get(); }
|
||
IRenderTargetView* GetRTV() { return m_rtv.get(); }
|
||
IDepthStencilView* GetDSV() { return m_dsv.get(); }
|
||
|
||
void* Map();
|
||
void Unmap();
|
||
|
||
private:
|
||
uint32_t m_width, m_height;
|
||
uint32_t m_mipLevels;
|
||
Format m_format;
|
||
void* m_nativeHandle = nullptr;
|
||
|
||
std::unique_ptr<IShaderResourceView> m_srv;
|
||
std::unique_ptr<IRenderTargetView> m_rtv;
|
||
std::unique_ptr<IDepthStencilView> m_dsv;
|
||
};
|
||
|
||
class RenderBuffer : public IResource {
|
||
public:
|
||
uint64_t GetSize() const { return m_size; }
|
||
BufferUsage GetUsage() const { return m_usage; }
|
||
|
||
void* GetNativeHandle() const { return m_nativeHandle; }
|
||
|
||
void SetData(const void* data, uint64_t size, uint64_t offset = 0);
|
||
void* Map();
|
||
void Unmap();
|
||
|
||
private:
|
||
uint64_t m_size;
|
||
BufferUsage m_usage;
|
||
void* m_nativeHandle = nullptr;
|
||
};
|
||
|
||
} // namespace Rendering
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
### 4.2 渲染图 (Render Graph)
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
namespace Rendering {
|
||
|
||
class RenderGraphResource {
|
||
public:
|
||
RenderGraphResource() = default;
|
||
RenderGraphResource(const String& name);
|
||
|
||
const String& GetName() const { return m_name; }
|
||
uint32_t GetIndex() const { return m_index; }
|
||
|
||
bool IsValid() const { return m_index != UINT32_MAX; }
|
||
operator bool() const { return IsValid(); }
|
||
|
||
private:
|
||
String m_name;
|
||
uint32_t m_index = UINT32_MAX;
|
||
friend class RenderGraph;
|
||
};
|
||
|
||
class RenderGraphPass {
|
||
public:
|
||
using ExecuteFn = std::function<void(RenderGraphPass&, ICommandList&)>;
|
||
|
||
RenderGraphPass(const String& name, PassType type);
|
||
|
||
RenderGraphResource Read(const String& resourceName);
|
||
RenderGraphResource Write(const String& resourceName);
|
||
RenderGraphResource ReadWrite(const String& resourceName, ResourceState initialState, ResourceState finalState);
|
||
|
||
void Execute(ExecuteFn&& fn);
|
||
void Execute() const;
|
||
|
||
void SetDebugColor(const Color& color);
|
||
|
||
const String& GetName() const { return m_name; }
|
||
PassType GetType() const { return m_type; }
|
||
const std::vector<RenderGraphResource>& GetReads() const { return m_reads; }
|
||
const std::vector<RenderGraphResource>& GetWrites() const { return m_writes; }
|
||
|
||
private:
|
||
String m_name;
|
||
PassType m_type;
|
||
std::vector<RenderGraphResource> m_reads;
|
||
std::vector<RenderGraphResource> m_writes;
|
||
ExecuteFn m_executeFn;
|
||
Color m_debugColor;
|
||
|
||
friend class RenderGraph;
|
||
};
|
||
|
||
class RenderGraph {
|
||
public:
|
||
RenderGraph();
|
||
~RenderGraph();
|
||
|
||
RenderGraphResource CreateTexture(const String& name, const TextureDesc& desc);
|
||
RenderGraphResource CreateBuffer(const String& name, const BufferDesc& desc);
|
||
|
||
RenderGraphPass& AddPass(const String& name, PassType type);
|
||
|
||
void Build();
|
||
void Execute(ICommandList* commandList);
|
||
|
||
void SetName(const String& name);
|
||
void Print() const;
|
||
void ExportToDot(const String& filePath) const;
|
||
|
||
void Clear();
|
||
|
||
private:
|
||
void Compile();
|
||
void Validate();
|
||
void SortPasses();
|
||
void AllocateResources();
|
||
|
||
struct ResourceInfo {
|
||
String name;
|
||
ResourceDesc desc;
|
||
ResourceState currentState;
|
||
uint32_t firstPassWrite = UINT32_MAX;
|
||
uint32_t lastPassRead = UINT32_MAX;
|
||
bool imported = false;
|
||
};
|
||
|
||
struct PassInfo {
|
||
String name;
|
||
PassType type;
|
||
std::vector<uint32_t> reads;
|
||
std::vector<uint32_t> writes;
|
||
std::function<void(RenderGraphPass&, ICommandList&)> executeFn;
|
||
};
|
||
|
||
std::vector<ResourceInfo> m_resources;
|
||
std::vector<PassInfo> m_passes;
|
||
std::unordered_map<String, uint32_t> m_resourceIndex;
|
||
|
||
bool m_built = false;
|
||
};
|
||
|
||
} // namespace Rendering
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
### 4.3 相机组件
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
|
||
class CameraComponent : public Component {
|
||
public:
|
||
void Awake() override;
|
||
void Start() override;
|
||
void Update(float deltaTime) override;
|
||
|
||
enum class ProjectionType : uint8_t {
|
||
Perspective,
|
||
Orthographic
|
||
};
|
||
|
||
void SetProjectionType(ProjectionType type) { m_projectionType = type; }
|
||
ProjectionType GetProjectionType() const { return m_projectionType; }
|
||
|
||
void SetFieldOfView(float fov) { m_fieldOfView = fov; }
|
||
float GetFieldOfView() const { return m_fieldOfView; }
|
||
|
||
void SetOrthographicSize(float size) { m_orthographicSize = size; }
|
||
float GetOrthographicSize() const { return m_orthographicSize; }
|
||
|
||
void SetNearClipPlane(float near) { m_nearPlane = near; }
|
||
float GetNearClipPlane() const { return m_nearPlane; }
|
||
|
||
void SetFarClipPlane(float far) { m_farPlane = far; }
|
||
float GetFarClipPlane() const { return m_farPlane; }
|
||
|
||
void SetViewport(const Rect& rect) { m_viewportRect = rect; }
|
||
const Rect& GetViewport() const { return m_viewportRect; }
|
||
|
||
void SetCullingMask(int32_t mask) { m_cullingMask = mask; }
|
||
int32_t GetCullingMask() const { return m_cullingMask; }
|
||
|
||
void SetDepth(float depth) { m_depth = depth; }
|
||
float GetDepth() const { return m_depth; }
|
||
|
||
Matrix4x4 GetViewMatrix() const;
|
||
Matrix4x4 GetProjectionMatrix() const;
|
||
Matrix4x4 GetViewProjectionMatrix() const;
|
||
|
||
Vector3 ScreenToWorldPoint(const Vector3& screenPoint) const;
|
||
Vector3 WorldToScreenPoint(const Vector3& worldPoint) const;
|
||
Ray ScreenPointToRay(const Vector2& screenPoint) const;
|
||
|
||
Frustum& GetFrustum() { return m_frustum; }
|
||
|
||
private:
|
||
ProjectionType m_projectionType = ProjectionType::Perspective;
|
||
float m_fieldOfView = 60.0f;
|
||
float m_orthographicSize = 5.0f;
|
||
float m_nearPlane = 0.1f;
|
||
float m_farPlane = 1000.0f;
|
||
float m_aspectRatio = 16.0f / 9.0f;
|
||
Rect m_viewportRect = Rect(0, 0, 1, 1);
|
||
float m_depth = 0.0f;
|
||
int32_t m_cullingMask = -1;
|
||
Frustum m_frustum;
|
||
};
|
||
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
### 4.4 光照组件
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
|
||
class RenderLightComponent : public Component {
|
||
public:
|
||
void Awake() override;
|
||
void Update(float deltaTime) override;
|
||
|
||
enum class LightType : uint8_t {
|
||
Directional,
|
||
Point,
|
||
Spot,
|
||
Area
|
||
};
|
||
|
||
void SetLightType(LightType type) { m_type = type; }
|
||
LightType GetLightType() const { return m_type; }
|
||
|
||
void SetColor(const Vector3& color) { m_color = color; }
|
||
Vector3 GetColor() const { return m_color; }
|
||
|
||
void SetIntensity(float intensity) { m_intensity = intensity; }
|
||
float GetIntensity() const { return m_intensity; }
|
||
|
||
void SetRange(float range) { m_range = range; }
|
||
float GetRange() const { return m_range; }
|
||
|
||
void SetSpotAngle(float angle) { m_spotAngle = angle; }
|
||
float GetSpotAngle() const { return m_spotAngle; }
|
||
|
||
void SetCastShadows(bool cast) { m_castShadows = cast; }
|
||
bool GetCastShadows() const { return m_castShadows; }
|
||
|
||
void SetShadowResolution(uint32_t resolution) { m_shadowResolution = resolution; }
|
||
uint32_t GetShadowResolution() const { return m_shadowResolution; }
|
||
|
||
void SetCullingMask(int32_t mask) { m_cullingMask = mask; }
|
||
int32_t GetCullingMask() const { return m_cullingMask; }
|
||
|
||
private:
|
||
LightType m_type = LightType::Point;
|
||
Vector3 m_color = Vector3::One();
|
||
float m_intensity = 1.0f;
|
||
float m_range = 10.0f;
|
||
float m_spotAngle = 30.0f;
|
||
float m_penumbraAngle = 5.0f;
|
||
bool m_castShadows = true;
|
||
uint32_t m_shadowResolution = 1024;
|
||
float m_shadowBias = 0.005f;
|
||
float m_normalOffsetBias = 0.001f;
|
||
float m_nearPlane = 0.1f;
|
||
int32_t m_cullingMask = -1;
|
||
float m_intensityVariation = 0.0f;
|
||
ResourceGUID m_cookieTextureGuid = ResourceGUID::Invalid;
|
||
float m_cookieSize = 5.0f;
|
||
};
|
||
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
### 4.5 渲染网格组件
|
||
|
||
```cpp
|
||
namespace XCEngine {
|
||
|
||
class RenderMeshComponent : public Component {
|
||
public:
|
||
void Awake() override;
|
||
void Start() override;
|
||
void Update(float deltaTime) override;
|
||
|
||
ResourceGUID GetMesh() const { return m_meshGuid; }
|
||
void SetMesh(const ResourceGUID& guid);
|
||
|
||
ResourceGUID GetMaterial() const { return m_materialGuid; }
|
||
void SetMaterial(const ResourceGUID& guid);
|
||
|
||
bool GetCastShadows() const { return m_castShadows; }
|
||
void SetCastShadows(bool cast) { m_castShadows = cast; }
|
||
|
||
bool GetReceiveShadows() const { return m_receiveShadows; }
|
||
void SetReceiveShadows(bool receive) { m_receiveShadows = receive; }
|
||
|
||
private:
|
||
ResourceGUID m_meshGuid;
|
||
ResourceGUID m_materialGuid;
|
||
bool m_castShadows = true;
|
||
bool m_receiveShadows = true;
|
||
};
|
||
|
||
} // namespace XCEngine
|
||
```
|
||
|
||
---
|
||
|
||
## 第五章 目录结构
|
||
|
||
```
|
||
XCVolumeRenderer/
|
||
├── engine/ # 引擎核心库(静态库)
|
||
│ ├── CMakeLists.txt
|
||
│ ├── include/
|
||
│ │ └── XCGameEngine/
|
||
│ │ ├── Core/ # 核心基础
|
||
│ │ │ ├── Assert.h
|
||
│ │ │ ├── Event.h
|
||
│ │ │ ├── TypeTraits.h
|
||
│ │ │ └── UniquePtr.h
|
||
│ │ ├── Math/ # 数学库
|
||
│ │ │ ├── Vector2.h
|
||
│ │ │ ├── Vector3.h
|
||
│ │ │ ├── Vector4.h
|
||
│ │ │ ├── Matrix3.h
|
||
│ │ │ ├── Matrix4.h
|
||
│ │ │ ├── Quaternion.h
|
||
│ │ │ ├── Transform.h
|
||
│ │ │ ├── Color.h
|
||
│ │ │ ├── Ray.h
|
||
│ │ │ ├── Plane.h
|
||
│ │ │ ├── Sphere.h
|
||
│ │ │ ├── Box.h
|
||
│ │ │ └── Frustum.h
|
||
│ │ ├── Containers/ # 容器
|
||
│ │ │ ├── Array.h
|
||
│ │ │ ├── String.h
|
||
│ │ │ └── HashMap.h
|
||
│ │ ├── Memory/ # 内存管理
|
||
│ │ │ ├── Allocator.h
|
||
│ │ │ ├── LinearAllocator.h
|
||
│ │ │ ├── PoolAllocator.h
|
||
│ │ │ └── ProxyAllocator.h
|
||
│ │ ├── Threading/ # 线程
|
||
│ │ │ ├── Thread.h
|
||
│ │ │ ├── Mutex.h
|
||
│ │ │ ├── TaskSystem.h
|
||
│ │ │ └── Atomic.h
|
||
│ │ ├── Debug/ # 调试
|
||
│ │ │ ├── Logger.h
|
||
│ │ │ └── Profiler.h
|
||
│ │ ├── Components/ # 组件系统
|
||
│ │ │ ├── GameObject.h
|
||
│ │ │ ├── Component.h
|
||
│ │ │ ├── TransformComponent.h
|
||
│ │ │ ├── RenderMeshComponent.h
|
||
│ │ │ ├── RenderLightComponent.h
|
||
│ │ │ └── CameraComponent.h
|
||
│ │ ├── Scene/ # 场景系统
|
||
│ │ │ ├── Scene.h
|
||
│ │ │ └── SceneManager.h
|
||
│ │ ├── Renderer/ # 渲染系统
|
||
│ │ │ ├── Device.h
|
||
│ │ │ ├── Context.h
|
||
│ │ │ ├── SwapChain.h
|
||
│ │ │ ├── Buffer.h
|
||
│ │ │ ├── Texture.h
|
||
│ │ │ ├── Shader.h
|
||
│ │ │ ├── Pipeline.h
|
||
│ │ │ ├── RenderPass.h
|
||
│ │ │ ├── CommandList.h
|
||
│ │ │ ├── RenderGraph.h
|
||
│ │ │ └── RenderModule.h
|
||
│ │ └── XCGameEngine.h # 主头文件
|
||
│ ├── src/
|
||
│ │ ├── Core/
|
||
│ │ ├── Math/
|
||
│ │ ├── Components/
|
||
│ │ ├── Scene/
|
||
│ │ ├── Renderer/
|
||
│ │ └── ...
|
||
│ └── third_party/
|
||
│ ├── stb/
|
||
│ └── json/
|
||
│
|
||
├── runtime/ # 游戏运行时(独立可执行文件)
|
||
│ ├── CMakeLists.txt
|
||
│ ├── src/
|
||
│ │ ├── GameMain.cpp
|
||
│ │ └── EntryPoint.cpp
|
||
│ └── resources/
|
||
│
|
||
├── tools/ # 工具链
|
||
│ ├── ShaderCompiler/ # 着色器编译器
|
||
│ └── BuildTool/ # 构建打包工具
|
||
│
|
||
├── content/ # 资源内容
|
||
│ ├── Assets/
|
||
│ │ ├── Scenes/
|
||
│ │ ├── Materials/
|
||
│ │ ├── Meshes/
|
||
│ │ ├── Textures/
|
||
│ │ └── Shaders/
|
||
│ └── Library/
|
||
│
|
||
└── docs/ # 文档
|
||
```
|
||
|
||
---
|
||
|
||
## 附录:待扩展功能
|
||
|
||
以下功能将在后续迭代中添加:
|
||
|
||
1. **物理系统** - RigidBodyComponent, ColliderComponent, PhysicsWorld
|
||
2. **音频系统** - AudioSourceComponent, AudioListenerComponent, AudioEngine
|
||
3. **动画系统** - AnimatorComponent, AnimationClip, Skeleton
|
||
4. **粒子系统** - ParticleSystemComponent, GPUParticles
|
||
5. **UI系统** - CanvasComponent, ImageComponent, TextComponent, ButtonComponent
|
||
6. **网络系统** - NetworkIdentityComponent, NetworkTransformComponent
|
||
7. **完整编辑器** - HierarchyPanel, InspectorPanel, SceneViewPanel
|