4565 lines
127 KiB
Markdown
4565 lines
127 KiB
Markdown
|
|
# 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)
|
|||
|
|
|
|||
|
|
```cpp
|
|||
|
|
namespace XCEngine {
|
|||
|
|
namespace Math {
|
|||
|
|
|
|||
|
|
struct Vector2 {
|
|||
|
|
float x, y;
|
|||
|
|
|
|||
|
|
static Vector2 Zero() { return Vector2{0, 0}; }
|
|||
|
|
static Vector2 One() { return Vector2{1, 1}; }
|
|||
|
|
static Vector2 Up() { return Vector2{0, 1}; }
|
|||
|
|
static Vector2 Down() { return Vector2{0, -1}; }
|
|||
|
|
static Vector2 Right() { return Vector2{1, 0}; }
|
|||
|
|
static Vector2 Left() { return Vector2{-1, 0}; }
|
|||
|
|
|
|||
|
|
static float Dot(const Vector2& a, const Vector2& b);
|
|||
|
|
static float Cross(const Vector2& a, const Vector2& b);
|
|||
|
|
static Vector2 Normalize(const Vector2& v);
|
|||
|
|
static float Magnitude(const Vector2& v);
|
|||
|
|
static Vector2 Lerp(const Vector2& a, const Vector2& b, float t);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
struct Vector3 {
|
|||
|
|
float x, y, z;
|
|||
|
|
|
|||
|
|
static Vector3 Zero() { return Vector3{0, 0, 0}; }
|
|||
|
|
static Vector3 One() { return Vector3{1, 1, 1}; }
|
|||
|
|
static Vector3 Forward() { return Vector3{0, 0, 1}; }
|
|||
|
|
static Vector3 Back() { return Vector3{0, 0, -1}; }
|
|||
|
|
static Vector3 Up() { return Vector3{0, 1, 0}; }
|
|||
|
|
static Vector3 Down() { return Vector3{0, -1, 0}; }
|
|||
|
|
static Vector3 Right() { return Vector3{1, 0, 0}; }
|
|||
|
|
static Vector3 Left() { return Vector3{-1, 0, 0}; }
|
|||
|
|
|
|||
|
|
static Vector3 Cross(const Vector3& a, const Vector3& b);
|
|||
|
|
static float Dot(const Vector3& a, const Vector3& b);
|
|||
|
|
static Vector3 Normalize(const Vector3& v);
|
|||
|
|
static float Magnitude(const Vector3& v);
|
|||
|
|
static float SqrMagnitude(const Vector3& v);
|
|||
|
|
static Vector3 Lerp(const Vector3& a, const Vector3& b, float t);
|
|||
|
|
static Vector3 MoveTowards(const Vector3& current, const Vector3& target, float maxDistance);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
struct Vector4 { float x, y, z, w; };
|
|||
|
|
|
|||
|
|
struct Matrix3x3 {
|
|||
|
|
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)
|
|||
|
|
|
|||
|
|
```cpp
|
|||
|
|
namespace XCEngine {
|
|||
|
|
namespace Memory {
|
|||
|
|
|
|||
|
|
class IAllocator {
|
|||
|
|
public:
|
|||
|
|
virtual ~IAllocator() = default;
|
|||
|
|
|
|||
|
|
virtual void* Allocate(size_t size, size_t alignment = 0) = 0;
|
|||
|
|
virtual void Free(void* ptr) = 0;
|
|||
|
|
virtual void* Reallocate(void* ptr, size_t newSize) = 0;
|
|||
|
|
|
|||
|
|
virtual size_t GetTotalAllocated() const = 0;
|
|||
|
|
virtual size_t GetTotalFreed() const = 0;
|
|||
|
|
virtual size_t GetPeakAllocated() const = 0;
|
|||
|
|
virtual size_t GetAllocationCount() const = 0;
|
|||
|
|
|
|||
|
|
virtual const char* GetName() const = 0;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
class LinearAllocator : public IAllocator {
|
|||
|
|
public:
|
|||
|
|
explicit LinearAllocator(size_t size, IAllocator* parent = nullptr);
|
|||
|
|
~LinearAllocator();
|
|||
|
|
|
|||
|
|
void* Allocate(size_t size, size_t alignment = 8) override;
|
|||
|
|
void Free(void* ptr) override;
|
|||
|
|
void Clear();
|
|||
|
|
|
|||
|
|
void* GetMarker() const;
|
|||
|
|
void SetMarker(void* marker);
|
|||
|
|
|
|||
|
|
private:
|
|||
|
|
byte* m_buffer = nullptr;
|
|||
|
|
size_t m_capacity = 0;
|
|||
|
|
size_t m_offset = 0;
|
|||
|
|
IAllocator* m_parent = nullptr;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
class PoolAllocator : public IAllocator {
|
|||
|
|
public:
|
|||
|
|
PoolAllocator(size_t blockSize, size_t poolSize, size_t alignment = 8);
|
|||
|
|
~PoolAllocator();
|
|||
|
|
|
|||
|
|
void* Allocate(size_t size, size_t alignment = 0) override;
|
|||
|
|
void Free(void* ptr) override;
|
|||
|
|
|
|||
|
|
bool Contains(void* ptr) const;
|
|||
|
|
size_t GetBlockSize() const { return m_blockSize; }
|
|||
|
|
size_t GetFreeBlockCount() const;
|
|||
|
|
|
|||
|
|
private:
|
|||
|
|
struct FreeNode {
|
|||
|
|
FreeNode* next;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
size_t m_blockSize = 0;
|
|||
|
|
size_t m_alignment = 0;
|
|||
|
|
void* m_memory = nullptr;
|
|||
|
|
FreeNode* m_freeList = nullptr;
|
|||
|
|
size_t m_totalBlocks = 0;
|
|||
|
|
size_t m_freeBlocks = 0;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
class ProxyAllocator : public IAllocator {
|
|||
|
|
public:
|
|||
|
|
ProxyAllocator(IAllocator* underlying, const char* name);
|
|||
|
|
|
|||
|
|
void* Allocate(size_t size, size_t alignment = 0) override;
|
|||
|
|
void Free(void* ptr) override;
|
|||
|
|
void* Reallocate(void* ptr, size_t newSize) override;
|
|||
|
|
|
|||
|
|
struct Stats {
|
|||
|
|
size_t totalAllocated;
|
|||
|
|
size_t totalFreed;
|
|||
|
|
size_t peakAllocated;
|
|||
|
|
size_t allocationCount;
|
|||
|
|
size_t memoryOverhead;
|
|||
|
|
};
|
|||
|
|
const Stats& GetStats() const;
|
|||
|
|
|
|||
|
|
private:
|
|||
|
|
IAllocator* m_underlying;
|
|||
|
|
const char* m_name;
|
|||
|
|
Stats m_stats;
|
|||
|
|
Mutex m_mutex;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
class MemoryManager {
|
|||
|
|
public:
|
|||
|
|
static MemoryManager& Get();
|
|||
|
|
|
|||
|
|
void Initialize();
|
|||
|
|
void Shutdown();
|
|||
|
|
|
|||
|
|
IAllocator* GetSystemAllocator();
|
|||
|
|
|
|||
|
|
std::unique_ptr<LinearAllocator> CreateLinearAllocator(size_t size);
|
|||
|
|
std::unique_ptr<PoolAllocator> CreatePoolAllocator(size_t blockSize, size_t count);
|
|||
|
|
std::unique_ptr<ProxyAllocator> CreateProxyAllocator(const char* name);
|
|||
|
|
|
|||
|
|
void SetTrackAllocations(bool track);
|
|||
|
|
void DumpMemoryLeaks();
|
|||
|
|
void GenerateMemoryReport();
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
#define XE_ALLOC(allocator, size, ...) allocator->Allocate(size, ##__VA_ARGS__)
|
|||
|
|
#define XE_FREE(allocator, ptr) allocator->Free(ptr)
|
|||
|
|
|
|||
|
|
} // namespace Memory
|
|||
|
|
} // namespace XCEngine
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 1.3 容器库 (Containers)
|
|||
|
|
|
|||
|
|
```cpp
|
|||
|
|
namespace XCEngine {
|
|||
|
|
namespace Containers {
|
|||
|
|
|
|||
|
|
template<typename T>
|
|||
|
|
class Array {
|
|||
|
|
public:
|
|||
|
|
using Iterator = T*;
|
|||
|
|
using ConstIterator = const T*;
|
|||
|
|
|
|||
|
|
Array() = default;
|
|||
|
|
explicit Array(size_t capacity);
|
|||
|
|
Array(size_t count, const T& value);
|
|||
|
|
Array(std::initializer_list<T> init);
|
|||
|
|
~Array();
|
|||
|
|
|
|||
|
|
Array(const Array& other);
|
|||
|
|
Array(Array&& other) noexcept;
|
|||
|
|
Array& operator=(const Array& other);
|
|||
|
|
Array& operator=(Array&& other) noexcept;
|
|||
|
|
|
|||
|
|
T& operator[](size_t index);
|
|||
|
|
const T& operator[](size_t index) const;
|
|||
|
|
|
|||
|
|
T* Data() { return m_data; }
|
|||
|
|
const T* Data() const { return m_data; }
|
|||
|
|
|
|||
|
|
size_t Size() const { return m_size; }
|
|||
|
|
size_t Capacity() const { return m_capacity; }
|
|||
|
|
|
|||
|
|
void Clear();
|
|||
|
|
void PushBack(const T& value);
|
|||
|
|
void PushBack(T&& value);
|
|||
|
|
template<typename... Args>
|
|||
|
|
T& EmplaceBack(Args&&... args);
|
|||
|
|
void PopBack();
|
|||
|
|
|
|||
|
|
private:
|
|||
|
|
T* m_data = nullptr;
|
|||
|
|
size_t m_size = 0;
|
|||
|
|
size_t m_capacity = 0;
|
|||
|
|
IAllocator* m_allocator = nullptr;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
class String {
|
|||
|
|
public:
|
|||
|
|
String();
|
|||
|
|
String(const char* str);
|
|||
|
|
String(const char* str, size_t len);
|
|||
|
|
~String();
|
|||
|
|
|
|||
|
|
String& operator+=(const String& other);
|
|||
|
|
String& operator+=(const char* str);
|
|||
|
|
|
|||
|
|
String Substring(size_t pos, size_t len = npos) const;
|
|||
|
|
String Trim() const;
|
|||
|
|
String ToLower() const;
|
|||
|
|
String ToUpper() const;
|
|||
|
|
|
|||
|
|
size_t Find(const char* str, size_t pos = 0) const;
|
|||
|
|
bool StartsWith(const String& prefix) const;
|
|||
|
|
bool EndsWith(const String& suffix) const;
|
|||
|
|
|
|||
|
|
const char* CStr() const { return m_data; }
|
|||
|
|
size_t Length() const { return m_length; }
|
|||
|
|
|
|||
|
|
private:
|
|||
|
|
char* m_data = nullptr;
|
|||
|
|
size_t m_length = 0;
|
|||
|
|
size_t m_capacity = 0;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
template<typename Key, typename Value>
|
|||
|
|
class HashMap {
|
|||
|
|
public:
|
|||
|
|
struct Pair {
|
|||
|
|
Key first;
|
|||
|
|
Value second;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
HashMap() = default;
|
|||
|
|
explicit HashMap(size_t bucketCount, IAllocator* allocator = nullptr);
|
|||
|
|
|
|||
|
|
Value& operator[](const Key& key);
|
|||
|
|
Value* Find(const Key& key);
|
|||
|
|
const Value* Find(const Key& key) const;
|
|||
|
|
bool Contains(const Key& key) const;
|
|||
|
|
|
|||
|
|
bool Insert(const Key& key, const Value& value);
|
|||
|
|
bool Erase(const Key& key);
|
|||
|
|
void Clear();
|
|||
|
|
|
|||
|
|
size_t Size() const { return m_size; }
|
|||
|
|
|
|||
|
|
private:
|
|||
|
|
size_t GetBucketIndex(const Key& key) const;
|
|||
|
|
void Resize();
|
|||
|
|
|
|||
|
|
struct Bucket {
|
|||
|
|
Array<Pair> pairs;
|
|||
|
|
};
|
|||
|
|
Array<Bucket> m_buckets;
|
|||
|
|
size_t m_bucketCount = 0;
|
|||
|
|
size_t m_size = 0;
|
|||
|
|
float m_loadFactor = 0.75f;
|
|||
|
|
IAllocator* m_allocator = nullptr;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
} // namespace Containers
|
|||
|
|
} // namespace XCEngine
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 1.4 线程系统 (Threading)
|
|||
|
|
|
|||
|
|
```cpp
|
|||
|
|
namespace XCEngine {
|
|||
|
|
namespace Threading {
|
|||
|
|
|
|||
|
|
enum class TaskPriority : uint8_t {
|
|||
|
|
Critical = 0,
|
|||
|
|
High = 1,
|
|||
|
|
Normal = 2,
|
|||
|
|
Low = 3,
|
|||
|
|
Idle = 4
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
enum class TaskStatus : uint8_t {
|
|||
|
|
Pending,
|
|||
|
|
Scheduled,
|
|||
|
|
Running,
|
|||
|
|
Completed,
|
|||
|
|
Failed,
|
|||
|
|
Canceled
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
template<typename T = void()>
|
|||
|
|
using Func = std::function<T>;
|
|||
|
|
|
|||
|
|
class ITask {
|
|||
|
|
public:
|
|||
|
|
virtual ~ITask() = default;
|
|||
|
|
|
|||
|
|
virtual void Execute() = 0;
|
|||
|
|
virtual void OnComplete() {}
|
|||
|
|
virtual void OnCancel() {}
|
|||
|
|
|
|||
|
|
TaskPriority GetPriority() const { return m_priority; }
|
|||
|
|
TaskStatus GetStatus() const { return m_status; }
|
|||
|
|
uint64 GetId() const { return m_id; }
|
|||
|
|
|
|||
|
|
protected:
|
|||
|
|
TaskPriority m_priority = TaskPriority::Normal;
|
|||
|
|
TaskStatus m_status = TaskStatus::Pending;
|
|||
|
|
uint64 m_id = 0;
|
|||
|
|
std::atomic<uint32> m_refCount{1};
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
template<typename Func>
|
|||
|
|
class LambdaTask : public ITask {
|
|||
|
|
public:
|
|||
|
|
explicit LambdaTask(Func&& func, TaskPriority priority = TaskPriority::Normal)
|
|||
|
|
: m_func(std::move(func)), m_priority(priority) {}
|
|||
|
|
|
|||
|
|
void Execute() override {
|
|||
|
|
m_func();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private:
|
|||
|
|
Func m_func;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
class TaskGroup {
|
|||
|
|
public:
|
|||
|
|
using Callback = std::function<void()>;
|
|||
|
|
|
|||
|
|
TaskGroup();
|
|||
|
|
~TaskGroup();
|
|||
|
|
|
|||
|
|
uint64 AddTask(std::unique_ptr<ITask> task);
|
|||
|
|
uint64 AddTask(Func&& func, TaskPriority priority = TaskPriority::Normal);
|
|||
|
|
|
|||
|
|
void AddDependency(uint64 taskId, uint64 dependsOn);
|
|||
|
|
void Wait();
|
|||
|
|
bool WaitFor(std::chrono::milliseconds timeout);
|
|||
|
|
|
|||
|
|
void SetCompleteCallback(Callback&& callback);
|
|||
|
|
bool IsComplete() const;
|
|||
|
|
float GetProgress() const;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
class TaskSystem {
|
|||
|
|
public:
|
|||
|
|
static TaskSystem& Get();
|
|||
|
|
|
|||
|
|
void Initialize(const TaskSystemConfig& config);
|
|||
|
|
void Shutdown();
|
|||
|
|
|
|||
|
|
uint64 Submit(std::unique_ptr<ITask> task);
|
|||
|
|
uint64 Submit(Func&& func, TaskPriority priority = TaskPriority::Normal);
|
|||
|
|
|
|||
|
|
TaskGroup* CreateTaskGroup();
|
|||
|
|
void DestroyTaskGroup(TaskGroup* group);
|
|||
|
|
|
|||
|
|
void Wait(uint64 taskId);
|
|||
|
|
uint32 GetWorkerThreadCount() const;
|
|||
|
|
|
|||
|
|
void Update();
|
|||
|
|
|
|||
|
|
template<typename Func>
|
|||
|
|
void ParallelFor(int32 start, int32 end, Func&& func);
|
|||
|
|
|
|||
|
|
void RunOnMainThread(Func&& func);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
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 日志与调试系统
|
|||
|
|
|
|||
|
|
```cpp
|
|||
|
|
namespace XCEngine {
|
|||
|
|
namespace Core {
|
|||
|
|
|
|||
|
|
template<typename... Args>
|
|||
|
|
class Event {
|
|||
|
|
public:
|
|||
|
|
using Callback = std::function<void(Args...)>;
|
|||
|
|
using Listener = std::pair<uint64_t, Callback>;
|
|||
|
|
using Iterator = typename std::vector<Listener>::iterator;
|
|||
|
|
|
|||
|
|
uint64_t Subscribe(Callback callback) {
|
|||
|
|
std::lock_guard<std::mutex> lock(m_mutex);
|
|||
|
|
uint64_t id = ++m_nextId;
|
|||
|
|
m_listeners.emplace_back(id, std::move(callback));
|
|||
|
|
return id;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void Unsubscribe(uint64_t id) {
|
|||
|
|
std::lock_guard<std::mutex> lock(m_mutex);
|
|||
|
|
m_pendingUnsubscribes.push_back(id);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void ProcessUnsubscribes() {
|
|||
|
|
std::lock_guard<std::mutex> lock(m_mutex);
|
|||
|
|
for (uint64_t id : m_pendingUnsubscribes) {
|
|||
|
|
m_listeners.erase(
|
|||
|
|
std::remove_if(m_listeners.begin(), m_listeners.end(),
|
|||
|
|
[id](const auto& pair) { return pair.first == id; }),
|
|||
|
|
m_listeners.end()
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
m_pendingUnsubscribes.clear();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void Invoke(Args... args) const {
|
|||
|
|
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 组件基类
|
|||
|
|
|
|||
|
|
```cpp
|
|||
|
|
namespace XCEngine {
|
|||
|
|
|
|||
|
|
class Scene;
|
|||
|
|
class GameObject;
|
|||
|
|
class TransformComponent;
|
|||
|
|
|
|||
|
|
// 组件类型注册(用于运行时类型识别)
|
|||
|
|
class ComponentTypeRegistry {
|
|||
|
|
public:
|
|||
|
|
static ComponentTypeRegistry& Get();
|
|||
|
|
|
|||
|
|
template<typename T>
|
|||
|
|
static uint32_t GetTypeId() {
|
|||
|
|
static uint32_t id = Get().Register(typeid(T).name(), static_cast<uint32_t>(-1));
|
|||
|
|
return id;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
template<typename T>
|
|||
|
|
static uint32_t GetTypeId(const char* typeName) {
|
|||
|
|
static uint32_t id = Get().Register(typeName, static_cast<uint32_t>(-1));
|
|||
|
|
return id;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static uint32_t GetTypeIdFromName(const char* typeName) {
|
|||
|
|
return Get().GetIdByName(typeName);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static const char* GetTypeName(uint32_t typeId) {
|
|||
|
|
return Get().GetNameById(typeId);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private:
|
|||
|
|
uint32_t Register(const char* typeName, uint32_t suggestedId);
|
|||
|
|
uint32_t GetIdByName(const char* typeName) const;
|
|||
|
|
const char* GetNameById(uint32_t typeId) const;
|
|||
|
|
|
|||
|
|
std::atomic<uint32_t> m_nextTypeId{0};
|
|||
|
|
std::unordered_map<uint32_t, String> m_idToName;
|
|||
|
|
std::unordered_map<String, uint32_t> m_nameToId;
|
|||
|
|
Mutex m_mutex;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 组件基类(类Unity MonoBehaviour)
|
|||
|
|
class Component {
|
|||
|
|
public:
|
|||
|
|
Component();
|
|||
|
|
virtual ~Component();
|
|||
|
|
|
|||
|
|
GameObject* gameObject() const { return m_gameObject; }
|
|||
|
|
TransformComponent& transform() const { return m_gameObject->GetTransform(); }
|
|||
|
|
|
|||
|
|
bool IsEnabled() const { return m_enabled; }
|
|||
|
|
void SetEnabled(bool enabled) { m_enabled = enabled; }
|
|||
|
|
|
|||
|
|
Scene* GetScene() const;
|
|||
|
|
|
|||
|
|
template<typename T>
|
|||
|
|
T* GetComponent() const { return m_gameObject->GetComponent<T>(); }
|
|||
|
|
|
|||
|
|
template<typename T>
|
|||
|
|
std::vector<T*> GetComponents() const { return m_gameObject->GetComponents<T>(); }
|
|||
|
|
|
|||
|
|
virtual void Awake() {}
|
|||
|
|
virtual void Start() {}
|
|||
|
|
virtual void Update(float deltaTime) {}
|
|||
|
|
virtual void FixedUpdate() {}
|
|||
|
|
virtual void LateUpdate(float deltaTime) {}
|
|||
|
|
virtual void OnDestroy() {}
|
|||
|
|
virtual void OnEnable() {}
|
|||
|
|
virtual void OnDisable() {}
|
|||
|
|
|
|||
|
|
protected:
|
|||
|
|
GameObject* m_gameObject = nullptr;
|
|||
|
|
bool m_enabled = true;
|
|||
|
|
|
|||
|
|
friend class GameObject;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
} // namespace XCEngine
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2.2 Transform组件
|
|||
|
|
|
|||
|
|
```cpp
|
|||
|
|
namespace XCEngine {
|
|||
|
|
|
|||
|
|
class TransformComponent : public Component {
|
|||
|
|
public:
|
|||
|
|
Vector3 GetLocalPosition() const { return m_localPosition; }
|
|||
|
|
void SetLocalPosition(const Vector3& position) { m_localPosition = position; SetDirty(); }
|
|||
|
|
|
|||
|
|
Quaternion GetLocalRotation() const { return m_localRotation; }
|
|||
|
|
void SetLocalRotation(const Quaternion& rotation) { m_localRotation = rotation; SetDirty(); }
|
|||
|
|
|
|||
|
|
Vector3 GetLocalScale() const { return m_localScale; }
|
|||
|
|
void SetLocalScale(const Vector3& scale) { m_localScale = scale; SetDirty(); }
|
|||
|
|
|
|||
|
|
Vector3 GetPosition() const;
|
|||
|
|
void SetPosition(const Vector3& position);
|
|||
|
|
|
|||
|
|
Quaternion GetRotation() const;
|
|||
|
|
void SetRotation(const Quaternion& rotation);
|
|||
|
|
|
|||
|
|
Vector3 GetScale() const;
|
|||
|
|
void SetScale(const Vector3& scale);
|
|||
|
|
|
|||
|
|
Vector3 GetForward() const { return GetRotation() * Vector3::Forward(); }
|
|||
|
|
Vector3 GetRight() const { return GetRotation() * Vector3::Right(); }
|
|||
|
|
Vector3 GetUp() const { return GetRotation() * Vector3::Up(); }
|
|||
|
|
|
|||
|
|
const Matrix4x4& GetLocalToWorldMatrix() const;
|
|||
|
|
Matrix4x4 GetWorldToLocalMatrix() const;
|
|||
|
|
|
|||
|
|
TransformComponent* GetParent() const { return m_parent; }
|
|||
|
|
void SetParent(TransformComponent* parent, bool worldPositionStays = true);
|
|||
|
|
|
|||
|
|
int GetChildCount() const { return static_cast<int>(m_children.size()); }
|
|||
|
|
TransformComponent* GetChild(int index) const;
|
|||
|
|
TransformComponent* Find(const String& name) const;
|
|||
|
|
|
|||
|
|
void DetachChildren();
|
|||
|
|
void SetAsFirstSibling();
|
|||
|
|
void SetAsLastSibling();
|
|||
|
|
void SetSiblingIndex(int index);
|
|||
|
|
int GetSiblingIndex() const;
|
|||
|
|
|
|||
|
|
void LookAt(const Vector3& target);
|
|||
|
|
void LookAt(const Vector3& target, const Vector3& up);
|
|||
|
|
void Rotate(const Vector3& eulers);
|
|||
|
|
void Rotate(const Vector3& axis, float angle);
|
|||
|
|
void Translate(const Vector3& translation);
|
|||
|
|
void Translate(const Vector3& translation, Math::Space relativeTo);
|
|||
|
|
|
|||
|
|
Vector3 TransformPoint(const Vector3& point) const;
|
|||
|
|
Vector3 InverseTransformPoint(const Vector3& point) const;
|
|||
|
|
Vector3 TransformDirection(const Vector3& direction) const;
|
|||
|
|
Vector3 InverseTransformDirection(const Vector3& direction) const;
|
|||
|
|
|
|||
|
|
void SetDirty() { m_dirty = true; }
|
|||
|
|
|
|||
|
|
private:
|
|||
|
|
Vector3 m_localPosition = Vector3::Zero();
|
|||
|
|
Quaternion m_localRotation = Quaternion::Identity();
|
|||
|
|
Vector3 m_localScale = Vector3::One();
|
|||
|
|
|
|||
|
|
TransformComponent* m_parent = nullptr;
|
|||
|
|
std::vector<TransformComponent*> m_children;
|
|||
|
|
|
|||
|
|
mutable Matrix4x4 m_localToWorldMatrix;
|
|||
|
|
mutable Matrix4x4 m_worldToLocalMatrix;
|
|||
|
|
mutable Vector3 m_worldPosition;
|
|||
|
|
mutable Quaternion m_worldRotation;
|
|||
|
|
mutable Vector3 m_worldScale;
|
|||
|
|
mutable bool m_dirty = true;
|
|||
|
|
|
|||
|
|
void UpdateWorldTransform() const;
|
|||
|
|
|
|||
|
|
friend class GameObject;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
} // namespace XCEngine
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2.3 GameObject
|
|||
|
|
|
|||
|
|
```cpp
|
|||
|
|
namespace XCEngine {
|
|||
|
|
|
|||
|
|
class Scene;
|
|||
|
|
|
|||
|
|
class GameObject {
|
|||
|
|
public:
|
|||
|
|
GameObject();
|
|||
|
|
~GameObject();
|
|||
|
|
|
|||
|
|
struct ConstructParams {
|
|||
|
|
String name = "GameObject";
|
|||
|
|
GameObject* parent = nullptr;
|
|||
|
|
bool active = true;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
static GameObject* Create(const ConstructParams& params = {});
|
|||
|
|
static void Destroy(GameObject* obj);
|
|||
|
|
|
|||
|
|
String name;
|
|||
|
|
bool active = true;
|
|||
|
|
|
|||
|
|
TransformComponent& GetTransform() { return *m_transform; }
|
|||
|
|
const TransformComponent& GetTransform() const { return *m_transform; }
|
|||
|
|
|
|||
|
|
Scene* GetScene() const { return m_scene; }
|
|||
|
|
|
|||
|
|
template<typename T>
|
|||
|
|
T* AddComponent();
|
|||
|
|
|
|||
|
|
template<typename T>
|
|||
|
|
void RemoveComponent();
|
|||
|
|
|
|||
|
|
template<typename T>
|
|||
|
|
T* GetComponent() const;
|
|||
|
|
|
|||
|
|
template<typename T>
|
|||
|
|
std::vector<T*> GetComponents() const;
|
|||
|
|
|
|||
|
|
template<typename T>
|
|||
|
|
T* GetComponentInChildren() const;
|
|||
|
|
|
|||
|
|
template<typename T>
|
|||
|
|
std::vector<T*> GetComponentsInChildren() const;
|
|||
|
|
|
|||
|
|
template<typename T>
|
|||
|
|
T* GetComponentInParent() const;
|
|||
|
|
|
|||
|
|
GameObject* GetParent() const;
|
|||
|
|
void SetParent(GameObject* parent);
|
|||
|
|
void SetParent(GameObject* parent, bool worldPositionStays);
|
|||
|
|
const std::vector<GameObject*>& GetChildren() const;
|
|||
|
|
GameObject* GetChild(int index) const;
|
|||
|
|
int GetChildCount() const;
|
|||
|
|
int GetSiblingIndex() const;
|
|||
|
|
void SetSiblingIndex(int index);
|
|||
|
|
|
|||
|
|
void SetActive(bool active);
|
|||
|
|
bool IsActive() const;
|
|||
|
|
bool IsActiveInHierarchy() const;
|
|||
|
|
|
|||
|
|
static GameObject* Find(const String& name);
|
|||
|
|
static std::vector<GameObject*> FindObjectsOfType();
|
|||
|
|
static std::vector<GameObject*> FindGameObjectsWithTag(const String& tag);
|
|||
|
|
|
|||
|
|
void Destroy();
|
|||
|
|
|
|||
|
|
private:
|
|||
|
|
void AddComponentInternal(Component* component);
|
|||
|
|
void RemoveComponentInternal(Component* component);
|
|||
|
|
|
|||
|
|
std::vector<std::unique_ptr<Component>> m_components;
|
|||
|
|
std::unordered_map<uint32_t, size_t> m_componentTypeIndex;
|
|||
|
|
|
|||
|
|
std::vector<GameObject*> m_children;
|
|||
|
|
GameObject* m_parent = nullptr;
|
|||
|
|
Scene* m_scene = nullptr;
|
|||
|
|
|
|||
|
|
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
|
|||
|
|
|
|||
|
|
```cpp
|
|||
|
|
namespace XCEngine {
|
|||
|
|
|
|||
|
|
class Scene {
|
|||
|
|
public:
|
|||
|
|
Scene();
|
|||
|
|
~Scene();
|
|||
|
|
|
|||
|
|
const String& GetName() const { return m_name; }
|
|||
|
|
void SetName(const String& name) { m_name = name; }
|
|||
|
|
|
|||
|
|
GameObject* CreateGameObject(const String& name = "GameObject") {
|
|||
|
|
GameObject::ConstructParams params;
|
|||
|
|
params.name = name;
|
|||
|
|
params.parent = nullptr;
|
|||
|
|
params.active = true;
|
|||
|
|
|
|||
|
|
GameObject* obj = GameObject::Create(params);
|
|||
|
|
obj->m_scene = this;
|
|||
|
|
AddGameObject(obj);
|
|||
|
|
return obj;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
GameObject* CreateGameObject(const String& name, GameObject* parent) {
|
|||
|
|
GameObject::ConstructParams params;
|
|||
|
|
params.name = name;
|
|||
|
|
params.parent = parent;
|
|||
|
|
params.active = true;
|
|||
|
|
|
|||
|
|
GameObject* obj = GameObject::Create(params);
|
|||
|
|
obj->m_scene = this;
|
|||
|
|
AddGameObject(obj);
|
|||
|
|
return obj;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void DestroyGameObject(GameObject* obj);
|
|||
|
|
|
|||
|
|
std::vector<GameObject*> GetRootGameObjects() const {
|
|||
|
|
std::vector<GameObject*> roots;
|
|||
|
|
roots.reserve(m_gameObjects.size() / 2);
|
|||
|
|
for (auto& obj : m_gameObjects) {
|
|||
|
|
if (obj->GetParent() == nullptr) {
|
|||
|
|
roots.push_back(obj.get());
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return roots;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
GameObject* Find(const String& name) const;
|
|||
|
|
GameObject* FindGameObjectWithTag(const String& tag) const;
|
|||
|
|
std::vector<GameObject*> FindGameObjectsWithTag(const String& tag) const;
|
|||
|
|
template<typename T>
|
|||
|
|
std::vector<T*> FindObjectsOfType() const;
|
|||
|
|
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 公共类型定义
|
|||
|
|
|
|||
|
|
```cpp
|
|||
|
|
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 抽象层接口
|
|||
|
|
|
|||
|
|
```cpp
|
|||
|
|
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 实现
|
|||
|
|
|
|||
|
|
```cpp
|
|||
|
|
// ============================================
|
|||
|
|
// 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 相机组件
|
|||
|
|
|
|||
|
|
```cpp
|
|||
|
|
namespace XCEngine {
|
|||
|
|
|
|||
|
|
class CameraComponent : public Component {
|
|||
|
|
public:
|
|||
|
|
void Awake() override;
|
|||
|
|
void Start() override;
|
|||
|
|
void Update(float deltaTime) override;
|
|||
|
|
|
|||
|
|
enum class ProjectionType : uint8_t {
|
|||
|
|
Perspective,
|
|||
|
|
Orthographic
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
void SetProjectionType(ProjectionType type) { m_projectionType = type; }
|
|||
|
|
ProjectionType GetProjectionType() const { return m_projectionType; }
|
|||
|
|
|
|||
|
|
void SetFieldOfView(float fov) { m_fieldOfView = fov; }
|
|||
|
|
float GetFieldOfView() const { return m_fieldOfView; }
|
|||
|
|
|
|||
|
|
void SetOrthographicSize(float size) { m_orthographicSize = size; }
|
|||
|
|
float GetOrthographicSize() const { return m_orthographicSize; }
|
|||
|
|
|
|||
|
|
void SetNearClipPlane(float near) { m_nearPlane = near; }
|
|||
|
|
float GetNearClipPlane() const { return m_nearPlane; }
|
|||
|
|
|
|||
|
|
void SetFarClipPlane(float far) { m_farPlane = far; }
|
|||
|
|
float GetFarClipPlane() const { return m_farPlane; }
|
|||
|
|
|
|||
|
|
void SetViewport(const Rect& rect) { m_viewportRect = rect; }
|
|||
|
|
const Rect& GetViewport() const { return m_viewportRect; }
|
|||
|
|
|
|||
|
|
void SetCullingMask(int32_t mask) { m_cullingMask = mask; }
|
|||
|
|
int32_t GetCullingMask() const { return m_cullingMask; }
|
|||
|
|
|
|||
|
|
void SetDepth(float depth) { m_depth = depth; }
|
|||
|
|
float GetDepth() const { return m_depth; }
|
|||
|
|
|
|||
|
|
Matrix4x4 GetViewMatrix() const;
|
|||
|
|
Matrix4x4 GetProjectionMatrix() const;
|
|||
|
|
Matrix4x4 GetViewProjectionMatrix() const;
|
|||
|
|
|
|||
|
|
Vector3 ScreenToWorldPoint(const Vector3& screenPoint) const;
|
|||
|
|
Vector3 WorldToScreenPoint(const Vector3& worldPoint) const;
|
|||
|
|
Ray ScreenPointToRay(const Vector2& screenPoint) const;
|
|||
|
|
|
|||
|
|
Frustum& GetFrustum() { return m_frustum; }
|
|||
|
|
|
|||
|
|
private:
|
|||
|
|
ProjectionType m_projectionType = ProjectionType::Perspective;
|
|||
|
|
float m_fieldOfView = 60.0f;
|
|||
|
|
float m_orthographicSize = 5.0f;
|
|||
|
|
float m_nearPlane = 0.1f;
|
|||
|
|
float m_farPlane = 1000.0f;
|
|||
|
|
float m_aspectRatio = 16.0f / 9.0f;
|
|||
|
|
Rect m_viewportRect = Rect(0, 0, 1, 1);
|
|||
|
|
float m_depth = 0.0f;
|
|||
|
|
int32_t m_cullingMask = -1;
|
|||
|
|
Frustum m_frustum;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
} // namespace XCEngine
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 4.5 光照组件
|
|||
|
|
|
|||
|
|
```cpp
|
|||
|
|
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 渲染网格组件
|
|||
|
|
|
|||
|
|
```cpp
|
|||
|
|
namespace XCEngine {
|
|||
|
|
|
|||
|
|
class RenderMeshComponent : public Component {
|
|||
|
|
public:
|
|||
|
|
void Awake() override;
|
|||
|
|
void Start() override;
|
|||
|
|
void Update(float deltaTime) override;
|
|||
|
|
|
|||
|
|
ResourceGUID GetMesh() const { return m_meshGuid; }
|
|||
|
|
void SetMesh(const ResourceGUID& guid);
|
|||
|
|
|
|||
|
|
ResourceGUID GetMaterial() const { return m_materialGuid; }
|
|||
|
|
void SetMaterial(const ResourceGUID& guid);
|
|||
|
|
|
|||
|
|
bool GetCastShadows() const { return m_castShadows; }
|
|||
|
|
void SetCastShadows(bool cast) { m_castShadows = cast; }
|
|||
|
|
|
|||
|
|
bool GetReceiveShadows() const { return m_receiveShadows; }
|
|||
|
|
void SetReceiveShadows(bool receive) { m_receiveShadows = receive; }
|
|||
|
|
|
|||
|
|
private:
|
|||
|
|
ResourceGUID m_meshGuid;
|
|||
|
|
ResourceGUID m_materialGuid;
|
|||
|
|
bool m_castShadows = true;
|
|||
|
|
bool m_receiveShadows = true;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
} // namespace XCEngine
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 4.7 材质系统
|
|||
|
|
|
|||
|
|
```cpp
|
|||
|
|
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 渲染管线
|
|||
|
|
|
|||
|
|
```cpp
|
|||
|
|
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
|