RayTracking 光线跟踪算法

转自 http://www.cnblogs.com/daniagger/archive/2012/05/28/2521318.html   详细请看这位师兄的博客 


1. Irradiance(辐照度)

total amount of energy received per unit area of a surface

 

2. Illuminance(照明度)

essentially same as irradiance,the difference is that illuminance measures the amount of visible light energy in photometric terms

 

3. Radiance(辐射)

measure of energy that is reflected by the surface

 

4. Luminance(亮度)

measure of photometrically weighted light energy that leaves the surface

 

5. Luminous intensity

amount of light energy that is emitted by the surface in a given direction


实际上叫反向光线追踪(backward raytracing),因为计算是从camera开始发射光线,而不是从光源发射光线。

反向光线追踪步骤:

1、camera的胶片被分成离散的网格(即像素点),我们的目标是确定每一个像素点的颜色值。

2、对于每一个像素,从camera位置追踪一条光线,指向该像素点

3、对于这束光线,判断其是否和场景中的物体相交。如果相交,则转到步骤4;否则,将背景色填充到当前像素中去,回到步骤2,继续处理下一个像素。

4、如果光线和物体相交,计算物体表面交点的颜色值。该点的颜色值即为该像素的颜色值。

a、首先检查每个光源在该交点的贡献值。追踪一条新光线去光源,用来确定交点是被全部照亮、部分照亮还是没有被照亮,同时确定了阴影。

b、如果物体表面具有反射性质,计算初始光线的反射光线,然后追踪这条反射光线,转到步骤3。

c、如果物体表面具有折射性质,计算初始光线的折射光线,然后追踪这条折射光线,转到步骤3。

d、最终,根据表面性质(反射率、折射率),和不同类型光线计算得出的颜色值,来确定交点的颜色值,即当前像素点的颜色值。

5、回到步骤2,继续下一个像素点。重复这个过程直到像素点都遍历完成。


[Raytracing]四种主要类型的追踪光线

1、主光线(Primary rays)

从camera发出的光线。

2、阴影光线(Shadow/Light rays)

从交点发出的光线,指向光源。如果这条光线在指向光源之前不相交于任何物体,则这个光源对该交点有贡献值;否则,该交点位于该光源的阴影处。

3、反射光线(Reflection rays)

如果物体表面具有反射性质,则部分光将会被反射出去,继续在场景中前进。根据Snell定律,一条新的光线将会从交点发出。

4、折射光线(Refracted rays)

当物体表面具有折射性质并且部分透明,部分光线将会进入物体继续传播。根据Snell定律,一条新的光线将会从交点发出进入物体。

[Raytracing]光线追踪的问题和解决方案

问题

1、性能

算法的递归性质和大数目的追踪光线,渲染过程可能持续数小时。80-90%的渲染时间花费在计算光线和物体交点上。

 

2、走样

 

3、尖锐的阴影

基本的光线追踪算法只能得到尖锐的阴影(因为模拟的是点光源)。

 

4、局部光照和着色

算法只追踪少数目的光线,只有四种类型的光线被考虑在内,物体之间的漫反射光没有被考虑在内,即算法并不包括全局光照。

 

解决方案

1、性能

a、使用更多或者更好的硬件

b、大规模并行计算

每一个光线都相互独立。

将图像分割,分配在多核上或者分布式网络上;或者分配在多个线程上。

c、限制交点检测的数目

使用包围盒的层次关系。快速判断光线是否和一组物体相交。物体被分组在封闭的包围盒中。利用空间细分技术:octree,BSP,grid.

d、优化交点检测

e、限制追踪光线的数目

确定最大的递归层数。

根据光线对当前像素点贡献值大小来限制递归深度。一个阈值用来确定后续光线由于对像素点贡献太小而不会被追踪。

 

 

2、走样

使用超采样(super sampling)、抗锯齿(antialiasing)、jittering

a、追踪额外的主光线并取平均值

即超采样,相对于每一个像素点取一条光线,你可以取特定数目的光线。每一个像素被分为亚像素,对每一个亚像素发射一条光线。当所有的亚像素点都处理完毕,对亚像素点的颜色值取平均值,并将其赋值给该像素点。这种方法大大增加了渲染时间。

