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目录中。

  1. GlassMaterial
  2. MetalMaterial
  3. MirrorMaterial
  4. SubsurfaceMaterial
  5. TranslucentMaterial
  6. UberMaterial

PBRT笔记(8)——材质的更多相关文章

  1. PBRT笔记(14)——光线传播2:体积渲染

    传输公式 传输方程是控制光线在吸收.发射和散射辐射的介质中的行为的基本方程.它解释了第11章中描述的所有体积散射过程--吸收.发射和内.外散射.并给出了一个描述环境中辐射分布的方程.光传输方程实际上是 ...

  2. PBRT笔记(10)——体积散射

    体散射处理过程 3个影响参与介质在环境中的辐射度分布的主要因素: 吸收:减少光能,并将其转化为别的能量,例如热量. 发光:由光子发射光能至环境中. 散射:由于粒子碰撞,使得一个方向的辐射度散射至其他方 ...

  3. PBRT笔记(7)——反射模型

    基础术语 表面反射可以分为4大类: diffuse 漫反射 glossy specular 镜面反射高光 perfect specular 完美反射高光 retro-reflective distri ...

  4. PBRT笔记(6)——采样和重构

    前言 本文仅作为个人笔记分享,又因为本章涉及多个专业领域而本人皆未接触过,所以难免出错,请各位读者注意. 对于数字图像需要区分image pixels(特定采样处的函数值)和display pixel ...

  5. [Unreal]学习笔记之材质说明

    取消蓝图中的连接线:Alt+鼠标左键 在蓝图中,通过按住1,2,3,4加鼠标左键,可以快速生成1,2,3,4维的向量 材质和材质实例的区别:使用一个母材质,可以创建出多种场景中的材质实例:每次修改母材 ...

  6. PBRT笔记(13)——光线传播1:表面反射

    采样反射函数 BxDF::Sample_f()方法根据与相应的散射函数相似的分布来选择方向.在8.2节中,该方法用于寻找来自完美镜面的反射和透射光线;在这里讲介绍实现其他类型的采样技术. BxDF:: ...

  7. PBRT笔记(12)——蒙特卡洛积分

    这里还涉及到pdf.方差等概念,推荐去看<全局光照技术:从离线到实时渲染> 积累分布函数 cumulative distribution function (CDF) 蒙特卡洛估算 为了计 ...

  8. PBRT笔记(11)——光源

    自发光灯光 至今为止,人们发明了很多光源,现在被广泛使用的有: 白炽灯的钨丝很小.电流通过灯丝时,使得灯丝升温,从而使灯丝发出电磁波,其波长的分布取决于灯丝的温度.但大部分能量都被转化为热能而不是光能 ...

  9. PBRT笔记(9)——贴图

    采样与抗锯齿 当高分辨率贴图被缩小时,贴图会出现严重的混淆现象.虽然第7章中的非均匀采样技术可以减少这种混叠的视觉影响,但是更好的解决方案是实现基于分辨率进行采样的纹理函数. 可以在使用贴图时先对贴图 ...

随机推荐

  1. JAVA课设个人博客--多源数据教学管理系统

    JAVA课设个人博客--多源数据教学管理系统 1.团队课程设计博客链接 https://www.cnblogs.com/hq9-/p/10278470.html 2. 个人负责模块或任务说明 主要模块 ...

  2. hibernate之HQL,Criteria与SQL

    HQL是针对封装好的对象. HQL :hibernate自己用的sql语句   -------HQL不能出现表中的任何内容 ---------不经常使用开发中 基本查询:String hql = &q ...

  3. iTOP-4418/6818开发板用户使用手册内容有哪些

                    更多内容分享,请继续期待 iTOP-6818开发板与4418开发板共兼容同一底板: 核心板:::::: 尺寸:50mm*60mm 高度:核心板连接器组合高度1.5mm ...

  4. [经验交流] k8s mount 文件到容器目录

    docker 的 volume 可以 mount 单个文件(比如单个配置文件)到容器目录.同时保留原目录的内容.放到 k8s 中,结果却变成了这样:k8s 的 volume 把文件mount 到容器目 ...

  5. android shape 圆圈 圆环 圆角

    定义圆圈:比如角标: xml布局文件 <TextView android:id="@+id/item_order_pay_count" android:layout_widt ...

  6. 关于typecho0.9代码高亮与数学公式支持

    闲来无事,搭了一个博客,记录一下自己的学习生活,博客模板取自原来typecho官方博客,稍加修改,改了一下涂装,不得不说插件支持有一些问题,目前大多数插件已经同步更新到typecho1.0版本,新插件 ...

  7. Windows下Maven3.3.9安装与配置

    安装Maven步骤: 下载Maven,下载网址:http://archive.apache.org/dist/maven/maven-3/3.3.9/binaries/ 解压下载的文件:建议解压到全英 ...

  8. UiAutomator2.0 - Toast信息的验证

    目录 问题:在做UI自动化测试时,偶尔会碰到 Toast 这种提示信息(如图),通过Uiautomatorviewer 无法获该类控件的信息.所以无法验证,该条case不能实现.然后就没然后了... ...

  9. SQL语句case when then的用法

    case具有两种格式.简单case函数和case搜索函数. //简单case函数 case sex when '1' then '男' when '2' then '女’ else '其他' end ...

  10. 解决exlipse下 springboot 错误:找不到或无法加载主类

    简单描述:控制台出现了下图 废话不多说,直接上解决办法: 方法一:如果你很有自信,自己的pom 没问题,并且已经加载了所有依赖的jar.ok,这是eclipse的问题,window=>prefe ...