调料粉碎机厂家
免费服务热线

Free service

hotline

010-00000000
调料粉碎机厂家
热门搜索:
技术资讯
当前位置:首页 > 技术资讯

光线追踪技术的理论和实践面向对象

发布时间:2020-07-21 18:28:55 阅读: 来源:调料粉碎机厂家

介绍

本文引用地址:这篇文章将介绍光线追踪技术。在计算机图形领域中,这种技术被普遍应用于生成高质量的照片级图像。在为一个场景计算光照的时候,通过固定图形渲染管线可以计算phong光照模型,由于该模型的特征,使得渲染的物体看起来有塑料的质感。如果要渲染一个有金属质感且能反射周围环境的物体,phong模型就无能为力了。和固定渲染管线相比,可编程图形渲染管线的力能要强的多,虽然可以实现很多逼真的光照效果,比如利用环境贴图来现实物体对环境的反射效果。但是这种环境反射只能反射出已经保存在Cube Map中的图像。在真实世界中,如果一个能反射周围环境的物体周围还有很多其他物体,它们就会相互反射。一般的环境贴图技术达不到这样的效果,于是在渲染照片级画面的时候,就要用到光线追踪的技术。文本还将利用c++面向对象的方法来实现光线追踪。

原理

在介绍原理之前,先考虑一个问题:我们是怎样看到真实世界中的物体的?我们能看到物体,是因为该物体上有反射光线到达我们的眼睛。没有任何光线传入眼睛,我们就看不到任何东西。我们还经常看到一个物体表面能反射另一个物体。这也是因为被反射物体表面的反射光线到达该物体表面后,该物体继续将光线反射到我们的眼睛里,于是我们看到了该物体表面反射其他物体的效果。现在,我们将从物体表面出发最后到达眼睛的光线的方向反向。先来看看下面的Fig1,在Fig1中是一个虚拟的场景,场景中有2个球和1个圆锥,白色的点代表光源,中间四边形就是虚拟屏幕,屏幕上一个一个的小方格就代表像素,相机的位置代表观察者眼睛的位置。

(a)

(b)

Fig1 光线追踪场景

光线追踪的原理就是从相机的位置发出一条条通过每一个像素的射线,如果该射线和场景中的物体相交,那么就可以计算出该交点的颜色,这个颜色就是对应的像素的颜色。当然,计算像素颜色的时候首先要计算出交点处所有与光照计算相关量,比如法线,入射光线和反射光线等等。

(a)

(b)

Fig2 光线和空间物体相交

在Fig2中可以看到,从相机出发的射线依次穿过每一个像素,图中显示出其中的三条。这些射线都与物体有交点,不同物体的交点计算方法也不一样。射线与平面的交点计算方法和射线与球的交点计算方法是截然不同的。为了计算方便,这里就只以球为例。如果一个物体可以反射周围的环境,那么当一条射线与该物体相交后,射线还会在该点产生反射和折射等。例如在Fig2中,当射线和蓝色球相交后,光线会反射,反射的光线又可能和橙色圆锥和绿色球相交,所以我们能在蓝色球的表面看到橙色的圆锥和绿色球。整个光线追踪的原理就是这么简单,但是实际操作起来又有很多要注意的地方。

实践

用面向对象的方法来实现光线追踪比使用面向结构要来的容易一些。因为在光线追踪的整个过程中,比较容易抽象出对象的共同特征,比如我们可以抽象出射线,物体,光源,材质等等。当然,最最基本的一个类就是向量类,在计算光照的时候向量很重要。在这里我们假设已经实现了一个三维向量类GVector3,该类提供所有有关向量的操作。

除了向量,我们最先能想到一个关于射线的类,叫CRay。

对于一条射线最基本的就是它的出发点和方向,所以在CRay的类图中,能看到两个私有成员变量m_Origin和m_Direction,它们都是GVector3类型。由于类的设计原则要满足数据的封装性,既然射线的出发点和方向都是私有的,那么就要提供公共的成员方法来访问它们,于是我们还需要set和get方法。最后,getPoint(double)方法是通过向射线的参数方程传入参数t而获得在射线上的点。实现了射线CRay类后,那么在使用光线追踪计算每个像素颜色的时候,对于每一个像素都要创建一个CRay的实例。

for(int y=0; y=ImageHeight; y++)

{

for(int x=0; x=ImageWidth; x++)

{

double pixel_x = -20.0 +40.0/ImageWidth*x;

double pixel_y = -15.0 +30.0/ImageHeight*y;

GVector3 direction = GVector3(pixel_x, pixel_y,0)-CameraPosition;

CRay ray(CameraPosition, direction);

// call RayTracer function

}

}

从上面的代码可以看到,两个for循环用于扫描每一个像素,然后在循环里计算出每个像素的位置。如果我们假设Fig1中,四边形屏幕处于xy平面,长和宽分别是40和30,且左上顶点坐标和右下顶点坐标分别为(-20,15,0)和(20,-15,0)。为了将该屏幕映射到实际分辨率为800*600的窗口上,就要求出虚拟屏幕上每个像素的坐标pixel_x和pixel_y。然后对每一个像素都用一条射线穿过它,射线的方向自然就是像素的位置和相机位置的差向量的方向。要注意一点,实际窗口的分辨率比例要和虚拟屏幕长宽比例保持一致,这样渲染出来的画面看起来长宽比例才正确。

现在我们来考虑在场景中的物体。一个物体可能有很多可以描述它的特征,比如形状,大小,颜色,材质等等。使用面向对象的方法,就需要将这些物体的共同特征抽象出来。下面是一个抽象出来的物体类GCObject。

c++相关文章:c++教程

广州磨骨价格

合肥双眼皮修复

长春双眼皮医院

济南磨骨