✨ 前言
在三维图形学开发中,光照系统是撑起画面质感的核心基石,和材质 Material 类的设计思路高度相似。合理的面向对象封装,能让各类光源做到结构解耦、易于扩展、复用性拉满。
本文将从零带大家搭建一套标准的光照类继承体系:顶层抽象父类 Light + 派生子类平行光 DirectionalLight、环境光 AmbientLight,全程遵循工程化编码规范,拆分头文件与实现文件,适配后续渲染器接入与功能迭代。
Bilibili 同步视频
🌿 一、整体架构规划与目录设计
为了项目结构清晰、便于后期维护,我们在项目 framework 根目录下,单独新建 light 专用文件夹,统一存放所有光照相关类文件:
framework/
└── light/
├── Light.h // 光照基类头文件
├── Light.cpp // 光照基类实现文件
├── DirectionalLight.h // 平行光头文件
├── DirectionalLight.cpp// 平行光实现文件
├── AmbientLight.h // 环境光头文件
└── AmbientLight.cpp // 环境光实现文件
设计思路:
-
所有光源统一继承自
Light基类,抽取通用光照属性; -
不同子类仅扩展自身独有特性,符合面向对象继承、多态思想;
-
头文件
.h负责类声明,源文件.cpp负责函数实现,隔离声明与定义,预留未来扩展空间。
💡 开发小知识点 哪怕当前构造、析构函数暂无业务逻辑,也要严格拆分 h 与 cpp 文件。后期若需要给光源增加阴影计算、光照衰减、Shader 传参等逻辑,无需改动头文件结构,直接在 cpp 中扩展即可,极大提升项目可维护性。
☀️ 二、光照基类 Light 封装实现
所有光源(平行光、环境光等)都具备两个通用核心属性:
-
光源颜色 / 光照强度
m_color -
镜面反射高光强度
m_specular
2.1 Light.h 基类头文件
#pragma once
// 引入图形学必备数学库 glm
#include <glm/glm.hpp>
// 光照顶层基类
class Light
{
public:
// 构造函数
Light();
// 析构函数
~Light();
public:
// 光照颜色,默认初始化为白光 (1.0,1.0,1.0)
glm::vec3 m_color = glm::vec3(1.0f, 1.0f, 1.0f);
// 镜面反射高光强度,默认最大强度 1.0
float m_specular = 1.0f;
};
2.2 Light.cpp 基类实现文件
#include "Light.h"
Light::Light()
{
// 预留扩展接口:后期可初始化光照参数、绑定全局配置等
}
Light::~Light()
{
// 预留资源释放接口:后期可释放光照缓存、注销GPU资源等
}
2.3 设计细节解析
-
成员变量与成员函数均使用
public修饰,教学场景下方便快速调用与测试;正式商业工程中建议改为 private,提供对外 get/set 接口做封装; -
m_color采用glm::vec3存储,分别对应 R、G、B 三个通道,默认白光; -
m_specular控制物体受光后的镜面反射强弱,值越大高光越锐利; -
空构造与空析构不是多余写法,是工程化前置设计,为一年半载后的功能迭代留足扩展入口。
🧭 三、平行光 DirectionalLight 子类实现
平行光特性:仅有照射方向,无实际空间位置,适用于模拟太阳光、远距离自然光等场景。
在继承 Light 基类通用属性基础上,只需额外扩展光照方向独有成员。
3.1 DirectionalLight.h 平行光头文件
#pragma once
#include <glm/glm.hpp>
// 引入父类头文件
#include "Light.h"
// 平行光类,公有继承自Light基类
class DirectionalLight : public Light
{
public:
DirectionalLight();
~DirectionalLight();
public:
// 平行光照射方向,默认初始化 x/y/z 均为 -1
glm::vec3 m_direction = glm::vec3(-1.0f, -1.0f, -1.0f);
};
3.2 DirectionalLight.cpp 平行光实现文件
#include "DirectionalLight.h"
DirectionalLight::DirectionalLight()
{
// 可扩展:方向归一化、默认朝向校准等逻辑
}
DirectionalLight::~DirectionalLight()
{
// 预留资源回收扩展
}
3.4 核心特性说明
-
平行光不具备位置属性,只靠
m_direction决定光线照射角度; -
初始化为
(-1,-1,-1)是图形学常用默认朝向,可根据项目需求自由调整; -
自动继承父类
m_color、m_specular属性,无需重复定义,代码高度复用。
🌤 四、环境光 AmbientLight 子类实现
环境光作用:模拟场景中漫反射的基础环境亮度,让阴影区域不至于完全死黑。
设计极简:环境光仅需要基础光照颜色,所有通用属性已在 Light 基类中定义,子类无需额外扩展任何成员变量。
4.1 AmbientLight.h 环境光头文件
#pragma once
#include <glm/glm.hpp>
#include "Light.h"
// 环境光类,公有继承自Light基类
class AmbientLight : public Light
{
public:
AmbientLight();
~AmbientLight();
};
4.2 AmbientLight.cpp 环境光实现文件
#include "AmbientLight.h"
AmbientLight::AmbientLight()
{
// 可扩展:全局环境亮度统一配置、色调微调等
}
AmbientLight::~AmbientLight()
{
}
4.3 设计亮点
极致精简的继承设计,避免冗余代码; 后期如需给环境光增加全局雾效、环境贴图映射等功能,仅需在子类中少量扩展即可,架构兼容性极强。
📌 五、整体体系总结与后续拓展方向
1. 类体系关系梳理
-
父类
Light:抽取所有光源通用属性(颜色、高光强度); -
子类
DirectionalLight:扩展光照方向,适配太阳光; -
子类
AmbientLight:复用基类全部属性,适配全局环境补光。
2. 后续开发规划
当前仅完成光照类体系架构搭建,后续接入渲染器后,可继续实现:
-
将光照参数传递至 Shader 着色器;
-
新增点光源、聚光源子类,扩展完整光照类型;
-
加入光照衰减、阴影映射、PBR 物理光照等高级特性;
-
统一封装光照管理器,批量管理场景中所有光源对象。
3. 工程化开发心得
图形学开发中,先搭架构、后写业务永远是最优解。通过继承分层、文件拆分、预留扩展接口,既能满足当下开发需求,又能适配长期项目迭代,也是 C++ 大型图形项目的标准设计范式 ✨。