Moer框架解析与材质实现
Moer的框架很大,其中包含必要的多种工具链,除了渲染的多层之外的依赖全都放在ext中,包含FastMath(数学库很显然)、json(JSON化数据交换格式库)、nanovdb(稀释体积数据处理工具)、pcg(随机数生成库与工具)、stb(加载或者解码不同格式的图片)
由于学长希望我去做的是layered material的材质,所以这些工具链我暂时不用过度深究,跟着其他材料照猫画虎即可,关键的渲染实现部分代码放在src文件夹中,并且按照功能分成了CoreLayer,FunctionLayer,ResourceLayer三层,我接下来会仔细进行阐述和举例解析:
Contents
CoreLayer
├─Adapter
│ JsonUtil.cpp
│ JsonUtil.h
│ Random.h
│
├─ColorSpace
│ Color.h
│ RGB3.cpp
│ Spectrum.cpp
│ XYZ3.cpp
│
├─Geometry
│ Angle.cpp
│ Angle.h
│ BoundingBox.cpp
│ BoundingBox.h
│ Frame.h
│ Geometry.h
│ Matrix.cpp
│ Matrix.h
│ Normal.h
│ Point.h
│ Transform3d.cpp
│ Transform3d.h
│ Vector.h
│
├─Math
│ Common.h
│ LowDiscrepancy.cpp
│ LowDiscrepancy.h
│ Warp.h
│
└─Ray
Ray.cpp
Ray.h
CoreLayer的内容主要为五部分:Adapter,ColorSpace,Geometry,Math&Ray 这五块部分共同组成了图形学组装基本元素的基础,其实也不能这么讲,我们通过Adapter来处理建模参数,处理数据问题;使用ColorSpace来切换常用的颜色空间;Geometry用来存储、计算基本的几何结构以及相关数据;Math库来做一些复杂向量、矩阵以及数值求和等的精确或者简化计算;Ray则是存储光的几何结构,按照目前的实现来看没有过度考究“波动性”一类的微观特征(偏物理,也是最近几年才有比较多发展的工作)
Adapter
//TODO
ColorSpace
//TODO
Geometry
//TODO
Math
//TODO
Ray
//TODO
FunctionLayer
folder structure
│ Intersection.h
│
├─Acceleration
│ Accel.h
│ Bvh.cpp
│ Bvh.h
│ Embree.cpp
│ Embree.h
│
├─Camera
│ Camera.h
│ CameraFactory.cpp
│ CameraFactory.h
│ DifferentialPinhole.cpp
│ DifferentialPinhole.h
│ Perspective.h
│ Pinhole.cpp
│ Pinhole.h
│ Thinlens.cpp
│ Thinlens.h
│
├─Distribution
│ Distribution.cpp
│ Distribution.h
│
├─Film
│ Film.cpp
│ Film.h
│ ToneMapping.h
│
├─Filter
│ Filter.h
│
├─Integrator
│ │ AbstractPathIntegrator.cpp
│ │ AbstractPathIntegrator.h
│ │ GuidedPathIntegrator.cpp
│ │ GuidedPathIntegrator.h
│ │ Integrator.cpp
│ │ Integrator.h
│ │ MonteCarloIntegrator.cpp
│ │ MonteCarloIntegrator.h
│ │ NormalIntegrator.cpp
│ │ NormalIntegrator.h
│ │ PathIntegrator-new.cpp
│ │ PathIntegrator-new.h
│ │ PathIntegrator.cpp
│ │ PathIntegrator.h
│ │ VolPathIntegrator.cpp
│ │ VolPathIntegrator.h
│ │
│ └─guiding
│ AdaptiveKDTree.h
│ data.h
│ GuidedBxDF.h
│ guiding.h
│ vmm.h
│
├─Light
│ AreaLight.cpp
│ AreaLight.h
│ DiffuseAreaLight.cpp
│ DiffuseAreaLight.h
│ InfiniteSphereCapLight.cpp
│ InfiniteSphereCapLight.h
│ InfiniteSphereLight.cpp
│ InfiniteSphereLight.h
│ Light.h
│ PointLight.cpp
│ PointLight.h
│
├─Material
│ │ BumpMapMateiral.cpp
│ │ BumpMapMaterial.h
│ │ ConductorMaterial.cpp
│ │ ConductorMaterial.h
│ │ DielectricMaterial.cpp
│ │ DielectricMaterial.h
│ │ DisneyBSDF.cpp
│ │ DisneyBSDF.h
│ │ HairMaterial.cpp
│ │ HairMaterial.h
│ │ LayeredMaterial.cpp
│ │ LayeredMaterial.h
│ │ Material.cpp
│ │ Material.h
│ │ MaterialFactory.cpp
│ │ MaterialFactory.h
│ │ MatteMaterial.cpp
│ │ MatteMaterial.h
│ │ MirrorMaterial.cpp
│ │ MirrorMaterial.h
│ │ NormalMapMaterial.cpp
│ │ NormalMapMaterial.h
│ │ NullMaterial.cpp
│ │ NullMaterial.h
│ │ PlasticMaterial.cpp
│ │ PlasticMaterial.h
│ │
│ ├─BSSRDF
│ │ BSSRDF.h
│ │
│ └─BxDF
│ BxDF.h
│ ComplexIor.cpp
│ ComplexIor.h
│ ConductorBxDF.cpp
│ ConductorBxDF.h
│ DielectricBxDF.cpp
│ DielectricBxDF.h
│ Fresnel.h
│ GlintBxDF.cpp
│ GlintBxDF.h
│ HairBXDF.cpp
│ HairBXDF.h
│ LambertainBxDF.cpp
│ LambertainBxDF.h
│ LayeredBXDF.cpp
│ LayeredBXDF.h
│ MicrofacetDistribution.cpp
│ MicrofacetDistribution.h
│ MirrorBxDF.cpp
│ MirrorBxDF.h
│ PlasticBxDF.cpp
│ PlasticBxDF.h
│
├─Medium
│ Beerslaw.cpp
│ Beerslaw.h
│ Heterogeneous.cpp
│ Heterogeneous.h
│ HGPhase.cpp
│ HGPhase.h
│ Homogeneous.cpp
│ Homogeneous.h
│ IsotropicPhase.cpp
│ IsotropicPhase.h
│ Medium.h
│ MediumFactory.cpp
│ MediumFactory.h
│ Phase.h
│
├─Sampler
│ DirectSampler.cpp
│ DirectSampler.h
│ Halton.cpp
│ Halton.h
│ Independent.h
│ Sampler.cpp
│ Sampler.h
│ Stratified.cpp
│ Stratified.h
│ ZeroTwoSequence.cpp
│ ZeroTwoSequence.h
│
├─Scene
│ Scene.cpp
│ Scene.h
│
├─Shape
│ Cube.cpp
│ Cube.h
│ Curve.cpp
│ Curve.h
│ Entity.cpp
│ Entity.h
│ EntityFactory.cpp
│ EntityFactory.h
│ Mesh.cpp
│ Mesh.h
│ Quad.cpp
│ Quad.h
│ Sphere.cpp
│ Sphere.h
│ Triangle.cpp
│ Triangle.h
│
├─Texture
│ ImageTexture.cpp
│ ImageTexture.h
│ ProceduralTexture.cpp
│ ProceduralTexture.h
│ Texture.h
│ TextureFactory.h
│ TextureMapping.cpp
│ TextureMapping.h
│
└─TileGenerator
SequenceTileGenerator.cpp
SequenceTileGenerator.h
TileGenerator.cpp
TileGenerator.h
FunctionLayer在我看来是整个离线渲染器的核心,其中包含的内容围绕着具体的图形学技术细节以及tricks展开,比如图形的BVH加速结构、Distribution采样、纹理、材料、光源等核心方面的内容。所以我们主要针对这一层的各个实现进行解释和拆分
Acceleration
这一部分主要是为了实现光追的几个基本加速结构,详细的光追加速我就另开一篇文章来解释了
/// @brief Acceleration structure Interface.
class Accel {
public:
Accel() = default;
/*
* @brief basic interface for ray intersection.
* @param r The ray that intersect with a scene. This interface will only utilize its geometry information.
* @return The exactly closest intersection point on an entity in the scene with other useful information.
*/
virtual std::optional<Intersection> Intersect(const Ray &r) const = 0;
/*
* @brief get the bounding box of all the objects
*/
[[nodiscard]]
virtual BoundingBox3f getGlobalBoundingBox() const = 0;
};
这是整个加速结构的总体interface,包含求交、获得包围盒这两个接口
│Bvh.cpp
│ Bvh.h
│ Embree.cpp
│ Embree.h
implementation包括BVH和Embree两类
BVH里面定义了几个基本的数据结构:
/// @brief Entity information declaration for building BVH
struct EntityInfo {
EntityInfo(){}
EntityInfo(int _EntityId, const BoundingBox3f& _bounds): EntityId(_EntityId), bounds(_bounds), center(0.5 * (_bounds.pMin + _bounds.pMax)){}
int EntityId;
BoundingBox3f bounds;
Point3d center;
};
struct BvhTreeNode {
BoundingBox3f bounds;
std::shared_ptr<BvhTreeNode> children[2] = {nullptr, nullptr};//0: left, 1: right
int splitAxis;
int nEntites = 0;//0: interior nodes, otherwise: leaf nodes
int entityOffset;
};
/// @brief Bvh Nodes in Dfs-Order
struct LinearBvhNode {
BoundingBox3f bounds;
union
{
int firstdEntityOffset;//for leaves to enumerate
int secondChildOrder;//for interior nodes to traverse
};
int nEntites = 0;
int splitAxis;
};
EntityInfo
结构体包含三个成员:
EntityId
:一个整数,用于标识实体。bounds
:一个BoundingBox3f
类型的对象,表示实体的包围盒。BoundingBox3f
是一个自定义的类型,用于存储3D包围盒的信息。center
:一个Point3d
类型的对象,表示实体的中心点。Point3d
也是一个自定义的类型,用于存储3D点的信息。
EntityInfo
结构体提供了两个构造函数:
- 默认构造函数
EntityInfo()
:创建一个EntityInfo
对象,但不对其成员进行初始化。 - 带参数的构造函数
EntityInfo(int _EntityId, const BoundingBox3f& _bounds)
:创建一个EntityInfo
对象,并使用参数_EntityId
和_bounds
初始化EntityId
和bounds
成员。同时,它还计算出实体的中心点center
,方法是取包围盒的最小点和最大点的中点。