Files
XCEngine/docs/used/XCEngine渲染引擎架构设计.md
2026-03-29 01:36:53 +08:00

127 KiB
Raw Blame History

XCEngine - 渲染引擎架构设计文档

借鉴 Unity 渲染架构概念设计


渲染流程图

┌─────────────────────────────────────────────────────────────────────────────────────┐
│                              渲染流程                                                │
└─────────────────────────────────────────────────────────────────────────────────────┘

┌─────────────┐     ┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│   Scene     │────▶│  Culling    │────▶│ RenderQueue │────▶│  Renderer   │
│   场景数据   │     │   System    │     │   渲染队列   │     │   渲染器    │
└─────────────┘     └─────────────┘     └─────────────┘     └─────────────┘
                            │                   │                   │
                            ▼                   │                   ▼
                     ┌─────────────┐            │           ┌─────────────┐
                     │CullingResults│◀──────────┘           │  CommandList │
                     │  剔除结果    │     PrepareRender      │  命令列表    │
                     └─────────────┘     QueueEntries        └─────────────┘
                                                                 │
                                                                 ▼
┌─────────────┐     ┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│   Camera    │────▶│ LightManager│────▶│   Pass      │────▶│   GPU       │
│   相机      │     │   光照管理   │     │   渲染通道   │     │   GPU执行   │
└─────────────┘     └─────────────┘     └─────────────┘     └─────────────┘
                            │                     │
                            ▼                     ▼
                     ┌─────────────┐     ┌─────────────┐
                     │ ShadowAtlas │     │  Material   │
                     │   阴影图集   │     │    材质     │
                     └─────────────┘     └─────────────┘

流程说明:
1. Scene 提供场景数据GameObjects, Components
2. CullingSystem 执行视锥剔除,产出 CullingResults
3. RenderQueue 根据 CullingResults 准备渲染项Renderer::PrepareRenderQueueEntries
4. Renderer 遍历 RenderQueue通过 CommandList 提交绘制命令
5. LightManager/ShadowAtlas 处理光照和阴影
6. 最终 GPU 执行渲染命令
┌─────────────────────────────────────────────────────────────────────────────────────┐
│                           RHI 抽象层架构                                             │
└─────────────────────────────────────────────────────────────────────────────────────┘

                                    ┌─────────────────┐
                                    │   RHISystem     │  渲染系统入口
                                    └────────┬────────┘
                                             │
                     ┌───────────────────────┼───────────────────────┐
                     │                       │                       │
              ┌──────▼──────┐      ┌──────▼──────┐      ┌──────▼──────┐
              │ D3D12Device │      │  D3D11Device │      │ VulkanDevice │
              └──────┬──────┘      └──────┬──────┘      └──────┬──────┘
                     │                       │                       │
                     └───────────────────────┼───────────────────────┘
                                             │
                                    ┌────────▼────────┐
                                    │   IRHIDevice   │  抽象设备接口
                                    └────────┬────────┘
                                             │
         ┌──────────────────────────────────┼──────────────────────────────────┐
         │              │              │      │      │              │              │
    ┌────▼────┐  ┌───▼────┐ ┌────▼┐ ┌──▼────┐ ┌───▼───┐ ┌───▼────┐ ┌──▼────┐
    │CommandQueue│  │Descriptor│ │Fence│ │SwapChain│ │RootSig│ │PSO    │ │Texture│
    │ 命令队列  │  │Heap    │ │围栏 │ │交换链 │ │根签名 │ │管线状态│ │纹理   │
    └──────────┘  └────────┘ └─────┘ └────────┘ └───────┘ └───────┘ └───────┘

重要声明:本架构借鉴 Unity 渲染系统的核心概念与设计模式,包括:

  • CullingResults / CullingSystem - 剔除系统概念来自Unity SRP API
  • RenderPipeline / RenderPipelineManager - 渲染管线
  • RenderQueue / RenderQueueEntry - 渲染队列
  • Renderer - 渲染器核心
  • ScriptableRenderContext - 渲染上下文
  • Shader / Pass / Material - 着色器与材质
  • LightManager / ShadowAtlas - 光照与阴影管理

Unity底层C++渲染架构未公开本设计基于公开API概念与通用渲染引擎模式实现。

版本: 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 {
    float m[3][3];
    
    static Matrix3x3 Identity() {
        Matrix3x3 result{};
        result.m[0][0] = 1.0f; result.m[1][1] = 1.0f; result.m[2][2] = 1.0f;
        return result;
    }
    
    static Matrix3x3 Zero() {
        Matrix3x3 result{};
        return result;
    }
    
    Matrix3x3 operator*(const Matrix3x3& other) const;
    Vector3 operator*(const Vector3& v) const;
    Matrix3x3 Transpose() const;
    Matrix3x3 Inverse() const;
    float Determinant() const;
};

struct Matrix4x4 {
    float m[4][4];
    
    static Matrix4x4 Identity() {
        Matrix4x4 result{};
        result.m[0][0] = 1.0f; result.m[1][1] = 1.0f; 
        result.m[2][2] = 1.0f; result.m[3][3] = 1.0f;
        return result;
    }
    
    static Matrix4x4 Zero() {
        Matrix4x4 result{};
        return result;
    }
    
    static Matrix4x4 Translation(const Vector3& v);
    static Matrix4x4 Rotation(const Quaternion& q);
    static Matrix4x4 Scale(const Vector3& v);
    static Matrix4x4 TRS(const Vector3& translation, const Quaternion& rotation, const Vector3& scale);
    static Matrix4x4 LookAt(const Vector3& eye, const Vector3& target, const Vector3& up);
    static Matrix4x4 Perspective(float fov, float aspect, float near, float far);
    static Matrix4x4 Orthographic(float left, float right, float bottom, float top, float near, float far);
    
    Matrix4x4 operator*(const Matrix4x4& other) const;
    Vector4 operator*(const Vector4& v) const;
    Vector3 MultiplyPoint(const Vector3& v) const;
    Vector3 MultiplyVector(const Vector3& v) const;
    
    Matrix4x4 Transpose() const;
    Matrix4x4 Inverse() const;
    float Determinant() const;
    
    Vector3 GetTranslation() const;
    Quaternion GetRotation() const;
    Vector3 GetScale() const;
    
    void Decompose(Vector3& translation, Quaternion& rotation, Vector3& scale) const;
};

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);
};

class Mutex {
public:
    Mutex() = default;
    ~Mutex() = default;
    
    void Lock();
    void Unlock();
    bool TryLock();
    
private:
    std::mutex m_mutex;
};

class SpinLock {
public:
    void Lock();
    void Unlock();
    bool TryLock();
    
private:
    std::atomic_flag m_flag = ATOMIC_FLAG_INIT;
};

class ReadWriteLock {
public:
    void ReadLock();
    void ReadUnlock();
    void WriteLock();
    void WriteUnlock();
    
private:
    std::mutex m_mutex;
    std::condition_variable m_readCondition;
    std::condition_variable m_writeCondition;
    int32_t m_readers = 0;
    int32_t m_writersWaiting = 0;
    bool m_writerActive = false;
};

class Thread {
public:
    using Id = uint64_t;
    
    Thread();
    ~Thread();
    
    template<typename Func>
    void Start(Func&& func, const String& name = "Thread");
    void Join();
    void Detach();
    
    Id GetId() const { return m_id; }
    const String& GetName() const { return m_name; }
    
