smallpt: Global Illumination in 99 lines of C++

  • 光线追踪
    • 正向光线追踪
    • 逆向光线追踪介绍
  • 蒙特卡罗光线追踪算法
    • 非透明材质
      • 漫反射材质
      • 镜面反射材质
    • 透明材质
      • 反射与折射
        • 折射光线方向的计算:斯涅尔定律
        • 折射光线与反射光线混合:菲涅耳公式

smallpt: Global Illumination in 99 lines of C++

光线追踪

正向光线追踪

正向光线追踪符合常识:光线从发光物体出发出,“撞击”到被观察物体上,经过一系列光线传输进入人眼。

因此正向光线追踪的基本流程可以简述为:

  1. 追踪从发光体发射的所有光线
  2. 检测光线是否“撞击”物体
    • 如果没有“撞击”物体,直接抛弃
  3. 如果撞击到物体。看反射光线是否直接射入人眼
    -如果没有直接射入人眼,则其可能经过一系列传输才射入人眼(间接射入人眼),需要进步判断
    -如果直接射入人眼,则计算当前反射光线的颜色,作为该撞击点的颜色

从上述流程不难可以看出,正向光线追踪需要追所有光线。而在这所有光线中,只有一部分光线会“撞击”到观察体,“撞击”到观察体的光线也只有部分会射入人眼。因此追踪所有光线,计算量大且做无用功较多。

逆向光线追踪介绍

追踪光线的方向与正向相反:从眼睛处射出光线,追踪光线射击到物体后,是否能回到光源。如果能则说明该点被光源照亮,否则物体上该点可能被间接照亮,需要进一步判断。

逆向光线追踪为什么比正向光线追踪号好呢?
因为从图形学的角度来看

人眼发射出的光线是有限的,而光源发射出的光线是无限的:人眼接收图像是二维的像素组成的。每个像素记录着该点的颜色。也即对于每个像素计算其颜色, 代表着该像素上一次光线追踪的结果。

因此逆向光线追踪的基本流程可以简述为:

FOR 每个像素点 :构造人眼入射光线Ray光线追踪Ray :计算与光线Ray相交的最近的物体ObjIF obj == null :该像素点颜色为缺省值:全局环境光AmbientColorContinueELSE 看反射光Reflection是否能直接与光源相连(未被其他物体遮挡)IF 没有被遮挡该像素点颜色为光源颜色在该材质上的作用ELSE IF 被遮挡 该像素点颜色根据反射光的光线追踪结果得到。

蒙特卡罗光线追踪算法

个人理解,不对欢迎指正
蒙特卡洛思想介绍

蒙特卡罗光线追踪对逆向光线追踪模型进行改进,其中最大的区别在于把概率模型引入光线追踪。

  • 逆向光线追踪中物体的表面材质很单一。引入俄罗斯赌盘轮,可以设定漫反射、镜面反射、甚至折射的概率。丰富表面材质的显示
  • 每个像素点只采样一条光线计算出的颜色,正确率不高。引入蒙特卡罗可以多次采样求平均,优化渲染结果。

根据上述分析光线追踪算法中最重要的步骤可以分解成两个:

  1. 射线与多边形物体的求交判断(空间划分kdTree)
  2. 光线追踪这个递归子算法(包括对各种材质的处理)

下面由于准备材料不够,我先只主要介绍方面2:

非透明材质

漫反射材质

漫反射材质表现为表面不规则,因此反射光线的方向无法确定判断。它朝可能的任意方向反射。

我们假定对于漫反射材质,反射光线的方向范围可以限定在以撞击点为圆心,撞击点法相为中心的半圆内。

假设:
入射光线为Ray(x0, d0)。其中x0表示光线起点 d代表光线方向
入射光线与物体表面的相交点为x
入射光线与物体表面相交点x出的法向为n
目标:求反射光线Reflection Ray(x, d1).

1.构建以x点为中心,n为一个坐标轴的笛卡尔直角坐标系
w = n
u=((fabs(w.x)>.1?Vec(0,1,0):Vec(1,0,0)) * w).norm()
v=w * u
u/v/w即组成一个笛卡尔直角坐标系

2.将反射光线方向d1分解为u/v/w表示形式
如下图所示
d1 = |d1| * cosα * cosθ * u + |d1| * sinα * w + |d1| * cosα * sinθ * v
其中α为 [0, PI/2]中的随机数;θ为[0,2*PI]中的随机数

