WECHAT

扫码添加微信

YoungFan 微信二维码
← 返回全部项目
图形学C++DirectX 11HLSL

HelloD3D11

使用 C++ 与 DirectX 11 编写的练习型 3D 渲染器,实现延迟着色、三类动态光源、平行光级联阴影,并打通 Doom 3 场景与自定义材质加载流程。

年份2024
HelloD3D11 项目封面

项目概览

HelloD3D11 是我在学习 C++ 和阅读《Introduction to 3D Game Programming with DirectX 11》期间编写的练习型 3D 渲染器。项目从 Direct3D 11 的基础绘制流程起步,逐步扩展出渲染管线、光照与阴影、场景组织、资源加载和调试界面等模块。

它并非完整的商业引擎,而是我理解实时渲染流程的一次系统实践:从 CPU 侧组织场景和渲染数据,到 GPU 侧生成 GBuffer、计算光照并合成最终画面,再到接入外部场景编辑器形成可迭代的内容工作流。

延迟着色管线

项目实现了一套基础延迟着色管线。几何阶段将材质与表面信息写入多个 GBuffer,光照阶段再根据这些屏幕空间数据计算平行光、点光源和聚光灯的贡献。

世界坐标与高光指数

GBuffer 0 的 RGB 通道保存世界空间坐标,Alpha 通道保存 SpecularPower。世界坐标可供后续光照阶段重建像素与光源之间的位置关系,高光指数用于控制镜面反射的集中程度。

GBuffer 0:世界坐标与高光指数

法线与阴影标记

GBuffer 1 的 RGB 通道保存世界空间法线,Alpha 通道记录表面是否接收阴影。将阴影开关随表面数据写入缓冲后,光照阶段可以直接根据像素属性决定是否采样阴影。

GBuffer 1:世界空间法线与阴影标记

基础颜色

GBuffer 2 保存材质的 Albedo。光照阶段将基础颜色与法线、位置、阴影结果组合,得到最终受光表面。

GBuffer 2:材质基础颜色

管线还预留了额外 GBuffer,计划用于拆分和保存更完整的高光数据。除延迟着色外,工程中也保留了前向渲染路径,用于组织透明物体等不适合直接写入 GBuffer 的内容。

动态光照与级联阴影

当前光照系统支持三种常用动态光源:

  • 平行光,用于模拟太阳等远距离光源。
  • 点光源,从空间中的一点向四周发光。
  • 聚光灯,在指定方向和锥形范围内产生光照。

阴影部分实现了平行光 Cascade Shadow Map。系统按观察距离划分级联,为靠近摄像机的区域保留更高的阴影精度,同时让远处场景继续落在有效阴影范围内。当前版本尚未为点光源与聚光灯实现阴影。

平行光级联阴影调试结果

Doom 3 场景工作流

为了避免完全依赖代码摆放测试场景,我使用 DarkRadiant 作为外部场景编辑器。DarkRadiant 源于 Doom 3 系列 Radiant 工具,适合编辑基于 Brush、实体和材质定义的关卡。

在 DarkRadiant 中编辑测试场景

渲染器实现了 Doom 3 .map 与 .proc 场景文件的解析和加载,并制定了一套简化的材质描述格式。这样可以在编辑器中搭建场景,再由运行程序读取几何、实体和材质数据,形成“外部编辑—导出文件—运行时加载”的基础工作流。

渲染框架与资源管理

随着功能增加,我将底层绘制代码继续拆分为相对独立的系统:

  • 使用 Effect 系统管理 HLSL Shader 与渲染状态。
  • 通过 Render Pass 和 Render Pipeline 组织前向、延迟、阴影及透明物体绘制阶段。
  • 使用 RenderTexture 管理中间渲染目标和 GBuffer。
  • 仿照 Unity 的全屏 Blit,绘制一个覆盖屏幕的三角形完成后处理拷贝,避免使用两个三角形组成 Quad。
  • 使用 XNAMath 处理向量、矩阵等数学运算,并通过 XNACollision 完成视锥体剔除。
  • 使用 Dear ImGui 暴露光源方向、强度和背景颜色等调试参数。

资源加载方面,模型支持 OBJ 格式和书中示例使用的文本格式,其中 OBJ 由 tinyobjloader 解析;DDS 纹理由 DirectX 接口读取,其余常见图片格式通过 stb_image 加载。

项目仍有明确的练习性质,例如光源阴影覆盖不完整、材质模型较简单、资源格式支持有限,但这些边界也为后续继续实现点光源阴影、聚光灯阴影和更完整的材质数据留下了清晰方向。