    static Id GetCurrentId();
    static void Sleep(uint32_t milliseconds);
    static void Yield();
    
private:
    Id m_id = 0;
    String m_name;
    std::thread m_thread;
};

} // 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 {
        std::vector<Listener> listenersCopy;
        {
            std::lock_guard<std::mutex> lock(m_mutex);
            if (!m_pendingUnsubscribes.empty()) {
                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();
            }
            listenersCopy = m_listeners;
        }
        for (const auto& [id, callback] : listenersCopy) {
            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;
    
    std::unique_ptr<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 = std::make_unique<TransformComponent>();
    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;
    template<typename T>
    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

第四章 渲染系统

借鉴 Unity 渲染架构设计

4.0 公共类型定义

namespace XCEngine {
namespace Rendering {

// ============================================
// 前置类型定义 - 资源基类
// ============================================

enum class ResourceLoadState {
    Undefined,
    Unloaded,
    Loading,
    Loaded,
    Unloading,
    Failed
};

enum class ResourceType {
    Mesh,
    Texture,
    Shader,
    Material,
    ComputeBuffer,
    GraphicsBuffer,
    Sampler,
    RenderTarget,
    DepthStencil,
    VertexBuffer,
    IndexBuffer,
    Unknown
};

class IResource {
public:
    virtual ~IResource() = default;

    virtual void SetName(const std::string& name) { m_name = name; }
    virtual const std::string& GetName() const { return m_name; }

    virtual ResourceType GetType() const = 0;
    virtual ResourceLoadState GetLoadState() const { return m_loadState; }

    virtual bool IsValid() const { return m_loadState == ResourceLoadState::Loaded; }
    virtual void Load() = 0;
    virtual void Unload() = 0;

    virtual int GetRefCount() const { return m_refCount.load(); }
    virtual void AddRef() { m_refCount.fetch_add(1); }
    virtual void Release() { 
        if (m_refCount.fetch_sub(1) == 1) {
            delete this;
        }
    }

protected:
    IResource() : m_loadState(ResourceLoadState::Unloaded), m_memoryUsage(0) {}

    std::string m_name;
    ResourceLoadState m_loadState;
    uint64_t m_memoryUsage;
    std::atomic<int32_t> m_refCount{1};
};

// ============================================
// 缓冲区类型定义
// ============================================

class VertexBuffer : public IResource {
public:
    ResourceType GetType() const override { return ResourceType::VertexBuffer; }
    
    void Load() override {}
    void Unload() override {}
    
    uint32_t GetVertexCount() const { return m_vertexCount; }
    uint32_t GetStride() const { return m_stride; }
    uint64_t GetSize() const { return m_size; }
    
    void SetData(const void* data, uint64_t size);
    void* Map();
    void Unmap();
    
private:
    uint32_t m_vertexCount = 0;
    uint32_t m_stride = 0;
    uint64_t m_size = 0;
    void* m_nativeHandle = nullptr;
};

class IndexBuffer : public IResource {
public:
    ResourceType GetType() const override { return ResourceType::IndexBuffer; }
    
    void Load() override {}
    void Unload() override {}
    
    uint32_t GetIndexCount() const { return m_indexCount; }
    bool Is32Bit() const { return m_is32Bit; }
    uint64_t GetSize() const { return m_size; }
    
    void SetData(const void* data, uint64_t size);
    void* Map();
    void Unmap();
    
private:
    uint32_t m_indexCount = 0;
    bool m_is32Bit = false;
    uint64_t m_size = 0;
    void* m_nativeHandle = nullptr;
};

// ============================================
// 渲染目标类型定义
// ============================================

struct RenderTargetDesc {
    uint32_t width = 0;
    uint32_t height = 0;
    Format format = Format::R8G8B8A8_UNorm;
    SampleCount sampleCount = SampleCount::Count1;
    uint32_t mipLevels = 1;
    uint32_t arraySize = 1;
    bool enableUAV = false;
    String name;
};

class RenderTarget : public IResource {
public:
    ResourceType GetType() const override { return ResourceType::RenderTarget; }
    
    void Load() override {}
    void Unload() override {}
    
    uint32_t GetWidth() const { return m_width; }
    uint32_t GetHeight() const { return m_height; }
    Format GetFormat() const { return m_format; }
    
    void* GetNativeHandle() const { return m_nativeHandle; }
    
    IShaderResourceView* GetSRV() { return m_srv.get(); }
    IRenderTargetView* GetRTV() { return m_rtv.get(); }
    
private:
    uint32_t m_width = 0;
    uint32_t m_height = 0;
    Format m_format;
    void* m_nativeHandle = nullptr;
    std::unique_ptr<IShaderResourceView> m_srv;
    std::unique_ptr<IRenderTargetView> m_rtv;
};

struct DepthStencilDesc {
    uint32_t width = 0;
    uint32_t height = 0;
    Format format = Format::D24_UNorm_S8_UInt;
    SampleCount sampleCount = SampleCount::Count1;
    bool bindAsShaderResource = false;
    String name;
};

class DepthStencil : public IResource {
public:
    ResourceType GetType() const override { return ResourceType::DepthStencil; }
    
    void Load() override {}
    void Unload() override {}
    
    uint32_t GetWidth() const { return m_width; }
    uint32_t GetHeight() const { return m_height; }
    Format GetFormat() const { return m_format; }
    
    void* GetNativeHandle() const { return m_nativeHandle; }
    
    IDepthStencilView* GetDSV() { return m_dsv.get(); }
    IShaderResourceView* GetSRV() { return m_srv.get(); }
    
private:
    uint32_t m_width = 0;
    uint32_t m_height = 0;
    Format m_format;
    void* m_nativeHandle = nullptr;
    std::unique_ptr<IDepthStencilView> m_dsv;
    std::unique_ptr<IShaderResourceView> m_srv;
};

// ============================================
// 渲染通道描述
// ============================================

struct RenderPassAttachmentDesc {
    RenderTarget* renderTarget = nullptr;
    DepthStencil* depthStencil = nullptr;
    LoadAction loadAction = LoadAction::Clear;
    StoreAction storeAction = StoreAction::Store;
    Color clearColor = Color::Black();
    float clearDepth = 1.0f;
    uint8_t clearStencil = 0;
};

struct RenderPassDesc {
    RenderPassAttachmentDesc* colorAttachments = nullptr;
    uint32_t colorAttachmentCount = 0;
    RenderPassAttachmentDesc* depthStencilAttachment = nullptr;
    Rect viewport;
    Rect scissor;
};

// ============================================
// 基础枚举类型
// ============================================

enum class Format {
    Unknown = 0,
    R8_UNorm = 61,
    R8G8_UNorm = 49,
    R8G8B8A8_UNorm = 28,
    R16G16B16A16_Float = 10,
    R32G32B32A32_Float = 2,
    R16_Float = 54,
    R32_Float = 41,
    D16_UNorm = 55,
    D24_UNorm_S8_UInt = 45,
    D32_Float = 40,
    BC1_UNorm = 71,
    BC2_UNorm = 74,
    BC3_UNorm = 77,
    BC4_UNorm = 80,
    BC5_UNorm = 83,
    BC6H_UF16 = 95,
    BC7_UNorm = 98
};

enum class SampleCount : uint32_t {
    Count1 = 1,
    Count2 = 2,
    Count4 = 4,
    Count8 = 8
};

enum class CubemapFace : uint8_t {
    PositiveX = 0,
    NegativeX = 1,
    PositiveY = 2,
    NegativeY = 3,
    PositiveZ = 4,
    NegativeZ = 5
};

struct Frustum {
    Plane planes[6];
    
    bool Contains(const Vector3& point) const;
    bool Contains(const Sphere& sphere) const;
    bool Contains(const Bounds& bounds) const;
    bool Intersects(const Bounds& bounds) const;
};

enum class FilterMode {
    Point = 0,
    Bilinear = 1,
    Trilinear = 2
};

enum class TextureWrapMode {
    Repeat = 0,
    Clamp = 1,
    Mirror = 2,
    MirrorOnce = 3
};

enum class MeshTopology {
    Points,
    Lines,
    LineStrip,
    Triangles,
    TriangleStrip,
    Quads
};

struct Bounds {
    Vector3 center;
    Vector3 extents;
    Vector3 min;
    Vector3 max;
    
    Bounds() : center(Vector3::Zero()), extents(Vector3::Zero()) {}
    Bounds(const Vector3& center, const Vector3& size) 
        : center(center), extents(size * 0.5f) {
        min = center - extents;
        max = center + extents;
    }
    
    void SetMinMax(const Vector3& min, const Vector3& max) {
        this->min = min;
        this->max = max;
        center = (min + max) * 0.5f;
        extents = (max - min) * 0.5f;
    }
    
    bool Intersects(const Bounds& other) const;
    bool Contains(const Vector3& point) const;
    
    void Encapsulate(const Vector3& point);
    void Encapsulate(const Bounds& bounds);
    
    void Expand(float amount);
    void Expand(const Vector3& amount);
    
    Vector3 GetClosestPoint(const Vector3& point) const;
};

struct QualityLevel {
    enum {
        Fastest = 0,
        Fast = 1,
        Simple = 2,
        Good = 3,
        High = 4,
        Ultra = 5
    };
};

class StringView {
public:
    StringView() : m_data(nullptr), m_length(0) {}
    StringView(const char* str);
    StringView(const char* str, size_t len);
    StringView(const String& str);
    
    const char* Data() const { return m_data; }
    size_t Length() const { return m_length; }
    
    bool Empty() const { return m_length == 0; }
    
    char operator[](size_t index) const { return m_data[index]; }
    
    int Compare(const StringView& other) const;
    bool operator==(const StringView& other) const;
    bool operator!=(const StringView& other) const;
    
private:
    const char* m_data;
    size_t m_length;
};

class Texture {
public:
    virtual ~Texture() = default;
    
    uint32_t GetWidth() const { return m_width; }
    uint32_t GetHeight() const { return m_height; }
    uint32_t GetDepth() const { return m_depth; }
    uint32_t GetMipLevels() const { return m_mipLevels; }
    Format GetFormat() const { return m_format; }
    
    FilterMode GetFilterMode() const { return m_filterMode; }
    void SetFilterMode(FilterMode mode) { m_filterMode = mode; }
    
    TextureWrapMode GetWrapMode() const { return m_wrapMode; }
    void SetWrapMode(TextureWrapMode mode) { m_wrapMode = mode; }
    
    void* GetNativeHandle() const { return m_nativeHandle; }
    
protected:
    uint32_t m_width = 0;
    uint32_t m_height = 0;
    uint32_t m_depth = 1;
    uint32_t m_mipLevels = 1;
    Format m_format = Format::R8G8B8A8_UNorm;
    FilterMode m_filterMode = FilterMode::Bilinear;
    TextureWrapMode m_wrapMode = TextureWrapMode::Clamp;
    void* m_nativeHandle = nullptr;
};

class RenderTargetIdentifier {
public:
    RenderTargetIdentifier();
    RenderTargetIdentifier(int nameID);
    RenderTargetIdentifier(const String& name);
    RenderTargetIdentifier(Texture* texture);
    
    bool IsValid() const { return m_type != Buffer || m_nameID != -1; }
    bool operator==(const RenderTargetIdentifier& other) const;
    bool operator!=(const RenderTargetIdentifier& other) const { return !(*this == other); }
    
    int GetType() const { return m_type; }
    int GetNameID() const { return m_nameID; }
    Texture* GetTexture() const { return m_texture; }
    
private:
    int m_type = Buffer;
    int m_nameID = -1;
    Texture* m_texture = nullptr;
    
    enum { Buffer, Texture2D, RenderTarget };
};

class CommandBuffer {
public:
    CommandBuffer();
    ~CommandBuffer();
    
    void Clear();
    void BeginSample(const char* name);
    void EndSample(const char* name);
    void BeginDebugGroup(const char* name);
    void EndDebugGroup();
    
    void SetRenderTarget(
        RenderTargetIdentifier colorTarget,
        RenderTargetIdentifier depthTarget,
        int mipLevel = 0,
        CubemapFace cubemapFace = CubemapFace::PositiveX,
        bool depthIsWritable = true
    );
    
    void SetRenderTarget(
        const std::vector<RenderTargetIdentifier>& colorTargets,
        RenderTargetIdentifier depthTarget,
        int mipLevel = 0,
        CubemapFace cubemapFace = CubemapFace::PositiveX,
        bool depthIsWritable = true
    );
    
    void SetViewport(const Rect& rect);
    void SetScissor(const Rect& rect);
    
    void SetViewMatrix(const Matrix4x4& matrix);
    void SetProjectionMatrix(const Matrix4x4& matrix);
    
    void DrawMeshInstanced(
        const Mesh& mesh,
        int submeshIndex,
        Material* material,
        int shaderPass,
        const std::vector<Matrix4x4>& matrices
    );
    
    void DrawMeshInstancedIndirect(
        const Mesh& mesh,
        int submeshIndex,
        Material* material,
        int shaderPass,
        const ComputeBuffer& argsBuffer,
        int argsOffset
    );
    
    void DrawProcedural(
        Material* material,
        int shaderPass,
        MeshTopology topology,
        int vertexCount,
        int instanceCount
    );
    
    void Blit(
        Material* material,
        int pass,
        RenderTargetIdentifier source,
        RenderTargetIdentifier dest
    );
    
    void CopyTexture(
        RenderTargetIdentifier source,
        RenderTargetIdentifier dest
    );
    
    void GetTemporaryRT(
        const String& name,
        int width,
        int height,
        Format format = Format::R8G8B8A8_UNorm,
        FilterMode filter = FilterMode::Bilinear,
        TextureWrapMode wrap = TextureWrapMode::Clamp,
        int depthBufferBits = 0
    );
    
    void ReleaseTemporaryRT(const String& name);
    
    void GetCommandBufferPtr(void** ptr);
    
private:
    std::vector<uint8_t> m_data;
    std::vector<std::string> m_sampleNames;
    int m_sampleDepth = 0;
};

class Mesh : public IResource {
public:
    Mesh();
    ~Mesh();
    
    void SetVertices(const std::vector<Vector3>& vertices);
    void SetNormals(const std::vector<Vector3>& normals);
    void SetTangents(const std::vector<Vector4>& tangents);
    void SetUVs(int channel, const std::vector<Vector2>& uvs);
    void SetUVs(int channel, const std::vector<Vector3>& uvs);
    void SetTriangles(const std::vector<uint32_t>& triangles, int submesh);
    void SetIndices(const std::vector<uint16_t>& indices, int submesh);
    void SetIndices(const std::vector<uint32_t>& indices, int submesh);
    
    const std::vector<Vector3>& GetVertices() const { return m_vertices; }
    const std::vector<Vector3>& GetNormals() const { return m_normals; }
    const std::vector<Vector4>& GetTangents() const { return m_tangents; }
    
    int GetSubmeshCount() const { return m_submeshes.size(); }
    const struct SubmeshDescriptor& GetSubmesh(int index) const;
    
    int GetVertexCount() const { return static_cast<int>(m_vertices.size()); }
    int GetIndexCount(int submesh) const;
    
    MeshTopology GetTopology(int submesh) const;
    void SetTopology(MeshTopology topology, int submesh);
    
    void RecalculateNormals();
    void RecalculateTangents();
    void RecalculateBounds();
    
    void Optimize();
    
    bool IsUse32BitIndexBuffer() const { return m_use32BitIndex; }
    
    struct MeshData {
        std::vector<Vector3> vertices;
        std::vector<Vector3> normals;
        std::vector<Vector4> tangents;
        std::vector<Vector4> uvs[8];
        std::vector<uint32_t> indices32;
        std::vector<uint16_t> indices16;
    };
    void GetMeshData(MeshData& data) const;
    
private:
    std::vector<Vector3> m_vertices;
    std::vector<Vector3> m_normals;
    std::vector<Vector4> m_tangents;
    std::vector<Vector4> m_uvs[8];
    
    struct SubmeshDescriptor {
        int indexStart;
        int indexCount;
        int baseVertex;
        MeshTopology topology;
    };
    std::vector<SubmeshDescriptor> m_submeshes;
    
    Bounds m_bounds;
    bool m_use32BitIndex = false;
    bool m_hasVertices = false;
    bool m_hasNormals = false;
    bool m_hasTangents = false;
    
    friend class MeshCollider;
    friend class SkinnedMeshRenderer;
};

class ComputeBuffer : public IResource {
public:
    enum class Type {
        Default,
        Raw,
        Append,
        Counter,
        Structured,
        ByteAddress
    };
    
    ComputeBuffer(Type type, int count, int stride);
    ~ComputeBuffer();
    
    int GetCount() const { return m_count; }
    int GetStride() const { return m_stride; }
    Type GetType() const { return m_type; }
    
    void SetData(const void* data);
    void GetData(void* data) const;
    
    void SetCounterValue(uint32_t value);
    uint32_t GetCounterValue() const;
    
private:
    Type m_type;
    int m_count;
    int m_stride;
    void* m_buffer;
};

class GraphicsBuffer : public IResource {
public:
    enum class Target {
        Constant,
        IndexBuffer,
        VertexBuffer,
        Structured,
        Append,
        Counter,
        ReadWrite
    };
    
    GraphicsBuffer(Target target, uint32_t count, uint32_t stride);
    virtual ~GraphicsBuffer();
    
    Target GetTarget() const { return m_target; }
    uint32_t GetCount() const { return m_count; }
    uint32_t GetStride() const { return m_stride; }
    uint64_t GetSize() const { return m_size; }
    
    void SetData(const void* data);
    void GetData(void* data) const;
    
    void* Map();
    void Unmap();
    
    void SetCounterValue(uint32_t value);
    uint32_t GetCounterValue() const;
    
private:
    Target m_target;
    uint32_t m_count = 0;
    uint32_t m_stride = 0;
    uint64_t m_size = 0;
    void* m_buffer;
};

struct ShaderProgramDesc {
    enum class Stage {
        Vertex,
        Fragment,
        Compute,
        Geometry,
        Hull,
        Domain
    };
    
    Stage stage;
    String source;
    String entryPoint;
    
    bool debug = false;
    bool optimize = true;
};

} // namespace Rendering
} // namespace XCEngine

4.1 RHI 抽象层接口

namespace XCEngine {
namespace RHI {

// ============================================
// 跨平台枚举类型 - 不暴露平台特定类型
// ============================================

enum class GraphicsAPI {
    Unknown,
    Direct3D11,
    Direct3D12,
    Vulkan,
    Metal,
    OpenGL
};

enum class CommandListType {
    Direct,
    Compute,
    Copy,
    Bundle
};

enum class ShaderVisibility {
    All = 0,
    Vertex = 1,
    Hull = 2,
    Domain = 3,
    Geometry = 4,
    Pixel = 5,
    Amplification = 6,
    Mesh = 7
};

enum class ResourceStateFlag : uint32_t {
    Common = 0,
    VertexBuffer = 1 << 0,
    ConstantBuffer = 1 << 1,
    IndexBuffer = 1 << 2,
    RenderTarget = 1 << 3,
    UnorderedAccess = 1 << 4,
    DepthWrite = 1 << 5,
    DepthRead = 1 << 6,
    ShaderResource = 1 << 7,
    IndirectArgument = 1 << 8,
    CopyDest = 1 << 9,
    CopySource = 1 << 10,
    ResolveDest = 1 << 11,
    ResolveSource = 1 << 12,
    Present = 1 << 13,
    RaytracingAccelerationStructure = 1 << 14,
    ShadingRateSource = 1 << 15
};

inline ResourceStateFlag operator|(ResourceStateFlag a, ResourceStateFlag b) {
    return static_cast<ResourceStateFlag>(static_cast<uint32_t>(a) | static_cast<uint32_t>(b));
}

inline ResourceStateFlag operator&(ResourceStateFlag a, ResourceStateFlag b) {
    return static_cast<ResourceStateFlag>(static_cast<uint32_t>(a) & static_cast<uint32_t>(b));
}

enum class DescriptorHeapType {
    CBV_SRV_UAV,
    Sampler,
    RTV,
    DSV
};

enum class QueryType {
    Occlusion,
    Timestamp,
    PipelineStatistics
};

// ============================================
// 描述结构体
// ============================================

struct CommandQueueDesc {
    CommandListType type = CommandListType::Direct;
    int priority = 0;
    const char* name = nullptr;
};

struct DescriptorHeapDesc {
    DescriptorHeapType type;
    uint32_t count;
    bool shaderVisible;
    const char* name;
};

struct QueryHeapDesc {
    QueryType type;
    uint32_t count;
    const char* name;
};

struct SwapChainDesc {
    uint32_t width;
    uint32_t height;
    Format format;
    uint32_t bufferCount;
    bool vsync;
    bool fullscreen;
};

class ICommandQueue {
public:
    virtual ~ICommandQueue() = default;
    
    virtual void ExecuteCommandLists(ICommandList** lists, uint32_t count) = 0;
    virtual void Signal(IFence* fence, uint64_t value) = 0;
    virtual void Wait(IFence* fence, uint64_t value) = 0;
    
    virtual uint64_t GetTimestampFrequency() const = 0;
};

class ICommandAllocator {
public:
    virtual ~ICommandAllocator() = default;
    virtual void Reset() = 0;
};

class IFence {
public:
    virtual ~IFence() = default;
    
    virtual uint64_t GetCompletedValue() const = 0;
    virtual void Signal(uint64_t value) = 0;
    virtual void Wait(uint64_t value) = 0;
    virtual void Wait(uint64_t value, uint64_t timeoutMs) = 0;
};

class IDescriptorHeap {
public:
    virtual ~IDescriptorHeap() = default;
    
    virtual DescriptorHeapType GetType() const = 0;
    virtual uint32_t GetDescriptorCount() const = 0;
    
    virtual void* GetCPUDescriptorHandle(uint32_t index) const = 0;
    virtual uint64_t GetGPUDescriptorHandle(uint32_t index) const = 0;
    
    virtual void SetName(const String& name) = 0;
};

class IQueryHeap {
public:
    virtual ~IQueryHeap() = default;
    
    virtual QueryType GetType() const = 0;
    virtual uint32_t GetCount() const = 0;
    
    virtual void Begin(ICommandList* cmdList, uint32_t index) = 0;
    virtual void End(ICommandList* cmdList, uint32_t index) = 0;
    virtual void GetData(uint32_t index, void* data, uint32_t dataSize) = 0;
};

class ISwapChain {
public:
    virtual ~ISwapChain() = default;
    
    virtual bool Initialize(const SwapChainDesc& desc, void* windowHandle) = 0;
    virtual void Shutdown() = 0;
    
    virtual bool Present() = 0;
    virtual bool Resize(uint32_t width, uint32_t height) = 0;
    
    virtual uint32_t GetCurrentBufferIndex() const = 0;
    virtual RenderTexture* GetBuffer(uint32_t index) = 0;
    
    virtual void SetFullscreen(bool fullscreen) = 0;
    virtual bool IsFullscreen() const = 0;
};

struct RootParameter {
    enum class Type { DescriptorTable, Constants, CBV, SRV, UAV, Sampler };
    Type type;
    uint32_t shaderRegister;
    uint32_t registerSpace;
    ShaderVisibility visibility = ShaderVisibility::All;
};

struct RootSignatureDesc {
    RootParameter* parameters;
    uint32_t parameterCount;
    uint32_t flags;
};

class RootSignature {
public:
    virtual ~RootSignature() = default;
    virtual bool Initialize(const RootSignatureDesc& desc) = 0;
    virtual void SetName(const String& name) = 0;
};

struct PipelineDesc {
    RootSignature* rootSignature;
    Shader* vertexShader;
    Shader* pixelShader;
    Shader* computeShader;
    RenderState renderState;
    uint32_t numRenderTargets;
    Format rtvFormats[8];
    Format dsvFormat;
};

class PipelineStateObject {
public:
    virtual ~PipelineStateObject() = default;
    virtual void SetName(const String& name) = 0;
};

class ICommandList {
public:
    virtual ~ICommandList() = default;
    
    virtual void Reset(ICommandAllocator* allocator) = 0;
    virtual void Close() = 0;
    
    virtual void BeginRenderPass(const RenderPassDesc& desc) = 0;
    virtual void EndRenderPass() = 0;
    
    virtual void SetPipelineState(PipelineStateObject* pso) = 0;
    virtual void SetRootSignature(RootSignature* signature) = 0;
    
    virtual void SetVertexBuffer(uint32_t slot, VertexBuffer* buffer, uint32_t offset = 0) = 0;
    virtual void SetIndexBuffer(IndexBuffer* buffer, uint32_t offset = 0) = 0;
    
    virtual void SetDescriptorHeap(IDescriptorHeap* heap) = 0;
    virtual void SetGraphicsDescriptorTable(uint32_t rootParameterIndex, uint64_t baseDescriptor) = 0;
    virtual void SetComputeDescriptorTable(uint32_t rootParameterIndex, uint64_t baseDescriptor) = 0;
    
    virtual void DrawInstanced(uint32_t vertexCountPerInstance, uint32_t instanceCount,
                               uint32_t startVertex, uint32_t startInstance) = 0;
    virtual void DrawIndexedInstanced(uint32_t indexCountPerInstance, uint32_t instanceCount,
                                      uint32_t startIndex, int32_t baseVertex, uint32_t startInstance) = 0;
    virtual void Dispatch(uint32_t x, uint32_t y, uint32_t z) = 0;
    
    virtual void SetViewports(const Viewport* viewports, uint32_t count) = 0;
    virtual void SetScissorRects(const Rect* rects, uint32_t count) = 0;
    virtual void SetRenderTargets(const RenderTarget* const* targets, uint32_t count,
                                  const DepthStencil* depthStencil) = 0;
    
    virtual void ClearRenderTargetView(const RenderTarget* target, const float color[4]) = 0;
    virtual void ClearDepthStencilView(const DepthStencil* depth, float depthValue, uint8_t stencil) = 0;
    
    virtual void CopyResource(IResource* dst, const IResource* src) = 0;
    virtual void CopyBuffer(IResource* dst, uint64_t dstOffset, const IResource* src,
                           uint64_t srcOffset, uint64_t size) = 0;
    
    virtual void ResourceBarrier(IResource* resource, ResourceStateFlag before,
                                  ResourceStateFlag after) = 0;
};

class IShaderResourceView {
public:
    virtual ~IShaderResourceView() = default;
};

class IRenderTargetView {
public:
    virtual ~IRenderTargetView() = default;
};

class IDepthStencilView {
public:
    virtual ~IDepthStencilView() = default;
};

class IRHIDevice {
public:
    virtual ~IRHIDevice() = default;
    
    virtual GraphicsAPI GetAPI() const = 0;
    virtual const char* GetAPIName() const = 0;
    
    virtual bool Initialize() = 0;
    virtual void Shutdown() = 0;
    
    virtual bool CreateCommandQueue(ICommandQueue** queue, const CommandQueueDesc& desc) = 0;
    virtual bool CreateCommandAllocator(ICommandAllocator** allocator) = 0;
    virtual bool CreateCommandList(ICommandList** list, ICommandAllocator* allocator) = 0;
    virtual bool CreateFence(IFence** fence) = 0;
    
    virtual bool CreateDescriptorHeap(IDescriptorHeap** heap, const DescriptorHeapDesc& desc) = 0;
    virtual bool CreateQueryHeap(IQueryHeap** heap, const QueryHeapDesc& desc) = 0;
    
    virtual bool CreateRootSignature(RootSignature** signature, const RootSignatureDesc& desc) = 0;
    virtual bool CreatePipelineState(PipelineStateObject** pso, const PipelineDesc& desc) = 0;
    
    virtual bool CreateSwapChain(ISwapChain** swapChain, const SwapChainDesc& desc, void* windowHandle) = 0;
    virtual bool CreateRenderTarget(RenderTarget** target, const RenderTargetDesc& desc) = 0;
    virtual bool CreateDepthStencil(DepthStencil** depthStencil, const DepthStencilDesc& desc) = 0;
    
    virtual void* GetNativeDevice() const = 0;
};

} // namespace RHI
} // namespace XCEngine

4.3 Direct3D 12 特有的 RHI 实现

// ============================================
// D3D12 前向声明
// ============================================
struct ID3D12Device;
struct ID3D12CommandQueue;
struct ID3D12CommandAllocator;
struct ID3D12GraphicsCommandList;
struct ID3D12DescriptorHeap;
struct ID3D12RootSignature;
struct ID3D12PipelineState;
struct ID3D12Fence;
struct ID3D12QueryHeap;
struct IDXGISwapChain3;

template<typename T>
class ComPtr;

namespace XCEngine {
namespace RHI {
namespace D3D12 {

enum class D3D12_COMMAND_LIST_TYPE {
    DIRECT = 0,
    BUNDLE = 1,
    COMPUTE = 2,
    COPY = 3
};

enum class D3D12_DESCRIPTOR_HEAP_TYPE {
    CBV_SRV_UAV = 0,
    SAMPLER = 1,
    RTV = 2,
    DSV = 3,
    NUM_TYPES = 4
};

enum class D3D12_DESCRIPTOR_HEAP_FLAGS {
    NONE = 0,
    SHADER_VISIBLE = 1
};

enum class D3D12_RESOURCE_STATES {
    COMMON = 0,
    VERTEX_AND_CONSTANT_BUFFER = 0x1,
    INDEX_BUFFER = 0x2,
    RENDER_TARGET = 0x4,
    UNORDERED_ACCESS = 0x8,
    DEPTH_WRITE = 0x10,
    DEPTH_READ = 0x20,
    NON_PIXEL_SHADER_RESOURCE = 0x40,
    PIXEL_SHADER_RESOURCE = 0x80,
    STREAM_OUT = 0x100,
    INDIRECT_ARGUMENT = 0x200,
    COPY_DEST = 0x400,
    COPY_SOURCE = 0x800,
    RESOLVE_DEST = 0x1000,
    RESOLVE_SOURCE = 0x2000,
    RAYTRACING_ACCELERATION_STRUCTURE = 0x4000,
    SHADING_RATE_COARSE = 0x8000,
    SHADING_RATE_FINE = 0x10000,
    PRESENT = 0x0
};

enum class D3D12_SRV_DIMENSION {
    UNKNOWN = 0,
    BUFFER = 1,
    TEXTURE1D = 2,
    TEXTURE1DARRAY = 3,
    TEXTURE2D = 4,
    TEXTURE2DARRAY = 5,
    TEXTURE2DMS = 6,
    TEXTURE2DMSARRAY = 7,
    TEXTURE3D = 8,
    TEXTURECUBE = 9,
    TEXTURECUBEARRAY = 10
};

enum class D3D12_UAV_DIMENSION {
    UNKNOWN = 0,
    BUFFER = 1,
    TEXTURE1D = 2,
    TEXTURE1DARRAY = 3,
    TEXTURE2D = 4,
    TEXTURE2DARRAY = 5,
    TEXTURE3D = 8
};

enum class D3D12_RTV_DIMENSION {
    UNKNOWN = 0,
    BUFFER = 1,
    TEXTURE1D = 2,
    TEXTURE1DARRAY = 3,
    TEXTURE2D = 4,
    TEXTURE2DARRAY = 5,
    TEXTURE2DMS = 6,
    TEXTURE2DMSARRAY = 7,
    TEXTURE3D = 8
};

enum class D3D12_DSV_DIMENSION {
    UNKNOWN = 0,
    TEXTURE1D = 1,
    TEXTURE1DARRAY = 2,
    TEXTURE2D = 3,
    TEXTURE2DARRAY = 4,
    TEXTURE2DMS = 5,
    TEXTURE2DMSARRAY = 6
};

enum class D3D12_ROOT_SIGNATURE_FLAGS {
    NONE = 0,
    ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT = 0x1,
    DENY_VERTEX_SHADER_ROOT_ACCESS = 0x2,
    DENY_HULL_SHADER_ROOT_ACCESS = 0x4,
    DENY_DOMAIN_SHADER_ROOT_ACCESS = 0x8,
    DENY_GEOMETRY_SHADER_ROOT_ACCESS = 0x10,
    DENY_PIXEL_SHADER_ROOT_ACCESS = 0x20,
    ALLOW_STREAM_PIPELINE = 0x40,
    LOCAL_ROOT_SIGNATURE = 0x80
};

enum class D3D12_ROOT_PARAMETER_TYPE {
    DESCRIPTOR_TABLE = 0,
    _32BIT_CONSTANTS = 1,
    CBV = 2,
    SRV = 3,
    UAV = 4,
    SAMPLER = 5
};

enum class D3D12_SHADER_VISIBILITY {
    ALL = 0,
    VERTEX = 1,
    HULL = 2,
    DOMAIN = 3,
    GEOMETRY = 4,
    PIXEL = 5
};

enum class D3D12_FILTER {
    MIN_MAG_MIP_POINT = 0,
    MIN_MAG_POINT_MIP_LINEAR = 0x1,
    MIN_POINT_MAG_LINEAR_MIP_POINT = 0x2,
    MIN_POINT_MAG_MIP_LINEAR = 0x3,
    MIN_LINEAR_MAG_MIP_POINT = 0x4,
    MIN_LINEAR_MAG_POINT_MIP_LINEAR = 0x5,
    MIN_MAG_LINEAR_MIP_POINT = 0x6,
    MIN_MAG_MIP_LINEAR = 0x7,
    ANISOTROPIC = 0x15,
    COMPARISON_MIN_MAG_MIP_POINT = 0x80,
    COMPARISON_MIN_MAG_POINT_MIP_LINEAR = 0x81,
    COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT = 0x82,
    COMPARISON_MIN_POINT_MAG_MIP_LINEAR = 0x83,
    COMPARISON_MIN_LINEAR_MAG_MIP_POINT = 0x84,
    COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR = 0x85,
    COMPARISON_MIN_MAG_LINEAR_MIP_POINT = 0x86,
    COMPARISON_MIN_MAG_MIP_LINEAR = 0x87,
    COMPARISON_ANISOTROPIC = 0x95
};

enum class D3D12_TEXTURE_ADDRESS_MODE {
    WRAP = 1,
    MIRROR = 2,
    CLAMP = 3,
    BORDER = 4,
    MIRROR_ONCE = 5
};

enum class D3D12_COMPARISON_FUNC {
    NEVER = 1,
    LESS = 2,
    EQUAL = 3,
    LESS_EQUAL = 4,
    GREATER = 5,
    NOT_EQUAL = 6,
    GREATER_EQUAL = 7,
    ALWAYS = 8
};

enum class D3D12_BLEND {
    ZERO = 1,
    ONE = 2,
    SRC_COLOR = 3,
    INV_SRC_COLOR = 4,
    SRC_ALPHA = 5,
    INV_SRC_ALPHA = 6,
    DST_ALPHA = 7,
    INV_DST_ALPHA = 8,
    DST_COLOR = 9,
    INV_DST_COLOR = 10,
    SRC_ALPHA_SAT = 11,
    BLEND_FACTOR = 14,
    INV_BLEND_FACTOR = 15,
    SRC1_COLOR = 16,
    INV_SRC1_COLOR = 17,
    SRC1_ALPHA = 18,
    INV_SRC1_ALPHA = 19
};

enum class D3D12_BLEND_OP {
    ADD = 1,
    SUBTRACT = 2,
    REV_SUBTRACT = 3,
    MIN = 4,
    MAX = 5
};

enum class D3D12_COLOR_WRITE_ENABLE {
    RED = 1,
    GREEN = 2,
    BLUE = 4,
    ALPHA = 8,
    ALL = 15
};

enum class D3D12_CULL_MODE {
    NONE = 1,
    FRONT = 2,
    BACK = 3
};

enum class D3D12_FILL_MODE {
    WIREFRAME = 2,
    SOLID = 3
};

enum class D3D12_PRIMITIVE_TOPOLOGY_TYPE {
    UNDEFINED = 0,
    POINT = 1,
    LINE = 2,
    TRIANGLE = 3,
    PATCH = 4
};

enum class D3D12_PRIMITIVE_TOPOLOGY {
    UNDEFINED = 0,
    POINTLIST = 1,
    LINELIST = 2,
    LINESTRIP = 3,
    TRIANGLELIST = 4,
    TRIANGLESTRIP = 5,
    TRIANGLEFAN = 6,
    LINELIST_ADJ = 10,
    LINESTRIP_ADJ = 11,
    TRIANGLELIST_ADJ = 12,
    TRIANGLESTRIP_ADJ = 13,
    PATCHLIST_1 = 33,
    PATCHLIST_2 = 34,
    PATCHLIST_3 = 35,
    PATCHLIST_4 = 36,
    PATCHLIST_5 = 37,
    PATCHLIST_6 = 38,
    PATCHLIST_7 = 39,
    PATCHLIST_8 = 40,
    PATCHLIST_9 = 41,
    PATCHLIST_10 = 42,
    PATCHLIST_11 = 43,
    PATCHLIST_12 = 44,
    PATCHLIST_13 = 45,
    PATCHLIST_14 = 46,
    PATCHLIST_15 = 47,
    PATCHLIST_16 = 48,
    PATCHLIST_17 = 49,
    PATCHLIST_18 = 50,
    PATCHLIST_19 = 51,
    PATCHLIST_20 = 52,
    PATCHLIST_21 = 53,
    PATCHLIST_22 = 54,
    PATCHLIST_23 = 55,
    PATCHLIST_24 = 56,
    PATCHLIST_25 = 57,
    PATCHLIST_26 = 58,
    PATCHLIST_27 = 59,
    PATCHLIST_28 = 60,
    PATCHLIST_29 = 61,
    PATCHLIST_30 = 62,
    PATCHLIST_31 = 63,
    PATCHLIST_32 = 64
};

enum class D3D12_QUERY_TYPE {
    OCCLUSION = 0,
    TIMESTAMP = 1,
    PIPELINE_STATISTICS = 2,
    DEPTH_STENCIL_CLIP_CUT = 3
};

enum class D3D12_QUERY_HEAP_TYPE {
    OCCLUSION = 0,
    TIMESTAMP = 1,
    PIPELINE_STATISTICS = 2,
    SO_STATISTICS = 3,
    VIDEO_DECODE_STATISTICS = 4,
    COPY_QUEUE_TIMESTAMP = 5,
    TIME_STAMP = 6
};

struct D3D12_CPU_DESCRIPTOR_HANDLE {
    void* ptr;
};

struct D3D12_GPU_DESCRIPTOR_HANDLE {
    uint64_t ptr;
};

struct D3D12_RESOURCE_BARRIER {
    enum class Type {
        TRANSITION,
        ALIASING,
        UDV
    };
    
    Type Type;
    
    union {
        struct {
            IResource* pResource;
            int32_t Subresource;
            D3D12_RESOURCE_STATES StateBefore;
            D3D12_RESOURCE_STATES StateAfter;
        } Transition;
        
        struct {
            IResource* pResourceBefore;
            IResource* pResourceAfter;
        } Aliasing;
        
        struct {
            IResource* pResource;
            uint32_t NumRoadmapEntries;
            uint32_t* pRoadmap;
            D3D12_RESOURCE_STATES StateBefore;
            D3D12_RESOURCE_STATES StateAfter;
        } UAV;
    };
};

struct D3D12_VIEWPORT {
    float TopLeftX;
    float TopLeftY;
    float Width;
    float Height;
    float MinDepth;
    float MaxDepth;
};

struct D3D12_RECT {
    int32_t left;
    int32_t top;
    int32_t right;
    int32_t bottom;
};

struct D3D12_INPUT_ELEMENT_DESC {
    const char* SemanticName;
    uint32_t SemanticIndex;
    Format Format;
    uint32_t InputSlot;
    uint32_t AlignedByteOffset;
    D3D12_INPUT_CLASSIFICATION InputSlotClass;
    uint32_t InstanceDataStepRate;
};

enum class D3D12_INPUT_CLASSIFICATION {
    PER_VERTEX_DATA = 0,
    PER_INSTANCE_DATA = 1
};

struct D3D12_SO_DECLARATION_ENTRY {
    const char* SemanticName;
    uint32_t SemanticIndex;
    uint8_t StartComponent;
    uint8_t ComponentCount;
    uint8_t OutputSlot;
};

struct D3D12_SHADER_RESOURCE_VIEW_DESC {
    D3D12_SRV_DIMENSION ViewDimension;
    Format Format;
    uint32_t Shader4ComponentMapping;
    
    union {
        struct {
            uint32_t MostDetailedMip;
            uint32_t MipLevels;
            uint32_t PlaneSlice;
            float ResourceMinLODClamp;
        } Texture2D;
        
        struct {
            uint32_t MostDetailedMip;
            uint32_t MipLevels;
            uint32_t FirstArraySlice;
            uint32_t ArraySize;
            uint32_t PlaneSlice;
            float ResourceMinLODClamp;
        } Texture2DArray;
        
        struct {
            uint32_t FirstWSlice;
            uint32_t WSize;
            uint32_t MostDetailedMip;
            uint32_t MipLevels;
            float ResourceMinLODClamp;
        } Texture3D;
        
        struct {
            uint32_t MostDetailedMip;
            uint32_t MipLevels;
            uint32_t FirstArraySlice;
            uint32_t ArraySize;
            uint32_t PlaneSlice;
            float ResourceMinLODClamp;
        } TextureCube;
    };
};

struct D3D12_UNORDERED_ACCESS_VIEW_DESC {
    D3D12_UAV_DIMENSION ViewDimension;
    Format Format;
    uint32_t Shader4ComponentMapping;
    
    union {
        struct {
            uint32_t MipSlice;
        } Buffer;
        
        struct {
            uint32_t MipSlice;
            uint32_t FirstArraySlice;
            uint32_t ArraySize;
            uint32_t PlaneSlice;
        } Texture2D;
        
        struct {
            uint32_t MipSlice;
            uint32_t FirstWSlice;
            uint32_t WSize;
        } Texture3D;
    };
};

struct D3D12_RENDER_TARGET_VIEW_DESC {
    D3D12_RTV_DIMENSION ViewDimension;
    Format Format;
    
    union {
        struct {
            uint32_t MipSlice;
            uint32_t FirstArraySlice;
            uint32_t ArraySize;
        } Texture2D;
        
        struct {
            uint32_t MipSlice;
            uint32_t FirstArraySlice;
            uint32_t ArraySize;
            uint32_t PlaneSlice;
        } Texture2DMS;
    };
};

struct D3D12_DEPTH_STENCIL_VIEW_DESC {
    D3D12_DSV_DIMENSION ViewDimension;
    Format Format;
    uint32_t MipSlice;
    uint32_t FirstArraySlice;
    uint32_t ArraySize;
    uint32_t PlaneSlice;
};

struct D3D12_CONSTANT_BUFFER_VIEW_DESC {
    uint64_t BufferLocation;
    uint32_t SizeInBytes;
};

struct D3D12_SAMPLER_DESC {
    D3D12_FILTER Filter;
    D3D12_TEXTURE_ADDRESS_MODE AddressU;
    D3D12_TEXTURE_ADDRESS_MODE AddressV;
    D3D12_TEXTURE_ADDRESS_MODE AddressW;
    float MipLODBias;
    uint32_t MaxAnisotropy;
    D3D12_COMPARISON_FUNC ComparisonFunc;
    float BorderColor[4];
    float MinLOD;
    float MaxLOD;
};

struct InputLayout {
    D3D12_INPUT_ELEMENT_DESC* pInputElementDescs = nullptr;
    uint32_t NumInputElementDescs = 0;
};

struct StreamOutput {
    D3D12_SO_DECLARATION_ENTRY* pSODeclaration = nullptr;
    uint32_t NumSODeclarationEntries = 0;
    uint64_t* pBufferStrides = nullptr;
    uint32_t NumBufferStrides = 0;
    uint32_t RasterizedStream = 0;
};

struct BlendState {
    bool AlphaToCoverageEnable = false;
    bool IndependentBlendEnable = false;
    
    struct RenderTargetBlendDesc {
        bool BlendEnable = false;
        D3D12_BLEND SrcBlend = D3D12_BLEND::ONE;
        D3D12_BLEND DestBlend = D3D12_BLEND::ZERO;
        D3D12_BLEND_OP BlendOp = D3D12_BLEND_OP::ADD;
        D3D12_BLEND SrcBlendAlpha = D3D12_BLEND::ONE;
        D3D12_BLEND DestBlendAlpha = D3D12_BLEND::ZERO;
        D3D12_BLEND_OP BlendOpAlpha = D3D12_BLEND_OP::ADD;
        D3D12_COLOR_WRITE_ENABLE RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE::ALL;
    };
    RenderTargetBlendDesc RenderTarget[8];
};

struct RasterizerState {
    D3D12_FILL_MODE FillMode = D3D12_FILL_MODE::SOLID;
    D3D12_CULL_MODE CullMode = D3D12_CULL_MODE::BACK;
    bool FrontCounterClockwise = false;
    int32_t DepthBias = 0;
    float DepthBiasClamp = 0.0f;
    float SlopeScaledDepthBias = 0.0f;
    bool DepthClipEnable = true;
    bool MultisampleEnable = false;
    bool AntialiasedLineEnable = false;
    uint32_t ForcedSampleCount = 0;
    bool ConservativeRaster = false;
};

struct DepthStencilState {
    bool DepthEnable = true;
    D3D12_DEPTH_WRITE_MASK DepthWriteMask = D3D12_DEPTH_WRITE_MASK::ALL;
    D3D12_COMPARISON_FUNC DepthFunc = D3D12_COMPARISON_FUNC::LESS;
    bool StencilEnable = false;
    uint8_t StencilReadMask = 0xFF;
    uint8_t StencilWriteMask = 0xFF;
    
    struct DepthStencilOpDesc {
        D3D12_STENCIL_OP StencilFailOp = D3D12_STENCIL_OP::KEEP;
        D3D12_STENCIL_OP StencilDepthFailOp = D3D12_STENCIL_OP::KEEP;
        D3D12_STENCIL_OP StencilPassOp = D3D12_STENCIL_OP::KEEP;
        D3D12_COMPARISON_FUNC StencilFunc = D3D12_COMPARISON_FUNC::ALWAYS;
    };
    DepthStencilOpDesc FrontFace;
    DepthStencilOpDesc BackFace;
};

enum class D3D12_DEPTH_WRITE_MASK {
    ZERO = 0,
    ALL = 1
};

enum class D3D12_STENCIL_OP {
    KEEP = 1,
    ZERO = 2,
    REPLACE = 3,
    INCR_SAT = 4,
    DECR_SAT = 5,
    INVERT = 6,
    INCR = 7,
    DECR = 8
};

struct DXGI_SAMPLE_DESC {
    uint32_t Count = 1;
    uint32_t Quality = 0;
};

struct CachedPSO {
    void* pCachedBlob = nullptr;
    size_t CachedBlobSizeInBytes = 0;
};

enum class D3D12_PIPELINE_STATE_FLAGS {
    NONE = 0,
    TOOL_DEBUG = 1
};

struct D3D12_GRAPHICS_PIPELINE_STATE_DESC {
    InputLayout* InputLayout;
    RootSignature* pRootSignature;
    Shader* VS;
    Shader* HS;
    Shader* DS;
    Shader* GS;
    Shader* PS;
    StreamOutput* StreamOutput;
    BlendState* BlendState;
    uint32_t SampleMask;
    RasterizerState* RasterizerState;
    DepthStencilState* DepthStencilState;
    D3D12_PRIMITIVE_TOPOLOGY_TYPE PrimitiveTopologyType;
    uint32_t NumRenderTargets;
    Format RTVFormats[8];
    Format DSVFormat;
    DXGI_SAMPLE_DESC SampleDesc;
    uint32_t NodeMask;
    CachedPSO* cachedPSO;
    D3D12_PIPELINE_STATE_FLAGS Flags;
};

struct D3D12_COMPUTE_PIPELINE_STATE_DESC {
    RootSignature* pRootSignature;
    Shader* CS;
    uint32_t NodeMask;
    CachedPSO* cachedPSO;
    D3D12_PIPELINE_STATE_FLAGS Flags;
};

class D3D12Device : public IRHIDevice {
public:
    D3D12Device();
    virtual ~D3D12Device();
    
    GraphicsAPI GetAPI() const override { return GraphicsAPI::Direct3D12; }
    const char* GetAPIName() const override { return "Direct3D 12"; }
    
    bool Initialize() override;
    void Shutdown() override;
    
    ID3D12Device* GetD3D12Device() { return m_device.Get(); }
    ID3D12CommandQueue* GetCommandQueue(D3D12_COMMAND_LIST_TYPE type);
    
    bool CreateCommandQueue(ICommandQueue** queue, const CommandQueueDesc& desc) override;
    bool CreateCommandAllocator(ICommandAllocator** allocator) override;
    bool CreateCommandList(ICommandList** list, ICommandAllocator* allocator) override;
    bool CreateFence(IFence** fence) override;
    
    bool CreateDescriptorHeap(IDescriptorHeap** heap, const DescriptorHeapDesc& desc) override;
    bool CreateQueryHeap(IQueryHeap** heap, const QueryHeapDesc& desc) override;
    
    bool CreateRootSignature(RootSignature** signature, const RootSignatureDesc& desc) override;
    bool CreatePipelineState(PipelineStateObject** pso, const PipelineDesc& desc) override;
    
    bool CreateSwapChain(ISwapChain** swapChain, const SwapChainDesc& desc, void* windowHandle) override;
    
    bool CreateRenderTarget(RenderTarget** target, const RenderTargetDesc& desc) override;
    bool CreateDepthStencil(DepthStencil** depthStencil, const DepthStencilDesc& desc) override;
    
    void* GetNativeDevice() const override { return m_device.Get(); }
    
private:
    ComPtr<ID3D12Device> m_device;
    ComPtr<ID3D12CommandQueue> m_directQueue;
    ComPtr<ID3D12CommandQueue> m_computeQueue;
    ComPtr<ID3D12CommandQueue> m_copyQueue;
    
    D3D_FEATURE_LEVEL m_featureLevel;
    bool m_raytracingSupported;
    bool m_meshShadersSupported;
};

class D3D12CommandList : public ICommandList {
public:
    D3D12CommandList(ID3D12CommandAllocator* allocator);
    virtual ~D3D12CommandList();
    
    void Reset(ICommandAllocator* allocator) override;
    void Close() override;
    
    void BeginRenderPass(const RenderPassDesc& desc) override;
    void EndRenderPass() override;
    
    void SetPipelineState(PipelineStateObject* pso) override;
    void SetRootSignature(RootSignature* signature) override;
    
    void SetVertexBuffer(uint32_t slot, VertexBuffer* buffer, uint32_t offset = 0) override;
    void SetIndexBuffer(IndexBuffer* buffer, uint32_t offset = 0) override;
    
    void SetDescriptorHeap(IDescriptorHeap* heap) override;
    void SetGraphicsDescriptorTable(uint32_t rootParameterIndex, uint64_t baseDescriptor) override;
    void SetComputeDescriptorTable(uint32_t rootParameterIndex, uint64_t baseDescriptor) override;
    
    void DrawInstanced(
        uint32_t vertexCountPerInstance,
        uint32_t instanceCount,
        uint32_t startVertex,
        uint32_t startInstance
    ) override;
    
    void DrawIndexedInstanced(
        uint32_t indexCountPerInstance,
        uint32_t instanceCount,
        uint32_t startIndex,
        int32_t baseVertex,
        uint32_t startInstance
    ) override;
    
    void Dispatch(uint32_t threadGroupCountX, uint32_t threadGroupCountY, uint32_t threadGroupCountZ) override;
    
    void SetViewports(const Viewport* viewports, uint32_t count) override;
    void SetScissorRects(const Rect* rects, uint32_t count) override;
    
    void SetRenderTargets(
        const RenderTarget* const* renderTargets,
        uint32_t renderTargetCount,
        const DepthStencil* depthStencil
    ) override;
    
    void ClearRenderTargetView(const RenderTarget* target, const float color[4]) override;
    void ClearDepthStencilView(const DepthStencil* depthStencil, float depth, uint8_t stencil) override;
    
    void CopyResource(IResource* dst, const IResource* src) override;
    void CopyBuffer(IResource* dst, uint64_t dstOffset, const IResource* src, uint64_t srcOffset, uint64_t size) override;
    
    void ResourceBarrier(
        IResource* resource,
        ResourceStateFlag stateBefore,
        ResourceStateFlag stateAfter
    );
    
    ID3D12GraphicsCommandList* GetD3D12CommandList() { return m_commandList.Get(); }
    
private:
    ComPtr<ID3D12GraphicsCommandList> m_commandList;
    D3D12_PRIMITIVE_TOPOLOGY m_topology = D3D12_PRIMITIVE_TOPOLOGY::UNDEFINED;
};

class D3D12DescriptorHeap : public IDescriptorHeap {
public:
    D3D12DescriptorHeap(ID3D12DescriptorHeap* heap, DescriptorHeapType type, uint32_t count);
    virtual ~D3D12DescriptorHeap();
    
    DescriptorHeapType GetType() const override { return m_type; }
    uint32_t GetDescriptorCount() const override { return m_descriptorCount; }
    
    void* GetCPUDescriptorHandle(uint32_t index) const override;
    uint64_t GetGPUDescriptorHandle(uint32_t index) const override;
    
    void SetName(const String& name) override;
    
    ID3D12DescriptorHeap* GetD3D12DescriptorHeap() { return m_heap.Get(); }
    
private:
    ComPtr<ID3D12DescriptorHeap> m_heap;
    DescriptorHeapType m_type;
    uint32_t m_descriptorCount;
    uint32_t m_descriptorSize;
};

class D3D12RootSignature : public RootSignature {
public:
    D3D12RootSignature();
    virtual ~D3D12RootSignature();
    
    bool Initialize(const RootSignatureDesc& desc) override;
    void SetName(const String& name) override;
    
    ID3D12RootSignature* GetD3D12RootSignature() { return m_rootSignature.Get(); }
    
private:
    bool SerializeRootSignature(
        const RootSignatureDesc& desc,
        std::vector<uint8_t>& serializedData
    );
    
    ComPtr<ID3D12RootSignature> m_rootSignature;
};

class D3D12PipelineState : public PipelineStateObject {
public:
    D3D12PipelineState();
    virtual ~D3D12PipelineState();
    
    bool Initialize(const PipelineDesc& desc);
    void SetName(const String& name);
    
    ID3D12PipelineState* GetD3D12PipelineState() { return m_pipelineState.Get(); }
    
private:
    ComPtr<ID3D12PipelineState> m_pipelineState;
};

class D3D12Fence : public IFence {
public:
    D3D12Fence(ID3D12Fence* fence);
    virtual ~D3D12Fence();
    
    uint64_t GetCompletedValue() const override;
    void Signal(uint64_t value) override;
    void Wait(uint64_t value) override;
    void Wait(uint64_t value, uint64_t timeout) override;
    
    ID3D12Fence* GetD3D12Fence() { return m_fence.Get(); }
    
    HANDLE GetEventHandle() { return m_event; }
    
private:
    ComPtr<ID3D12Fence> m_fence;
    HANDLE m_event;
};

class D3D12QueryHeap : public IQueryHeap {
public:
    D3D12QueryHeap(ID3D12QueryHeap* heap, QueryType type, uint32_t count);
    virtual ~D3D12QueryHeap();
    
    QueryType GetType() const override { return m_type; }
    uint32_t GetCount() const override { return m_count; }
    
    void Begin(ICommandList* cmdList, uint32_t index) override;
    void End(ICommandList* cmdList, uint32_t index) override;
    
    void GetData(uint32_t index, void* data, uint32_t dataSize) override;
    
    ID3D12QueryHeap* GetD3D12QueryHeap() { return m_queryHeap.Get(); }
    
private:
    ComPtr<ID3D12QueryHeap> m_queryHeap;
    QueryType m_type;
    uint32_t m_count;
};

class D3D12SwapChain : public ISwapChain {
public:
    D3D12SwapChain(IDXGISwapChain3* swapChain);
    virtual ~D3D12SwapChain();
    
    bool Initialize(const SwapChainDesc& desc, void* windowHandle) override;
    void Shutdown() override;
    
    bool Present() override;
    bool Resize(uint32_t width, uint32_t height) override;
    
    uint32_t GetCurrentBufferIndex() const override;
    RenderTexture* GetBuffer(uint32_t index) override;
    
    void SetFullscreen(bool fullscreen) override;
    bool IsFullscreen() const override;
    
    IDXGISwapChain3* GetD3D12SwapChain() { return m_swapChain.Get(); }
    
private:
    ComPtr<IDXGISwapChain3> m_swapChain;
    std::vector<RenderTexture*> m_buffers;
    uint32_t m_bufferCount;
    bool m_fullscreen;
};

} // namespace D3D12
} // namespace RHI
} // namespace XCEngine

namespace XCEngine {
namespace Rendering {

using ICommandList = RHI::ICommandList;
using IBuffer = RHI::IResource;

enum class BufferUsage {
    Default,
    Immutable,
    Dynamic,
    Staging
};

enum class MemoryUsage {
    Default,
    GPU_Only,
    CPU_Only,
    CPU_GPU
};

enum class PassType {
    Graphics,
    Compute,
    Copy,
    Raytracing
};

enum class LoadAction {
    Load,
    Clear,
    DontCare
};

enum class StoreAction {
    Store,
    Resolve,
    StoreAndResolve,
    DontCare
};

enum class ResolveMode {
    None,
    Min,
    Average,
    Sample0,
    Sample1,
    Sample2,
    Sample3,
    Sample4,
    Sample5,
    Sample6,
    Sample7
};

enum class ComparisonFunc {
    Never,
    Less,
    Equal,
    LessEqual,
    Greater,
    NotEqual,
    GreaterEqual,
    Always
};

enum class BorderColor {
    TransparentBlack,
    OpaqueBlack,
    OpaqueWhite
};

struct IndexType {
    static constexpr uint8_t Uint16 = 0;
    static constexpr uint8_t Uint32 = 1;
};

enum class ResourceState {
    Undefined = 0,
    Common = 1,
    VertexBuffer = 2,
    ConstantBuffer = 3,
    IndexBuffer = 4,
    RenderTarget = 5,
    UnorderedAccess = 6,
    DepthWrite = 7,
    DepthRead = 8,
    ShaderResource = 9,
    IndirectArgument = 10,
    CopyDest = 11,
    CopySource = 12,
    ResolveDest = 13,
    ResolveSource = 14,
    Present = 15,
    GenericRead = 16
};

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 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();
    
    RHI::IRHIDevice* 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<RHI::IRHIDevice> m_device;
    std::unique_ptr<ICommandList> m_mainCommandList;
    std::unique_ptr<RHI::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;
};

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 RenderTexture {
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:
    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.4 相机组件

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.5 光照组件

namespace XCEngine {

class LightComponent : 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;
    float m_cookieSize = 5.0f;
};

} // namespace XCEngine

4.6 渲染网格组件

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

4.7 材质系统

namespace XCEngine {
namespace Rendering {

enum class ShaderType {
    Vertex,
    Fragment,
    Compute,
    Geometry,
    Hull,
    Domain
};

enum class UniformType {
    None,
    Float,
    Float2,
    Float3,
    Float4,
    Int,
    Int2,
    Int3,
    Int4,
    Bool,
    Sampler2D,
    Sampler3D,
    SamplerCube,
    Sampler2DArray,
    Matrix3x3,
    Matrix4x4
};

struct UniformDesc {
    String name;
    UniformType type;
    uint32_t arraySize = 1;
    uint32_t offset = 0;
};

struct ShaderUniformBlock {
    String name;
    uint32_t bindingSlot = 0;
    uint32_t size = 0;
    std::vector<UniformDesc> uniforms;
};

class Shader : public IResource {
public:
    const String& GetSource() const { return m_source; }
    ShaderType GetType() const { return m_type; }
    
    const std::vector<ShaderUniformBlock>& GetUniformBlocks() const { return m_uniformBlocks; }
    const std::vector<UniformDesc>& GetResources() const { return m_resources; }
    
    bool HasVariant(const String& variantName) const;
    Shader* GetVariant(const HashMap<String, String>& defines);
    
    bool IsCompiled() const { return m_compiled; }
    const String& GetCompileErrors() const { return m_compileErrors; }
    
private:
    String m_source;
    ShaderType m_type;
    bool m_compiled = false;
    String m_compileErrors;
    
    std::vector<ShaderUniformBlock> m_uniformBlocks;
    std::vector<UniformDesc> m_resources;
    HashMap<String, std::unique_ptr<Shader>> m_variants;
};

enum class BlendMode {
    Opaque,
    Transparent,
    Additive,
    Multiply,
    AlphaTest
};

enum class CullMode {
    None,
    Front,
    Back
};

enum class ZWriteMode {
    On,
    Off
};

enum class DepthTest {
    Never,
    Less,
    Equal,
    LessEqual,
    Greater,
    NotEqual,
    GreaterEqual,
    Always
};

struct RenderState {
    BlendMode blendMode = BlendMode::Opaque;
    CullMode cullMode = CullMode::Back;
    ZWriteMode zWriteMode = ZWriteMode::On;
    DepthTest depthTest = DepthTest::LessEqual;
    bool depthClip = true;
    bool scissorTest = false;
    bool stencilTest = false;
    
    uint8_t stencilReadMask = 0xFF;
    uint8_t stencilWriteMask = 0xFF;
    int32_t stencilRef = 0;
    
    uint32_t colorWriteMask = 0xF;
    
    bool operator==(const RenderState& other) const;
};

struct MaterialPropBlock {
    HashMap<String, Vector4> floatProps;
    HashMap<String, Vector4> intProps;
    HashMap<String, Matrix4x4> matrixProps;
    HashMap<String, ResourceGUID> textureProps;
    
    void SetFloat(const String& name, float value);
    void SetFloat(const String& name, const Vector4& value);
    void SetInt(const String& name, int32_t value);
    void SetMatrix(const String& name, const Matrix4x4& value);
    void SetTexture(const String& name, const ResourceGUID& guid);
    
    float GetFloat(const String& name, float defaultValue = 0.0f) const;
    Vector4 GetFloat4(const String& name, const Vector4& defaultValue = Vector4::Zero()) const;
    int32_t GetInt(const String& name, int32_t defaultValue = 0) const;
    Matrix4x4 GetMatrix(const String& name, const Matrix4x4& defaultValue = Matrix4x4::Identity()) const;
    ResourceGUID GetTexture(const String& name, ResourceGUID defaultValue = ResourceGUID::INVALID) const;
};

class Material : public IResource {
public:
    Material();
    explicit Material(Shader* shader);
    
    Shader* GetShader() const { return m_shader; }
    void SetShader(Shader* shader);
    
    const RenderState& GetRenderState() const { return m_renderState; }
    void SetRenderState(const RenderState& state) { m_renderState = state; }
    
    MaterialPropBlock& GetPropBlock() { return m_props; }
    const MaterialPropBlock& GetPropBlock() const { return m_props; }
    
    int32_t GetRenderQueue() const { return m_renderQueue; }
    void SetRenderQueue(int32_t queue) { m_renderQueue = queue; }
    
    void SetFloat(const String& name, float value);
    void SetFloat(const String& name, const Vector4& value);
    void SetInt(const String& name, int32_t value);
    void SetTexture(const String& name, const ResourceGUID& guid);
    
    float GetFloat(const String& name, float defaultValue = 0.0f) const;
    int32_t GetInt(const String& name, int32_t defaultValue = 0) const;
    ResourceGUID GetTexture(const String& name) const;
    
    bool IsInstanced() const { return m_instanced; }
    void SetInstanced(bool instanced) { m_instanced = instanced; }
    
private:
    Shader* m_shader = nullptr;
    RenderState m_renderState;
    MaterialPropBlock m_props;
    int32_t m_renderQueue = 0;
    bool m_instanced = false;
};

class MaterialManager {
public:
    static MaterialManager& Get();
    
    void Initialize();
    void Shutdown();
    
    Material* CreateMaterial(Shader* shader);
    Material* GetMaterial(const ResourceGUID& guid) const;
    void DestroyMaterial(Material* material);
    
    Material* FindMaterialByName(const String& name) const;
    
private:
    HashMap<ResourceGUID, std::unique_ptr<Material>> m_materials;
    uint64_t m_nextId = 1;
};

class MaterialPropertyBlock {
public:
    MaterialPropertyBlock();
    ~MaterialPropertyBlock();
    
    void Clear();
    
    void SetFloat(const String& name, float value);
    void SetVector(const String& name, const Vector4& value);
    void SetColor(const String& name, const Color& value);
    void SetMatrix(const String& name, const Matrix4x4& matrix);
    void SetTexture(const String& name, Texture* texture);
    
    bool HasProperty(const String& name) const;
    float GetFloat(const String& name, float defaultValue = 0.0f) const;
    Vector4 GetVector(const String& name, const Vector4& defaultValue = Vector4::Zero()) const;
    Color GetColor(const String& name, const Color& defaultValue = Color::White()) const;
    Matrix4x4 GetMatrix(const String& name, const Matrix4x4& defaultValue = Matrix4x4::Identity()) const;
    Texture* GetTexture(const String& name) const;
    
    bool IsEmpty() const { return m_properties.empty(); }
    size_t GetPropertyCount() const { return m_properties.size(); }
    
    void ApplyToMaterial(Material* material) const;
    void CopyFrom(const MaterialPropertyBlock& other);
    
private:
    struct PropertyValue {
        enum class Type { Float, Vector, Matrix, Texture };
        Type type;
        union {
            float floatValue;
            Vector4 vectorValue;
            Matrix4x4 matrixValue;
            Texture* textureValue;
        };
    };
    HashMap<String, PropertyValue> m_properties;
};

class RenderSettings {
public:
    static RenderSettings& Get();
    
    void Load();
    void Save();
    
    enum class AmbientMode {
        Skybox,
        Trilight,
        Flat,
        Custom
    };
    
    AmbientMode GetAmbientMode() const { return m_ambientMode; }
    void SetAmbientMode(AmbientMode mode) { m_ambientMode = mode; }
    
    Color GetAmbientSkyColor() const { return m_ambientSkyColor; }
    void SetAmbientSkyColor(const Color& color) { m_ambientSkyColor = color; }
    
    Color GetAmbientEquatorColor() const { return m_ambientEquatorColor; }
    void SetAmbientEquatorColor(const Color& color) { m_ambientEquatorColor = color; }
    
    Color GetAmbientGroundColor() const { return m_ambientGroundColor; }
    void SetAmbientGroundColor(const Color& color) { m_ambientGroundColor = color; }
    
    float GetAmbientIntensity() const { return m_ambientIntensity; }
    void SetAmbientIntensity(float intensity) { m_ambientIntensity = intensity; }
    
    bool GetFogEnabled() const { return m_fogEnabled; }
    void SetFogEnabled(bool enabled) { m_fogEnabled = enabled; }
    
    enum class FogMode {
        Linear,
        Exponential,
        ExponentialSquared
    };
    
    FogMode GetFogMode() const { return m_fogMode; }
    void SetFogMode(FogMode mode) { m_fogMode = mode; }
    
    Color GetFogColor() const { return m_fogColor; }
    void SetFogColor(const Color& color) { m_fogColor = color; }
    
    float GetFogDensity() const { return m_fogDensity; }
    void SetFogDensity(float density) { m_fogDensity = density; }
    
    float GetFogStartDistance() const { return m_fogStartDistance; }
    void SetFogStartDistance(float distance) { m_fogStartDistance = distance; }
    
    float GetFogEndDistance() const { return m_fogEndDistance; }
    void SetFogEndDistance(float distance) { m_fogEndDistance = distance; }
    
    float GetShadowDistance() const { return m_shadowDistance; }
    void SetShadowDistance(float distance) { m_shadowDistance = distance; }
    
    uint32_t GetShadowCascadeCount() const { return m_shadowCascadeCount; }
    void SetShadowCascadeCount(uint32_t count) { m_shadowCascadeCount = count; }
    
    float GetShadowResolution() const { return m_shadowResolution; }
    void SetShadowResolution(float resolution) { m_shadowResolution = resolution; }
    
    Texture* GetSkybox() const { return m_skybox; }
    void SetSkybox(Texture* skybox) { m_skybox = skybox; }
    
private:
    RenderSettings() = default;
    
    AmbientMode m_ambientMode = AmbientMode::Skybox;
    Color m_ambientSkyColor = Color{0.5f, 0.5f, 0.5f, 1.0f};
    Color m_ambientEquatorColor = Color{0.2f, 0.2f, 0.2f, 1.0f};
    Color m_ambientGroundColor = Color{0.1f, 0.1f, 0.1f, 1.0f};
    float m_ambientIntensity = 1.0f;
    
    bool m_fogEnabled = false;
    FogMode m_fogMode = FogMode::Linear;
    Color m_fogColor = Color{0.5f, 0.5f, 0.5f, 1.0f};
    float m_fogDensity = 0.01f;
    float m_fogStartDistance = 10.0f;
    float m_fogEndDistance = 100.0f;
    
    float m_shadowDistance = 150.0f;
    uint32_t m_shadowCascadeCount = 4;
    float m_shadowResolution = 1024.0f;
    
    Texture* m_skybox = nullptr;
};

class GraphicsSettings {
public:
    static GraphicsSettings& Get();
    
    void Load();
    void Save();
    
    enum class ColorSpace {
        Gamma,
        Linear
    };
    
    ColorSpace GetColorSpace() const { return m_colorSpace; }
    void SetColorSpace(ColorSpace space) { m_colorSpace = space; }
    
    enum class HDRSetting {
        Off,
        On,
        Auto
    };
    
    HDRSetting GetHDR() const { return m_hdr; }
    void SetHDR(HDRSetting hdr) { m_hdr = hdr; }
    
    uint32_t GetMSAASamples() const { return m_msaaSamples; }
    void SetMSAASamples(uint32_t samples) { m_msaaSamples = samples; }
    
    bool GetRealtimeReflectionProbes() const { return m_realtimeReflectionProbes; }
    void SetRealtimeReflectionProbes(bool enabled) { m_realtimeReflectionProbes = enabled; }
    
    float GetLODBias() const { return m_lodBias; }
    void SetLODBias(float bias) { m_lodBias = bias; }
    
    int GetMaximumLODLevel() const { return m_maximumLODLevel; }
    void SetMaximumLODLevel(int level) { m_maximumLODLevel = level; }
    
    enum class ShaderQuality {
        Low,
        Medium,
        High
    };
    
    ShaderQuality GetShaderQuality() const { return m_shaderQuality; }
    void SetShaderQuality(ShaderQuality quality) { m_shaderQuality = quality; }
    
private:
    GraphicsSettings() = default;
    
    ColorSpace m_colorSpace = ColorSpace::Linear;
    HDRSetting m_hdr = HDRSetting::Auto;
    uint32_t m_msaaSamples = 4;
    bool m_realtimeReflectionProbes = true;
    float m_lodBias = 1.0f;
    int m_maximumLODLevel = -1;
    ShaderQuality m_shaderQuality = ShaderQuality::High;
};

} // namespace Rendering
} // namespace XCEngine

4.8 渲染管线

namespace XCEngine {
namespace Rendering {

enum class RenderPipelineType {
    Forward,
    Deferred,
    Hybrid,
    Custom
};

struct RenderPipelineDesc {
    RenderPipelineType type = RenderPipelineType::Forward;
    uint32_t maxLights = 16;
    bool shadowEnabled = true;
    uint32_t shadowMapSize = 2048;
    bool ssaoEnabled = false;
    bool bloomEnabled = false;
    bool toneMappingEnabled = true;
    String toneMappingCurve = "ACES";
};

struct RenderItem {
    ResourceGUID meshGuid;
    Material* material = nullptr;
    Matrix4x4 worldMatrix;
    uint32_t instanceId = 0;
    int32_t renderQueue = 0;
    uint32_t subMeshIndex = 0;
    uint32_t lightingHash = 0;
    
    float GetDistanceSq(const Vector3& cameraPos) const;
    bool operator<(const RenderItem& other) const;
};

struct CullingParams {
    Vector3 position;
    float sphereCulling;
    
    Matrix4x4 viewMatrix;
    Matrix4x4 projectionMatrix;
    
    float nearClipPlane;
    float farClipPlane;
    
    Rect viewport;
    
    int32_t cullingPlaneFlags;
    int32_t cullingMask;
    int32_t ortho;
    
    float shadowDistance;
    float shadowNearPlaneDistance;
    
    bool isOrthographic;
    bool cullDynamicObjects;
    int32_t LODStripping;
    int32_t forceCullingMode;
    int32_t maximumLODLevel;
    int32_t minimumLODLevel;
};

struct CullingResults {
    struct VisibleObject {
        uint64_t instanceID;
        int32_t referenceID;
        
        Matrix4x4 localToWorldMatrix;
        Matrix4x4 localToWorldMatrixPrevious;
        
        uint64_t staticBatchRootID;
        
        uint32_t subMeshIndex;
        
        Vector4 lightmapScaleOffset;
        uint32_t lightmapIndex;
        
        bool staticShadowCaster;
        bool motionVectors;
    };
    
    std::vector<VisibleObject> visibleRenderers;
    
    struct LightData {
        uint64_t lightID;
        int32_t uniqueID;
        
        Vector3 position;
        Vector3 color;
        Vector3 forward;
        
        float range;
        float intensity;
        float spotAngle;
        
        int32_t lightType;
        int32_t renderMode;
        
        bool enabled;
        bool shadowsEnabled;
        
        int32_t cullingMask;
        
        Matrix4x4 viewMatrix;
        Matrix4x4 projectionMatrix;
    };
    
    std::vector<LightData> visibleLights;
    
    Frustum frustumPlanes[2];
};

class CullingSystem {
public:
    static CullingSystem& Get();
    
    void Initialize();
    void Shutdown();
    
    bool PerformCulling(
        const CullingParams& params,
        CullingResults& results,
        Scene* scene
    );
    
    void ComputeFrustumPlanes(
        const Matrix4x4& viewMatrix,
        const Matrix4x4& projectionMatrix,
        Frustum& frustum
    );
    
private:
    std::vector<uint64_t> m_visibleRenderers;
    Frustum m_frustum;
    std::vector<Plane> m_cullingPlanes;
};

class ScriptableRenderContext {
public:
    ScriptableRenderContext();
    ~ScriptableRenderContext();
    
    void SetRenderTarget(
        RenderTargetIdentifier colorTarget,
        RenderTargetIdentifier depthTarget
    );
    
    void PushDebugGroup(const char* name);
    void PopDebugGroup();
    
    void BeginSample(const char* name);
    void EndSample(const char* name);
    
    void DrawRenderer(
        RenderItem* renderers,
        size_t count,
        Material* material,
        int passIndex
    );
    
    void ExecuteAndPresent();
    
    void Submit();
    
private:
    CommandBuffer* m_commandBuffer;
    RenderTargetIdentifier m_activeColorTarget;
    RenderTargetIdentifier m_activeDepthTarget;
};

class LightManager {
public:
    static LightManager& Get();
    
    void Initialize();
    void Shutdown();
    
    void UpdateLights(
        Scene* scene,
        CameraComponent* camera,
        CullingResults& cullingResults
    );
    
    void GetMainLight(LightData& light);
    void GetVisibleLights(std::vector<LightData*>& lights);
    
    int GetVisibleLightCount() const { return m_visibleLights.size(); }
    bool HasShadows() const { return m_shadowsEnabled; }
    
    void SetShadowDistance(float distance) { m_shadowDistance = distance; }
    float GetShadowDistance() const { return m_shadowDistance; }
    
private:
    std::vector<LightData> m_visibleLights;
    int m_mainLightIndex = -1;
    
    float m_shadowDistance = 50.0f;
    bool m_shadowsEnabled = true;
};

class ShadowAtlas {
public:
    ShadowAtlas();
    ~ShadowAtlas();
    
    void Initialize(int width, int height);
    void Shutdown();
    
    void Update(
        const std::vector<LightData*>& lights,
        CullingResults& cullingResults
    );
    
    RenderTexture* GetTexture() const { return m_texture.get(); }
    
private:
    struct ShadowSlice {
        int x, y;
        int width, height;
        bool allocated;
        LightData* light;
    };
    
    std::unique_ptr<RenderTexture> m_texture;
    int m_width = 0;
    int m_height = 0;
    
    std::vector<ShadowSlice> m_slices;
};

class Renderer {
public:
    Renderer();
    ~Renderer();
    
    void Initialize();
    void Shutdown();
    
    void Render(
        ScriptableRenderContext& context,
        CameraComponent* camera,
        CullingResults& cullingResults,
        RenderQueue& renderQueue
    );
    
    void RenderOpaque(
        ScriptableRenderContext& context,
        CullingResults& cullingResults,
        RenderQueue& renderQueue
    );
    
    void RenderTransparent(
        ScriptableRenderContext& context,
        CullingResults& cullingResults,
        RenderQueue& renderQueue
    );
    
    void RenderShadowCasters(
        ScriptableRenderContext& context,
        CullingResults& cullingResults
    );
    
    void SortRenderers(RenderQueue& renderQueue);
    
private:
    void PrepareRenderQueueEntries(
        RenderQueue& renderQueue,
        CullingResults& cullingResults
    );
    
    Material* m_defaultMaterial = nullptr;
};

class RenderQueue {
public:
    void Clear();
    void Sort();
    
    void Add(const RenderItem& item);
    void AddRange(const RenderItem* items, size_t count);
    
    const std::vector<RenderItem>& GetOpaque() const { return m_opaque; }
    const std::vector<RenderItem>& GetTransparent() const { return m_transparent; }
    const std::vector<RenderItem>& GetAlphaTest() const { return m_alphaTest; }
    
    size_t GetOpaqueCount() const { return m_opaque.size(); }
    size_t GetTransparentCount() const { return m_transparent.size(); }
    size_t GetAlphaTestCount() const { return m_alphaTest.size(); }
    
private:
    std::vector<RenderItem> m_opaque;
    std::vector<RenderItem> m_transparent;
    std::vector<RenderItem> m_alphaTest;
};

struct CameraData {
    Matrix4x4 viewMatrix;
    Matrix4x4 projectionMatrix;
    Matrix4x4 viewProjectionMatrix;
    Vector3 position;
    Vector3 forward;
    Vector3 up;
    Vector3 right;
    float nearPlane;
    float farPlane;
    float fov;
    float aspectRatio;
    Rect viewport;
    bool isOrthographic;
};

struct RenderContextData {
    CameraData camera;
    std::vector<LightData> lights;
    std::vector<LightData> visibleLights;
    float deltaTime;
    float time;
    uint32_t frameIndex;
    uint64_t frameCount;
};

class RenderPipeline {
public:
    virtual ~RenderPipeline() = default;
    
    virtual void Initialize(const RenderPipelineDesc& desc);
    virtual void Shutdown();
    
    virtual void Prepare(RenderContextData& context);
    virtual void Execute(RHI::ICommandList* cmdList, RenderContextData& context);
    virtual void Present();
    
    RenderQueue& GetRenderQueue() { return m_renderQueue; }
    const RenderQueue& GetRenderQueue() const { return m_renderQueue; }
    
    RenderTexture* GetColorTarget() const { return m_colorTarget.get(); }
    RenderTexture* GetDepthTarget() const { return m_depthTarget.get(); }
    
    virtual void Resize(uint32_t width, uint32_t height);
    
protected:
    virtual void CollectRenderItems(Scene* scene, CameraComponent* camera);
    virtual void SortRenderItems();
    virtual void SetupLights(Scene* scene, CameraComponent* camera);
    
    RenderPipelineDesc m_desc;
    RenderQueue m_renderQueue;
    
    std::unique_ptr<RenderTexture> m_colorTarget;
    std::unique_ptr<RenderTexture> m_depthTarget;
    
    std::vector<LightData> m_mainLightData;
    std::vector<LightData> m_additionalLightData;
};

class ForwardPipeline : public RenderPipeline {
public:
    void Initialize(const RenderPipelineDesc& desc) override;
    void Execute(RHI::ICommandList* cmdList, RenderContextData& context) override;
    
private:
    void RenderOpaque(RHI::ICommandList* cmdList, RenderContextData& context);
    void RenderTransparent(RHI::ICommandList* cmdList, RenderContextData& context);
    void RenderAlphaTest(RHI::ICommandList* cmdList, RenderContextData& context);
    void RenderShadowMaps(RHI::ICommandList* cmdList);
    void RenderLighting(RHI::ICommandList* cmdList, RenderContextData& context);
};

class DeferredPipeline : public RenderPipeline {
public:
    void Initialize(const RenderPipelineDesc& desc) override;
    void Execute(RHI::ICommandList* cmdList, RenderContextData& context) override;
    
private:
    void RenderGBuffer(RHI::ICommandList* cmdList);
    void RenderDeferredLighting(RHI::ICommandList* cmdList);
    void RenderDeferredShading(RHI::ICommandList* cmdList);
    
    std::unique_ptr<RenderTexture> m_gBufferAlbedo;
    std::unique_ptr<RenderTexture> m_gBufferNormal;
    std::unique_ptr<RenderTexture> m_gBufferMetallicRoughness;
    std::unique_ptr<RenderTexture> m_gBufferDepth;
};

class RenderPipelineManager {
public:
    static RenderPipelineManager& Get();
    
    void Initialize(const RenderPipelineDesc& desc);
    void Shutdown();
    
    RenderPipeline* GetPipeline() const { return m_pipeline.get(); }
    
    void SetPipeline(std::unique_ptr<RenderPipeline> pipeline);
    void CreatePipeline(RenderPipelineType type);
    
    void Resize(uint32_t width, uint32_t height);
    
private:
    std::unique_ptr<RenderPipeline> m_pipeline;
    RenderPipelineDesc m_desc;
};

} // namespace Rendering
} // namespace XCEngine

第五章 目录结构(与 Unity 引擎目录结构一致)

XCVolumeRenderer/
├── engine/                          # 引擎核心库(静态库)
│   ├── CMakeLists.txt
│   ├── include/
│   │   └── XCEngine/
│   │       ├── Core/                # 核心基础
│   │       │   ├── Assert.h
│   │       │   ├── Event.h
│   │       │   ├── TypeTraits.h
│   │       │   └── UniquePtr.h
│   │       ├── Math/                # 数学库(与 Unity Mathf 对应)
│   │       │   ├── Vector2.h
│   │       │   ├── Vector3.h
│   │       │   ├── Vector4.h
│   │       │   ├── Matrix3.h
│   │       │   ├── Matrix4.h
│   │       │   ├── Quaternion.h
│   │       │   ├── Transform.h
│   │       │   ├── Color.h
│   │       │   ├── Ray.h
│   │       │   ├── Plane.h
│   │       │   ├── Sphere.h
│   │       │   ├── Box.h
│   │       │   ├── Bounds.h
│   │       │   └── Frustum.h
│   │       ├── Containers/         # 容器(与 Unity Collections 对应)
│   │       │   ├── Array.h
│   │       │   ├── String.h
│   │       │   ├── StringView.h
│   │       │   └── HashMap.h
│   │       ├── Memory/             # 内存管理
│   │       │   ├── Allocator.h
│   │       │   ├── LinearAllocator.h
│   │       │   ├── PoolAllocator.h
│   │       │   └── ProxyAllocator.h
│   │       ├── Threading/          # 线程系统
│   │       │   ├── Thread.h
│   │       │   ├── Mutex.h
│   │       │   ├── SpinLock.h
│   │       │   ├── ReadWriteLock.h
│   │       │   ├── TaskSystem.h
│   │       │   └── Atomic.h
│   │       ├── Debug/              # 调试系统
│   │       │   ├── Logger.h
│   │       │   ├── Profiler.h
│   │       │   └── LogSink.h
│   │       ├── Components/           # 组件系统(与 Unity Component 对应)
│   │       │   ├── GameObject.h
│   │       │   ├── Component.h
│   │       │   ├── ComponentTypeRegistry.h
│   │       │   ├── TransformComponent.h
│   │       │   ├── RenderMeshComponent.h
│   │       │   ├── LightComponent.h
│   │       │   └── CameraComponent.h
│   │       ├── Scene/              # 场景系统(与 Unity SceneManager 对应)
│   │       │   ├── Scene.h
│   │       │   ├── SceneManager.h
│   │       │   └── GameObjectBuilder.h
│   │       ├── Renderer/            # 渲染系统(核心,与 Unity Graphics/Shader 对应)
│   │       │   ├── Device.h            # 设备抽象
│   │       │   ├── Context.h           # 渲染上下文
│   │       │   ├── SwapChain.h        # 交换链
│   │       │   ├── Buffer.h           # 缓冲区
│   │       │   ├── Texture.h          # 纹理
│   │       │   ├── Shader.h          # Shader
│   │       │   ├── Material.h        # 材质
│   │       │   ├── Pipeline.h        # 渲染管线
│   │       │   ├── RenderPass.h      # 渲染通道
│   │       │   ├── CommandList.h    # 命令列表
│   │       │   ├── RenderQueue.h    # 渲染队列
│   │       │   ├── RenderPipeline.h # 渲染管线基类
│   │       │   ├── CullingSystem.h  # 剔除系统
│   │       │   ├── Renderer.h        # 渲染器
│   │       │   ├── LightManager.h    # 光照管理器
│   │       │   ├── ShadowAtlas.h    # 阴影图集
│   │       │   └── RenderModule.h   # 渲染模块
│   │       ├── RHI/                # 渲染硬件抽象层(与 Unity GraphicsDevice 对应)
│   │       │   ├── RHISystem.h      # RHI 系统入口
│   │       │   ├── RHIDevice.h      # 抽象设备接口
│   │       │   ├── CommandQueue.h   # 命令队列
│   │       │   ├── CommandList.h   # 命令列表
│   │       │   ├── CommandAllocator.h # 命令分配器
│   │       │   ├── Fence.h          # 同步围栏
│   │       │   ├── DescriptorHeap.h # 描述符堆
│   │       │   ├── QueryHeap.h      # 查询堆
│   │       │   ├── RootSignature.h  # 根签名
│   │       │   ├── PipelineState.h # 管线状态
│   │       │   ├── Sampler.h        # 采样器
│   │       │   └── SwapChain.h      # 交换链
│   │       ├── RHI/D3D12/          # D3D12 后端实现
│   │       │   ├── D3D12Device.h
│   │       │   ├── D3D12CommandList.h
│   │       │   ├── D3D12CommandQueue.h
│   │       │   ├── D3D12DescriptorHeap.h
│   │       │   ├── D3D12RootSignature.h
│   │       │   ├── D3D12PipelineState.h
│   │       │   ├── D3D12Fence.h
│   │       │   ├── D3D12QueryHeap.h
│   │       │   ├── D3D12SwapChain.h
│   │       │   ├── D3D12Texture.h
│   │       │   └── D3D12Buffer.h
│   │       └── XCEngine.h       # 主头文件
│   ├── src/
│   │   ├── Core/
│   │   ├── Math/
│   │   ├── Components/
│   │   ├── Scene/
│   │   ├── Renderer/
│   │   ├── RHI/
│   │   │   ├── CMakeLists.txt
│   │   │   └── D3D12/
│   │   └── ...
│   └── third_party/
│       ├── DirectX/              # DirectX SDK
│       ├── stb/                  # stb 图像库
│       ├── json/                 # json 解析库
│       └── NanoVDB/             # NanoVDB 体积渲染库
│
├── runtime/                        # 游戏运行时(独立可执行文件)
│   ├── CMakeLists.txt
│   ├── src/
│   │   ├── GameMain.cpp
│   │   ├── EntryPoint.cpp
│   │   └── Application.cpp
│   └── resources/
│       ├── Shaders/
│       ├── Models/
│       ├── Textures/
│       └── Volumes/
│
├── tools/                          # 工具链
│   ├── ShaderCompiler/            # 着色器编译器
│   │   ├── ShaderCompiler.h
│   │   └── ShaderCompileOptions.h
│   ├── BuildTool/                # 构建打包工具
│   └── AssetProcessor/            # 资源处理工具
│
├── content/                       # 资源内容
│   ├── Assets/                    # 资源文件夹
│   ├── Scenes/                   # 场景文件
│   └── Packages/                # 资源包
│
└── projects/                      # 项目文件夹
    └── ..

# Unity 引擎目录结构对照
# Unity/Editor/Data/Resources/
# Unity/Editor/Data/Modules/
# Unity/Editor/Data/Tools/

附录:待扩展功能

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

  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