实现光线追踪

Posted leeqmoon

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实现光线追踪相关的知识,希望对你有一定的参考价值。

C++实现光线追踪之详解

[参考文章]http://www.cnblogs.com/miloyip/archive/2010/03/29/1698953.html
技术图片

1. 本文简介

作者正大三,刚好选修到计算机图形学这门课,基于兴趣,便试着实现全局光照的效果,由此,写下此篇文章。

2. 光线追踪

所谓光线追踪,是指从眼睛出发,经过图像平面每一像素,投射光线到场景中,求该光线与场景中几何图形的最近交点,然后求该交点的颜色属性,并将该颜色值记录下来,再根据相交点的材质判断性地进行反射、折射等现象继续追踪计算,最终把多次追踪交点颜色值的结果混合得到最终该像素的颜色值。(本文皆是介绍反向追踪)
技术图片

  • 图片来源: https://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-overview/ray-tracing-rendering-technique-overview

    3. 场景说明

    4.1 摄像机
    此次实验,本人将摄像机放置于世界坐标系下的Vec3(0,5,15)下,图像平面置于Vec3(0,0,-1)处。注,为了简化,直接将图像设置width,height一致,均为600。
    技术图片
    图一
    特别注意:(|front| = 1)
    4.2 场景
    本实验中,场景由两个球以及一个无限平面组成。
    Sphere1:
    Sphere(Vec3(-10,10,-10),float(10))
    参数一:球心
    参数二:球径
    Sphere2:
    Sphere(Vec3(-10,10,-10),float(10))
    Plane:
    在数学表达上,无限平面可表示为(nP=d),其中n为平面法向量,d为原点到平面的最短距离。
    Plane(Vec3(0,1,0),float(0))
    4.3 图像中坐标的转换
    最初,图像是600*600的平面,左上角为原点。现先转换为以左下角为原点的[0,1]范围内的平面。
    左上角为原点且范围为[0,600]:
    (X = X)...(1)
    (Y = Y)...(2)
    左下角为原点且范围为[0,1]:
    (X = X/width)...(2)
    (Y = 1-Y/height)...(2)
    图像中心为原点且范围为[-1,1]:
    (X = 2X-1)...(3)
    (Y=2Y-1)...(3)

4. 过程详解

(1)对于图像平面,自左向右,自上而下的经过每一像素投射光线
(2)计算光线与场景中几何图形的最近交点,都无交点即直接返回黑色,进行(5),否则进(3)
(3)取样 即计算最近交点的颜色属性
(4)计算反射光线继续追踪,回到(2)。
(5)赋像素予颜色值,回到(1)

4.1 步骤一之生成光线
由图一可知,
(Ray.dire = SampleVector+front)...(4)
(SampleVector=Vec3(X,Y,0))...(5)[注:此时是以中心为原点了]
即可得到初始化的Ray对象Ray(eye.origin,Ray.dire);
技术图片

转换为中心为原点计算光线原因如下:
4.2 步骤二之计算最近交点

  • 光线
    (R(t)=eye.origin+tD)(t为参数)
  • 平面
    (nP=d)
    1)判断光线与法向量n是否垂直
    2)不垂直即可计算交点
    光线与无限平面的法向量位置情况:
    技术图片
    由上图可知,当(n·Ray.dire>=0)时,没有交点;否则,有交点。
    3)交点的计算:
    (D=(d-eys.origin·n)/(t·n))

  • 推导过程复杂,作者不在此详细阐述,有兴趣的朋友可去这里查看

以上是关于实现光线追踪的主要内容,如果未能解决你的问题,请参考以下文章

基本光线追踪软件的设计与实现

没有递归光线追踪就不可能实现反射和折射?

Imagination 推新款GPU IP,首次实现桌面级光线追踪效果

光线追踪 - 反射

如何在现代 OpenGL 中进行光线追踪?

光线追踪框相交