Files
XCEngine/docs/XCVolumeRenderer渲染引擎架构设计.md

52 KiB
Raw Blame History

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/                          # 文档

附录:待扩展功能

以下功能将在后续迭代中添加:

  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