Update API documentation and remove obsolete plan files
This commit is contained in:
@@ -1,403 +0,0 @@
|
||||
# D3D12 Texture 封装架构修复方案
|
||||
|
||||
## 1. 问题分析
|
||||
|
||||
### 1.1 当前问题
|
||||
|
||||
**问题 A:双重 Texture 包装导致悬垂指针**
|
||||
|
||||
```cpp
|
||||
// D3D12SwapChain 内部:
|
||||
std::vector<D3D12Texture> m_backBuffers; // SwapChain 内部的包装
|
||||
|
||||
// minimal/main.cpp:
|
||||
D3D12Texture gColorRTs[2]; // 用户代码又创建了一套包装!
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
ID3D12Resource* buffer = nullptr;
|
||||
gSwapChain.GetSwapChain()->GetBuffer(i, IID_PPV_ARGS(&buffer)); // 获取原生指针
|
||||
gColorRTs[i].InitializeFromExisting(buffer); // 再包装一次
|
||||
}
|
||||
```
|
||||
|
||||
**问题**:
|
||||
- `m_backBuffers[i]` 和 `gColorRTs[i]` 是两个不同的 `D3D12Texture` 对象
|
||||
- 但它们内部都持有指向**同一个** `ID3D12Resource` 的 `ComPtr`
|
||||
- 当其中一个调用 `Shutdown()` → `m_resource.Reset()`,另一个就变成悬垂指针!
|
||||
|
||||
**问题 B:`InitializeFromExisting` 不区分所有权语义**
|
||||
|
||||
```cpp
|
||||
void D3D12Texture::Shutdown() {
|
||||
m_resource.Reset(); // 无条件释放资源
|
||||
}
|
||||
```
|
||||
|
||||
如果通过 `InitializeFromExisting` 包装了 SwapChain 的 back buffer,Shutdown 会错误地释放它!
|
||||
|
||||
**问题 C:`D3D12SwapChain::GetBackBuffer()` 返回内部引用,用户可能误用**
|
||||
|
||||
```cpp
|
||||
D3D12Texture* D3D12SwapChain::GetBackBuffer(uint32_t index) const {
|
||||
return const_cast<D3DTexture*>(&m_backBuffers[index]); // 返回内部成员引用
|
||||
}
|
||||
|
||||
// 用户可能写出:
|
||||
D3D12Texture* rt = gSwapChain.GetBackBuffer(0);
|
||||
gSwapChain.Shutdown(); // rt 变成悬垂指针!
|
||||
```
|
||||
|
||||
### 1.2 问题根因
|
||||
|
||||
| 问题 | 根因 |
|
||||
|------|------|
|
||||
| 双重包装 | 没有阻止用户创建额外的包装 |
|
||||
| 所有权模糊 | `InitializeFromExisting` 不区分"接管"和"借用" |
|
||||
| 悬垂引用 | `GetBackBuffer` 返回内部指针,生命周期不安全 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 修复方案
|
||||
|
||||
### 2.1 方案概述
|
||||
|
||||
引入**所有权语义标记**和**生命周期安全保证**:
|
||||
|
||||
1. **`InitializeFromExisting` 增加 `ownsResource` 参数**
|
||||
2. **`D3D12Texture` 内部根据标记决定是否释放资源**
|
||||
3. **`D3D12SwapChain::GetBackBuffer` 返回安全引用(弱引用或克隆)**
|
||||
4. **提供统一的 Back Buffer 访问接口,避免用户直接调用 `GetSwapChain()->GetBuffer()`**
|
||||
|
||||
### 2.2 详细设计
|
||||
|
||||
#### 2.2.1 修改 `D3D12Texture`
|
||||
|
||||
**文件**: `engine/include/XCEngine/RHI/D3D12/D3D12Texture.h`
|
||||
|
||||
```cpp
|
||||
class D3D12Texture : public RHITexture {
|
||||
public:
|
||||
D3D12Texture();
|
||||
~D3D12Texture() override;
|
||||
|
||||
// 创建并拥有资源
|
||||
bool Initialize(ID3D12Device* device, const D3D12_RESOURCE_DESC& desc,
|
||||
D3D12_RESOURCE_STATES initialState = D3D12_RESOURCE_STATE_COMMON);
|
||||
|
||||
// 包装已有资源,明确所有权语义
|
||||
// ownsResource = true : 获取所有权,Shutdown 时释放
|
||||
// ownsResource = false : 不获取所有权,Shutdown 时不释放
|
||||
bool InitializeFromExisting(ID3D12Resource* resource, bool ownsResource = false);
|
||||
|
||||
bool InitializeFromData(ID3D12Device* device, ID3D12GraphicsCommandList* commandList,
|
||||
const void* pixelData, uint32_t width, uint32_t height, DXGI_FORMAT format);
|
||||
bool InitializeDepthStencil(ID3D12Device* device, uint32_t width, uint32_t height,
|
||||
DXGI_FORMAT format = DXGI_FORMAT_D24_UNORM_S8_UINT);
|
||||
|
||||
void Shutdown() override;
|
||||
|
||||
ID3D12Resource* GetResource() const { return m_resource.Get(); }
|
||||
D3D12_RESOURCE_DESC GetDesc() const { return m_resource->GetDesc(); }
|
||||
|
||||
// 检查是否拥有资源所有权
|
||||
bool OwnsResource() const { return m_ownsResource; }
|
||||
|
||||
// ... 其他现有方法 ...
|
||||
|
||||
private:
|
||||
ComPtr<ID3D12Resource> m_resource;
|
||||
ResourceStates m_state = ResourceStates::Common;
|
||||
std::string m_name;
|
||||
bool m_ownsResource = false; // 新增:所有权标记
|
||||
};
|
||||
```
|
||||
|
||||
**文件**: `engine/src/RHI/D3D12/D3D12Texture.cpp`
|
||||
|
||||
```cpp
|
||||
bool D3D12Texture::InitializeFromExisting(ID3D12Resource* resource, bool ownsResource) {
|
||||
m_resource = resource;
|
||||
m_ownsResource = ownsResource; // 明确设置所有权
|
||||
return true;
|
||||
}
|
||||
|
||||
void D3D12Texture::Shutdown() {
|
||||
if (m_ownsResource) {
|
||||
// 仅当拥有所有权时才释放
|
||||
m_resource.Reset();
|
||||
}
|
||||
// 如果不拥有资源,只是清除引用,不释放底层的 COM 对象
|
||||
m_resource.Reset(); // ComPtr::Reset() 只是减少引用计数,不是释放
|
||||
// 但要注意:如果不拥有所有权,我们需要保留原始指针以防止意外释放
|
||||
// 实际上 ComPtr::Reset() 总是会调用 Release()
|
||||
// 所以我们需要用不同的策略
|
||||
}
|
||||
```
|
||||
|
||||
**等等,`ComPtr::Reset()` 总是会调用 Release()。如果我们要实现"不拥有但不释放",需要用原始指针存储。**
|
||||
|
||||
**修正方案**:
|
||||
|
||||
```cpp
|
||||
class D3D12Texture : public RHITexture {
|
||||
private:
|
||||
ComPtr<ID3D12Resource> m_resource; // 始终持有
|
||||
ID3D12Resource* m_externalResource = nullptr; // 外部资源指针(不拥有)
|
||||
bool m_ownsResource = false;
|
||||
|
||||
public:
|
||||
void Shutdown() override {
|
||||
if (m_ownsResource) {
|
||||
m_resource.Reset(); // 释放拥有的资源
|
||||
}
|
||||
// 如果是外部资源(不拥有),只是清除引用
|
||||
m_externalResource = nullptr;
|
||||
m_resource.Reset(); // 总是 Reset,因为 m_resource 可能持有原始指针的副本
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
**更简洁的方案**:让用户自己决定是否通过 `Initialize` 创建 texture。`InitializeFromExisting` 包装但不拥有,使用者负责保证生命周期。
|
||||
|
||||
---
|
||||
|
||||
#### 2.2.2 修改 `D3D12SwapChain`
|
||||
|
||||
**目标**:提供安全的 BackBuffer 访问接口,阻止用户创建重复包装。
|
||||
|
||||
**文件**: `engine/include/XCEngine/RHI/D3D12/D3D12SwapChain.h`
|
||||
|
||||
```cpp
|
||||
class D3D12SwapChain : public RHISwapChain {
|
||||
public:
|
||||
// ... 现有接口 ...
|
||||
|
||||
// 获取 BackBuffer - 返回引用而非指针,防止悬垂
|
||||
// 返回的引用在 SwapChain 存活期间有效
|
||||
D3D12Texture& GetBackBuffer(uint32_t index);
|
||||
const D3D12Texture& GetBackBuffer(uint32_t index) const;
|
||||
|
||||
// 获取当前 BackBuffer
|
||||
D3D12Texture& GetCurrentBackBuffer();
|
||||
const D3D12Texture& GetCurrentBackBuffer() const;
|
||||
|
||||
// 删除不安全的 GetSwapChain() 暴露方法!
|
||||
// 旧接口:IDXGISwapChain3* GetSwapChain() const { return m_swapChain.Get(); }
|
||||
// 新策略:如果确实需要原生指针,提供 GetNativeHandle() 但不返回具体类型
|
||||
|
||||
private:
|
||||
// 确保 BackBuffer 不能被外部直接修改
|
||||
void SetBackBuffer(uint32_t index, D3D12Texture& texture) = delete;
|
||||
};
|
||||
```
|
||||
|
||||
**修正 `GetBackBuffer` 返回值**:
|
||||
|
||||
```cpp
|
||||
D3D12Texture& D3D12SwapChain::GetBackBuffer(uint32_t index) {
|
||||
assert(index < m_backBuffers.size() && "BackBuffer index out of range");
|
||||
return m_backBuffers[index];
|
||||
}
|
||||
|
||||
const D3D12Texture& D3D12SwapChain::GetBackBuffer(uint32_t index) const {
|
||||
assert(index < m_backBuffers.size() && "BackBuffer index out of range");
|
||||
return m_backBuffers[index];
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 2.2.3 更新 `minimal/main.cpp`
|
||||
|
||||
```cpp
|
||||
// 修改前(有问题):
|
||||
for (int i = 0; i < 2; i++) {
|
||||
ID3D12Resource* buffer = nullptr;
|
||||
gSwapChain.GetSwapChain()->GetBuffer(i, IID_PPV_ARGS(&buffer)); // ❌ 原生 API
|
||||
gColorRTs[i].InitializeFromExisting(buffer);
|
||||
// ...
|
||||
}
|
||||
|
||||
// 修改后(使用封装):
|
||||
for (int i = 0; i < 2; i++) {
|
||||
// 直接使用封装好的 BackBuffer,不再重复包装
|
||||
D3D12Texture& backBuffer = gSwapChain.GetBackBuffer(i);
|
||||
|
||||
// RTV 创建
|
||||
CPUDescriptorHandle rtvCpuHandle = gRTVHeap.GetCPUDescriptorHandle(i);
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = { rtvCpuHandle.ptr };
|
||||
gRTVs[i].InitializeAt(device, backBuffer.GetResource(), rtvHandle, nullptr);
|
||||
}
|
||||
```
|
||||
|
||||
**但是**:`gColorRTs[i]` 仍然存在且被用于后续渲染。我们需要决定是:
|
||||
- 方案 A:直接使用 `gSwapChain.GetBackBuffer(i)` 替代 `gColorRTs[i]`
|
||||
- 方案 B:让 `gColorRTs[i]` 变成对 `gSwapChain.GetBackBuffer(i)` 的引用
|
||||
|
||||
**推荐方案 A**:移除 `gColorRTs` 数组,直接使用 `gSwapChain.GetBackBuffer()`。这样避免重复引用。
|
||||
|
||||
---
|
||||
|
||||
### 2.3 完整修改清单
|
||||
|
||||
| 文件 | 修改内容 |
|
||||
|------|----------|
|
||||
| `D3D12Texture.h` | 添加 `m_ownsResource` 成员,修改 `InitializeFromExisting` 签名 |
|
||||
| `D3D12Texture.cpp` | 实现所有权语义,`Shutdown` 根据所有权决定是否释放 |
|
||||
| `D3D12SwapChain.h` | 修改 `GetBackBuffer` 返回引用,删除 `GetSwapChain()` 暴露 |
|
||||
| `D3D12SwapChain.cpp` | 实现返回引用的 `GetBackBuffer`,添加断言检查 |
|
||||
| `minimal/main.cpp` | 使用封装后的 `GetBackBuffer()`,移除原生 API 调用 |
|
||||
| `TEST_SPEC.md` | 更新架构说明,移除已知限制 7.2 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 实施步骤
|
||||
|
||||
### Phase 1: 基础修改
|
||||
1. 修改 `D3D12Texture` 添加所有权语义
|
||||
2. 修改 `D3D12SwapChain` 的 `GetBackBuffer` 返回引用
|
||||
3. 运行单元测试确保基础功能正常
|
||||
|
||||
### Phase 2: 更新集成测试
|
||||
1. 修改 `minimal/main.cpp` 使用新的 `GetBackBuffer()` API
|
||||
2. 移除 `gColorRTs` 数组(如果可能)
|
||||
3. 验证截图功能正常
|
||||
|
||||
### Phase 3: 文档和清理
|
||||
1. 更新 `TEST_SPEC.md`
|
||||
2. 删除 `OpenGL_Test_Restructuring_Plan.md` 中对 D3D12 的过时引用
|
||||
3. 提交所有更改
|
||||
|
||||
---
|
||||
|
||||
## 4. 风险和注意事项
|
||||
|
||||
### 4.1 兼容性风险
|
||||
- `InitializeFromExisting` 签名变更会影响所有调用方
|
||||
- 需要检查所有使用此方法的代码
|
||||
|
||||
### 4.2 生命周期风险
|
||||
- `GetBackBuffer()` 返回的引用在 `Shutdown()` 后无效
|
||||
- 用户必须确保在 SwapChain 存活期间使用
|
||||
|
||||
### 4.3 ComPtr 行为澄清
|
||||
|
||||
```cpp
|
||||
// ComPtr::Reset() 调用 Release()
|
||||
// 如果多个 ComPtr 指向同一资源,Reset 只会减少引用计数
|
||||
// 只有最后一个 Reset 才会真正释放
|
||||
|
||||
ComPtr<ID3D12Resource> a = resource; // AddRef
|
||||
ComPtr<ID3D12Resource> b = resource; // AddRef
|
||||
|
||||
a.Reset(); // Release,资源仍未释放(b 还持有)
|
||||
b.Reset(); // 最后一个 Release,资源被释放
|
||||
```
|
||||
|
||||
**关键点**:如果 `D3D12Texture` 和 `m_backBuffers` 都持有同一个 `ID3D12Resource` 的 `ComPtr`,那么:
|
||||
- `gColorRTs[i].InitializeFromExisting(buffer)` 会让 `gColorRTs[i].m_resource` 指向 `buffer`
|
||||
- `m_backBuffers[i].InitializeFromExisting(buffer)` 已经让 `m_backBuffers[i].m_resource` 指向 `buffer`
|
||||
- 现在有两个 `ComPtr` 指向同一个资源
|
||||
|
||||
**问题**:这两个 `ComPtr` 是在不同对象中的,它们各自会增加引用计数。但原始的 `GetBuffer()` 返回的 `buffer` 指针被两个 `ComPtr` 接管了。
|
||||
|
||||
让我重新审视 `D3D12SwapChain::Initialize`:
|
||||
|
||||
```cpp
|
||||
m_backBuffers.resize(m_bufferCount);
|
||||
for (uint32_t i = 0; i < m_bufferCount; ++i) {
|
||||
ID3D12Resource* resource = nullptr;
|
||||
m_swapChain->GetBuffer(i, IID_PPV_ARGS(&resource)); // resource 的引用计数 = 1
|
||||
m_backBuffers[i].InitializeFromExisting(resource); // ComPtr 接管,引用计数 = 2
|
||||
}
|
||||
```
|
||||
|
||||
**问题**:`resource` 被传给了 `InitializeFromExisting`,ComPtr 构造时会 `AddRef`。但 `resource` 是局部变量,函数结束后 `resource` 局部变量销毁但不影响 COM 对象的引用计数。
|
||||
|
||||
等等,这里有个问题:
|
||||
|
||||
```cpp
|
||||
ID3D12Resource* resource = nullptr;
|
||||
m_swapChain->GetBuffer(i, IID_PPV_ARGS(&resource)); // GetBuffer 返回的指针赋给 resource,引用计数 = 1
|
||||
m_backBuffers[i].InitializeFromExisting(resource); // ComPtr 拷贝构造,引用计数 = 2
|
||||
// 函数结束,resource 局部变量销毁(不影响引用计数,因为是指针变量)
|
||||
```
|
||||
|
||||
所以 `m_backBuffers[i].m_resource` 和 `m_swapChain` 内部都持有同一个 COM 对象的引用。
|
||||
|
||||
然后 `minimal/main.cpp` 又做了一次:
|
||||
|
||||
```cpp
|
||||
ID3D12Resource* buffer = nullptr;
|
||||
gSwapChain.GetSwapChain()->GetBuffer(i, IID_PPV_ARGS(&buffer)); // buffer 引用计数 = 3
|
||||
gColorRTs[i].InitializeFromExisting(buffer); // gColorRTs[i].m_resource 引用计数 = 4
|
||||
// buffer 局部变量销毁
|
||||
```
|
||||
|
||||
现在有三个 `ComPtr`(`m_backBuffers[i].m_resource`, `gColorRTs[i].m_resource`, `m_swapChain` 内部)指向同一个对象。引用计数 = 4。
|
||||
|
||||
**这不是问题**!因为 `ComPtr` 的拷贝构造会 `AddRef`。最终:
|
||||
- `m_backBuffers[i]` 销毁 → 引用计数--
|
||||
- `gColorRTs[i]` 销毁 → 引用计数--
|
||||
- `m_swapChain` 销毁 → 引用计数--
|
||||
|
||||
引用计数最终归零,资源被正确释放。
|
||||
|
||||
**那问题是什么?**
|
||||
|
||||
回到 `Shutdown`:
|
||||
|
||||
```cpp
|
||||
void D3D12Texture::Shutdown() {
|
||||
m_resource.Reset(); // ComPtr::Reset() 调用 Release()
|
||||
}
|
||||
```
|
||||
|
||||
如果 `gColorRTs[i]` 先于 `m_swapChain` 销毁:
|
||||
- `gColorRTs[i].Shutdown()` → `m_resource.Reset()` → Release() → 引用计数从 4 变成 3
|
||||
- `m_swapChain` 销毁时 → 内部资源 Release() → 引用计数从 3 变成 2
|
||||
|
||||
**这也应该是正常的...**
|
||||
|
||||
但等等!`m_backBuffers[i]` 是在 `D3D12SwapChain` 内部的 vector 中:
|
||||
|
||||
```cpp
|
||||
std::vector<D3D12Texture> m_backBuffers;
|
||||
```
|
||||
|
||||
如果 `minimal/main.cpp` 中 `gSwapChain.Shutdown()` 被调用:
|
||||
- `D3D12SwapChain::~D3D12SwapChain()` 调用 `Shutdown()`
|
||||
- `Shutdown()` 调用 `m_swapChain.Reset()`(仅重置 swapchain 指针)
|
||||
- 然后 vector `m_backBuffers` 销毁,每个 `D3D12Texture` 析构调用 `Shutdown()`
|
||||
- 每个 `Shutdown()` 调用 `m_resource.Reset()` → 释放 back buffer
|
||||
|
||||
**但是**:`gColorRTs[i]` 是在全局变量中独立创建的:
|
||||
|
||||
```cpp
|
||||
D3D12Texture gColorRTs[2]; // 独立于 SwapChain
|
||||
```
|
||||
|
||||
如果 `gSwapChain.Shutdown()` 先执行,`m_backBuffers` 的 `m_resource` 被释放,那么 `gColorRTs[i].m_resource` 就变成悬垂的 `ComPtr`!
|
||||
|
||||
```cpp
|
||||
// gSwapChain.Shutdown() 执行后:
|
||||
m_backBuffers[0].m_resource.Reset(); // 资源被释放!
|
||||
// 但 gColorRTs[0].m_resource 仍然持有同一个(已释放的)指针!
|
||||
// 调用 gColorRTs[0].GetResource() 会返回已释放的 COM 对象!
|
||||
```
|
||||
|
||||
**这就是 bug!** 当 SwapChain 先 shutdown,用户代码中的 `gColorRTs` 就变成悬垂指针。
|
||||
|
||||
---
|
||||
|
||||
## 5. 最终结论
|
||||
|
||||
### 根因
|
||||
`minimal/main.cpp` 创建了与 `D3D12SwapChain` 内部 `m_backBuffers` **重复包装**的 `gColorRTs` 数组。当任何一个先销毁,另一个就变成悬垂指针。
|
||||
|
||||
### 修复方案
|
||||
1. **最小改动**:直接使用 `gSwapChain.GetBackBuffer(i)` 而非创建新的 `gColorRTs`
|
||||
2. **长期方案**:增强 `D3D12Texture` 的所有权语义,区分拥有和非拥有资源
|
||||
|
||||
### 实施
|
||||
按照第 2.3 节的修改清单执行。
|
||||
@@ -1,731 +0,0 @@
|
||||
# OpenGL 测试架构重构方案
|
||||
|
||||
本文档是 XCEngine 测试规范的 OpenGL 专项补充,旨在将 OpenGL 后端测试体系重构为与 D3D12 同样规范的标准架构。
|
||||
|
||||
**前置阅读**:
|
||||
- [tests/TEST_SPEC.md](../tests/TEST_SPEC.md) - 通用测试规范
|
||||
- [tests/RHI/D3D12/TEST_SPEC.md](./D3D12/TEST_SPEC.md) - D3D12 专项规范(参考模板)
|
||||
|
||||
**规范版本**: 1.0
|
||||
**最后更新**: 2026-03-20
|
||||
|
||||
---
|
||||
|
||||
## 1. 现状分析
|
||||
|
||||
### 1.1 当前目录结构
|
||||
|
||||
```
|
||||
tests/RHI/OpenGL/
|
||||
├── CMakeLists.txt # 混乱的一级配置
|
||||
├── fixtures/
|
||||
│ ├── OpenGLTestFixture.h
|
||||
│ └── OpenGLTestFixture.cpp
|
||||
├── test_device.cpp
|
||||
├── test_buffer.cpp # 被注释,未启用
|
||||
├── test_fence.cpp # 被注释,未启用
|
||||
├── test_texture.cpp
|
||||
├── test_shader.cpp # 被注释,未启用
|
||||
├── test_pipeline_state.cpp
|
||||
├── test_vertex_array.cpp
|
||||
├── test_command_list.cpp
|
||||
├── test_render_target_view.cpp
|
||||
├── test_depth_stencil_view.cpp
|
||||
├── test_swap_chain.cpp
|
||||
├── test_sampler.cpp
|
||||
└── Res/ # 空文件夹,无实际资源
|
||||
├── Data/
|
||||
├── Shader/
|
||||
└── Texture/
|
||||
```
|
||||
|
||||
### 1.2 当前测试统计
|
||||
|
||||
| 组件 | 文件 | 测试数 | 状态 |
|
||||
|------|------|--------|------|
|
||||
| Device | `test_device.cpp` | 6 | ✅ 启用 |
|
||||
| Buffer | `test_buffer.cpp` | 6 | ❌ 被注释 |
|
||||
| Fence | `test_fence.cpp` | 5 | ❌ 被注释 |
|
||||
| Texture | `test_texture.cpp` | 4 | ✅ 启用 |
|
||||
| Shader | `test_shader.cpp` | 4 | ❌ 被注释 |
|
||||
| PipelineState | `test_pipeline_state.cpp` | 3 | ✅ 启用 |
|
||||
| VertexArray | `test_vertex_array.cpp` | 1 | ✅ 启用 |
|
||||
| CommandList | `test_command_list.cpp` | 14 | ✅ 启用 |
|
||||
| Sampler | `test_sampler.cpp` | 2 | ✅ 启用 |
|
||||
| SwapChain | `test_swap_chain.cpp` | 3 | ✅ 启用 |
|
||||
| RTV | `test_render_target_view.cpp` | 2 | ✅ 启用 |
|
||||
| DSV | `test_depth_stencil_view.cpp` | 2 | ✅ 启用 |
|
||||
| **总计** | | **52** | **37 启用, 15 被注释** |
|
||||
|
||||
### 1.3 与 D3D12 对比
|
||||
|
||||
| 方面 | D3D12 (规范) | OpenGL (现状) |
|
||||
|------|-------------|--------------|
|
||||
| **目录分层** | `unit/` + `integration/` 分离 | 全部扁平 |
|
||||
| **CMake 结构** | 顶层 + unit + integration 三级 | 仅一级 |
|
||||
| **Fixture 设计** | 每测试独立设备 | 静态共享上下文 |
|
||||
| **被注释测试** | 无 | 3 个文件被注释 |
|
||||
| **集成测试** | 有 (Python + Golden Image) | **缺失** |
|
||||
| **测试规范文档** | `TEST_SPEC.md` | **缺失** |
|
||||
| **Res 资源** | 按测试隔离 | 空文件夹 |
|
||||
| **资源复制** | POST_BUILD 自动复制 | 未配置 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 问题详解
|
||||
|
||||
### 2.1 Fixture 设计缺陷
|
||||
|
||||
**当前问题**:
|
||||
```cpp
|
||||
// OpenGL - 静态成员所有测试共享,存在状态污染
|
||||
static GLFWwindow* m_window; // 共享窗口
|
||||
static bool m_contextInitialized; // 共享状态
|
||||
static OpenGLDevice* m_device; // 共享设备
|
||||
```
|
||||
|
||||
**D3D12 规范做法**:
|
||||
```cpp
|
||||
// 每个测试独立创建设备
|
||||
void D3D12TestFixture::SetUp() {
|
||||
D3D12CreateDevice(nullptr, D3D_FEATURE_LEVEL_12_0, ...);
|
||||
}
|
||||
```
|
||||
|
||||
**OpenGL 重构方向**:
|
||||
```cpp
|
||||
// 方案A: 每测试创建独立上下文 (推荐)
|
||||
class OpenGLTestFixture : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
// 创建独立 OpenGL 上下文
|
||||
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
|
||||
m_window = glfwCreateWindow(640, 480, "Test", nullptr, nullptr);
|
||||
glfwMakeContextCurrent(m_window);
|
||||
gladLoadGLLoader(...);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### 2.2 CMake 配置混乱
|
||||
|
||||
**当前问题**:
|
||||
```cmake
|
||||
# 硬编码绝对路径
|
||||
include_directories(${CMAKE_SOURCE_DIR}/tests/OpenPackage/include/)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/tests/OpenPackage/lib/)
|
||||
link_directories(${CMAKE_SOURCE_DIR}/tests/OpenPackage/lib/)
|
||||
|
||||
# 被注释的测试源文件
|
||||
# test_buffer.cpp
|
||||
# test_fence.cpp
|
||||
# test_shader.cpp
|
||||
```
|
||||
|
||||
**D3D12 规范做法**:
|
||||
```cmake
|
||||
# 顶层 CMakeLists.txt 仅做 add_subdirectory
|
||||
add_subdirectory(unit)
|
||||
add_subdirectory(integration)
|
||||
|
||||
# unit/CMakeLists.txt 独立配置
|
||||
# integration/CMakeLists.txt 独立配置
|
||||
```
|
||||
|
||||
### 2.3 资源目录为空
|
||||
|
||||
当前 `Res/` 下的 `Data/`、`Shader/`、`Texture/` 均为空目录,没有实际测试资源。
|
||||
|
||||
---
|
||||
|
||||
## 3. 重构目标
|
||||
|
||||
### 3.1 目标目录结构
|
||||
|
||||
```
|
||||
tests/RHI/OpenGL/
|
||||
├── CMakeLists.txt # 顶层配置
|
||||
├── TEST_SPEC.md # 本文档 (OpenGL 专项)
|
||||
├── TEST_IMPROVEMENT_PLAN.md # 改进计划
|
||||
├── unit/
|
||||
│ ├── CMakeLists.txt # 单元测试构建
|
||||
│ ├── fixtures/
|
||||
│ │ ├── OpenGLTestFixture.h
|
||||
│ │ └── OpenGLTestFixture.cpp
|
||||
│ ├── test_device.cpp
|
||||
│ ├── test_buffer.cpp
|
||||
│ ├── test_fence.cpp
|
||||
│ ├── test_texture.cpp
|
||||
│ ├── test_shader.cpp
|
||||
│ ├── test_pipeline_state.cpp
|
||||
│ ├── test_vertex_array.cpp
|
||||
│ ├── test_command_list.cpp
|
||||
│ ├── test_render_target_view.cpp
|
||||
│ ├── test_depth_stencil_view.cpp
|
||||
│ ├── test_swap_chain.cpp
|
||||
│ └── test_sampler.cpp
|
||||
└── integration/
|
||||
├── CMakeLists.txt
|
||||
├── run_integration_test.py # 公共脚本
|
||||
├── compare_ppm.py # PPM 图像比对
|
||||
├── run.bat # Windows 启动脚本
|
||||
├── minimal/ # 最小化测试
|
||||
│ ├── main.cpp
|
||||
│ ├── GT_minimal.ppm
|
||||
│ └── Res/
|
||||
│ └── Shader/
|
||||
│ ├── simple.vert
|
||||
│ └── simple.frag
|
||||
└── render_model/ # 模型渲染测试
|
||||
├── main.cpp
|
||||
├── GT.ppm
|
||||
└── Res/
|
||||
├── Image/
|
||||
├── Model/
|
||||
└── Shader/
|
||||
```
|
||||
|
||||
### 3.2 测试数量目标
|
||||
|
||||
| 组件 | 当前 | 重构后 | 变化 |
|
||||
|------|------|--------|------|
|
||||
| Device | 6 | 6 | - |
|
||||
| Buffer | 0 (被注释) | 6 | +6 |
|
||||
| Fence | 0 (被注释) | 5 | +5 |
|
||||
| Texture | 4 | 4 | - |
|
||||
| Shader | 0 (被注释) | 4 | +4 |
|
||||
| PipelineState | 3 | 3 | - |
|
||||
| VertexArray | 1 | 2 | +1 |
|
||||
| CommandList | 14 | 14 | - |
|
||||
| Sampler | 2 | 2 | - |
|
||||
| SwapChain | 3 | 3 | - |
|
||||
| RTV | 2 | 2 | - |
|
||||
| DSV | 2 | 2 | - |
|
||||
| **单元测试总计** | **37** | **53** | **+16** |
|
||||
| **集成测试** | **0** | **2** | **+2** |
|
||||
|
||||
---
|
||||
|
||||
## 4. 分阶段实施计划
|
||||
|
||||
### Phase 1: 目录结构重构
|
||||
|
||||
**目标**: 建立与 D3D12 一致的目录分层
|
||||
|
||||
**步骤**:
|
||||
1. 创建 `unit/` 和 `integration/` 子目录
|
||||
2. 移动现有测试文件到 `unit/`
|
||||
3. 创建顶层 `CMakeLists.txt` 做 `add_subdirectory`
|
||||
4. 重构 `unit/CMakeLists.txt` 独立配置
|
||||
|
||||
**目录变更**:
|
||||
```
|
||||
# 重构前
|
||||
tests/RHI/OpenGL/CMakeLists.txt
|
||||
tests/RHI/OpenGL/test_*.cpp
|
||||
tests/RHI/OpenGL/fixtures/
|
||||
|
||||
# 重构后
|
||||
tests/RHI/OpenGL/CMakeLists.txt # 顶层,仅 add_subdirectory
|
||||
tests/RHI/OpenGL/unit/CMakeLists.txt # 单元测试构建
|
||||
tests/RHI/OpenGL/unit/test_*.cpp # 测试文件
|
||||
tests/RHI/OpenGL/unit/fixtures/ # Fixture
|
||||
tests/RHI/OpenGL/integration/ # 新增
|
||||
tests/RHI/OpenGL/integration/...
|
||||
```
|
||||
|
||||
### Phase 2: Fixture 重构
|
||||
|
||||
**目标**: 消除静态共享状态,避免测试间污染
|
||||
|
||||
**重构内容**:
|
||||
|
||||
```cpp
|
||||
// OpenGLTestFixture.h 重构
|
||||
class OpenGLTestFixture : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override;
|
||||
void TearDown() override;
|
||||
|
||||
GLFWwindow* GetWindow() { return m_window; }
|
||||
void MakeContextCurrent();
|
||||
void DoneContextCurrent();
|
||||
|
||||
void ClearGLErrors();
|
||||
bool CheckGLError(const char* file, int line);
|
||||
void ResetGLState();
|
||||
|
||||
private:
|
||||
GLFWwindow* m_window = nullptr;
|
||||
OpenGLDevice* m_device = nullptr;
|
||||
};
|
||||
|
||||
// OpenGLTestFixture.cpp 重构
|
||||
void OpenGLTestFixture::SetUp() {
|
||||
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
|
||||
m_window = glfwCreateWindow(640, 480, "OpenGL Tests", nullptr, nullptr);
|
||||
if (!m_window) {
|
||||
GTEST_SKIP() << "Failed to create GLFW window";
|
||||
return;
|
||||
}
|
||||
|
||||
glfwMakeContextCurrent(m_window);
|
||||
|
||||
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
|
||||
GTEST_SKIP() << "Failed to initialize GLAD";
|
||||
glfwDestroyWindow(m_window);
|
||||
m_window = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
m_device = new OpenGLDevice();
|
||||
m_device->CreateRenderWindow(640, 480, "Test Window", false);
|
||||
|
||||
ClearGLErrors();
|
||||
}
|
||||
|
||||
void OpenGLTestFixture::TearDown() {
|
||||
ResetGLState();
|
||||
|
||||
if (m_device) {
|
||||
delete m_device;
|
||||
m_device = nullptr;
|
||||
}
|
||||
|
||||
if (m_window) {
|
||||
glfwDestroyWindow(m_window);
|
||||
m_window = nullptr;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Phase 3: 启用被注释的测试
|
||||
|
||||
**目标**: 激活 `test_buffer.cpp`、`test_fence.cpp`、`test_shader.cpp`
|
||||
|
||||
**步骤**:
|
||||
1. 取消 CMakeLists.txt 中的注释
|
||||
2. 检查并修复可能的编译错误
|
||||
3. 运行测试验证
|
||||
|
||||
**预期新增测试**:
|
||||
- Buffer: 6 tests
|
||||
- Fence: 5 tests
|
||||
- Shader: 4 tests
|
||||
|
||||
### Phase 4: 完善单元测试
|
||||
|
||||
**目标**: 补充缺失的测试用例
|
||||
|
||||
**新增测试计划**:
|
||||
|
||||
| 组件 | 新增测试 | 说明 |
|
||||
|------|---------|------|
|
||||
| VertexArray | 1 | `VertexArray_Bind_MultipleAttributes` |
|
||||
|
||||
### Phase 5: 建立集成测试体系
|
||||
|
||||
**目标**: 建立与 D3D12 一致的集成测试框架
|
||||
|
||||
**步骤**:
|
||||
1. 创建 `integration/` 目录结构
|
||||
2. 复制 `run_integration_test.py` 和 `compare_ppm.py`
|
||||
3. 创建 `minimal/` 集成测试
|
||||
4. 创建 `render_model/` 集成测试
|
||||
5. 配置 CTest 注册
|
||||
|
||||
**minimal/ 集成测试**:
|
||||
```cpp
|
||||
// integration/minimal/main.cpp
|
||||
// 渲染一个简单三角形,输出 PPM 截图
|
||||
int main() {
|
||||
// 1. 初始化 GLFW + OpenGL
|
||||
// 2. 创建窗口
|
||||
// 3. 渲染简单场景
|
||||
// 4. 截图保存为 minimal.ppm
|
||||
// 5. 退出
|
||||
}
|
||||
```
|
||||
|
||||
**Golden Image 生成流程**:
|
||||
1. 在干净硬件环境运行集成测试
|
||||
2. 截图保存为 `GT_<name>.ppm`
|
||||
3. 人工验证截图正确性
|
||||
4. 提交到版本控制
|
||||
|
||||
### Phase 6: 编写测试规范文档
|
||||
|
||||
**目标**: 创建 `TEST_SPEC.md` 和 `TEST_IMPROVEMENT_PLAN.md`
|
||||
|
||||
---
|
||||
|
||||
## 5. CMake 重构详细方案
|
||||
|
||||
### 5.1 顶层 CMakeLists.txt
|
||||
|
||||
```cmake
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
project(OpenGLEngineTests)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
add_subdirectory(unit)
|
||||
add_subdirectory(integration)
|
||||
```
|
||||
|
||||
### 5.2 unit/CMakeLists.txt
|
||||
|
||||
```cmake
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
get_filename_component(PROJECT_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../.. ABSOLUTE)
|
||||
|
||||
find_package(OpenGL REQUIRED)
|
||||
|
||||
include_directories(${PROJECT_ROOT_DIR}/engine/include)
|
||||
include_directories(${PROJECT_ROOT_DIR}/engine/src)
|
||||
|
||||
link_directories(${CMAKE_SOURCE_DIR}/tests/OpenGL/package/lib/)
|
||||
|
||||
find_package(GTest REQUIRED)
|
||||
|
||||
set(TEST_SOURCES
|
||||
${CMAKE_SOURCE_DIR}/tests/OpenGL/package/src/glad.c
|
||||
fixtures/OpenGLTestFixture.cpp
|
||||
test_device.cpp
|
||||
test_buffer.cpp
|
||||
test_fence.cpp
|
||||
test_texture.cpp
|
||||
test_shader.cpp
|
||||
test_pipeline_state.cpp
|
||||
test_vertex_array.cpp
|
||||
test_command_list.cpp
|
||||
test_render_target_view.cpp
|
||||
test_depth_stencil_view.cpp
|
||||
test_swap_chain.cpp
|
||||
test_sampler.cpp
|
||||
)
|
||||
|
||||
add_executable(opengl_engine_tests ${TEST_SOURCES})
|
||||
|
||||
target_link_libraries(opengl_engine_tests PRIVATE
|
||||
opengl32
|
||||
glfw3
|
||||
XCEngine
|
||||
GTest::gtest
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
target_include_directories(opengl_engine_tests PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/fixtures
|
||||
${PROJECT_ROOT_DIR}/engine/include
|
||||
${PROJECT_ROOT_DIR}/engine/src
|
||||
)
|
||||
|
||||
target_compile_definitions(opengl_engine_tests PRIVATE
|
||||
TEST_RESOURCES_DIR="${PROJECT_ROOT_DIR}/tests/RHI/OpenGL/integration/minimal/Res"
|
||||
)
|
||||
|
||||
add_custom_command(TARGET opengl_engine_tests POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
${PROJECT_ROOT_DIR}/tests/RHI/OpenGL/integration/minimal/Res
|
||||
$<TARGET_FILE_DIR:opengl_engine_tests>/Res
|
||||
)
|
||||
|
||||
enable_testing()
|
||||
add_test(NAME OpenGLEngineTests COMMAND opengl_engine_tests)
|
||||
```
|
||||
|
||||
### 5.3 integration/CMakeLists.txt
|
||||
|
||||
```cmake
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
project(OpenGL_Integration)
|
||||
|
||||
set(ENGINE_ROOT_DIR ${CMAKE_SOURCE_DIR}/engine)
|
||||
|
||||
find_package(Python3 REQUIRED)
|
||||
|
||||
enable_testing()
|
||||
|
||||
# Minimal test
|
||||
add_executable(OpenGL_Minimal
|
||||
WIN32
|
||||
minimal/main.cpp
|
||||
)
|
||||
|
||||
target_include_directories(OpenGL_Minimal PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/minimal
|
||||
${ENGINE_ROOT_DIR}/include
|
||||
)
|
||||
|
||||
target_link_libraries(OpenGL_Minimal PRIVATE
|
||||
opengl32
|
||||
glfw3
|
||||
d3d12
|
||||
dxgi
|
||||
d3dcompiler
|
||||
XCEngine
|
||||
)
|
||||
|
||||
# Copy Res folder
|
||||
add_custom_command(TARGET OpenGL_Minimal POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/minimal/Res
|
||||
$<TARGET_FILE_DIR:OpenGL_Minimal>/Res
|
||||
)
|
||||
|
||||
# Copy test scripts
|
||||
add_custom_command(TARGET OpenGL_Minimal POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/run.bat
|
||||
$<TARGET_FILE_DIR:OpenGL_Minimal>/
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/compare_ppm.py
|
||||
$<TARGET_FILE_DIR:OpenGL_Minimal>/
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/run_integration_test.py
|
||||
$<TARGET_FILE_DIR:OpenGL_Minimal>/
|
||||
)
|
||||
|
||||
# Register integration test with CTest
|
||||
add_test(NAME OpenGL_Minimal_Integration
|
||||
COMMAND ${Python3_EXECUTABLE} $<TARGET_FILE_DIR:OpenGL_Minimal>/run_integration_test.py
|
||||
$<TARGET_FILE:OpenGL_Minimal>
|
||||
minimal.ppm
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/minimal/GT_minimal.ppm
|
||||
5
|
||||
WORKING_DIRECTORY $<TARGET_FILE_DIR:OpenGL_Minimal>
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 测试前缀对应表
|
||||
|
||||
| 类名 | 测试前缀 |
|
||||
|------|---------|
|
||||
| OpenGLDevice | Device |
|
||||
| OpenGLBuffer | Buffer |
|
||||
| OpenGLFence | Fence |
|
||||
| OpenGLTexture | Texture |
|
||||
| OpenGLShader | Shader |
|
||||
| OpenGLPipelineState | PipelineState |
|
||||
| OpenGLVertexArray | VertexArray |
|
||||
| OpenGLCommandList | CommandList |
|
||||
| OpenGLSampler | Sampler |
|
||||
| OpenGLSwapChain | SwapChain |
|
||||
| OpenGLRenderTargetView | RTV |
|
||||
| OpenGLDepthStencilView | DSV |
|
||||
|
||||
---
|
||||
|
||||
## 7. 测试执行
|
||||
|
||||
### 7.1 单元测试
|
||||
|
||||
```bash
|
||||
# 方式 1: 使用统一脚本
|
||||
python scripts/run_tests.py --unit-only
|
||||
|
||||
# 方式 2: 直接使用 CTest
|
||||
cd build/tests/RHI/OpenGL/unit
|
||||
ctest -C Debug --output-on-failure
|
||||
```
|
||||
|
||||
### 7.2 集成测试
|
||||
|
||||
```bash
|
||||
# 方式 1: 使用统一脚本
|
||||
python scripts/run_tests.py --integration
|
||||
|
||||
# 方式 2: 直接使用 CTest
|
||||
cd build/tests/RHI/OpenGL/integration
|
||||
ctest -C Debug --output-on-failure
|
||||
```
|
||||
|
||||
### 7.3 构建和测试
|
||||
|
||||
```bash
|
||||
# 构建
|
||||
cmake --build . --target OpenGL_Minimal --config Debug
|
||||
|
||||
# 运行测试
|
||||
python scripts/run_tests.py --build
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. CI 集成
|
||||
|
||||
### 8.1 GitHub Actions 配置
|
||||
|
||||
```yaml
|
||||
name: OpenGL Tests
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Configure CMake
|
||||
run: cmake -B build -DCMAKE_BUILD_TYPE=Debug
|
||||
|
||||
- name: Build OpenGL Tests
|
||||
run: cmake --build build --target opengl_engine_tests OpenGL_Minimal --config Debug
|
||||
|
||||
- name: Run Unit Tests
|
||||
run: cd build/tests/RHI/OpenGL/unit && ctest -C Debug --output-on-failure
|
||||
|
||||
- name: Run Integration Tests
|
||||
run: python scripts/run_tests.py --integration
|
||||
```
|
||||
|
||||
### 8.2 CI 模式
|
||||
|
||||
`--ci` 模式会跳过需要 GUI 的集成测试:
|
||||
```bash
|
||||
python scripts/run_tests.py --ci # 仅运行单元测试
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. 文件清单
|
||||
|
||||
### 9.1 需创建的文件
|
||||
|
||||
| 文件路径 | 说明 |
|
||||
|---------|------|
|
||||
| `tests/RHI/OpenGL/CMakeLists.txt` | 顶层 CMake 配置 |
|
||||
| `tests/RHI/OpenGL/TEST_SPEC.md` | OpenGL 专项规范 |
|
||||
| `tests/RHI/OpenGL/TEST_IMPROVEMENT_PLAN.md` | 改进计划 |
|
||||
| `tests/RHI/OpenGL/unit/CMakeLists.txt` | 单元测试构建配置 |
|
||||
| `tests/RHI/OpenGL/integration/CMakeLists.txt` | 集成测试构建配置 |
|
||||
| `tests/RHI/OpenGL/integration/run_integration_test.py` | 集成测试运行脚本 |
|
||||
| `tests/RHI/OpenGL/integration/compare_ppm.py` | PPM 图像比对脚本 |
|
||||
| `tests/RHI/OpenGL/integration/run.bat` | Windows 启动脚本 |
|
||||
| `tests/RHI/OpenGL/integration/minimal/main.cpp` | 最小化集成测试 |
|
||||
| `tests/RHI/OpenGL/integration/minimal/GT_minimal.ppm` | Golden Image |
|
||||
| `tests/RHI/OpenGL/integration/minimal/Res/Shader/*.vert` | Vertex Shader |
|
||||
| `tests/RHI/OpenGL/integration/minimal/Res/Shader/*.frag` | Fragment Shader |
|
||||
|
||||
### 9.2 需修改的文件
|
||||
|
||||
| 文件路径 | 修改内容 |
|
||||
|---------|---------|
|
||||
| `tests/RHI/OpenGL/fixtures/OpenGLTestFixture.h` | 重构 Fixture 接口 |
|
||||
| `tests/RHI/OpenGL/fixtures/OpenGLTestFixture.cpp` | 重构 Fixture 实现 |
|
||||
| `tests/RHI/OpenGL/CMakeLists.txt` | 简化为 add_subdirectory |
|
||||
|
||||
### 9.3 需移动的文件
|
||||
|
||||
| 原路径 | 新路径 |
|
||||
|-------|-------|
|
||||
| `tests/RHI/OpenGL/test_*.cpp` | `tests/RHI/OpenGL/unit/test_*.cpp` |
|
||||
| `tests/RHI/OpenGL/fixtures/*` | `tests/RHI/OpenGL/unit/fixtures/*` |
|
||||
|
||||
---
|
||||
|
||||
## 10. OpenGL 与 D3D12 测试差异说明
|
||||
|
||||
### 10.1 平台特性差异
|
||||
|
||||
| 方面 | D3D12 | OpenGL |
|
||||
|------|-------|--------|
|
||||
| **设备创建** | `D3D12CreateDevice()` 每测试独立 | 共享 GLFWcontext + Glad |
|
||||
| **上下文管理** | 无 | GLFWwindow 生命周期 |
|
||||
| **错误检查** | `HRESULT` 返回值 | `glGetError()` 状态码 |
|
||||
| **渲染目标** | RTV/DSV descriptor | OpenGL Framebuffer Object |
|
||||
| **同步原语** | `ID3D12Fence` | `glFenceSync` + `glClientWaitSync` |
|
||||
| **管线状态** | PSO 对象 | OpenGL State Machine |
|
||||
| **资源绑定** | CommandList + DescriptorHeap | `glBindBuffer`, `glBindTexture` |
|
||||
|
||||
### 10.2 Fixture 设计差异
|
||||
|
||||
```cpp
|
||||
// D3D12 - 每测试独立 COM 对象
|
||||
class D3D12TestFixture : public ::testing::Test {
|
||||
ComPtr<ID3D12Device> mDevice;
|
||||
ComPtr<ID3D12CommandQueue> mCommandQueue;
|
||||
};
|
||||
|
||||
// OpenGL - 需要共享 context,但每测试独立 window
|
||||
class OpenGLTestFixture : public ::testing::Test {
|
||||
GLFWwindow* m_window; // 每测试独立
|
||||
OpenGLDevice* m_device; // 每测试独立
|
||||
};
|
||||
```
|
||||
|
||||
### 10.3 测试资源差异
|
||||
|
||||
| 方面 | D3D12 | OpenGL |
|
||||
|------|-------|--------|
|
||||
| **Shader 格式** | HLSL (.hlsl) | GLSL (.vert, .frag, .geom) |
|
||||
| **纹理格式** | DDS | PNG/BMP/TGA |
|
||||
| **模型格式** | 自定义 .lhsm | 自定义 .lhsm |
|
||||
|
||||
---
|
||||
|
||||
## 11. 已知问题与待办
|
||||
|
||||
### 11.1 Phase 1 待办
|
||||
|
||||
- [ ] 创建 `unit/` 和 `integration/` 目录
|
||||
- [ ] 移动测试文件到 `unit/`
|
||||
- [ ] 创建顶层 `CMakeLists.txt`
|
||||
- [ ] 重构 `unit/CMakeLists.txt`
|
||||
|
||||
### 11.2 Phase 2 待办
|
||||
|
||||
- [ ] 重构 `OpenGLTestFixture` 消除静态成员
|
||||
- [ ] 验证测试隔离效果
|
||||
|
||||
### 11.3 Phase 3 待办
|
||||
|
||||
- [ ] 启用 `test_buffer.cpp`
|
||||
- [ ] 启用 `test_fence.cpp`
|
||||
- [ ] 启用 `test_shader.cpp`
|
||||
- [ ] 修复编译错误
|
||||
|
||||
### 11.4 Phase 4 待办
|
||||
|
||||
- [ ] 补充 `VertexArray_Bind_MultipleAttributes` 测试
|
||||
|
||||
### 11.5 Phase 5 待办
|
||||
|
||||
- [ ] 创建 `integration/` 目录结构
|
||||
- [ ] 复制并适配 `run_integration_test.py`
|
||||
- [ ] 复制并适配 `compare_ppm.py`
|
||||
- [ ] 创建 `minimal/` 集成测试
|
||||
- [ ] 创建 `render_model/` 集成测试
|
||||
- [ ] 生成 Golden Image
|
||||
|
||||
### 11.6 Phase 6 待办
|
||||
|
||||
- [ ] 编写 `TEST_SPEC.md`
|
||||
- [ ] 编写 `TEST_IMPROVEMENT_PLAN.md`
|
||||
|
||||
---
|
||||
|
||||
## 12. 规范更新记录
|
||||
|
||||
| 版本 | 日期 | 变更 |
|
||||
|------|------|------|
|
||||
| 1.0 | 2026-03-20 | 初始版本,参考 D3D12 TEST_SPEC.md 制定重构方案 |
|
||||
|
||||
---
|
||||
|
||||
**规范版本**: 1.0
|
||||
**最后更新**: 2026-03-20
|
||||
**前置文档**:
|
||||
- [tests/TEST_SPEC.md](../tests/TEST_SPEC.md)
|
||||
- [tests/RHI/D3D12/TEST_SPEC.md](./D3D12/TEST_SPEC.md)
|
||||
@@ -58,7 +58,7 @@ using namespace XCEngine::Math;
|
||||
void MatrixExample() {
|
||||
Matrix4 mat = Matrix4::TRS(
|
||||
Vector3(1.0f, 2.0f, 3.0f),
|
||||
Quaternion::FromEuler(0.0f, 90.0f, 0.0f),
|
||||
Quaternion::FromEulerAngles(0.0f, 90.0f, 0.0f),
|
||||
Vector3(1.5f, 1.5f, 1.5f)
|
||||
);
|
||||
|
||||
|
||||
@@ -65,5 +65,5 @@ struct Rect {
|
||||
## 相关文档
|
||||
|
||||
- [Math 模块总览](../math.md) - 返回 Rect 模块总览
|
||||
- [RectInt](rectint.md) - 整数矩形版本
|
||||
- [Viewport](viewport.md) - 渲染视口
|
||||
- [RectInt](../rectint/rectint.md) - 整数矩形版本
|
||||
- [Viewport](../viewport/viewport.md) - 渲染视口
|
||||
|
||||
@@ -76,6 +76,6 @@ int main() {
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [`RectInt`](rectint.md) - 整数矩形
|
||||
- [`Viewport`](viewport.md) - 视口
|
||||
- [`RectInt`](../rectint/rectint.md) - 整数矩形
|
||||
- [`Viewport`](../viewport/viewport.md) - 视口
|
||||
- [`Vector2`](../vector2/vector2.md) - 二维向量
|
||||
@@ -1,24 +0,0 @@
|
||||
# RectInt::Contains
|
||||
|
||||
```cpp
|
||||
bool Contains(int32_t px, int32_t py) const
|
||||
```
|
||||
|
||||
检测整数坐标点是否在矩形内。
|
||||
|
||||
**参数:**
|
||||
- `px` - 点的 x 坐标
|
||||
- `py` - 点的 y 坐标
|
||||
|
||||
**返回:** `bool` - 点在矩形内(包含边界)返回 true
|
||||
|
||||
**复杂度:** O(1)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
RectInt rect(0, 0, 1920, 1080);
|
||||
if (rect.Contains(pixelX, pixelY)) {
|
||||
// 像素在矩形内
|
||||
}
|
||||
```
|
||||
@@ -1,18 +0,0 @@
|
||||
# RectInt::GetBottom
|
||||
|
||||
```cpp
|
||||
int32_t GetBottom() const
|
||||
```
|
||||
|
||||
获取矩形下边界。
|
||||
|
||||
**返回:** `int32_t` - 下边界坐标 (y + height)
|
||||
|
||||
**复杂度:** O(1)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
RectInt rect(10, 20, 100, 50);
|
||||
int32_t bottom = rect.GetBottom(); // 70
|
||||
```
|
||||
@@ -1,18 +0,0 @@
|
||||
# RectInt::GetCenter
|
||||
|
||||
```cpp
|
||||
Vector2 GetCenter() const
|
||||
```
|
||||
|
||||
获取矩形中心点(转换为浮点)。
|
||||
|
||||
**返回:** `Vector2` - 中心点坐标
|
||||
|
||||
**复杂度:** O(1)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
RectInt rect(10, 20, 100, 50);
|
||||
Vector2 center = rect.GetCenter(); // (60.0f, 45.0f)
|
||||
```
|
||||
@@ -1,18 +0,0 @@
|
||||
# RectInt::GetLeft
|
||||
|
||||
```cpp
|
||||
int32_t GetLeft() const
|
||||
```
|
||||
|
||||
获取矩形左边界。
|
||||
|
||||
**返回:** `int32_t` - 左边界坐标 (x)
|
||||
|
||||
**复杂度:** O(1)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
RectInt rect(10, 20, 100, 50);
|
||||
int32_t left = rect.GetLeft(); // 10
|
||||
```
|
||||
@@ -1,18 +0,0 @@
|
||||
# RectInt::GetPosition
|
||||
|
||||
```cpp
|
||||
Vector2 GetPosition() const
|
||||
```
|
||||
|
||||
获取矩形左上角位置(转换为浮点)。
|
||||
|
||||
**返回:** `Vector2` - 位置向量
|
||||
|
||||
**复杂度:** O(1)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
RectInt rect(10, 20, 100, 50);
|
||||
Vector2 pos = rect.GetPosition(); // (10.0f, 20.0f)
|
||||
```
|
||||
@@ -1,18 +0,0 @@
|
||||
# RectInt::GetRight
|
||||
|
||||
```cpp
|
||||
int32_t GetRight() const
|
||||
```
|
||||
|
||||
获取矩形右边界。
|
||||
|
||||
**返回:** `int32_t` - 右边界坐标 (x + width)
|
||||
|
||||
**复杂度:** O(1)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
RectInt rect(10, 20, 100, 50);
|
||||
int32_t right = rect.GetRight(); // 110
|
||||
```
|
||||
@@ -1,18 +0,0 @@
|
||||
# RectInt::GetSize
|
||||
|
||||
```cpp
|
||||
Vector2 GetSize() const
|
||||
```
|
||||
|
||||
获取矩形尺寸(转换为浮点)。
|
||||
|
||||
**返回:** `Vector2` - 尺寸向量
|
||||
|
||||
**复杂度:** O(1)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
RectInt rect(10, 20, 100, 50);
|
||||
Vector2 size = rect.GetSize(); // (100.0f, 50.0f)
|
||||
```
|
||||
@@ -1,18 +0,0 @@
|
||||
# RectInt::GetTop
|
||||
|
||||
```cpp
|
||||
int32_t GetTop() const
|
||||
```
|
||||
|
||||
获取矩形上边界。
|
||||
|
||||
**返回:** `int32_t` - 上边界坐标 (y)
|
||||
|
||||
**复杂度:** O(1)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
RectInt rect(10, 20, 100, 50);
|
||||
int32_t top = rect.GetTop(); // 20
|
||||
```
|
||||
@@ -1,24 +0,0 @@
|
||||
# RectInt::Intersects
|
||||
|
||||
```cpp
|
||||
bool Intersects(const RectInt& other) const
|
||||
```
|
||||
|
||||
检测两整数矩形是否相交。
|
||||
|
||||
**参数:**
|
||||
- `other` - 另一个整数矩形
|
||||
|
||||
**返回:** `bool` - 两矩形相交返回 true
|
||||
|
||||
**复杂度:** O(1)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
RectInt rectA(0, 0, 100, 100);
|
||||
RectInt rectB(50, 50, 100, 100);
|
||||
if (rectA.Intersects(rectB)) {
|
||||
// 两矩形相交
|
||||
}
|
||||
```
|
||||
@@ -1,53 +0,0 @@
|
||||
# RectInt
|
||||
|
||||
整数矩形结构体,用于像素级 2D 区域表示。
|
||||
|
||||
**头文件:** `#include <XCEngine/Math/Rect.h>`
|
||||
|
||||
**命名空间:** `XCEngine::Math`
|
||||
|
||||
## 结构体定义
|
||||
|
||||
```cpp
|
||||
struct RectInt {
|
||||
int32_t x = 0;
|
||||
int32_t y = 0;
|
||||
int32_t width = 0;
|
||||
int32_t height = 0;
|
||||
|
||||
RectInt() = default;
|
||||
RectInt(int32_t x, int32_t y, int32_t w, int32_t h);
|
||||
};
|
||||
```
|
||||
|
||||
## 构造函数
|
||||
|
||||
| 方法 | 描述 |
|
||||
|------|------|
|
||||
| `RectInt()` | 默认构造 |
|
||||
| `RectInt(x, y, w, h)` | 从整数坐标和尺寸构造 |
|
||||
|
||||
## 边界访问
|
||||
|
||||
| 方法 | 返回值 | 描述 |
|
||||
|------|--------|------|
|
||||
| [GetLeft()](rectint-getleft.md) | `int32_t` | 左边界 |
|
||||
| [GetRight()](rectint-getright.md) | `int32_t` | 右边界 |
|
||||
| [GetTop()](rectint-gettop.md) | `int32_t` | 上边界 |
|
||||
| [GetBottom()](rectint-getbottom.md) | `int32_t` | 下边界 |
|
||||
| [GetPosition()](rectint-getposition.md) | `Vector2` | 位置(转换为浮点) |
|
||||
| [GetSize()](rectint-getsize.md) | `Vector2` | 尺寸(转换为浮点) |
|
||||
| [GetCenter()](rectint-getcenter.md) | `Vector2` | 中心点 |
|
||||
|
||||
## 检测方法
|
||||
|
||||
| 方法 | 返回值 | 描述 |
|
||||
|------|--------|------|
|
||||
| [Contains(px, py)](rectint-contains.md) | `bool` | 整数坐标点检测 |
|
||||
| [Intersects(other)](rectint-intersects.md) | `bool` | 与另一矩形相交 |
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [Math 模块总览](../math.md) - 返回 Rect 模块总览
|
||||
- [Rect](rect-overview.md) - 浮点矩形版本
|
||||
- [Viewport](viewport.md) - 渲染视口
|
||||
@@ -1,18 +0,0 @@
|
||||
# Viewport::GetAspectRatio
|
||||
|
||||
```cpp
|
||||
float GetAspectRatio() const
|
||||
```
|
||||
|
||||
获取视口宽高比。
|
||||
|
||||
**返回:** `float` - 宽高比 (width / height),height 为 0 时返回 0.0f
|
||||
|
||||
**复杂度:** O(1)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
Viewport viewport(0, 0, 1920, 1080);
|
||||
float aspect = viewport.GetAspectRatio(); // 1.777... (16:9)
|
||||
```
|
||||
@@ -1,18 +0,0 @@
|
||||
# Viewport::GetRect
|
||||
|
||||
```cpp
|
||||
Rect GetRect() const
|
||||
```
|
||||
|
||||
将视口转换为 Rect。
|
||||
|
||||
**返回:** `Rect` - 对应的矩形 (x, y, width, height),不包含深度范围
|
||||
|
||||
**复杂度:** O(1)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
Viewport viewport(0, 0, 1920, 1080, 0.0f, 1.0f);
|
||||
Rect rect = viewport.GetRect(); // (0, 0, 1920, 1080)
|
||||
```
|
||||
@@ -1,45 +0,0 @@
|
||||
# Viewport
|
||||
|
||||
渲染视口结构体,用于屏幕到归一化坐标的映射。
|
||||
|
||||
**头文件:** `#include <XCEngine/Math/Rect.h>`
|
||||
|
||||
**命名空间:** `XCEngine::Math`
|
||||
|
||||
## 结构体定义
|
||||
|
||||
```cpp
|
||||
struct Viewport {
|
||||
float x = 0.0f;
|
||||
float y = 0.0f;
|
||||
float width = 0.0f;
|
||||
float height = 0.0f;
|
||||
float minDepth = 0.0f;
|
||||
float maxDepth = 1.0f;
|
||||
|
||||
Viewport() = default;
|
||||
Viewport(float x, float y, float w, float h);
|
||||
Viewport(float x, float y, float w, float h, float minD, float maxD);
|
||||
};
|
||||
```
|
||||
|
||||
## 构造函数
|
||||
|
||||
| 方法 | 描述 |
|
||||
|------|------|
|
||||
| `Viewport()` | 默认构造 |
|
||||
| `Viewport(x, y, w, h)` | 2D 视口 |
|
||||
| `Viewport(x, y, w, h, minD, maxD)` | 带深度范围的 3D 视口 |
|
||||
|
||||
## 方法
|
||||
|
||||
| 方法 | 返回值 | 描述 |
|
||||
|------|--------|------|
|
||||
| [GetAspectRatio()](viewport-getaspectratio.md) | `float` | 宽高比 (width / height) |
|
||||
| [GetRect()](viewport-getrect.md) | `Rect` | 转换为 Rect |
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [Math 模块总览](../math.md) - 返回 Math 模块总览
|
||||
- [Rect](rect-overview.md) - 浮点矩形
|
||||
- [RectInt](rectint.md) - 整数矩形
|
||||
@@ -1,47 +1,24 @@
|
||||
# RectInt::Contains
|
||||
|
||||
```cpp
|
||||
bool Contains(int32_t px, int32_t py) const;
|
||||
bool Contains(int32_t px, int32_t py) const
|
||||
```
|
||||
|
||||
判断整数坐标点是否在矩形内部。
|
||||
|
||||
矩形使用左上位坐标系,内部定义为:x >= left && x < right && y >= top && y < bottom。即左边界和上边界在内部,右边界和下边界在外部。
|
||||
检测整数坐标点是否在矩形内。
|
||||
|
||||
**参数:**
|
||||
- `px` - 点的 x 坐标
|
||||
- `py` - 点的 y 坐标
|
||||
|
||||
**返回:** 点在矩形内部返回 true,否则返回 false
|
||||
|
||||
**线程安全:** ✅
|
||||
**返回:** `bool` - 点在矩形内(包含边界)返回 true
|
||||
|
||||
**复杂度:** O(1)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
#include "XCEngine/Math/Rect.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace XCEngine::Math;
|
||||
|
||||
int main() {
|
||||
RectInt rect(0, 0, 1920, 1080);
|
||||
|
||||
if (rect.Contains(960, 540)) {
|
||||
std::cout << "Point (960, 540) is inside\n";
|
||||
}
|
||||
|
||||
if (!rect.Contains(2000, 1000)) {
|
||||
std::cout << "Point (2000, 1000) is outside\n";
|
||||
}
|
||||
|
||||
return 0;
|
||||
RectInt rect(0, 0, 1920, 1080);
|
||||
if (rect.Contains(pixelX, pixelY)) {
|
||||
// 像素在矩形内
|
||||
}
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [`RectInt::Intersects`](intersects.md) - 判断是否相交
|
||||
- [RectInt 总览](rectint.md)
|
||||
@@ -1,36 +1,18 @@
|
||||
# RectInt::GetBottom
|
||||
|
||||
```cpp
|
||||
int32_t GetBottom() const;
|
||||
int32_t GetBottom() const
|
||||
```
|
||||
|
||||
获取矩形下边界 y 坐标。
|
||||
获取矩形下边界。
|
||||
|
||||
**返回:** 矩形下边界 y 坐标(等于 y + height)
|
||||
|
||||
**线程安全:** ✅
|
||||
**返回:** `int32_t` - 下边界坐标 (y + height)
|
||||
|
||||
**复杂度:** O(1)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
#include "XCEngine/Math/Rect.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace XCEngine::Math;
|
||||
|
||||
int main() {
|
||||
RectInt rect(10, 20, 100, 50);
|
||||
int32_t bottom = rect.GetBottom();
|
||||
std::cout << "Bottom: " << bottom << "\n";
|
||||
return 0;
|
||||
}
|
||||
RectInt rect(10, 20, 100, 50);
|
||||
int32_t bottom = rect.GetBottom(); // 70
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [`RectInt::GetLeft`](getleft.md) - 获取左边界
|
||||
- [`RectInt::GetRight`](getright.md) - 获取右边界
|
||||
- [`RectInt::GetTop`](gettop.md) - 获取上边界
|
||||
- [RectInt 总览](rectint.md)
|
||||
@@ -1,35 +1,18 @@
|
||||
# RectInt::GetCenter
|
||||
|
||||
```cpp
|
||||
Vector2 GetCenter() const;
|
||||
Vector2 GetCenter() const
|
||||
```
|
||||
|
||||
获取矩形中心点坐标。
|
||||
获取矩形中心点(转换为浮点)。
|
||||
|
||||
**返回:** 表示矩形中心点的 Vector2(转换为浮点)
|
||||
|
||||
**线程安全:** ✅
|
||||
**返回:** `Vector2` - 中心点坐标
|
||||
|
||||
**复杂度:** O(1)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
#include "XCEngine/Math/Rect.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace XCEngine::Math;
|
||||
|
||||
int main() {
|
||||
RectInt rect(10, 20, 100, 50);
|
||||
Vector2 center = rect.GetCenter();
|
||||
std::cout << "Center: (" << center.x << ", " << center.y << ")\n";
|
||||
return 0;
|
||||
}
|
||||
RectInt rect(10, 20, 100, 50);
|
||||
Vector2 center = rect.GetCenter(); // (60.0f, 45.0f)
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [`RectInt::GetPosition`](getposition.md) - 获取位置
|
||||
- [`RectInt::GetSize`](getsize.md) - 获取尺寸
|
||||
- [RectInt 总览](rectint.md)
|
||||
@@ -1,36 +1,18 @@
|
||||
# RectInt::GetLeft
|
||||
|
||||
```cpp
|
||||
int32_t GetLeft() const;
|
||||
int32_t GetLeft() const
|
||||
```
|
||||
|
||||
获取矩形左边界 x 坐标。
|
||||
获取矩形左边界。
|
||||
|
||||
**返回:** 矩形左边界 x 坐标(等于 x 成员变量)
|
||||
|
||||
**线程安全:** ✅
|
||||
**返回:** `int32_t` - 左边界坐标 (x)
|
||||
|
||||
**复杂度:** O(1)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
#include "XCEngine/Math/Rect.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace XCEngine::Math;
|
||||
|
||||
int main() {
|
||||
RectInt rect(10, 20, 100, 50);
|
||||
int32_t left = rect.GetLeft();
|
||||
std::cout << "Left: " << left << "\n";
|
||||
return 0;
|
||||
}
|
||||
RectInt rect(10, 20, 100, 50);
|
||||
int32_t left = rect.GetLeft(); // 10
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [`RectInt::GetRight`](getright.md) - 获取右边界
|
||||
- [`RectInt::GetTop`](gettop.md) - 获取上边界
|
||||
- [`RectInt::GetBottom`](getbottom.md) - 获取下边界
|
||||
- [RectInt 总览](rectint.md)
|
||||
@@ -1,35 +1,18 @@
|
||||
# RectInt::GetPosition
|
||||
|
||||
```cpp
|
||||
Vector2 GetPosition() const;
|
||||
Vector2 GetPosition() const
|
||||
```
|
||||
|
||||
获取矩形位置(x, y 坐标)。
|
||||
获取矩形左上角位置(转换为浮点)。
|
||||
|
||||
**返回:** 表示矩形位置的 Vector2(转换为浮点)
|
||||
|
||||
**线程安全:** ✅
|
||||
**返回:** `Vector2` - 位置向量
|
||||
|
||||
**复杂度:** O(1)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
#include "XCEngine/Math/Rect.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace XCEngine::Math;
|
||||
|
||||
int main() {
|
||||
RectInt rect(10, 20, 100, 50);
|
||||
Vector2 pos = rect.GetPosition();
|
||||
std::cout << "Position: (" << pos.x << ", " << pos.y << ")\n";
|
||||
return 0;
|
||||
}
|
||||
RectInt rect(10, 20, 100, 50);
|
||||
Vector2 pos = rect.GetPosition(); // (10.0f, 20.0f)
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [`RectInt::GetSize`](getsize.md) - 获取尺寸
|
||||
- [`RectInt::GetCenter`](getcenter.md) - 获取中心点
|
||||
- [RectInt 总览](rectint.md)
|
||||
@@ -1,36 +1,18 @@
|
||||
# RectInt::GetRight
|
||||
|
||||
```cpp
|
||||
int32_t GetRight() const;
|
||||
int32_t GetRight() const
|
||||
```
|
||||
|
||||
获取矩形右边界 x 坐标。
|
||||
获取矩形右边界。
|
||||
|
||||
**返回:** 矩形右边界 x 坐标(等于 x + width)
|
||||
|
||||
**线程安全:** ✅
|
||||
**返回:** `int32_t` - 右边界坐标 (x + width)
|
||||
|
||||
**复杂度:** O(1)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
#include "XCEngine/Math/Rect.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace XCEngine::Math;
|
||||
|
||||
int main() {
|
||||
RectInt rect(10, 20, 100, 50);
|
||||
int32_t right = rect.GetRight();
|
||||
std::cout << "Right: " << right << "\n";
|
||||
return 0;
|
||||
}
|
||||
RectInt rect(10, 20, 100, 50);
|
||||
int32_t right = rect.GetRight(); // 110
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [`RectInt::GetLeft`](getleft.md) - 获取左边界
|
||||
- [`RectInt::GetTop`](gettop.md) - 获取上边界
|
||||
- [`RectInt::GetBottom`](getbottom.md) - 获取下边界
|
||||
- [RectInt 总览](rectint.md)
|
||||
@@ -1,35 +1,18 @@
|
||||
# RectInt::GetSize
|
||||
|
||||
```cpp
|
||||
Vector2 GetSize() const;
|
||||
Vector2 GetSize() const
|
||||
```
|
||||
|
||||
获取矩形尺寸(width, height)。
|
||||
获取矩形尺寸(转换为浮点)。
|
||||
|
||||
**返回:** 表示矩形尺寸的 Vector2(转换为浮点)
|
||||
|
||||
**线程安全:** ✅
|
||||
**返回:** `Vector2` - 尺寸向量
|
||||
|
||||
**复杂度:** O(1)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
#include "XCEngine/Math/Rect.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace XCEngine::Math;
|
||||
|
||||
int main() {
|
||||
RectInt rect(10, 20, 100, 50);
|
||||
Vector2 size = rect.GetSize();
|
||||
std::cout << "Size: (" << size.x << ", " << size.y << ")\n";
|
||||
return 0;
|
||||
}
|
||||
RectInt rect(10, 20, 100, 50);
|
||||
Vector2 size = rect.GetSize(); // (100.0f, 50.0f)
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [`RectInt::GetPosition`](getposition.md) - 获取位置
|
||||
- [`RectInt::GetCenter`](getcenter.md) - 获取中心点
|
||||
- [RectInt 总览](rectint.md)
|
||||
@@ -1,36 +1,18 @@
|
||||
# RectInt::GetTop
|
||||
|
||||
```cpp
|
||||
int32_t GetTop() const;
|
||||
int32_t GetTop() const
|
||||
```
|
||||
|
||||
获取矩形上边界 y 坐标。
|
||||
获取矩形上边界。
|
||||
|
||||
**返回:** 矩形上边界 y 坐标(等于 y 成员变量)
|
||||
|
||||
**线程安全:** ✅
|
||||
**返回:** `int32_t` - 上边界坐标 (y)
|
||||
|
||||
**复杂度:** O(1)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
#include "XCEngine/Math/Rect.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace XCEngine::Math;
|
||||
|
||||
int main() {
|
||||
RectInt rect(10, 20, 100, 50);
|
||||
int32_t top = rect.GetTop();
|
||||
std::cout << "Top: " << top << "\n";
|
||||
return 0;
|
||||
}
|
||||
RectInt rect(10, 20, 100, 50);
|
||||
int32_t top = rect.GetTop(); // 20
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [`RectInt::GetLeft`](getleft.md) - 获取左边界
|
||||
- [`RectInt::GetRight`](getright.md) - 获取右边界
|
||||
- [`RectInt::GetBottom`](getbottom.md) - 获取下边界
|
||||
- [RectInt 总览](rectint.md)
|
||||
@@ -1,48 +1,24 @@
|
||||
# RectInt::Intersects
|
||||
|
||||
```cpp
|
||||
bool Intersects(const RectInt& other) const;
|
||||
bool Intersects(const RectInt& other) const
|
||||
```
|
||||
|
||||
判断此矩形是否与另一矩形相交。
|
||||
|
||||
使用 AABB(轴对齐包围盒)碰撞检测算法。如果两个矩形在 x 轴和 y 轴上都有重叠,则返回 true。
|
||||
检测两整数矩形是否相交。
|
||||
|
||||
**参数:**
|
||||
- `other` - 另一个矩形
|
||||
- `other` - 另一个整数矩形
|
||||
|
||||
**返回:** 两矩形相交返回 true,否则返回 false
|
||||
|
||||
**线程安全:** ✅
|
||||
**返回:** `bool` - 两矩形相交返回 true
|
||||
|
||||
**复杂度:** O(1)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
#include "XCEngine/Math/Rect.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace XCEngine::Math;
|
||||
|
||||
int main() {
|
||||
RectInt rectA(0, 0, 100, 100);
|
||||
RectInt rectB(50, 50, 100, 100);
|
||||
|
||||
if (rectA.Intersects(rectB)) {
|
||||
std::cout << "Rects intersect\n";
|
||||
}
|
||||
|
||||
RectInt rectC(200, 200, 50, 50);
|
||||
if (!rectA.Intersects(rectC)) {
|
||||
std::cout << "Rects do not intersect\n";
|
||||
}
|
||||
|
||||
return 0;
|
||||
RectInt rectA(0, 0, 100, 100);
|
||||
RectInt rectB(50, 50, 100, 100);
|
||||
if (rectA.Intersects(rectB)) {
|
||||
// 两矩形相交
|
||||
}
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [`RectInt::Contains`](contains.md) - 判断点是否在矩形内
|
||||
- [RectInt 总览](rectint.md)
|
||||
@@ -1,63 +1,53 @@
|
||||
# RectInt
|
||||
|
||||
**命名空间**: `XCEngine::Math`
|
||||
整数矩形结构体,用于像素级 2D 区域表示。
|
||||
|
||||
**类型**: `struct`
|
||||
**头文件:** `#include <XCEngine/Math/Rect.h>`
|
||||
|
||||
**头文件**: `XCEngine/Math/Rect.h`
|
||||
**命名空间:** `XCEngine::Math`
|
||||
|
||||
**描述**: 二维整数矩形,用于表示像素级 2D 区域
|
||||
## 结构体定义
|
||||
|
||||
## 概述
|
||||
```cpp
|
||||
struct RectInt {
|
||||
int32_t x = 0;
|
||||
int32_t y = 0;
|
||||
int32_t width = 0;
|
||||
int32_t height = 0;
|
||||
|
||||
RectInt 结构体表示一个二维整数矩形,由整数位置 `(x, y)` 和尺寸 `(width, height)` 组成。与 Rect 不同,它使用 `int32_t` 类型,适合像素级操作和坐标计算。
|
||||
RectInt() = default;
|
||||
RectInt(int32_t x, int32_t y, int32_t w, int32_t h);
|
||||
};
|
||||
```
|
||||
|
||||
## 公共方法
|
||||
## 构造函数
|
||||
|
||||
| 方法 | 描述 |
|
||||
|------|------|
|
||||
| [`GetLeft`](getleft.md) | 获取矩形左边界 |
|
||||
| [`GetRight`](getright.md) | 获取矩形右边界 |
|
||||
| [`GetTop`](gettop.md) | 获取矩形上边界 |
|
||||
| [`GetBottom`](getbottom.md) | 获取矩形下边界 |
|
||||
| [`GetPosition`](getposition.md) | 获取矩形位置 |
|
||||
| [`GetSize`](getsize.md) | 获取矩形尺寸 |
|
||||
| [`GetCenter`](getcenter.md) | 获取矩形中心点 |
|
||||
| [`Contains`](contains.md) | 判断点是否在矩形内 |
|
||||
| [`Intersects`](intersects.md) | 判断是否与另一矩形相交 |
|
||||
| `RectInt()` | 默认构造 |
|
||||
| `RectInt(x, y, w, h)` | 从整数坐标和尺寸构造 |
|
||||
|
||||
## 使用示例
|
||||
## 边界访问
|
||||
|
||||
```cpp
|
||||
#include "XCEngine/Math/Rect.h"
|
||||
#include "XCEngine/Math/Vector2.h"
|
||||
#include <iostream>
|
||||
| 方法 | 返回值 | 描述 |
|
||||
|------|--------|------|
|
||||
| [GetLeft()](rectint-getleft.md) | `int32_t` | 左边界 |
|
||||
| [GetRight()](rectint-getright.md) | `int32_t` | 右边界 |
|
||||
| [GetTop()](rectint-gettop.md) | `int32_t` | 上边界 |
|
||||
| [GetBottom()](rectint-getbottom.md) | `int32_t` | 下边界 |
|
||||
| [GetPosition()](rectint-getposition.md) | `Vector2` | 位置(转换为浮点) |
|
||||
| [GetSize()](rectint-getsize.md) | `Vector2` | 尺寸(转换为浮点) |
|
||||
| [GetCenter()](rectint-getcenter.md) | `Vector2` | 中心点 |
|
||||
|
||||
using namespace XCEngine::Math;
|
||||
## 检测方法
|
||||
|
||||
int main() {
|
||||
RectInt rect(10, 20, 100, 50);
|
||||
|
||||
std::cout << "Position: (" << rect.x << ", " << rect.y << ")\n";
|
||||
std::cout << "Size: " << rect.width << " x " << rect.height << "\n";
|
||||
std::cout << "Left: " << rect.GetLeft() << ", Right: " << rect.GetRight() << "\n";
|
||||
std::cout << "Top: " << rect.GetTop() << ", Bottom: " << rect.GetBottom() << "\n";
|
||||
|
||||
if (rect.Contains(50, 30)) {
|
||||
std::cout << "Point (50, 30) is inside rect\n";
|
||||
}
|
||||
|
||||
RectInt other(60, 40, 100, 50);
|
||||
if (rect.Intersects(other)) {
|
||||
std::cout << "Rects intersect\n";
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
| 方法 | 返回值 | 描述 |
|
||||
|------|--------|------|
|
||||
| [Contains(px, py)](rectint-contains.md) | `bool` | 整数坐标点检测 |
|
||||
| [Intersects(other)](rectint-intersects.md) | `bool` | 与另一矩形相交 |
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [`Rect`](../rect/rect.md) - 浮点矩形
|
||||
- [`Viewport`](../rect/viewport.md) - 视口
|
||||
- [`Vector2`](../vector2/vector2.md) - 二维向量
|
||||
- [Math 模块总览](../math.md) - 返回 Rect 模块总览
|
||||
- [Rect](rect-overview.md) - 浮点矩形版本
|
||||
- [Viewport](viewport.md) - 渲染视口
|
||||
|
||||
40
docs/api/math/transform/space.md
Normal file
40
docs/api/math/transform/space.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Transform::Space
|
||||
|
||||
**命名空间**: `XCEngine::Math`
|
||||
|
||||
**类型**: `enum class`
|
||||
|
||||
**头文件**: `XCEngine/Math/Transform.h`
|
||||
|
||||
## 概述
|
||||
|
||||
`Space` 枚举用于指定变换操作的参考空间。
|
||||
|
||||
## 枚举值
|
||||
|
||||
| 枚举值 | 数值 | 描述 |
|
||||
|--------|------|------|
|
||||
| `Self` | `0` | 相对于自身空间进行变换 |
|
||||
| `World` | `1` | 相对于世界空间进行变换 |
|
||||
|
||||
## 使用示例
|
||||
|
||||
```cpp
|
||||
#include "XCEngine/Math/Transform.h"
|
||||
#include "XCEngine/Math/Vector3.h"
|
||||
|
||||
using namespace XCEngine::Math;
|
||||
|
||||
Transform transform;
|
||||
transform.position = Vector3(10.0f, 0.0f, 0.0f);
|
||||
|
||||
// 在自身空间旋转
|
||||
// transform.Rotate(Vector3::Up(), 45.0f * DEG_TO_RAD, Space::Self);
|
||||
|
||||
// 在世界空间旋转
|
||||
// transform.Rotate(Vector3::Up(), 45.0f * DEG_TO_RAD, Space::World);
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [Transform 总览](transform.md) - Transform 类总览
|
||||
@@ -34,6 +34,12 @@
|
||||
| [`InverseTransformPoint`](inverse-transform-point.md) | 逆变换一个点 |
|
||||
| [`InverseTransformDirection`](inverse-transform-direction.md) | 逆变换一个方向 |
|
||||
|
||||
## 枚举
|
||||
|
||||
| 枚举 | 描述 |
|
||||
|------|------|
|
||||
| [`Space`](space.md) | 变换参考空间(Self 或 World) |
|
||||
|
||||
## 使用示例
|
||||
|
||||
```cpp
|
||||
|
||||
29
docs/api/math/vector2/operator-add-assign.md
Normal file
29
docs/api/math/vector2/operator-add-assign.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# Vector2::operator+=
|
||||
|
||||
```cpp
|
||||
Vector2& operator+=(const Vector2& other)
|
||||
```
|
||||
|
||||
向量加法赋值,将 `other` 的分量加到当前向量。
|
||||
|
||||
**参数:**
|
||||
- `other` - 要加的向量
|
||||
|
||||
**返回:** `Vector2&` - 引用到修改后的当前向量
|
||||
|
||||
**线程安全:** ✅
|
||||
|
||||
**复杂度:** O(1)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
Vector2 v(1.0f, 2.0f);
|
||||
v += Vector2(3.0f, 4.0f); // v = (4.0f, 6.0f)
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [Vector2 总览](vector2.md)
|
||||
- [`operator+`](operator-add.md) - 加法
|
||||
- [`operator-=`](operator-sub-assign.md) - 减法赋值
|
||||
30
docs/api/math/vector2/operator-add.md
Normal file
30
docs/api/math/vector2/operator-add.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# Vector2::operator+
|
||||
|
||||
```cpp
|
||||
Vector2 operator+(const Vector2& other) const
|
||||
```
|
||||
|
||||
向量加法,将当前向量与另一个向量相加。
|
||||
|
||||
**参数:**
|
||||
- `other` - 要相加的向量
|
||||
|
||||
**返回:** `Vector2` - 相加结果向量
|
||||
|
||||
**线程安全:** ✅
|
||||
|
||||
**复杂度:** O(1)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
Vector2 a(1.0f, 2.0f);
|
||||
Vector2 b(3.0f, 4.0f);
|
||||
Vector2 c = a + b; // (4.0f, 6.0f)
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [Vector2 总览](vector2.md)
|
||||
- [`operator-`](operator-sub.md) - 减法
|
||||
- [`operator+=`](operator-add-assign.md) - 加法赋值
|
||||
29
docs/api/math/vector2/operator-div-assign.md
Normal file
29
docs/api/math/vector2/operator-div-assign.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# Vector2::operator/=
|
||||
|
||||
```cpp
|
||||
Vector2& operator/=(float scalar)
|
||||
```
|
||||
|
||||
向量除法赋值,将当前向量除以标量。
|
||||
|
||||
**参数:**
|
||||
- `scalar` - 标量值(不能为零)
|
||||
|
||||
**返回:** `Vector2&` - 引用到修改后的当前向量
|
||||
|
||||
**线程安全:** ✅
|
||||
|
||||
**复杂度:** O(1)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
Vector2 v(4.0f, 6.0f);
|
||||
v /= 2.0f; // v = (2.0f, 3.0f)
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [Vector2 总览](vector2.md)
|
||||
- [`operator/`](operator-div.md) - 除法
|
||||
- [`operator*=`](operator-mul-assign.md) - 乘法赋值
|
||||
29
docs/api/math/vector2/operator-div.md
Normal file
29
docs/api/math/vector2/operator-div.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# Vector2::operator/
|
||||
|
||||
```cpp
|
||||
Vector2 operator/(float scalar) const
|
||||
```
|
||||
|
||||
向量数除,将向量除以标量。
|
||||
|
||||
**参数:**
|
||||
- `scalar` - 标量值(不能为零)
|
||||
|
||||
**返回:** `Vector2` - 缩放后的向量
|
||||
|
||||
**线程安全:** ✅
|
||||
|
||||
**复杂度:** O(1)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
Vector2 v(4.0f, 6.0f);
|
||||
Vector2 result = v / 2.0f; // (2.0f, 3.0f)
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [Vector2 总览](vector2.md)
|
||||
- [`operator*`](operator-mul.md) - 乘法
|
||||
- [`operator/=`](operator-div-assign.md) - 除法赋值
|
||||
29
docs/api/math/vector2/operator-eq.md
Normal file
29
docs/api/math/vector2/operator-eq.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# Vector2::operator==
|
||||
|
||||
```cpp
|
||||
bool operator==(const Vector2& other) const
|
||||
```
|
||||
|
||||
判断两个向量是否相等。使用 EPSILON 进行浮点比较。
|
||||
|
||||
**参数:**
|
||||
- `other` - 要比较的向量
|
||||
|
||||
**返回:** `bool` - 如果所有分量差的绝对值都小于 EPSILON 则返回 true
|
||||
|
||||
**线程安全:** ✅
|
||||
|
||||
**复杂度:** O(1)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
Vector2 a(1.0f, 2.0f);
|
||||
Vector2 b(1.0f, 2.0f);
|
||||
bool equal = (a == b); // true
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [Vector2 总览](vector2.md)
|
||||
- [`operator!=`](operator-neq.md) - 不等比较
|
||||
29
docs/api/math/vector2/operator-mul-assign.md
Normal file
29
docs/api/math/vector2/operator-mul-assign.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# Vector2::operator*=
|
||||
|
||||
```cpp
|
||||
Vector2& operator*=(float scalar)
|
||||
```
|
||||
|
||||
向量乘法赋值,将当前向量乘以标量。
|
||||
|
||||
**参数:**
|
||||
- `scalar` - 标量值
|
||||
|
||||
**返回:** `Vector2&` - 引用到修改后的当前向量
|
||||
|
||||
**线程安全:** ✅
|
||||
|
||||
**复杂度:** O(1)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
Vector2 v(2.0f, 3.0f);
|
||||
v *= 2.0f; // v = (4.0f, 6.0f)
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [Vector2 总览](vector2.md)
|
||||
- [`operator*`](operator-mul.md) - 乘法
|
||||
- [`operator/=`](operator-div-assign.md) - 除法赋值
|
||||
29
docs/api/math/vector2/operator-mul.md
Normal file
29
docs/api/math/vector2/operator-mul.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# Vector2::operator*
|
||||
|
||||
```cpp
|
||||
Vector2 operator*(float scalar) const
|
||||
```
|
||||
|
||||
向量数乘,将向量与标量相乘。
|
||||
|
||||
**参数:**
|
||||
- `scalar` - 标量值
|
||||
|
||||
**返回:** `Vector2` - 缩放后的向量
|
||||
|
||||
**线程安全:** ✅
|
||||
|
||||
**复杂度:** O(1)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
Vector2 v(2.0f, 3.0f);
|
||||
Vector2 scaled = v * 2.0f; // (4.0f, 6.0f)
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [Vector2 总览](vector2.md)
|
||||
- [`operator/`](operator-div.md) - 除法
|
||||
- [`operator*=`](operator-mul-assign.md) - 乘法赋值
|
||||
29
docs/api/math/vector2/operator-neq.md
Normal file
29
docs/api/math/vector2/operator-neq.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# Vector2::operator!=
|
||||
|
||||
```cpp
|
||||
bool operator!=(const Vector2& other) const
|
||||
```
|
||||
|
||||
判断两个向量是否不相等。
|
||||
|
||||
**参数:**
|
||||
- `other` - 要比较的向量
|
||||
|
||||
**返回:** `bool` - 如果任何分量差的绝对值大于等于 EPSILON 则返回 true
|
||||
|
||||
**线程安全:** ✅
|
||||
|
||||
**复杂度:** O(1)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
Vector2 a(1.0f, 2.0f);
|
||||
Vector2 b(3.0f, 4.0f);
|
||||
bool notEqual = (a != b); // true
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [Vector2 总览](vector2.md)
|
||||
- [`operator==`](operator-eq.md) - 相等比较
|
||||
29
docs/api/math/vector2/operator-sub-assign.md
Normal file
29
docs/api/math/vector2/operator-sub-assign.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# Vector2::operator-=
|
||||
|
||||
```cpp
|
||||
Vector2& operator-=(const Vector2& other)
|
||||
```
|
||||
|
||||
向量减法赋值,将 `other` 的分量从当前向量减去。
|
||||
|
||||
**参数:**
|
||||
- `other` - 要减的向量
|
||||
|
||||
**返回:** `Vector2&` - 引用到修改后的当前向量
|
||||
|
||||
**线程安全:** ✅
|
||||
|
||||
**复杂度:** O(1)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
Vector2 v(5.0f, 8.0f);
|
||||
v -= Vector2(2.0f, 3.0f); // v = (3.0f, 5.0f)
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [Vector2 总览](vector2.md)
|
||||
- [`operator-`](operator-sub.md) - 减法
|
||||
- [`operator+=`](operator-add-assign.md) - 加法赋值
|
||||
30
docs/api/math/vector2/operator-sub.md
Normal file
30
docs/api/math/vector2/operator-sub.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# Vector2::operator-
|
||||
|
||||
```cpp
|
||||
Vector2 operator-(const Vector2& other) const
|
||||
```
|
||||
|
||||
向量减法,将当前向量减去另一个向量。
|
||||
|
||||
**参数:**
|
||||
- `other` - 要减去的向量
|
||||
|
||||
**返回:** `Vector2` - 相减结果向量
|
||||
|
||||
**线程安全:** ✅
|
||||
|
||||
**复杂度:** O(1)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
Vector2 a(5.0f, 8.0f);
|
||||
Vector2 b(2.0f, 3.0f);
|
||||
Vector2 c = a - b; // (3.0f, 5.0f)
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [Vector2 总览](vector2.md)
|
||||
- [`operator+`](operator-add.md) - 加法
|
||||
- [`operator-=`](operator-sub-assign.md) - 减法赋值
|
||||
@@ -23,31 +23,30 @@ Vector2 是 XCEngine 中的二维向量结构体,用于表示 2D 空间中的
|
||||
|
||||
| 方法 | 描述 |
|
||||
|------|------|
|
||||
| [`Zero`](Zero.md) | 返回 (0, 0) 零向量 |
|
||||
| [`One`](One.md) | 返回 (1, 1) 单位向量 |
|
||||
| [`Up`](Up.md) | 返回 (0, 1) 上方向 |
|
||||
| [`Down`](Down.md) | 返回 (0, -1) 下方向 |
|
||||
| [`Right`](Right.md) | 返回 (1, 0) 右方向 |
|
||||
| [`Left`](Left.md) | 返回 (-1, 0) 左方向 |
|
||||
| [`Dot`](Dot.md) | 计算两个向量的点积 |
|
||||
| [`Cross`](Cross.md) | 计算两个向量的叉积(返回标量) |
|
||||
| [`Normalize`](Normalize.md) | 归一化向量为单位长度 |
|
||||
| [`Magnitude`](Magnitude.md) | 计算向量长度 |
|
||||
| [`SqrMagnitude`](SqrMagnitude.md) | 计算向量长度平方 |
|
||||
| [`Lerp`](Lerp.md) | 线性插值 |
|
||||
| [`MoveTowards`](MoveTowards.md) | 朝目标移动 |
|
||||
| [`Magnitude`](Magnitude.md) | 实例方法,计算当前向量长度 |
|
||||
| [`SqrMagnitude`](SqrMagnitude.md) | 实例方法,计算当前向量长度平方 |
|
||||
| [`Normalized`](Normalized.md) | 实例方法,返回归一化副本 |
|
||||
| [`Zero`](zero.md) | 返回 (0, 0) 零向量 |
|
||||
| [`One`](one.md) | 返回 (1, 1) 单位向量 |
|
||||
| [`Up`](up.md) | 返回 (0, 1) 上方向 |
|
||||
| [`Down`](down.md) | 返回 (0, -1) 下方向 |
|
||||
| [`Right`](right.md) | 返回 (1, 0) 右方向 |
|
||||
| [`Left`](left.md) | 返回 (-1, 0) 左方向 |
|
||||
| [`Dot`](dot.md) | 计算两个向量的点积 |
|
||||
| [`Cross`](cross.md) | 计算两个向量的叉积(返回标量) |
|
||||
| [`Normalize`](normalize.md) | 归一化向量为单位长度(静态方法) |
|
||||
| [`Magnitude`](magnitude.md) | 计算向量长度 |
|
||||
| [`SqrMagnitude`](sqrmagnitude.md) | 计算向量长度平方 |
|
||||
| [`Lerp`](lerp.md) | 线性插值 |
|
||||
| [`MoveTowards`](movetowards.md) | 朝目标移动 |
|
||||
| [`Normalized`](normalized.md) | 实例方法,返回归一化副本 |
|
||||
|
||||
## 运算符
|
||||
|
||||
| 运算符 | 描述 |
|
||||
|--------|------|
|
||||
| `+`, `-` | 向量加减运算 |
|
||||
| `*`, `/` | 向量与标量乘除运算 |
|
||||
| `+=`, `-=`, `*=`, `/=` | 复合赋值运算 |
|
||||
| `==`, `!=` | 相等性比较(基于 EPSILON 浮点比较) |
|
||||
| [`+`](operator-add.md), [`-`](operator-sub.md) | 向量加减运算 |
|
||||
| [`*`](operator-mul.md), [`/`](operator-div.md) | 向量与标量乘除运算 |
|
||||
| [`*=`](operator-mul-assign.md), [`/=`](operator-div-assign.md) | 复合赋值运算 |
|
||||
| [`+=`](operator-add-assign.md), [`-=`](operator-sub-assign.md) | 复合赋值运算 |
|
||||
| [`==`](operator-eq.md), [`!=`](operator-neq.md) | 相等性比较(基于 EPSILON 浮点比较) |
|
||||
|
||||
## 使用示例
|
||||
|
||||
|
||||
27
docs/api/math/vector3/magnitude-instance.md
Normal file
27
docs/api/math/vector3/magnitude-instance.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# Vector3::Magnitude
|
||||
|
||||
```cpp
|
||||
float Magnitude() const
|
||||
```
|
||||
|
||||
计算向量的长度(模)。
|
||||
|
||||
**返回:** `float` - 向量的长度
|
||||
|
||||
**线程安全:** ✅
|
||||
|
||||
**复杂度:** O(1)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
Vector3 v(3.0f, 4.0f, 0.0f);
|
||||
float mag = v.Magnitude(); // 5.0f
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [Vector3 总览](vector3.md)
|
||||
- [`SqrMagnitude`](sqrmagnitude.md) - 长度的平方
|
||||
- [`Normalized`](normalized.md) - 归一化副本
|
||||
- [`static Magnitude`](magnitude.md) - 静态版本
|
||||
27
docs/api/math/vector3/normalized-instance.md
Normal file
27
docs/api/math/vector3/normalized-instance.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# Vector3::Normalized
|
||||
|
||||
```cpp
|
||||
Vector3 Normalized() const
|
||||
```
|
||||
|
||||
返回向量的归一化副本(单位长度为 1 的向量)。不会修改原向量。
|
||||
|
||||
**返回:** `Vector3` - 归一化后的向量副本;如果向量长度接近零,则返回零向量
|
||||
|
||||
**线程安全:** ✅
|
||||
|
||||
**复杂度:** O(1)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
Vector3 v(3.0f, 4.0f, 0.0f);
|
||||
Vector3 normalized = v.Normalized(); // (0.6f, 0.8f, 0.0f)
|
||||
// v 仍然是 (3.0f, 4.0f, 0.0f)
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [Vector3 总览](vector3.md)
|
||||
- [`static Normalize`](normalize.md) - 静态版本(会修改原向量)
|
||||
- [`Magnitude`](magnitude-instance.md) - 向量长度
|
||||
27
docs/api/math/vector3/sqrmagnitude-instance.md
Normal file
27
docs/api/math/vector3/sqrmagnitude-instance.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# Vector3::SqrMagnitude
|
||||
|
||||
```cpp
|
||||
float SqrMagnitude() const
|
||||
```
|
||||
|
||||
计算向量长度的平方。用于在不计算平方根的情况下比较长度,性能更优。
|
||||
|
||||
**返回:** `float` - 向量长度的平方
|
||||
|
||||
**线程安全:** ✅
|
||||
|
||||
**复杂度:** O(1)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
Vector3 v(3.0f, 4.0f, 0.0f);
|
||||
float sqrMag = v.SqrMagnitude(); // 25.0f
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [Vector3 总览](vector3.md)
|
||||
- [`Magnitude`](magnitude-instance.md) - 向量长度
|
||||
- [`Normalized`](normalized.md) - 归一化副本
|
||||
- [`static SqrMagnitude`](sqrmagnitude.md) - 静态版本
|
||||
@@ -51,11 +51,20 @@ Vector3 是 XCEngine 中用于表示三维向量的核心类型,支持常见
|
||||
|--------|------|
|
||||
| [`+`](operator_add.md), [`-`](operator_sub.md) | 向量加减 |
|
||||
| [`*`](operator_mul.md), [`/`](operator_div.md) | 向量与标量或分量相乘/相除 |
|
||||
| [`+=`](operator_add_assign.md), [`-=`](operator_sub_assign.md) | 复合赋值运算符 |
|
||||
| [`*=`](operator_mul_assign.md), [`/=`](operator_div_assign.md) | 复合赋值运算符 |
|
||||
| [`[]`](./operator_index.md) | 下标访问 x, y, z 分量 |
|
||||
| [`==`](operator_eq.md), [`!=`](operator_neq.md) | 相等性比较 |
|
||||
| [`* (Quaternion)`](quaternion-multiply.md) | 用四元数旋转向量 |
|
||||
|
||||
## 实例方法
|
||||
|
||||
| 方法 | 描述 |
|
||||
|------|------|
|
||||
| [`Magnitude()`](magnitude-instance.md) | 计算向量长度 |
|
||||
| [`SqrMagnitude()`](sqrmagnitude-instance.md) | 计算向量长度的平方 |
|
||||
| [`Normalized()`](normalized-instance.md) | 返回归一化副本 |
|
||||
|
||||
## 使用示例
|
||||
|
||||
```cpp
|
||||
|
||||
26
docs/api/math/vector4/operator-neg.md
Normal file
26
docs/api/math/vector4/operator-neg.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# Vector4::operator-
|
||||
|
||||
```cpp
|
||||
Vector4 operator-() const
|
||||
```
|
||||
|
||||
一元负号运算符,返回当前向量的负向量。
|
||||
|
||||
**返回:** `Vector4` - 每个分量取负的新向量
|
||||
|
||||
**线程安全:** ✅
|
||||
|
||||
**复杂度:** O(1)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
Vector4 v(1.0f, 2.0f, 3.0f, 4.0f);
|
||||
Vector4 neg = -v; // (-1.0f, -2.0f, -3.0f, -4.0f)
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [Vector4 总览](vector4.md)
|
||||
- [`operator+`](operator-add.md) - 加法
|
||||
- [`operator-`](operator-sub.md) - 二元减法
|
||||
@@ -1,34 +1,18 @@
|
||||
# Viewport::GetAspectRatio
|
||||
|
||||
```cpp
|
||||
float GetAspectRatio() const;
|
||||
float GetAspectRatio() const
|
||||
```
|
||||
|
||||
获取视口宽高比。
|
||||
|
||||
**返回:** 宽高比 (width / height),如果 height 为 0 则返回 0.0f
|
||||
|
||||
**线程安全:** ✅
|
||||
**返回:** `float` - 宽高比 (width / height),height 为 0 时返回 0.0f
|
||||
|
||||
**复杂度:** O(1)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
#include "XCEngine/Math/Rect.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace XCEngine::Math;
|
||||
|
||||
int main() {
|
||||
Viewport viewport(0.0f, 0.0f, 1920.0f, 1080.0f);
|
||||
float aspect = viewport.GetAspectRatio();
|
||||
std::cout << "Aspect Ratio: " << aspect << "\n";
|
||||
return 0;
|
||||
}
|
||||
Viewport viewport(0, 0, 1920, 1080);
|
||||
float aspect = viewport.GetAspectRatio(); // 1.777... (16:9)
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [`Viewport::GetRect`](getrect.md) - 转换为 Rect
|
||||
- [Viewport 总览](viewport.md)
|
||||
@@ -1,34 +1,18 @@
|
||||
# Viewport::GetRect
|
||||
|
||||
```cpp
|
||||
Rect GetRect() const;
|
||||
Rect GetRect() const
|
||||
```
|
||||
|
||||
将视口转换为 Rect。
|
||||
|
||||
**返回:** 对应的 Rect(x, y, width, height),不包含深度范围
|
||||
|
||||
**线程安全:** ✅
|
||||
**返回:** `Rect` - 对应的矩形 (x, y, width, height),不包含深度范围
|
||||
|
||||
**复杂度:** O(1)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
#include "XCEngine/Math/Rect.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace XCEngine::Math;
|
||||
|
||||
int main() {
|
||||
Viewport viewport(0.0f, 0.0f, 1920.0f, 1080.0f, 0.0f, 1.0f);
|
||||
Rect rect = viewport.GetRect();
|
||||
std::cout << "Rect: (" << rect.x << ", " << rect.y << ", " << rect.width << ", " << rect.height << ")\n";
|
||||
return 0;
|
||||
}
|
||||
Viewport viewport(0, 0, 1920, 1080, 0.0f, 1.0f);
|
||||
Rect rect = viewport.GetRect(); // (0, 0, 1920, 1080)
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [`Viewport::GetAspectRatio`](getaspectratio.md) - 获取宽高比
|
||||
- [Viewport 总览](viewport.md)
|
||||
@@ -1,49 +1,45 @@
|
||||
# Viewport
|
||||
|
||||
**命名空间**: `XCEngine::Math`
|
||||
渲染视口结构体,用于屏幕到归一化坐标的映射。
|
||||
|
||||
**类型**: `struct`
|
||||
**头文件:** `#include <XCEngine/Math/Rect.h>`
|
||||
|
||||
**头文件**: `XCEngine/Math/Viewport.h`
|
||||
**命名空间:** `XCEngine::Math`
|
||||
|
||||
**描述**: 视口,用于渲染目标区域和坐标映射
|
||||
## 结构体定义
|
||||
|
||||
## 概述
|
||||
```cpp
|
||||
struct Viewport {
|
||||
float x = 0.0f;
|
||||
float y = 0.0f;
|
||||
float width = 0.0f;
|
||||
float height = 0.0f;
|
||||
float minDepth = 0.0f;
|
||||
float maxDepth = 1.0f;
|
||||
|
||||
Viewport 结构体表示一个渲染视口,除了位置和尺寸外,还包含深度范围 `(minDepth, maxDepth)`。主要用于屏幕到归一化设备坐标(NDC)的映射,以及渲染目标区域的定义。
|
||||
Viewport() = default;
|
||||
Viewport(float x, float y, float w, float h);
|
||||
Viewport(float x, float y, float w, float h, float minD, float maxD);
|
||||
};
|
||||
```
|
||||
|
||||
## 公共方法
|
||||
## 构造函数
|
||||
|
||||
| 方法 | 描述 |
|
||||
|------|------|
|
||||
| [`GetAspectRatio`](getaspectratio.md) | 获取视口宽高比 |
|
||||
| [`GetRect`](getrect.md) | 转换为 Rect |
|
||||
| `Viewport()` | 默认构造 |
|
||||
| `Viewport(x, y, w, h)` | 2D 视口 |
|
||||
| `Viewport(x, y, w, h, minD, maxD)` | 带深度范围的 3D 视口 |
|
||||
|
||||
## 使用示例
|
||||
## 方法
|
||||
|
||||
```cpp
|
||||
#include "XCEngine/Math/Rect.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace XCEngine::Math;
|
||||
|
||||
int main() {
|
||||
Viewport viewport(0.0f, 0.0f, 1920.0f, 1080.0f, 0.0f, 1.0f);
|
||||
|
||||
std::cout << "Position: (" << viewport.x << ", " << viewport.y << ")\n";
|
||||
std::cout << "Size: " << viewport.width << " x " << viewport.height << "\n";
|
||||
std::cout << "Depth: " << viewport.minDepth << " to " << viewport.maxDepth << "\n";
|
||||
std::cout << "Aspect Ratio: " << viewport.GetAspectRatio() << "\n";
|
||||
|
||||
Rect rect = viewport.GetRect();
|
||||
std::cout << "As Rect: (" << rect.x << ", " << rect.y << ", " << rect.width << ", " << rect.height << ")\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
| 方法 | 返回值 | 描述 |
|
||||
|------|--------|------|
|
||||
| [GetAspectRatio()](viewport-getaspectratio.md) | `float` | 宽高比 (width / height) |
|
||||
| [GetRect()](viewport-getrect.md) | `Rect` | 转换为 Rect |
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [`Rect`](../rect/rect.md) - 浮点矩形
|
||||
- [`RectInt`](../rect/rectint.md) - 整数矩形
|
||||
- [`Vector2`](../vector2/vector2.md) - 二维向量
|
||||
- [Math 模块总览](../math.md) - 返回 Math 模块总览
|
||||
- [Rect](rect-overview.md) - 浮点矩形
|
||||
- [RectInt](rectint.md) - 整数矩形
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
# D3D12CommandList::ClearUnorderedAccessView
|
||||
|
||||
```cpp
|
||||
void ClearUnorderedAccessView(
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE viewHandle,
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE resourceHandle,
|
||||
ID3D12Resource* unorderedAccess,
|
||||
const float values[4],
|
||||
uint32_t rectCount = 0,
|
||||
const D3D12_RECT* rects = nullptr
|
||||
);
|
||||
```
|
||||
|
||||
清除无序访问视图。
|
||||
|
||||
**参数:**
|
||||
- `viewHandle` - GPU 描述符句柄
|
||||
- `resourceHandle` - CPU 描述符句柄
|
||||
- `unorderedAccess` - UAV 资源指针
|
||||
- `values` - 清除值 [x, y, z, w]
|
||||
- `rectCount` - 清除矩形数量
|
||||
- `rects` - 清除矩形数组
|
||||
|
||||
**复杂度:** O(n) 其中 n 为 rectCount
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [D3D12CommandList 总览](command-list.md) - 返回类总览
|
||||
@@ -21,8 +21,8 @@
|
||||
|
||||
| 方法 | 描述 |
|
||||
|------|------|
|
||||
| [`D3D12CommandList`](../../../threading/lambdatask/constructor.md) | 构造函数 |
|
||||
| [`~D3D12CommandList`](../../../threading/readwritelock/destructor.md) | 析构函数 |
|
||||
| [`D3D12CommandList`](constructor.md) | 构造函数 |
|
||||
| [`~D3D12CommandList`](destructor.md) | 析构函数 |
|
||||
| [`Initialize`](initialize.md) | 初始化命令列表 |
|
||||
| [`Shutdown`](shutdown.md) | 关闭命令列表 |
|
||||
| [`Reset`](reset.md) | 重置命令列表 |
|
||||
@@ -51,6 +51,8 @@
|
||||
| [`SetGraphicsRootDescriptorTable`](set-graphics-root-descriptor-table.md) | 设置图形根描述符表 |
|
||||
| [`SetGraphicsRootShaderResourceView`](set-graphics-root-shader-resource-view.md) | 设置图形根着色器资源视图 |
|
||||
| [`SetStencilRef`](set-stencil-ref.md) | 设置模板引用值 |
|
||||
| [`SetDepthStencilState`](set-depth-stencil-state.md) | 设置深度模板状态 |
|
||||
| [`SetBlendState`](set-blend-state.md) | 设置混合状态 |
|
||||
| [`SetBlendFactor`](set-blend-factor.md) | 设置混合因子 |
|
||||
| [`SetDepthBias`](set-depth-bias.md) | 设置深度偏移 |
|
||||
| [`Draw`](draw.md) | 绘制 |
|
||||
@@ -60,6 +62,7 @@
|
||||
| [`Clear`](clear.md) | 清除 |
|
||||
| [`ClearRenderTarget`](clear-render-target.md) | 清除渲染目标 |
|
||||
| [`ClearDepthStencil`](clear-depth-stencil.md) | 清除深度模板 |
|
||||
| [`ClearUnorderedAccessView`](clear-unordered-access-view.md) | 清除无序访问视图 |
|
||||
| [`CopyResource`](copy-resource.md) | 复制资源 |
|
||||
| [`CopyBuffer`](copy-buffer.md) | 复制缓冲区 |
|
||||
| [`CopyTexture`](copy-texture.md) | 复制纹理 |
|
||||
|
||||
16
docs/api/rhi/d3d12/command-list/set-blend-state.md
Normal file
16
docs/api/rhi/d3d12/command-list/set-blend-state.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# D3D12CommandList::SetBlendState
|
||||
|
||||
```cpp
|
||||
void SetBlendState(const BlendState& state) override;
|
||||
```
|
||||
|
||||
设置混合状态。
|
||||
|
||||
**参数:**
|
||||
- `state` - 混合状态结构体
|
||||
|
||||
**复杂度:** O(1)
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [D3D12CommandList 总览](command-list.md) - 返回类总览
|
||||
16
docs/api/rhi/d3d12/command-list/set-depth-stencil-state.md
Normal file
16
docs/api/rhi/d3d12/command-list/set-depth-stencil-state.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# D3D12CommandList::SetDepthStencilState
|
||||
|
||||
```cpp
|
||||
void SetDepthStencilState(const DepthStencilState& state) override;
|
||||
```
|
||||
|
||||
设置深度模板状态。
|
||||
|
||||
**参数:**
|
||||
- `state` - 深度模板状态结构体
|
||||
|
||||
**复杂度:** O(1)
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [D3D12CommandList 总览](command-list.md) - 返回类总览
|
||||
@@ -74,4 +74,4 @@
|
||||
## 相关文档
|
||||
|
||||
- [../rhi/rhi.md](../rhi.md) - RHI 模块总览
|
||||
- [OpenGL 后端](../opengl/overview.md)
|
||||
- [OpenGL 后端](../opengl/opengl.md)
|
||||
|
||||
27
docs/api/rhi/d3d12/depth-stencil-view/constructor.md
Normal file
27
docs/api/rhi/d3d12/depth-stencil-view/constructor.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# D3D12DepthStencilView::D3D12DepthStencilView
|
||||
|
||||
## 函数签名
|
||||
|
||||
```cpp
|
||||
D3D12DepthStencilView()
|
||||
```
|
||||
|
||||
## 描述
|
||||
|
||||
默认构造函数。创建空的深度模板视图实例,成员变量初始化为零值和空指针。
|
||||
|
||||
## 返回值
|
||||
|
||||
无
|
||||
|
||||
## 示例
|
||||
|
||||
```cpp
|
||||
D3D12DepthStencilView dsv; // 创建空实例
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [D3D12DepthStencilView](depth-stencil-view.md) - 类总览
|
||||
- [D3D12DepthStencilView::Initialize](initialize.md) - 初始化方法
|
||||
- [D3D12DepthStencilView::~D3D12DepthStencilView](destructor.md) - 析构函数
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
**类型**: `class`
|
||||
|
||||
**头文件**: `XCEngine/RHI/D3D12/D3D12DepthStencilView.h`
|
||||
|
||||
**描述**: DirectX 12 深度模板视图的 D3D12 实现,用于渲染管线中的深度/模板测试。
|
||||
|
||||
## 概述
|
||||
@@ -14,8 +16,8 @@
|
||||
|
||||
| 方法 | 描述 |
|
||||
|------|------|
|
||||
| [`D3D12DepthStencilView()`](initialize.md) | 构造函数 |
|
||||
| [`~D3D12DepthStencilView()`](initialize.md) | 析构函数 |
|
||||
| [`D3D12DepthStencilView()`](constructor.md) | 构造函数 |
|
||||
| [`~D3D12DepthStencilView()`](destructor.md) | 析构函数 |
|
||||
| [`Initialize`](initialize.md) | 初始化深度模板视图 |
|
||||
| [`InitializeAt`](initialize-at.md) | 在指定位置初始化深度模板视图 |
|
||||
| [`Shutdown`](shutdown.md) | 关闭深度模板视图 |
|
||||
|
||||
34
docs/api/rhi/d3d12/depth-stencil-view/destructor.md
Normal file
34
docs/api/rhi/d3d12/depth-stencil-view/destructor.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# D3D12DepthStencilView::~D3D12DepthStencilView
|
||||
|
||||
## 函数签名
|
||||
|
||||
```cpp
|
||||
~D3D12DepthStencilView()
|
||||
```
|
||||
|
||||
## 描述
|
||||
|
||||
析构函数。自动调用 `Shutdown()` 释放内部资源。
|
||||
|
||||
## 返回值
|
||||
|
||||
无
|
||||
|
||||
## 注意事项
|
||||
|
||||
此析构函数不直接释放 D3D12 资源,仅清理类内部状态。实际资源释放由描述符堆管理。
|
||||
|
||||
## 示例
|
||||
|
||||
```cpp
|
||||
{
|
||||
D3D12DepthStencilView dsv;
|
||||
dsv.Initialize(device, depthBuffer, nullptr);
|
||||
// 使用 dsv...
|
||||
} // dsv 析构时自动调用 Shutdown()
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [D3D12DepthStencilView](depth-stencil-view.md) - 类总览
|
||||
- [D3D12DepthStencilView::Shutdown](shutdown.md) - 关闭方法
|
||||
@@ -59,4 +59,4 @@ heap.Shutdown();
|
||||
|
||||
- [D3D12 后端总览](../d3d12.md)
|
||||
- [RHIDescriptorPool](../../descriptor-pool/descriptor-pool.md) - 抽象描述符池接口
|
||||
- [D3D12Enum](d3d12-enum.md) - D3D12 类型枚举映射
|
||||
- [D3D12Enum](../enums/enums.md) - D3D12 类型枚举映射
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
|
||||
**命名空间**: `XCEngine::RHI`
|
||||
|
||||
**类型**: `class`
|
||||
|
||||
**头文件**: `XCEngine/RHI/D3D12/D3D12RenderTargetView.h`
|
||||
|
||||
**描述**: DirectX 12 渲染目标视图的 D3D12 实现,用于在渲染管线中作为渲染目标使用。
|
||||
|
||||
## 公共方法
|
||||
|
||||
27
docs/api/rhi/d3d12/root-signature/constructor.md
Normal file
27
docs/api/rhi/d3d12/root-signature/constructor.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# D3D12RootSignature::D3D12RootSignature
|
||||
|
||||
## 函数签名
|
||||
|
||||
```cpp
|
||||
D3D12RootSignature()
|
||||
```
|
||||
|
||||
## 描述
|
||||
|
||||
默认构造函数。创建空的根签名实例,成员变量初始化为零值和空指针。
|
||||
|
||||
## 返回值
|
||||
|
||||
无
|
||||
|
||||
## 示例
|
||||
|
||||
```cpp
|
||||
D3D12RootSignature rootSig; // 创建空实例
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [D3D12RootSignature](root-signature.md) - 类总览
|
||||
- [D3D12RootSignature::Initialize](initialize.md) - 初始化方法
|
||||
- [D3D12RootSignature::~D3D12RootSignature](destructor.md) - 析构函数
|
||||
34
docs/api/rhi/d3d12/root-signature/destructor.md
Normal file
34
docs/api/rhi/d3d12/root-signature/destructor.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# D3D12RootSignature::~D3D12RootSignature
|
||||
|
||||
## 函数签名
|
||||
|
||||
```cpp
|
||||
~D3D12RootSignature()
|
||||
```
|
||||
|
||||
## 描述
|
||||
|
||||
析构函数。自动调用 `Shutdown()` 释放内部资源。
|
||||
|
||||
## 返回值
|
||||
|
||||
无
|
||||
|
||||
## 注意事项
|
||||
|
||||
此析构函数自动调用 Shutdown() 确保资源被正确释放。
|
||||
|
||||
## 示例
|
||||
|
||||
```cpp
|
||||
{
|
||||
D3D12RootSignature rootSig;
|
||||
rootSig.Initialize(device, desc);
|
||||
// 使用 rootSig...
|
||||
} // rootSig 析构时自动调用 Shutdown()
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [D3D12RootSignature](root-signature.md) - 类总览
|
||||
- [D3D12RootSignature::Shutdown](shutdown.md) - 关闭方法
|
||||
@@ -4,12 +4,16 @@
|
||||
|
||||
**类型**: `class` (D3D12-specific, does not inherit from RHI)
|
||||
|
||||
**头文件**: `XCEngine/RHI/D3D12/D3D12RootSignature.h`
|
||||
|
||||
**描述**: DirectX 12 根签名的 D3D12 实现,提供根签名序列化、参数创建等功能。
|
||||
|
||||
## 公共方法
|
||||
|
||||
| 方法 | 描述 |
|
||||
|------|------|
|
||||
| [`D3D12RootSignature`](constructor.md) | 构造函数 |
|
||||
| [`~D3D12RootSignature`](destructor.md) | 析构函数 |
|
||||
| [`Initialize`](initialize.md) | 初始化根签名 |
|
||||
| [`Shutdown`](shutdown.md) | 关闭根签名 |
|
||||
| [`GetRootSignature`](get-root-signature.md) | 获取 D3D12 根签名 |
|
||||
@@ -44,4 +48,4 @@ if (rootSig.Initialize(device, desc)) {
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [D3D12 后端总览](../../opengl/overview.md)
|
||||
- [D3D12 后端总览](../d3d12.md)
|
||||
|
||||
@@ -13,4 +13,4 @@
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [D3D12 后端总览](../../opengl/overview.md)
|
||||
- [D3D12 后端总览](../d3d12.md)
|
||||
|
||||
@@ -45,4 +45,4 @@ delete srv;
|
||||
## 相关文档
|
||||
|
||||
- [D3D12 后端概览](../d3d12.md)
|
||||
- [OpenGL 后端](../../opengl/overview.md)
|
||||
- [OpenGL 后端](../../opengl/opengl.md)
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
| [`CreateRenderWindow`](create-render-window.md) | 创建渲染窗口 |
|
||||
| [`InitializeWithExistingWindow`](initialize-with-existing-window.md) | 使用现有窗口初始化 |
|
||||
| [`GetWindow`](get-window.md) | 获取 GLFW 窗口指针 |
|
||||
| [`GetDC`](get-dc.md) | 获取 Windows 设备上下文 |
|
||||
| [`GetContext`](get-context.md) | 获取 OpenGL 渲染上下文 |
|
||||
| [`GetDeviceInfoImpl`](get-device-info-impl.md) | 获取设备信息实现 |
|
||||
| [`SwapBuffers`](swap-buffers.md) | 交换前后缓冲区 |
|
||||
| [`PollEvents`](poll-events.md) | 处理窗口事件 |
|
||||
|
||||
31
docs/api/rhi/opengl/device/get-context.md
Normal file
31
docs/api/rhi/opengl/device/get-context.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# OpenGLDevice::GetContext
|
||||
|
||||
获取 OpenGL 渲染上下文(Rendering Context)。
|
||||
|
||||
```cpp
|
||||
HGLRC GetContext() const;
|
||||
```
|
||||
|
||||
返回 OpenGL 渲染上下文的句柄。
|
||||
|
||||
**参数:** 无
|
||||
|
||||
**返回:** `HGLRC` - OpenGL 渲染上下文句柄
|
||||
|
||||
**线程安全:** ❌
|
||||
|
||||
**注意:** 此方法返回原生 OpenGL 渲染上下文句柄,可用于 `wglShareLists`、`wglMakeCurrent` 等原生 OpenGL 上下文操作。大多数情况下不需要直接使用此方法。
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
HGLRC hglrc = device.GetContext();
|
||||
// 可以使用 hglrc 进行原生 OpenGL 上下文操作
|
||||
HGLRC currentContext = wglGetCurrentContext();
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [OpenGLDevice 总览](device.md) - 返回类总览
|
||||
- [GetDC](get-dc.md) - 获取 Windows 设备上下文
|
||||
- [GetWindow](get-window.md) - 获取 GLFW 窗口指针
|
||||
31
docs/api/rhi/opengl/device/get-dc.md
Normal file
31
docs/api/rhi/opengl/device/get-dc.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# OpenGLDevice::GetDC
|
||||
|
||||
获取 OpenGL 设备的设备上下文(Device Context)。
|
||||
|
||||
```cpp
|
||||
HDC GetDC() const;
|
||||
```
|
||||
|
||||
返回与 OpenGL 渲染上下文关联的 Windows 设备上下文句柄。
|
||||
|
||||
**参数:** 无
|
||||
|
||||
**返回:** `HDC` - Windows 设备上下文句柄
|
||||
|
||||
**线程安全:** ❌
|
||||
|
||||
**注意:** 此方法返回原生 Windows HDC,可用于低级 GDI 操作或与原生 Windows OpenGL 上下文交互。大多数情况下不需要直接使用此方法。
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
HDC hdc = device.GetDC();
|
||||
// 可以使用 hdc 进行原生 Windows OpenGL 操作
|
||||
HDC currentDC = wglGetCurrentDC();
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [OpenGLDevice 总览](device.md) - 返回类总览
|
||||
- [GetContext](get-context.md) - 获取 OpenGL 渲染上下文
|
||||
- [GetWindow](get-window.md) - 获取 GLFW 窗口指针
|
||||
34
docs/api/rhi/opengl/shader/set-mat2.md
Normal file
34
docs/api/rhi/opengl/shader/set-mat2.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# OpenGLShader::SetMat2
|
||||
|
||||
设置 2x2 矩阵 uniform 变量。
|
||||
|
||||
```cpp
|
||||
void SetMat2(const char* name, const float* value);
|
||||
```
|
||||
|
||||
通过名称查找并设置着色器中的 2x2 变换矩阵 uniform 变量。矩阵按列主序存储。
|
||||
|
||||
**参数:**
|
||||
- `name` - uniform 变量名称
|
||||
- `value` - 指向 4 个 float 元素的数组指针(列主序排列)
|
||||
|
||||
**返回:** 无
|
||||
|
||||
**线程安全:** ❌(需要在渲染线程调用)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
// 设置 2x2 旋转矩阵
|
||||
float rotation[4] = {
|
||||
cos(angle), sin(angle), // 第一列
|
||||
-sin(angle), cos(angle) // 第二列
|
||||
};
|
||||
shader->SetMat2("u_rotation", rotation);
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [OpenGLShader 总览](shader.md) - 返回类总览
|
||||
- [SetMat3](set-mat3.md) - 设置 3x3 矩阵
|
||||
- [SetMat4](../../shader/set-mat4.md) - 设置 4x4 矩阵
|
||||
35
docs/api/rhi/opengl/shader/set-mat3.md
Normal file
35
docs/api/rhi/opengl/shader/set-mat3.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# OpenGLShader::SetMat3
|
||||
|
||||
设置 3x3 矩阵 uniform 变量。
|
||||
|
||||
```cpp
|
||||
void SetMat3(const char* name, const float* value);
|
||||
```
|
||||
|
||||
通过名称查找并设置着色器中的 3x3 变换矩阵 uniform 变量。矩阵按列主序存储。常见用途包括设置法线矩阵、模型矩阵的 3x3 部分等。
|
||||
|
||||
**参数:**
|
||||
- `name` - uniform 变量名称
|
||||
- `value` - 指向 9 个 float 元素的数组指针(列主序排列)
|
||||
|
||||
**返回:** 无
|
||||
|
||||
**线程安全:** ❌(需要在渲染线程调用)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
// 设置 3x3 法线矩阵
|
||||
float normalMatrix[9] = {
|
||||
1.0f, 0.0f, 0.0f, // 第一列
|
||||
0.0f, 1.0f, 0.0f, // 第二列
|
||||
0.0f, 0.0f, 1.0f // 第三列
|
||||
};
|
||||
shader->SetMat3("u_normalMatrix", normalMatrix);
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [OpenGLShader 总览](shader.md) - 返回类总览
|
||||
- [SetMat2](set-mat2.md) - 设置 2x2 矩阵
|
||||
- [SetMat4](../../shader/set-mat4.md) - 设置 4x4 矩阵
|
||||
44
docs/api/rhi/opengl/shader/set-mat4-array.md
Normal file
44
docs/api/rhi/opengl/shader/set-mat4-array.md
Normal file
@@ -0,0 +1,44 @@
|
||||
# OpenGLShader::SetMat4Array
|
||||
|
||||
设置 4x4 矩阵数组 uniform 变量。
|
||||
|
||||
```cpp
|
||||
void SetMat4Array(const char* name, const float* values, unsigned int count);
|
||||
```
|
||||
|
||||
通过名称查找并设置着色器中的 4x4 矩阵数组 uniform 变量。矩阵按列主序存储。
|
||||
|
||||
**参数:**
|
||||
- `name` - uniform 变量名称
|
||||
- `values` - 指向 `count * 16` 个 float 元素的数组指针(列主序排列)
|
||||
- `count` - 矩阵数量
|
||||
|
||||
**返回:** 无
|
||||
|
||||
**线程安全:** ❌(需要在渲染线程调用)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
// 设置多个变换矩阵(例如骨骼动画)
|
||||
const unsigned int boneCount = 4;
|
||||
float boneMatrices[4 * 16] = {
|
||||
// 第一个矩阵
|
||||
1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f,
|
||||
// 第二个矩阵
|
||||
0.5f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.5f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.5f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f,
|
||||
// ...更多矩阵
|
||||
};
|
||||
shader->SetMat4Array("u_boneMatrices", boneMatrices, boneCount);
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [OpenGLShader 总览](shader.md) - 返回类总览
|
||||
- [SetMat4 (single)](../../shader/set-mat4.md) - 设置单个 4x4 矩阵
|
||||
35
docs/api/rhi/opengl/shader/set-vec3-array.md
Normal file
35
docs/api/rhi/opengl/shader/set-vec3-array.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# OpenGLShader::SetVec3
|
||||
|
||||
设置三维向量 uniform 变量(数组重载版本)。
|
||||
|
||||
```cpp
|
||||
void SetVec3(const char* name, const float* values);
|
||||
```
|
||||
|
||||
通过名称查找并设置着色器中的三维向量 uniform 变量,使用浮点数数组作为输入。
|
||||
|
||||
**参数:**
|
||||
- `name` - uniform 变量名称
|
||||
- `values` - 指向 3 个 float 元素的数组指针
|
||||
|
||||
**返回:** 无
|
||||
|
||||
**线程安全:** ❌(需要在渲染线程调用)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
// 设置光照方向
|
||||
float lightDir[3] = { 0.5f, 1.0f, 0.3f };
|
||||
shader->SetVec3("u_lightDir", lightDir);
|
||||
|
||||
// 设置法线
|
||||
float normal[3] = { 0.0f, 1.0f, 0.0f };
|
||||
shader->SetVec3("u_normal", normal);
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [OpenGLShader 总览](shader.md) - 返回类总览
|
||||
- [SetVec3 (xyz)](../../shader/set-vec3.md) - xyz分量版本
|
||||
- [SetVec4 (float*)](set-vec4-array.md) - 四维向量数组版本
|
||||
35
docs/api/rhi/opengl/shader/set-vec4-array.md
Normal file
35
docs/api/rhi/opengl/shader/set-vec4-array.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# OpenGLShader::SetVec4
|
||||
|
||||
设置四维向量 uniform 变量(数组重载版本)。
|
||||
|
||||
```cpp
|
||||
void SetVec4(const char* name, const float* values);
|
||||
```
|
||||
|
||||
通过名称查找并设置着色器中的四维向量 uniform 变量,使用浮点数数组作为输入。
|
||||
|
||||
**参数:**
|
||||
- `name` - uniform 变量名称
|
||||
- `values` - 指向 4 个 float 元素的数组指针
|
||||
|
||||
**返回:** 无
|
||||
|
||||
**线程安全:** ❌(需要在渲染线程调用)
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
// 设置颜色
|
||||
float color[4] = { 1.0f, 0.5f, 0.2f, 1.0f };
|
||||
shader->SetVec4("u_color", color);
|
||||
|
||||
// 设置齐次坐标
|
||||
float position[4] = { 10.0f, 20.0f, 30.0f, 1.0f };
|
||||
shader->SetVec4("u_position", position);
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [OpenGLShader 总览](shader.md) - 返回类总览
|
||||
- [SetVec4 (xyzw)](../../shader/set-vec4.md) - xyzw分量版本
|
||||
- [SetVec3 (float*)](set-vec3-array.md) - 三维向量数组版本
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
## 公共方法
|
||||
|
||||
### 编译方法
|
||||
|
||||
| 方法 | 描述 |
|
||||
|------|------|
|
||||
| [`CompileFromFile`](compile-from-file-vs-fs.md) | 从文件编译顶点+片段着色器 |
|
||||
@@ -13,16 +15,36 @@
|
||||
| [`Compile`](compile-type.md) | 从源码编译单着色器 |
|
||||
| [`CompileCompute`](compile-compute.md) | 编译计算着色器 |
|
||||
| [`Shutdown`](../../shader/shutdown.md) | 关闭着色器 |
|
||||
|
||||
### 绑定方法
|
||||
|
||||
| 方法 | 描述 |
|
||||
|------|------|
|
||||
| [`Use`](use.md) | 使用着色器 |
|
||||
| [`Bind`](../../shader/bind.md) | 绑定着色器 |
|
||||
| [`Unbind`](../../shader/unbind.md) | 解绑着色器 |
|
||||
|
||||
### Uniform 设置方法
|
||||
|
||||
| 方法 | 描述 |
|
||||
|------|------|
|
||||
| [`SetInt`](../../shader/set-int.md) | 设置整数 uniform |
|
||||
| [`SetIntArray`](set-int-array.md) | 设置整数数组 uniform |
|
||||
| [`SetFloat`](../../shader/set-float.md) | 设置浮点数 uniform |
|
||||
| [`SetFloatArray`](set-float-array.md) | 设置浮点数数组 uniform |
|
||||
| [`SetVec3`](../../shader/set-vec3.md) | 设置 vec3 uniform |
|
||||
| [`SetVec4`](../../shader/set-vec4.md) | 设置 vec4 uniform |
|
||||
| [`SetVec3`](../../shader/set-vec3.md) | 设置 vec3 uniform (xyz分量) |
|
||||
| [`SetVec3`](set-vec3-array.md) | 设置 vec3 uniform (数组) |
|
||||
| [`SetVec4`](../../shader/set-vec4.md) | 设置 vec4 uniform (xyzw分量) |
|
||||
| [`SetVec4`](set-vec4-array.md) | 设置 vec4 uniform (数组) |
|
||||
| [`SetMat2`](set-mat2.md) | 设置 mat2 uniform |
|
||||
| [`SetMat3`](set-mat3.md) | 设置 mat3 uniform |
|
||||
| [`SetMat4`](../../shader/set-mat4.md) | 设置 mat4 uniform |
|
||||
| [`SetMat4Array`](set-mat4-array.md) | 设置 mat4 数组 uniform |
|
||||
|
||||
### 查询方法
|
||||
|
||||
| 方法 | 描述 |
|
||||
|------|------|
|
||||
| [`GetUniformLocation`](get-uniform-location.md) | 获取 uniform 位置 |
|
||||
| [`GetID`](get-id.md) | 获取着色器 ID |
|
||||
| [`GetNativeHandle`](../../buffer/get-native-handle.md) | 获取原生句柄 |
|
||||
|
||||
@@ -116,7 +116,7 @@ delete device;
|
||||
## 后端文档
|
||||
|
||||
- [D3D12 后端](d3d12/d3d12.md) - DirectX 12 实现详情
|
||||
- [OpenGL 后端](opengl/overview.md) - OpenGL 实现详情
|
||||
- [OpenGL 后端](opengl/opengl.md) - OpenGL 实现详情
|
||||
|
||||
### D3D12 实现
|
||||
|
||||
|
||||
Reference in New Issue
Block a user