b、自适应抗锯齿

在颜色剧烈变化的地方使用追踪的主光线,颜色变化不大的地方使用最少的主光线。

c、随机抗锯齿

随机取样代替常规取样。

 

3、尖锐的阴影

原因:使用点光源、每个交点仅仅对应一条阴影光线。

a、区域光(area light)

使用一系列点光源来模拟区域光源。对于每一个交点,需要和点光源数目一样多的追踪光线。

b、Monte Carlo光线追踪法

使用随机超采样,光源建模成球形光源,阴影光线指向代表光源的球上面的点。阴影光线颜色的平均值决定该交点最终的颜色值。


4、全局光照

依旧可以使用Monte Carlo法。使用Radiosity算法。

[Raytracing]代码框架

该伪代码总结了光线追踪算法。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
Function Raytrace(Scene World)
{
     for (each pixel of the image)
     {
          Calculate the ray corresponding to the pixel
             (projection);
          Pixel color=trace(ray,0);
     }
}
 
color trace(Ray myRay,interger recurs_level)
{
      if (myRay intersects an object Obj)
      {
          Calculate normal N at point of intersection Pi;
          Calculate surface color SC at point of intersection Pi;
          Final_Color=Shade(Obj,myRay,N,SC,Pi,recurs_level);
      }
      else
      {
          Calculate background color BkgC;
          Final_Color=BkgC;
      }
      return  Final_Color;
}
 
color Shade(Object obj,Ray myRay,Normal N,Surface_Color SC,
Point Pi,integer recurslevel)
{
      recurslevel++;
      if (recurslevel>MAX_RECURSION_LEVEL)
          return  0;
      
      for (each light source)
      {
          Calculate light ray(Pi points to light source);
          if (light ray doesn't intersect an object)
          {
              add light contribution to color based
               on the angle between light ray and myRay;
          }
      }
      calculate reflect ray;
      refl_color=trace(refl_ray,recurslevel);
      calculate refract ray;
      refr_color=trace(refr_ray,recurslevel);
      
      return  average(color,refl_color,refr_color);
}

[Raytracing]扩展光线追踪

1、随机采样

在基本光线追踪算法中,只追踪有限数目的光线。这是一个采样过程(sampling process)。

采样有很多种方法:

a、均匀采样

举例:根据给定的区间绘制数学函数。

将区间划分为许多小的宽度一致的小区间,在小区间的中点处计算函数的值,最终将这些点平滑连接出来。

QQ截图20120528084540

在小区间数目很少的情况下,均匀采样可能会得到错误的结果。

b、随机采样

使用随机间隔宽度代替统一间隔宽度。

QQ截图20120528084945

可以使用随机采样绘制平滑的阴影;绘制模糊的反射和折射;考虑景深;考虑运动模糊。

 

2、路径追踪

路径追踪算法考虑了全局光照问题。之前的光线追踪只考虑了四种类型的光线,没有哪一条光线考虑了物体之间的作用。

通过追踪交点周围所有路径的光线来计算间接光照,为了避免无限渲染次数,所有的可能光线路径使用随机采样。这种方法的光线分布通常是半球形,中心点是交点。

渲染有天空光的户外场景中,路径追踪算法非常有效率。因为这种场景下光变化的频率不大,也就是说,采样的函数值变化不大,小规模的采样依然可以得到很好的效果。

QQ截图20120528090503

双向(Bidirectional)路径追踪额外追踪了发自光源的光线,减少了路径追踪的采样次数。

 

3、光子映射(photon mapping)

两通道算法,考虑了全局光照和物体之间的反射,实现了caustics effect。

Pass 1-创建photon map

光线(光子)从光源开始追踪,光子携带从光源散发的一部分能量。

当光子在场景中传播时,可能被反射、穿透、吸收。

当光子击中漫反射表面时,使用map存储射进的能量。

photon map以k-d tree数据结构实现。

Pass 2-渲染阶段

使用光线追踪算法。在交点处,使用存储在map中的信息去估计光照度。

猜你喜欢

转载自blog.csdn.net/qq_41598072/article/details/79931187
今日推荐