光线追踪技术 第二章
光线追踪技术 - 第二章 – Phone光照模型、镜像和阴影
原作者:Jacco Bikker
原文地址:
http://www.flipcode.com/archives/Raytracing_Topics_Techniques-Part_2_Phong_Mirrors_and_Shadows.shtml
引言
在第一章中,我介绍了光线追踪的基础知识:从摄像机发射一系列穿过屏幕到达场景的射线,找出每条射线最近的交点,然后用交点的法线点乘指向光源的向量得出一个简单的漫反射阴影。
在第二章中,我将介绍Phone先生,他的卫生间的镜子和他的背光面:)
主射线 VS 二级射线
考虑下面的这张图:
图一:主射线
这张图展示了第一章中的简单光线跟踪器的射线发射到场景中的情形。一条射线可以与光源或一个物体碰撞,或者什么都没有碰到。这些射线没有反射和折射,它们被称为“主射线”。
除主射线外,你可以使用“二级射线”。下面图片展示了此种情况:
图2:各种各样的二级射线
图中蓝色的线是反射光线。对于反射来说,它简单的从一个平面弹回来。稍后会介绍如何计算它。
绿色的线是折射光线。它比反射光线要难计算一些,但也是可以计算的。计算它需要知道折射率和一个由Snell先生(Willebrord Snellius)制定的公式。
红色的线用来探测光源。简单来说,当计算漫反射光照时,如果光源对交点可见,则将点积乘以1,如果被阻挡则乘以0,如果有一般光源可见,则乘以0.5。(译者注:这段话是要解决光源不是一个点的情况。当光源具有一定体积时,就可能出现光源被遮挡不完全的状况。此时,用第一章中讲的点乘的方式计算出来的这一点的光照强度,需要根据遮挡的情况做调整,需要将计算结果乘以光源没有被遮挡的部分所占的百分比。)
如果你从摄像机开始,沿着一条黄色线出发,你会注意到每条射线都产生了一整套二级射线:一条反射射线、一条折射射线和每个光源的阴影射线。当生成以后,每条二级射线(除了阴影射线)都被看作是一条普通射线。这意味着一条反射射线可以被再次反射、第三次反射、第四次反生......这种技术被称为“递归光线跟踪”。每一条新的射线都会讲它的颜色汇集到它上一级的射线中去,这样,每条射线都会影响到主射线穿过的这个像素点(屏幕上的一个像素)的最终颜色。
为使递归循环可以结束和避免花费过多渲染时间,通常我们会设置一个值来限制递归的深度。
反射
通过法线计算反射射线,可以使用下面的公式:
R = V - 2 * DOT( V, N ) * N;
(R是反射射线,V是入射射线,N是平面法线)
下面的代码可以添加到光线追踪器中为每个光源计算漫反射光照的循环中去。
// calculate reflection
float refl = prim->GetMaterial()->GetReflection();
if (refl > 0.0f)
{
vector3 N = prim->GetNormal( pi );
vector3 R = a_Ray.GetDirection() - 2.0f * DOT( a_Ray.GetDirection(), N ) * N;
if (a_Depth < TRACEDEPTH)
{
Color rcol( 0, 0, 0 );
float dist;
Raytrace( Ray( pi + R * EPSILON, R ), rcol, a_Depth + 1, a_RIndex, dist );
a_Acc += refl * rcol * prim->GetMaterial()->GetColor();
}
}
如果你没有更改光线追踪器的场景,你会看到下面的图像:
这是一个很大的进步。球体间互相映现,此外,球体也映现出地面。
Phone光照模型
创建一个“完美的”光照模型是非常复杂的,所以我们取真实光照的近似值。到目前为止,我们使用的漫反射光照模型很好的表现了看起来比较柔和的物体,但是对于有光泽的物体的表现还不够。换言之,现在的光照模型除了光强之外,我们什么都控制不了。
看一下下面的图:
上面图片展示了我们目前使用的光照模型:光源向量与法线的点积。它从黑到白是线性变换的。
下面图片展示的也是同样的点积,但是这次将幂指数提高到50。这次,在两个向量夹角很小的时候,会出现亮斑。随着角度增大,亮度快速下降到零。
组合这些改进是很重要的:我们得到了想当的灵活性。一个材质可以具有漫反射阴影和镜面反射阴影;我们可以通过调整幂指数来改变高光区域的大小。
这还不是很正确。
漫反射阴影是正确的:漫反射材质在所有方向上散射光线,所以最亮的区域应该是在面对光源的地方。可以通过法线与光源方向的向量做点乘来计算这个结果。
镜面反射则有一些不同:简单来说,镜面反射是对光源的反射。你可以在真实世界中检查这个现象:找一个有光泽的物体,把它放到在一个灯光下的桌子上,然后移动你的头。你会注意到当你移动的时候高光区域并不是停留在物体的同一个区域:高光区域就是对光源的反射,它随着视角的变化而变化。Phone建议下面的光照模型,这个模型将反射向量包括在其中:
intensity = diffuse * (L.N) + specular * (V.R)n
(L是从交点到光源的向量,N是交点的法线,V是观察的方向向量, R是L在交点上的反射向量)(译者注:上式中最后的n为n次幂,n是幂指数)
注意这个公式包含了漫反射和镜面反射光照模型。
下面是代码实现:
vector3 V = a_Ray.GetDirection();
vector3 R = L - 2.0f * DOT( L, N ) * N;
float dot = DOT( V, R );
if (dot > 0)
{
float spec = powf( dot, 20 ) * prim->GetMaterial()->GetSpecular() * shade;
// add specular component to ray color
a_Acc += spec * light->GetMaterial()->GetColor();
}
将这些代码加入光照计算中后,光线渲染器会渲染出如下效果的图片:
画面又是一个很大的进步。
阴影
最后一种二级射线是阴影射线。这跟其它的射线有一些不同:它们不直接向产生他们的射线提供颜色信息;它们是用来检测一个光源是否可以“看到”这个交点。这个测试的结果被用在漫反射和镜面反射的计算中。
下面的代码为每个光源创建一条阴影射线,然后把这些射线与场景中的其他物体做相交测试。
// handle point light source
float shade = 1.0f;
if (light->GetType() == Primitive::SPHERE)
{
vector3 L = ((Sphere*)light)->GetCentre() - pi;
float tdist = LENGTH( L );
L *= (1.0f / tdist);
Ray r = Ray( pi + L * EPSILON, L );
for ( int s = 0; s < m_Scene->GetNrPrimitives(); s++ )
{
Primitive* pr = m_Scene->GetPrimitive( s );
if ((pr != light) && (pr->Intersect( r, tdist )))
{
shade = 0;
break;
}
}
}
大部分的代码应该很熟悉了。测试的结果存储在一个浮点型的变量“shade”中:值为1表示一个可见的光源,0表示不可见。用一个浮点型来表示看起来很奇怪;我们以后将会加入区域光源,它们通常只有一部分是可见的。在那种情况下,“shade”就会在0-1之间取值了。
另外,上面的代码没有检测在阴影射线上与其交点最近的物体。因为不需要这样做:只要检测到比光源近的任意一个交点就可以。这是一个很重要的优化,这样做可以尽快结束交点检测部分的循环。
图片:
这是最终效果。两个球体,镜像,漫反射和镜面反射,两个光源引起的阴影。平面上的光照小时在远方,是因为远处的漫反射点积越来越小,球体的光照很好。所有这些在一秒钟就可以渲染完成。
注意观察平面上的阴影的表示,阴影是怎样使平面的谋一部分变为全黑的。还要注意观察球体的颜色是怎样影响被镜像到球体表面的平面的颜色。
结尾
光线追踪的一个有意思的地方是,你可以向其中插入新东西,其他的东西照常运行。例如,添加阴影和Phong光照模型的同时加入了镜像和高光。这跟光线追踪的平行性质有关:每个射线之间是没有关联的,这使得递归光线追踪非常适合在多处理器上渲染,同时也非常适合组合多种多样的算法。
另外,在目前的光线追踪器中有一个错误,我会在第三版本中修正:阴影射线测试的结果被同时使用在漫反射和镜面反射上。这显然是错误的。:)
这就是第二章的全部了。第二版本的光线渲染器可以通过以下链接下载:
http://115.com/file/c2ct7jke#raytracer2.zip
- Phone
- 光线追踪
- bat's blog
- 要发表评论,请先登录 或 注册
- 990 围观
光线追踪技术 第二章相关推荐
- 计算机网络第二章选择题,计算机网络技术第二章习题
计算机网络技术第二章习题 一.填空题 1.信道是_________________________,信道容量是指_________________,信道带宽是指_____________ ...
- (Raytracing)光线追踪技术 - 第一章 – 入门
(Raytracing)光线追踪技术 - 第一章 – 入门 RAYTRACING TOPICS & TECHNIQUES - PART 1 – INTRODUCTION 原作者:Jacco B ...
- 计算机科学与技术第二章ppt,计算机科学与技术-编译原理-第二章重点.ppt
计算机科学与技术-编译原理-第二章重点.ppt * 自下而上分析法举例 例2解: a b b c d e (1) a b b c d e A A (2) a b b c d e A A (3) a b ...
- 软件工程技术--第二章 可行性研究
第二章 可行性研究及软件计划 1.软件定义--做什么? 软件生命周期的阶段划分: 软件计划:问题定义.可行性研究 软件开发:需求分析.软件设计(概要设计.详细设计).程序编写.软件测试 软件运行维护: ...
- 计算机三级网络技术第二章基础知识总结
第2章 中小型网络系统总体规划与设计 考点三题三分 ①路由器技术指标 ②网络系统分层设计(上下级之比,核心层设计) ③交换机技术指标(总带宽计算方法) ④网络服务器性能(系统高可能性) 基于网络的信息 ...
- 计算机三级网络技术——第二章:中小型网络系统总体规划与设计
中小型网络系统总体规划与设计 文章目录 中小型网络系统总体规划与设计 网络关键设备选型 网络总体设计基本方法 核心层网络结构设计 汇聚层网络与接入层网络结构设计 路由器的关键技术指标 路由器的分类 路 ...
- 企业网络高级技术第二章STP实验
STP spanning tree protocol 生成树协议 STP产生的原因:在实际的网络环境中,物理环路可以提高网络的可靠性,当一条线路断掉的时候,另一条链路仍然可以传输数据.但是,在交换 ...
- 如鹏网 net高级技术 第二章 委托和事件(复习)
委托 委托是一种数据类型,可以声明委托类型变量. 委托是一种可以指向方法的数据类型. 声明委托的方式:delegate返回值类型 委托类型名(参数) 比如 delegate void MyDel( ...
- 工程数据计算机处理的方法有,第二章 CADCAM技术基础-工程数据的计算机处理2011.ppt...
文档介绍: CAD/CAM技术基础 CAD/CAM Technology Base 主讲人:XXX E-mail:XXX 第二章 工程数据的计算机处理 Computer Processing of E ...
- 数据结构与算法(C#版)第二章 C#语言与面向对象技术(下)V1.0
由于本学期我给本科生上<数据结构与算法>这门课程,边上边把自己的教案进行总结,发到CSDN上面,希望大家多多指正. 第二章 C#语言与面向对象技术(下) 二.面向对象技术 5.属性 6.索 ...
最新文章
- python编写程序模拟硬币的投掷、假设0表示硬币的反面_修改了Python中的硬币投掷程序,无法完成循环...
- 介绍一个欧神写的剪贴板多端同步神器
- spark 2.x ML概念与应用
- 金秋10月丰收季,送3本Java书New一个秋天的对象
- linux driver开发
- 从零开始刷Leetcode——数组(31.33)
- 从大整数乘法的实现到 Karatsuba 快速算法
- AtCoder Beginner Contest 137 解题报告(A ~ E)
- 评价——模糊综合评价
- UWP 中的各种文件路径(用户、缓存、漫游、安装……)
- deprecate(反对) 关于依赖版本低的问题
- SimpleBGC三轴云台用户手册
- 软件从业者不可不读的一本书
- 计算机之父,你知道是谁吗?
- 计算机组成原理唐朔飞第二版答案第六章,计算机组成原理第六章部分课后题答案(唐朔飞版)...
- 正确认高分子PEG:识MTA mPEG,Myristic-acid PEG,肉豆蔻酸 PEG,PEG改性肉豆蔻酸
- 广东民办大学计算机专业,二本考生:12所民办大学的计算机专业实力不错,报考难度较低...
- 最速下降法求解函数极小值原理
- 程序员专属表情包,正在疯传中!
- 计算机教师读56 号教室体会,《第56号教室的奇迹》读后感(精选7篇)
热门文章
- 别浪费生活中灵光一闪的创意,发到实现网试试,万一实现了呢?
- java 错误: 无法将类 Customer中的构造器 Customer应用到给定类型
- win7如何更改计算机管理员用户名和密码,Win7如何修改管理用户名
- wps表格l制作甘特图_十分钟学会制作Excel甘特图,工作进度一目了然!
- python下载b站视频_python怎么下载b站视频
- 少儿编程软件Scratch下载(Mac、Windows皆可)
- 暑假ACM集训第一周总结
- 免费WiFi上网软件是什么?怎么用?
- ios客户端发现_华为爱奇艺手机活动开发总结
- 如何注册谷歌账号、邮箱(22.8.23亲测可用)