Skip to content

Repository files navigation

Forge-SR

一个用 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 build

项目目标

Forge-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() 将渲染拆成四个阶段:

  1. Vertex Shading
    • 有自定义 VS 时调用 custom_vs_fn_
    • 无自定义 VS 时走内置 VertexStage
    • 输出写入 geometry_buffer
  2. Transform
    • 透视除法、视口变换、计算 1/w 和深度。
    • 深度写回 SV_Depth 槽位。
  3. Rasterization
    • 扫描线光栅化。
    • 输出片元坐标、primitive id、重心坐标。
  4. 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();

自定义 Shader 约定

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 的机制已经移除。

材质与 PBR

材质系统采用三层分离:

类型 作用
数据 Material 存储纹理和参数 variant
应用 Material::apply_to(ShaderResources&) 将材质写入资源槽
查询 MaterialView PS 内只读查询材质参数和纹理
光照 shading::* 纯函数光照模型

当前支持的 shading 函数:

  • shading::unlit
  • shading::lambert
  • shading::blinn_phong
  • shading::cook_torrance

PBR 当前覆盖:

  • GGX / Trowbridge-Reitz NDF。
  • Smith-GGX 几何遮蔽。
  • Schlick Fresnel。
  • Metallic / Roughness 参数。
  • Albedo / Normal / Roughness / Metallic / AO 贴图示例。
  • Reinhard Tonemap + Gamma 输出。

RenderGraph

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 纹理加载与采样 ImageLoaderTextureViewNearestSampler
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 纹理链 MipChainTrilinearSampler、显式 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 | |

后续方向

优先级建议:

  1. 文档与示例说明持续同步。
  2. MeshDraw 抽象 ✅ 已完成(18mesh-draw)。
  3. Profiler 适配多 draw call ✅ 已完成(累积统计 + draw call 计数)。
  4. IBL ✅ 已完成(Irradiance Map、Prefiltered Specular、BRDF LUT,20ibl)。
  5. Early-Z 深度预测试 ✅ 已完成(22early-z,Fragment 加速 1.3x)。
  6. Mipmap / Trilinear 显式 LOD ✅ 已完成(23mipmapMipChain + TrilinearSampler)。
  7. SampleApp 功能聚合模板 ✅ 已完成(24app-template,SDL-free headless)。
  8. SSAO 屏幕空间环境光遮蔽 ✅ 已完成(25ssao,Crytek 半球采样法)。
  9. HBAO 水平基准环境光遮蔽 ✅ 已完成(26hbao,8 方向光线步进)。
  10. Deferred 延迟渲染 ✅ 已完成(27deferred,Tile-Based + CPU 光源裁剪)。
  11. Multi-Light 多光源 Forward vs Deferred ✅ 已完成(28multi-light,32 点光源 A/B 对比)。
  12. 性能优化:Profiler 基础设施已修正,后续基于采集数据分析热点。
  13. Early-Z 前置深度插值:深度单独提前插值,减少无用全属性插值开销。
  14. 光栅化阶段并行:三角形级并行光栅化。
  15. 真正的三角形级背面剔除优化。
  16. SwapBuffer 与 RenderGraph 输出整合。
  17. 多核并行渲染:任务系统 / 线程池 / tile-based 并行。
  18. 更多 Tonemap 算子:ACES / Filmic。
  19. HDR/Equirectangular 环境贴图加载。

许可证

详见 LICENSE

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages