52 KiB
52 KiB
XCVolumeRenderer - 渲染引擎架构设计文档
基于 XCGameEngine 架构提取的渲染引擎子集 版本: 1.0 日期: 2026-03-13 目标: 构建专业级实时体积渲染引擎
第一章 核心基础层
1.1 数学库 (Math Library)
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)
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)
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)
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 日志与调试系统
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 组件基类
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组件
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
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
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 渲染抽象层
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)
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 相机组件
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 光照组件
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 渲染网格组件
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/ # 文档
附录:待扩展功能
以下功能将在后续迭代中添加:
- 物理系统 - RigidBodyComponent, ColliderComponent, PhysicsWorld
- 音频系统 - AudioSourceComponent, AudioListenerComponent, AudioEngine
- 动画系统 - AnimatorComponent, AnimationClip, Skeleton
- 粒子系统 - ParticleSystemComponent, GPUParticles
- UI系统 - CanvasComponent, ImageComponent, TextComponent, ButtonComponent
- 网络系统 - NetworkIdentityComponent, NetworkTransformComponent
- 完整编辑器 - HierarchyPanel, InspectorPanel, SceneViewPanel