PBRT笔记(8)——材质
BSDF类
表面着色器会绑定场景中每一个图元(被赋予了这个着色器),而表面着色器则由Material类的实例来表示。它会拥有一个BSDF类对象(可能是BSSDF),用于计算表面上每一点的辐射度(颜色)。
BSDF代表了BRDFs与BTDFs的集合。BSDF构造函数接受一个SurfaceInteraction对象,该对象包含关于表面上任意一点的微分几何信息,以及一个参数eta,该参数给出了边界上的相对折射率。对于不透明的表面,该参数则无效。构造函数将使用着色法线来构造一个正交坐标系。本节中ns表示着色法线(法线贴图上对应坐标的值)和ng代表了几何法线(面法线)。
BSDF存储了最多8个BxDF组件,因为在pbrt中不需要更多组件。BSDF实现了BxDFs坐标系与世界坐标系转换的方法。WorldToLocal(const Vector3f &v)与LocalToWorld(const Vector3f &v)。
着色法线与几何法线的冲突问题
实际渲染的过程中着色法线可能会发生如图9.2这样的漏光现象情况,也就是说直接计算出得到错误的光线遮挡关系。解决方法是:使用几何法线来决定是计算反射还是计算透射,如果ωi与ωo在同一个几何法线的半球,计算BRDFs,不然则计算BTDFs。与上一步不同,在计算散射方程时,法线和入射方向的点积仍然是用着色法线而不是几何法线来处理的。
首先将向量从世界坐标系转换为BSDF坐标系,然后决定是使用BRDFs还是BTDFs。然后循环遍历适当的集合并计算它们的辐射度贡献之和。
Spectrum BSDF::f(const Vector3f &woW, const Vector3f &wiW,
BxDFType flags) const {
ProfilePhase pp(Prof::BSDFEvaluation);
Vector3f wi = WorldToLocal(wiW), wo = WorldToLocal(woW);
if (wo.z == 0) return 0.;
bool reflect = Dot(wiW, ng) * Dot(woW, ng) > 0;
Spectrum f(0.f);
for (int i = 0; i < nBxDFs; ++i)
if (bxdfs[i]->MatchesFlags(flags) &&
((reflect && (bxdfs[i]->type & BSDF_REFLECTION)) ||
(!reflect && (bxdfs[i]->type & BSDF_TRANSMISSION))))
f += bxdfs[i]->f(wo, wi);
return f;
}
Material类
Material的派生类必须实现ComputeScatteringFunctions();该函数获取一个SurfaceInteraction对象,该方法用于确定反射属性,并且初始化相应的SurfaceInteraction::BSDF,如果包含了次表面散射,那SurfaceInteraction::BSSRDF也会被初始化。另外几个形参别分是:所使用的内存池引用,透射模式,是否使用多层复合材质的BxDFs(类似车漆这种),之后SurfaceInteraction的实例会调用这个函数进行渲染。
void SurfaceInteraction::ComputeScatteringFunctions(const RayDifferential &ray,MemoryArena &arena,bool allowMultipleLobes,TransportMode mode) {
ComputeDifferentials(ray);
primitive->ComputeScatteringFunctions(this, arena, mode,
allowMultipleLobes);
}
金属材质
kd为漫反射值,sigma为粗糙度值。如果sigma为0,即为兰伯特材质,不然就使用OrenNayar模型,另外还有一个凹凸贴图指针变量,在其有效的情况下,用与着色法线的计算。
void MatteMaterial::ComputeScatteringFunctions(SurfaceInteraction *si,MemoryArena &arena,TransportMode mode,bool allowMultipleLobes) const {
if (bumpMap) Bump(bumpMap, si);
si->bsdf = ARENA_ALLOC(arena, BSDF)(*si);
Spectrum r = Kd->Evaluate(*si).Clamp();
Float sig = Clamp(sigma->Evaluate(*si), 0, 90);
if (!r.IsBlack()) {
if (sig == 0)
si->bsdf->Add(ARENA_ALLOC(arena, LambertianReflection)(r));
else
si->bsdf->Add(ARENA_ALLOC(arena, OrenNayar)(r, sig));
}
}
塑料材质
塑料可以被建模为漫反射和光泽散射函数的混合物,参数控制特定的颜色和高光尺寸。塑料材质的参数为Kd和Ks,分别控制漫反射和高光的量。
reaproughness为控制粗糙度效果的变量,如果remapRoughness参数为true,那么roughness将会映射到0~1范围,其中粗糙度值越高,高光亮点越大。如果为false,那么粗糙度直接初始化microfacet分布的参数α(8.4.2的内容)
void PlasticMaterial::ComputeScatteringFunctions(
SurfaceInteraction *si, MemoryArena &arena, TransportMode mode,
bool allowMultipleLobes) const {
// Perform bump mapping with _bumpMap_, if present
if (bumpMap) Bump(bumpMap, si);
si->bsdf = ARENA_ALLOC(arena, BSDF)(*si);
// Initialize diffuse component of plastic material
Spectrum kd = Kd->Evaluate(*si).Clamp();
if (!kd.IsBlack())
si->bsdf->Add(ARENA_ALLOC(arena, LambertianReflection)(kd));
// Initialize specular component of plastic material
Spectrum ks = Ks->Evaluate(*si).Clamp();
if (!ks.IsBlack()) {
Fresnel *fresnel = ARENA_ALLOC(arena, FresnelDielectric)(1.5f, 1.f);
// Create microfacet distribution _distrib_ for plastic material
Float rough = roughness->Evaluate(*si);
if (remapRoughness)
rough = TrowbridgeReitzDistribution::RoughnessToAlpha(rough);
MicrofacetDistribution *distrib =
ARENA_ALLOC(arena, TrowbridgeReitzDistribution)(rough, rough);
BxDF *spec =
ARENA_ALLOC(arena, MicrofacetReflection)(ks, distrib, fresnel);
si->bsdf->Add(spec);
}
}
混和材质
存储了2个材质的指针,以及一个缩放参数。
void MixMaterial::ComputeScatteringFunctions(SurfaceInteraction *si,MemoryArena &arena,TransportMode mode,bool allowMultipleLobes) const {
// Compute weights and original _BxDF_s for mix material
Spectrum s1 = scale->Evaluate(*si).Clamp();
Spectrum s2 = (Spectrum(1.f) - s1).Clamp();
SurfaceInteraction si2 = *si;
m1->ComputeScatteringFunctions(si, arena, mode, allowMultipleLobes);
m2->ComputeScatteringFunctions(&si2, arena, mode, allowMultipleLobes);
// Initialize _si->bsdf_ with weighted mixture of _BxDF_s
int n1 = si->bsdf->NumComponents(), n2 = si2.bsdf->NumComponents();
for (int i = 0; i < n1; ++i)
si->bsdf->bxdfs[i] =
ARENA_ALLOC(arena, ScaledBxDF)(si->bsdf->bxdfs[i], s1);
for (int i = 0; i < n2; ++i)
si->bsdf->Add(ARENA_ALLOC(arena, ScaledBxDF)(si2.bsdf->bxdfs[i], s2));
}
除此之外的材质
PBRT还实现了一些别的材质,其实现代码都在materials目录中。
- GlassMaterial
- MetalMaterial
- MirrorMaterial
- SubsurfaceMaterial
- TranslucentMaterial
- UberMaterial
PBRT笔记(8)——材质的更多相关文章
- PBRT笔记(14)——光线传播2:体积渲染
传输公式 传输方程是控制光线在吸收.发射和散射辐射的介质中的行为的基本方程.它解释了第11章中描述的所有体积散射过程--吸收.发射和内.外散射.并给出了一个描述环境中辐射分布的方程.光传输方程实际上是 ...
- PBRT笔记(10)——体积散射
体散射处理过程 3个影响参与介质在环境中的辐射度分布的主要因素: 吸收:减少光能,并将其转化为别的能量,例如热量. 发光:由光子发射光能至环境中. 散射:由于粒子碰撞,使得一个方向的辐射度散射至其他方 ...
- PBRT笔记(7)——反射模型
基础术语 表面反射可以分为4大类: diffuse 漫反射 glossy specular 镜面反射高光 perfect specular 完美反射高光 retro-reflective distri ...
- PBRT笔记(6)——采样和重构
前言 本文仅作为个人笔记分享,又因为本章涉及多个专业领域而本人皆未接触过,所以难免出错,请各位读者注意. 对于数字图像需要区分image pixels(特定采样处的函数值)和display pixel ...
- [Unreal]学习笔记之材质说明
取消蓝图中的连接线:Alt+鼠标左键 在蓝图中,通过按住1,2,3,4加鼠标左键,可以快速生成1,2,3,4维的向量 材质和材质实例的区别:使用一个母材质,可以创建出多种场景中的材质实例:每次修改母材 ...
- PBRT笔记(13)——光线传播1:表面反射
采样反射函数 BxDF::Sample_f()方法根据与相应的散射函数相似的分布来选择方向.在8.2节中,该方法用于寻找来自完美镜面的反射和透射光线;在这里讲介绍实现其他类型的采样技术. BxDF:: ...
- PBRT笔记(12)——蒙特卡洛积分
这里还涉及到pdf.方差等概念,推荐去看<全局光照技术:从离线到实时渲染> 积累分布函数 cumulative distribution function (CDF) 蒙特卡洛估算 为了计 ...
- PBRT笔记(11)——光源
自发光灯光 至今为止,人们发明了很多光源,现在被广泛使用的有: 白炽灯的钨丝很小.电流通过灯丝时,使得灯丝升温,从而使灯丝发出电磁波,其波长的分布取决于灯丝的温度.但大部分能量都被转化为热能而不是光能 ...
- PBRT笔记(9)——贴图
采样与抗锯齿 当高分辨率贴图被缩小时,贴图会出现严重的混淆现象.虽然第7章中的非均匀采样技术可以减少这种混叠的视觉影响,但是更好的解决方案是实现基于分辨率进行采样的纹理函数. 可以在使用贴图时先对贴图 ...
随机推荐
- Lucene的中文分词器
1 什么是中文分词器 学过英文的都知道,英文是以单词为单位的,单词与单词之间以空格或者逗号句号隔开. 而中文的语义比较特殊,很难像英文那样,一个汉字一个汉字来划分. 所以需要一个能自动识别中文语义的分 ...
- Centos7.2正常启动关闭CDH5.16.1
1.正常的启动.关闭流程 关闭流程 cluster1 stop Cloudera Management Service stop 4台agent:systemctl stop cloudera ...
- java错误分类
IllegalArgumentException 回直接crashError
- 转:jsp与servlet的区别与联系
jsp与servlet的区别与联系 - gsyabc - 博客园https://www.cnblogs.com/sanyouge/p/7325656.html jsp和servlet的区别和联系:1. ...
- JS判断数组的值出现的次数,以及去重
var arr = ["曹阳","曹阳","曹阳","张三","张三","张三" ...
- 基于Python的Webservice开发(二)-如何用Spyne开发Webservice
一.功能需求 本次案例是开发一个Item的新建的WebService.IN&OUT的类型JsonDocument. 通过传入相关的参数创建Item,且相关的参数可以被缺省. 二.实现代码 引入 ...
- [Kubernetes]关于 Kubernetes ,你想要的,都在这儿了
陆陆续续,关于 Kubernetes 写了有 20+ 篇文章了. 今天这篇文章来一个整合,从实践到理论,可以按需查看(我是按照博客发表时间来排序的,如果后续有想要更新的内容,也会及时更新到这篇文章中) ...
- VGA、DVI、HDMI三种视频信号接口
目前,电脑显示器常见的接口主要有HDMI.DP.DVI.VGA等4种接口.显示器数据线性能排名:DP>HDMI>DVI>VGA.其中 VGA是模拟信号,已经被主流所淘汰,DVI.H ...
- 深度探索C++对象模型
深度探索C++对象模型 什么是C++对象模型: 语言中直接支持面向对象程序设计的部分. 对于各个支持的底层实现机制. 抽象性与实际性之间找出平衡点, 需要知识, 经验以及许多思考. 导读 这本书是C+ ...
- Linux性能调优之gprof和oprofile
为了更好的优化程序性能,我们必须找到性能瓶颈点,“好钢用在刀刃上”才能取 得好的效果,否则可能白做工作. 为了找到关键路径,我们可以使用profilng技术,在linux平台上,我们可以使用gprof ...