一个用 C++23 编写的教育性软件渲染器,用于从零学习光栅化、可编程管线、材质系统、多 Pass 后处理和基础 PBR 工作流。
Forge-SR 是学习项目,不面向生产环境。
| 组件 | 版本 / 说明 |
|---|---|
| 操作系统 | Windows 10+(主要开发环境) |
| 编译器 | MSVC 2022(Visual Studio 2022,需安装"使用 C++ 的桌面开发"工作负载) |
| C++ 标准 | C++23(含 C++20 Modules) |
| 构建系统 | xmake 2.9+(推荐通过 winget install xmake 或官网安装) |
所有依赖库(SDL3、Catch2、stb、tinyobjloader、nlohmann_json)由 xmake 自动拉取编译,无需手动安装。
# 克隆仓库
git clone <repo-url> && cd Forge-SR
# Debug 模式构建全部 target
xmake config -m debug && xmake build
# 或 Release 模式(编译快、日志少,适合性能观察)
xmake config -m release && xmake build# 运行指定示例(rundir = runtime/,GPU 无关,纯 CPU 渲染)
xmake run 24app-template
# Headless 模式:不创建窗口,渲染 N 帧后退出
xmake run 24app-template --headless 3
# 运行全部单元测试
xmake build unit_tests && xmake run unit_tests所有 sample 以 runtime/ 为工作目录,程序启动依赖该目录存在(构建后项目根目录已包含 runtime/,分发时请勿删除)。
若修改 .cppm 接口后链接报错,整体清理重建:
xmake clean -a && xmake buildForge-SR 追求的是“看得见的渲染管线”:每个阶段都尽量保持简单、可调试、可验证。当前项目已经从基础三角形推进到 RenderGraph 后处理与 PBR 示例。
核心关注点:
- 现代 C++:C++23 + C++20 Modules。
- 软件渲染:完整 CPU 光栅化管线。
- 教学友好:sample 即文档,配合
PipelineProfiler和日志观察运行过程。 - 渐进架构:从单 Pass 到 RenderGraph,从 Lambert 到 Cook-Torrance PBR。
| 方向 | 状态 |
|---|---|
| 基础光栅化管线 | 完成 |
| 自定义 VS/PS Shader 系统 | 完成 |
| 纹理采样与图像加载 | 完成 |
| 材质系统 | 完成 |
| 多线程渲染基础 | 完成 |
| Skybox / Cubemap | 完成 |
| RenderGraph / 多 Pass 调度 | 主线已完成 |
| Tonemap / Bloom / FXAA 后处理 | 已有示例 |
| Cook-Torrance PBR | 已有示例 |
| PBR 材质贴图 | 已有程序化贴图示例 |
| MeshDraw 抽象 | 完成 |
| Blueprint + AssetLoader 端到端渲染 | 完成(OBJ + JSON + Headless 截图) |
| PipelineProfiler 多 draw call 适配 | 完成 |
| IBL (Image-Based Lighting) | 完成(Irradiance / Prefiltered Specular / BRDF LUT) |
| Early-Z 深度预测试 | 完成 |
| Mipmap / Trilinear 显式 LOD 采样 | 完成 |
| SampleApp 功能聚合模板 | 完成(24app-template,headless 不创建 SDL Window) |
| SSAO 屏幕空间环境光遮蔽 | 完成(Crytek 半球采样法) |
| HBAO 水平基准环境光遮蔽 | 完成(8 方向光线步进) |
| Deferred 延迟渲染 | 完成(Tile-Based,CPU 光源裁剪) |
| Multi-Light 多光源 Forward vs Deferred | 完成(32 点光源 A/B 对比) |
| 真背面剔除 | 待推进 |
当前最新 sample:28multi-light。
# 构建核心库
xmake build forge_core
# 构建指定示例
xmake build 20ibl
# 运行指定示例
xmake run 24app-template
# Headless 模式(渲染 N 帧后截图退出,不创建 SDL Window)
xmake run 24app-template --headless 3
# 构建并运行单元测试
xmake build unit_tests && xmake run unit_tests
# 按 tag 过滤测试
xmake run unit_tests "[pipeline]"
# 查看所有 target
xmake show -l targets
# 模块依赖异常时清理重建
xmake clean -a && xmake build注意:xmake build 一次只接受一个 target,不要写成 xmake build unit_tests 17pbr-textured。
src/forge/
├── core/ # forge.core:日志、数学、性能分析、平台辅助
├── pipeline/ # forge.pipeline:渲染管线、数据布局、Shader、材质、资源、Worker
├── rendergraph/ # forge.rendergraph:RenderGraph / RenderPass / ResourcePool
└── platform/ # forge.platform.window:SDL3 窗口封装
sample/
├── 01hello-log/ # 日志系统
├── 02hello-window/ # SDL3 窗口
├── 03hello-triangle/ # 三角形
├── 04hello-cube/ # MVP + 深度 + Lambert 立方体
├── 05hello-sphere/ # UV Sphere
├── 06hello-texture/ # 纹理加载与采样基础
├── 07texture-cube/ # 自定义 VS/PS + 纹理立方体
├── 08multi-thread/ # 多线程渲染架构
├── 09render-worker/ # RenderWorker 高级封装
├── 10material-demo/ # 材质系统演示
├── 11skybox/ # Skybox + Cubemap
├── 12rendergraph/ # RenderGraph 多 Pass 共享 RT
├── 13tonemap/ # Reinhard Tonemap 后处理
├── 14bloom/ # Bloom 后处理
├── 15fxaa/ # FXAA 后处理
├── 16pbr/ # Cook-Torrance PBR 材质球
├── 17pbr-textured/ # PBR 材质贴图示例
├── 18mesh-draw/ # MeshDraw 抽象 + DrawList
├── 19blueprint/ # Blueprint + AssetLoader + OBJ 端到端渲染
├── 20ibl/ # IBL (Image-Based Lighting) PBR 环境光照
├── 21pbr-materials/ # 真实 PBR 材质贴图 + IBL
├── 22early-z/ # Early-Z 深度预测试优化
├── 23mipmap/ # Mipmap + Trilinear 显式 LOD
├── 24app-template/ # 功能聚合 App 模板
├── 25ssao/ # SSAO 屏幕空间环境光遮蔽
├── 26hbao/ # HBAO 水平基准环境光遮蔽
├── 27deferred/ # Tile-Based 延迟渲染
├── 28multi-light/ # 多光源 Forward vs Deferred 对比
└── common/ # sample 共享工具(sample_utils.hpp + sample_app.hpp)
tests/unit/ # Catch2 单元测试
doc/ # 设计文档与阶段记录
scripts/ # 构建/测试脚本
images/ # 归档效果截图(统一存储展示用 PNG)
forge_core 是唯一的静态库 target,sample 和测试 target 都依赖它。
Pipeline::execute() 将渲染拆成四个阶段:
- Vertex Shading
- 有自定义 VS 时调用
custom_vs_fn_。 - 无自定义 VS 时走内置
VertexStage。 - 输出写入
geometry_buffer。
- 有自定义 VS 时调用
- Transform
- 透视除法、视口变换、计算
1/w和深度。 - 深度写回
SV_Depth槽位。
- 透视除法、视口变换、计算
- Rasterization
- 扫描线光栅化。
- 输出片元坐标、primitive id、重心坐标。
- Fragment Shading
- 对所有 varying 做透视校正插值。
- 执行自定义 PS 或内置 FragmentStage。
- 深度测试通过后写入
Framebuffer。
透视校正公式:
result = sum(attr_i * inv_w_i * lambda_i) / sum(inv_w_i * lambda_i)
| 类型 | 职责 |
|---|---|
VaryingLayout |
描述 semantic、元素数量、offset、stride |
StreamBuffer |
按 stride 存储动态字节数据 |
DynamicView |
基于 layout + byte span 提供 view<T>(Semantic) |
PipelineData |
输入顶点数据及布局 |
PipelineDataBuilder<T> |
从用户顶点结构构建 PipelineData |
标准输入数据模式:
VaryingLayout layout;
layout.add_float3(Semantic::Position);
layout.add_float2(Semantic::TexCoord0);
auto data = PipelineDataBuilder<VertexUV>(layout)
.put(vertices)
.bind(Semantic::Position, &VertexUV::position)
.bind(Semantic::TexCoord0, &VertexUV::uv)
.build();pipeline.bind_vertex_shader<VSInput, VSOutput>(MyVS{&cb});
pipeline.bind_fragment_shader<PSInput, PSOutput>(MyPS{&pipeline.shader_resources()});要求:
VSInput::from_view(const DynamicView&)。VSOutput继承VertexShaderOutputBase。VSOutput::write_to_view(DynamicView&)。VSOutput::output_layout()。PSInput::from_view(const DynamicView&)。PSOutput继承FragmentShaderOutputBase。
重要规则:自定义 VSOutput::output_layout() 必须显式包含:
layout.add_float4(Semantic::SV_Position);
layout.add_float(Semantic::SV_Depth);自动补充 SV_Depth 的机制已经移除。
材质系统采用三层分离:
| 层 | 类型 | 作用 |
|---|---|---|
| 数据 | Material |
存储纹理和参数 variant |
| 应用 | Material::apply_to(ShaderResources&) |
将材质写入资源槽 |
| 查询 | MaterialView |
PS 内只读查询材质参数和纹理 |
| 光照 | shading::* |
纯函数光照模型 |
当前支持的 shading 函数:
shading::unlitshading::lambertshading::blinn_phongshading::cook_torrance
PBR 当前覆盖:
- GGX / Trowbridge-Reitz NDF。
- Smith-GGX 几何遮蔽。
- Schlick Fresnel。
- Metallic / Roughness 参数。
- Albedo / Normal / Roughness / Metallic / AO 贴图示例。
- Reinhard Tonemap + Gamma 输出。
RenderGraph 由三部分组成:
RenderGraph
├── ResourcePool # Framebuffer / Image / Cubemap 统一管理
└── RenderPass DAG # 字符串依赖 + Kahn 拓扑排序
└── RenderPass # 每个 Pass 持有私有 Pipeline
关键接口:
RenderGraph graph;
Framebuffer output_rt(W, H);
graph.set_output_rt(output_rt);
// 写方:创建或获取命名中间 RT
auto& scene = resource_pool().acquire_framebuffer("scene_color", W, H);
// 读方:把命名 Framebuffer 的 color attachment 包装成 TextureView
auto scene_view = resource_pool().sample_framebuffer("scene_color");
// 输出通道:与命名中间纹理系统解耦
auto* output = render_graph().output_rt();典型后处理链:
SkyboxPass -> GeometryPass -> PostProcessPass -> output_rt
Bloom 示例链路:
Skybox -> Cube -> Sphere -> BrightPass -> BlurH -> BlurV -> Composite
| 示例 | 说明 | 关键点 |
|---|---|---|
01hello-log |
日志演示 | 6 级日志 |
02hello-window |
窗口演示 | SDL3 事件循环 |
03hello-triangle |
三角形 | 最小光栅化路径 |
04hello-cube |
立方体 | MVP、深度、Lambert |
05hello-sphere |
球体 | UV sphere、法线变换 |
06hello-texture |
纹理加载与采样 | ImageLoader、TextureView、NearestSampler |
07texture-cube |
纹理立方体 | 自定义 VS/PS、双视口采样对比 |
08multi-thread |
多线程渲染 | SwapBuffer、进度反馈 |
09render-worker |
Worker 封装 | 高级多线程 API |
10material-demo |
材质系统 | Unlit / Lambert / BlinnPhong |
11skybox |
天空盒 | Cubemap、sv_depth = 1.0 |
12rendergraph |
多 Pass 调度 | 共享中间 RT、拓扑排序 |
13tonemap |
Tonemap | sample_framebuffer、Reinhard |
14bloom |
Bloom | BrightPass、Gaussian Blur、Composite |
15fxaa |
FXAA | 屏幕空间抗锯齿 |
16pbr |
PBR 材质球 | Cook-Torrance、roughness/metallic 网格 |
17pbr-textured |
PBR 贴图 | Albedo/Normal/Roughness/Metallic/AO |
18mesh-draw |
MeshDraw 抽象 | MeshData、MeshDraw、DrawList、多物体渲染 |
19blueprint |
端到端渲染 | Blueprint + AssetLoader + OBJ + Headless 截图 |
20ibl |
IBL 环境光照 | Irradiance Map、Prefiltered Specular、BRDF LUT |
21pbr-materials |
真实 PBR 材质贴图 | Gold / Rusted Iron / Grass / Plastic / Wall + IBL |
22early-z |
Early-Z 深度预测试 | 多层遮挡球体、Front-to-Back 排序、Profiler |
23mipmap |
Mipmap 纹理链 | MipChain、TrilinearSampler、显式 LOD |
24app-template |
功能聚合 App 模板 | SampleApp、SDL-free headless、并行、时间戳截图、mipmap 默认启用 |
25ssao |
SSAO 环境光遮蔽 | Crytek 半球采样(56 samples)、G-Buffer、可分离高斯模糊、范围检查 |
26hbao |
HBAO 环境光遮蔽 | 8 方向光线步进(6 steps)、NdotD 角度偏置、逐像素抖动旋转、深度感知模糊 |
27deferred |
延迟渲染 | 3 通道 G-Buffer、Tile-Based(16×16)、CPU 光源裁剪、Cook-Torrance PBR |
28multi-light |
多光源对比 | 32 点光源 Forward vs Tile Deferred A/B、HSV 色相旋转、--benchmark 模式、热力图 |
测试框架:Catch2。
当前参考规模:
704 assertions / 58 test cases
归档效果图统一存放在 images/ 目录,运行时临时产物(带时间戳)保留在 runtime/。
| 示例 | 截图 |
|---|---|---|
| 19 Blueprint |
|
| 20 IBL |
|
| 21 PBR Materials |
|
| 22 Early-Z |
|
| 23 Mipmap |
|
| 24 App Template |
|
| 25 SSAO |
|
| 26 HBAO |
|
| 27 Deferred |
|
| 28 Multi-Light |
|
优先级建议:
- 文档与示例说明持续同步。
MeshDraw 抽象✅ 已完成(18mesh-draw)。Profiler 适配多 draw call✅ 已完成(累积统计 + draw call 计数)。IBL✅ 已完成(Irradiance Map、Prefiltered Specular、BRDF LUT,20ibl)。Early-Z 深度预测试✅ 已完成(22early-z,Fragment 加速 1.3x)。Mipmap / Trilinear 显式 LOD✅ 已完成(23mipmap,MipChain+TrilinearSampler)。SampleApp 功能聚合模板✅ 已完成(24app-template,SDL-free headless)。SSAO 屏幕空间环境光遮蔽✅ 已完成(25ssao,Crytek 半球采样法)。HBAO 水平基准环境光遮蔽✅ 已完成(26hbao,8 方向光线步进)。Deferred 延迟渲染✅ 已完成(27deferred,Tile-Based + CPU 光源裁剪)。Multi-Light 多光源 Forward vs Deferred✅ 已完成(28multi-light,32 点光源 A/B 对比)。- 性能优化:Profiler 基础设施已修正,后续基于采集数据分析热点。
- Early-Z 前置深度插值:深度单独提前插值,减少无用全属性插值开销。
- 光栅化阶段并行:三角形级并行光栅化。
- 真正的三角形级背面剔除优化。
- SwapBuffer 与 RenderGraph 输出整合。
- 多核并行渲染:任务系统 / 线程池 / tile-based 并行。
- 更多 Tonemap 算子:ACES / Filmic。
- HDR/Equirectangular 环境贴图加载。
详见 LICENSE。