这两个步骤对应smallpt: Global Illumination in 99 lines of C++中代码片段56-60

 if (obj.refl == DIFF){                  // Ideal DIFFUSE reflection double r1=2*M_PI*erand48(Xi), r2=erand48(Xi), r2s=sqrt(r2); Vec w=nl, u=((fabs(w.x)>.1?Vec(0,1):Vec(1))%w).norm(), v=w%u; Vec d = (u*cos(r1)*r2s + v*sin(r1)*r2s + w*sqrt(1-r2)).norm(); return obj.e + f.mult(radiance(Ray(x,d),depth,Xi)); }

镜面反射材质

镜面反射比较简单,反射光线可假定严格按照反射定律来求(入射角定于反射角)

假设:
入射光线为Ray(x0, d0)。其中x0表示光线起点 d代表光线方向
入射光线与物体表面的相交点为x
入射光线与物体表面相交点x出的法向为n
目标:求反射光线Reflection Ray(x, d1).
具体计算步骤如下图所示
d1 = d0 - n * 2 * (n * d0)

这两个步骤对应smallpt: Global Illumination in 99 lines of C++中代码片段61-62

else if (obj.refl == SPEC)            // Ideal SPECULAR reflection return obj.e + f.mult(radiance(Ray(x,r.d-n*2*n.dot(r.d)),depth,Xi));

透明材质

反射与折射

非透明材质在光线追踪的过程中,要不是漫反射,要不是镜面反射。与非透明材质不同,透明材质在光线作用下,反射和折射是同时存在的(全反射除外)。因此在光线追踪透明材质时,需要同时考虑这两种发射情况。

折射光线方向的计算:斯涅尔定律

简单介绍一下斯涅尔定律,它主要是描述清楚了入射角与折射角之间的关系:
n1sinθ1 = n2sinθ2
其中n1/n2是两个介质的折射率;θ12分别是入射角/折射角

折射光线方向计算:
假设:
入射光线为Ray(x0, d0)。其中x0表示光线起点 d代表光线方向
入射光线与物体表面的相交点为x
入射光线与物体表面相交点x出的法向为n
两种介质的折射率分别为n1、n2
目标:求折射光线Reflection Ray(x, d1).


这个步骤对应smallpt: Global Illumination in 99 lines of C++中代码片段68

Vec tdir = (r.d*nnt - n*((into?1:-1)*(ddn*nnt+sqrt(cos2t)))).norm();

考虑全反射:入射角大于某一临界角θc(光线远离法线)时,折射光线将会消失,所有的入射光线将被反射。
当折射角等于90°时,入射角即达到临界角。
这部分步骤对应smallpt: Global Illumination in 99 lines of C++中代码片段63-67

Ray reflRay(x, r.d-n*2*n.dot(r.d));     // Ideal dielectric REFRACTION
bool into = n.dot(nl)>0;                // Ray from outside going in?
double nc=1, nt=1.5, nnt=into?nc/nt:nt/nc, ddn=r.d.dot(nl), cos2t;
if ((cos2t=1-nnt*nnt*(1-ddn*ddn))<0)    // Total internal reflection   全反射return obj.e + f.mult(radiance(reflRay,depth,Xi));

折射光线与反射光线混合:菲涅耳公式


这部分步骤对应smallpt: Global Illumination in 99 lines of C++中代码片段69-73

double a=nt-nc, b=nt+nc, R0=a*a/(b*b), c = 1-(into?-ddn:tdir.dot(n));
double Re=R0+(1-R0)*c*c*c*c*c,Tr=1-Re,P=.25+.5*Re,RP=Re/P,TP=Tr/(1-P);
return obj.e + f.mult(depth>2 ? (erand48(Xi)<P ?   // Russian roulette 俄罗斯赌盘radiance(reflRay,depth,Xi)*RP:radiance(Ray(x,tdir),depth,Xi)*TP) : radiance(reflRay,depth,Xi)*Re+radiance(Ray(x,tdir),depth,Xi)*Tr);

待更新


参考:
1.smallpt: Global Illumination in 99 lines of C++
2.scratchapixel: Introduction to Ray Tracing: a Simple Method for Creating 3D Images
3.scratchapixel:Rendering an Image of a 3D Scene: A Light Simulator
4.百度百科:斯涅尔定律、菲涅耳公式
5.知乎:如何用 C++ 实现光线跟踪软渲染器?

smallpt: Global Illumination in 99 lines of C++讲解相关推荐

  1. 全局光照技术解析Global Illumination Explained

    解析全局光照Global Illumination Explained 前言:Global Illumination全局光照技术是实时渲染的必然发展方向.我参考了一些研究成果,琢磨了一下,让更多的人可 ...

  2. Real-Time Rendering——Chapter 9 Global Illumination

    radiance is the final quantity computed by the rendering process. 渲染的最终结果是计算辐射率.我们使用反射率方程进行求解. so fa ...

  3. 实时高清渲染:全局光照(Global Illumination)[1]

    目录 基础知识: Radiance: Irradiance: Radiant flux: Radiant Intensity: Solid Angle: Lambertian surface: Lam ...

  4. Unity Global Illumination(Unity 全局光照 ) 官方手册笔记系列之Enlighten

    Enlighten 本文档主要是对Unity官方手册的个人理解与总结(其实以翻译记录为主:>) 仅作为个人学习使用,不得作为商业用途,欢迎转载,并请注明出处. 文章中涉及到的操作都是基于Unit ...

  5. UE建筑可视化全局照明学习 Unreal Engine: Global Illumination for Arch. Visualization

    虚幻引擎:建筑可视化的全局照明 你会学到: 使用轻量级地理信息引擎 聚焦胃肠计算 生成灯光贴图Uv 轻度烘焙 控制光反弹 使用环境遮挡 动画和地理信息 暴露 保存高分辨率图像 课程获取:UE建筑可视化 ...

  6. SVO实时全局光照优化(里程碑MK2):Sparse Voxel Octree based Global Illumination (SVO GI)...

    自主实现的实时渲染引擎,对标对象ue4/ce5,超越u3d/klayge.MK2版本侧重于质量与速度的均衡,以下上传示范均为实测截图,均为全分辨率(网页上显示缩小了)1080p/60fps. 转载于: ...

  7. Q89:全局光照(Global Illumination)——Path Tracing(只用于间接光照)

    89.1 Path Tracing只用于间接光照 根据Path Trace的算法,只有当最终的反射光线撞击到发光材质物体时,才会对最初的撞击点进行"有效"着色,否则着色为" ...

  8. Q88:全局光照(Global Illumination)——Path Tracing算法生成反射焦散效果的图形

    由于在镜面反射中,光线几乎可以保持来自光源的全部能量,并在表面曲度和折射率的作用下,产生聚焦或者发散,当这种光线接触到场景中其它对象的表面时,又会产生新的照明效果,于是焦散便产生了. 简而言之,即是: ...

  9. Q88:全局光照(Global Illumination)——Path Tracing

    88.1 引入(Introduction) 截至当前,回忆一下我们学过的针对直接光照和间接光照的不同反射模型. 直接光照: Phong反射模型.包含漫反射部分和高光反射部分. 间接光照: 对于镜面材料 ...

最新文章

  1. iOS App上架流程(2016详细版)
  2. 概率论 第四章 随机变量的数字特征
  3. 火狐浏览器百度网盘服务器响应,火狐浏览器打不开百度网盘怎么解决?解决百度网盘打不开的步骤分享...
  4. printf(%d,5.01)和printf(%f,5)的输出结果
  5. 手机射频电路全面解析
  6. 学生健康管理软件/中小学体检数据管理系统
  7. Java 拾遗补阙 ----- 数据类型
  8. arduino和单片机的区别是什么
  9. c语言16进制转2进制代码
  10. 【供应链架构day4】途牛进销存架构的演进之路 - 从诞生到发展
  11. 华为海思总裁:压在保密柜里面的芯片可以拿出来了
  12. mysql binlog grep_通过mysqlbinlog和grep命令定位binlog文件中指定操作
  13. 色度学:RGB颜色空间与CMYK颜色空间的比较与图示
  14. Tf2.0+基于注意力的神经机器翻译训练发布过程
  15. 微信登录画面_每次打开微信登录界面,都会看到一个小人,他是谁呢?
  16. WPF 开机启动因为触摸初始化锁住界面显示
  17. FEBE恢复Firefox配置方法[Z]
  18. 50天50个前端小项目(纯html+css+js)第六天(页面滚动动画)
  19. Echarts自定义地图和添加图标
  20. 对模式的迷信,大部分是幻觉和妄想

热门文章

  1. bde oracle 商友的流程_BDE动态连接Oracle数据库
  2. 【LOD for 3D Graphics】LOD技术背景调查
  3. 51单片机实战教程(34 线缆摇摆测试机设计)
  4. 技嘉Gigabyte主板Z370HD3安装1080ti+ubuntu17.10+Cuda9.1+cudnn7+tensorflow
  5. luogu P2852 [USACO06DEC]牛奶模式Milk Patterns
  6. 爱学习的小虫子——Who Am I ?
  7. TDA4 J721 EVM开发板开发学习
  8. 一般网站需要多少流量多大空间才够用
  9. 【数字信号】基于matlab GUI多音双频(DTMF)拨号音频解码仿真系统【含Matlab源码 1084期】
  10. Consul微服务注册与发现