一个从零开始构建的 C++ 软件光栅化渲染器(Software Renderer / CPU Rasterizer),模拟类似 OpenGL ES 的 GPU 图形管线。本项目包含 23 个循序渐进的章节,从基础窗口创建逐步推进到 3D 模型加载、光照计算和相机系统。
- 纯 CPU 渲染:不依赖 OpenGL、DirectX、Vulkan 等任何硬件图形 API
- 模拟 OpenGL 风格 API:VAO、VBO、EBO、Shader、Texture、FrameBuffer
- 完整图形管线:顶点着色 → 裁剪 → 透视除法 → 背面剔除 → 屏幕映射 → 光栅化 → 片元着色 → 深度测试 → 混合
- 跨平台 UI:使用 Slint UI 框架作为窗口和显示层
- 自研数学库:向量、矩阵、变换函数等基础数学工具
- 循序渐进:23 个独立章节,每章聚焦一个核心图形学概念
| 层级 | 技术 |
|---|---|
| 语言 | C++17 |
| 构建系统 | CMake |
| 目标平台 | Linux (x86_64) |
| UI 框架 | Slint C++ SDK v1.15.1 |
| 数学库 | 项目内自建 header-only 库 |
| 图像加载 | stb_image.h |
| 模型加载 | Assimp (第 23 章) |
| 章节 | 目录 | 内容 |
|---|---|---|
| 01 | 01-窗口 |
基础窗口与 Slint 集成 |
| 02 | 02-视口 |
视口与帧缓冲概念 |
| 03 | 03-直线光栅化 |
Bresenham 直线算法 |
| 04 | 04-向量计算 |
向量数学库 |
| 05 | 05-三角形光栅化-颜色插值 |
三角形光栅化与颜色插值 |
| 06 | 06-混合-透明度 |
Alpha 混合 |
| 07 | 07-纹理 |
纹理映射 |
| 08 | 08-最临近插值-双线性插值 |
纹理过滤 |
| 09 | 09-纹理寻址 |
纹理环绕模式 |
| 10 | 10-矩阵 |
矩阵数学 |
| 11 | 11-空间变换 |
3D 空间变换 |
| 12 | 12-顶点对象 |
顶点数组/缓冲区对象抽象 |
| 13 | 13-数据重构 |
数据结构重构 |
| 14 | 14-绘制管线 |
绘制管线 |
| 15 | 15-裁剪 |
视锥体裁剪 |
| 16 | 16-透视校正 |
透视校正插值 |
| 17 | 17-面剔除 |
背面剔除 |
| 18 | 18-深度测试 |
深度测试(Z-Buffer) |
| 19 | 19-混合 |
混合管线完善 |
| 20 | 20-高级纹理 |
高级纹理 |
| 21 | 21-相机 |
相机系统 |
| 22 | 22-光照 |
光照计算 |
| 23 | 23-模型 |
模型加载(Assimp) |
本项目循序渐进地覆盖了计算机图形学从数学基础到完整渲染管线的核心知识,可分为数学基础与图形学核心两大板块。
| 知识点 | 对应章节 | 说明 |
|---|---|---|
| 向量代数 | 04-向量计算 |
向量表示、加减、标量乘、点乘(投影与夹角)、叉乘(法向量与方向判断)、归一化、长度计算 |
| 矩阵运算 | 10-矩阵 |
矩阵乘法、转置、逆矩阵、行列式;列主序存储方式 |
| 空间变换 | 11-空间变换 |
平移、旋转、缩放矩阵;模型矩阵(Model)、视图矩阵(View / lookAt)、投影矩阵(正交 / 透视);NDC 与视口变换;屏幕空间变换矩阵 |
| 插值与采样 | 05-三角形光栅化-颜色插值 08-最临近插值-双线性插值 16-透视校正 |
线性插值(Lerp);重心坐标插值;透视校正插值(Perspective-Correct Interpolation,对 1/w 插值后恢复属性);纹理采样中的最邻近插值与双线性插值 |
| 基础几何 | 04-向量计算 17-面剔除 |
平面法向量;利用叉积符号判断三角形朝向(顺时针 / 逆时针) |
| 知识点 | 对应章节 | 说明 |
|---|---|---|
| 窗口与显示 | 01-窗口 02-视口 |
窗口系统集成、事件循环、帧缓冲(FrameBuffer)概念、视口(Viewport)变换 |
| 直线光栅化 | 03-直线光栅化 |
Bresenham 直线算法,利用整数步进高效绘制直线 |
| 三角形光栅化 | 05-三角形光栅化-颜色插值 |
三角形扫描线光栅化、边界方程、重心坐标计算、顶点属性插值 |
| 顶点数据管理 | 12-顶点对象 13-数据重构 |
模拟 OpenGL 的 VAO(顶点数组对象)、VBO(顶点缓冲对象)、EBO(索引缓冲对象);顶点属性描述(BindingDescription)与数据布局 |
| 纹理映射 | 07-纹理 08-最临近插值-双线性插值 09-纹理寻址 20-高级纹理 |
UV 坐标映射、二维纹理采样器、纹理过滤(Nearest / Bilinear)、纹理寻址模式(Repeat / Clamp / Mirror) |
| 裁剪 | 15-裁剪 |
视锥体裁剪(Frustum Clipping)、Sutherland-Hodgman 多边形裁剪算法 |
| 透视除法 | 16-透视校正 |
齐次坐标除法(除以 w),从裁剪空间转换到 NDC(Normalized Device Coordinates) |
| 背面剔除 | 17-面剔除 |
根据三角形法向量与视线方向的点积判断正面 / 背面;CULL_FACE、FRONT_FACE 状态控制 |
| 深度测试 | 18-深度测试 |
Z-Buffer(深度缓冲)原理、深度值计算、深度比较函数(DEPTH_LESS、DEPTH_EQUAL 等) |
| 颜色混合 | 06-混合-透明度 19-混合 |
Alpha 混合原理、混合方程(SrcAlpha / OneMinusSrcAlpha)、预乘 Alpha、混合管线开关控制 |
| 着色器模型 | 14-绘制管线 22-光照 |
顶点着色器(Vertex Shader)与片元着色器(Fragment Shader);Uniform 变量;varying 插值数据;可编程 Shader 抽象基类 |
| 相机系统 | 21-相机 |
FPS 风格相机(WASD 移动 + 鼠标视角控制)、欧拉角(俯仰角 / 偏航角)、LookAt 矩阵、视图与投影矩阵分离管理 |
| 光照模型 | 22-光照 |
方向光、环境光(Ambient)、漫反射(Diffuse / Lambert)、镜面反射(Specular / Phong 与 Blinn-Phong)、法向量、半角向量(Halfway Vector) |
| 模型加载 | 23-模型 |
使用 Assimp 加载层级 3D 模型、网格(Mesh)与材质、漫反射纹理、节点变换层级、多网格渲染 |
sudo dnf install cmake clang pkg-config ninja-build
sudo dnf install freetype-devel fontconfig-devel
sudo dnf install libinput-devel libxkbcommon-devel systemd-devel gbm-devel libseat-devel
sudo dnf install assimp-devel # 仅第 23 章需要每章都是独立的 CMake 工程,进入对应目录后构建:
cd 23-模型 # 或任意章节
cmake -B build -G Ninja
cmake --build build
./build/softRenderer注意:早期章节(01~02)可能需要显式指定编译器为 Clang,并开启
SLINT_FEATURE_BACKEND_LINUXKMS等选项。参考编译.md中的完整配置。
GPU::drawElement() 按以下顺序执行软件图形管线:
- 顶点着色 — 运行用户提供的
Shader::vertexShader() - 裁剪 — 视锥体裁剪
- 透视除法 — 除以
w得到 NDC - 背面剔除 — 根据叉积符号剔除背面/正面
- 屏幕映射 — 将 NDC 转换为像素坐标
- 光栅化 — 生成逐片元数据
- 透视恢复 — 恢复被
w除过的属性 - 片元着色 — 运行
Shader::fragmentShader() - 深度测试 — 与深度缓冲比较
- 混合 — Alpha 混合
- 写入帧缓冲 — 将最终颜色写入颜色缓冲
<章节>/
├── CMakeLists.txt # 根 CMake
├── main.cpp # 程序入口
├── ui/
│ └── app-window.slint # Slint UI 定义
├── application/ # 应用层(输入、相机、模型加载)
├── gpu/ # 软件 GPU(渲染管线、着色器、光栅化)
├── math/ # 自研数学库(header-only)
├── global/ # 基础类型与常量
└── assets/ # 运行时资源(纹理、模型)
- 类名:大写驼峰(
GPU,FrameBuffer) - 成员变量:
m前缀(mModelMatrix) - 函数名:大写驼峰(
initSurface,drawElement) - 矩阵存储:列主序(Column-Major),与 OpenGL 一致
- 单例:
sgl→GPU::getInstance(),app→Application::getInstance()
本项目为学习/教学用途的图形学工程。