简单的逆向光线跟踪

        摘要:光线跟踪属于计算机图形学的经典理论,在高质量的场景渲染领域有着很广泛的应用,虽然读研没在图形所,但还是非常有幸的上了学校里大牛老师的课,俗话说,没吃过猪肉,还没见过猪跑么,呵呵,开玩笑,下面的文章以作者研一上课图形学大作业为背景,因为最近要增加博客的点击率,所以把陈年的谷子给翻了出 来,下面进入正题,呵呵。

 

        第一部分: 原理部分

光线跟踪是模拟从照相机(人眼)位置发射一条光线,穿过屏幕,和虚拟世界的物体相交与一点,光线跟踪的主要任务就是计算相交点的亮度值,相交点的亮度由两部分组成,一是直接光源的照射,二是其它物体表面的反射。如图所示:


 

图1 照相机发射光线穿越屏幕

图2 照相机发射光线与物体相交处的亮度计算

光线到达物体后有两部分运算:

  1. 光照计算(局部与全局)

一部分是局部光照计算,包括漫反射,镜面反射,环境光等。这部分主要采用phong模型来计算局部光照强度。

  1. 漫反射,从光源发出的光到达物体后沿着各个方向均匀反射,这里主要要计算物体交点的法向量及此点与光源的连线的夹角余弦值。然后可以算出亮度值。如下图所示:


图3漫反射效果图

  1. 镜面反射沿着出射光线方向偏离越远光线越暗,如下图所示,L为入射光线,R为反射光线,V为视点与交点连线,V看到的点亮度与V R的夹角余弦值成正比:

 

图4 镜面反射模型


 

     

另一部分是全局光照计算,包括反射,折射等。全局光照计算主要涉及到光线的递归,为了防止光线在物体上不停的折射反射,一般都设置一个递归深度,当达到递归深度后不再进行计算。

在计算过程中有三种情况会终止光线的跟踪,一种情况是光线被物体挡住,此时可以终止计算此点像素值,返回一个(0,0,0)的颜色值,另外一种情况是直接照射到光源,此时也会停止光线跟踪,返回光源颜色。第三种情况是到达递归深度时仍然没有达到上面两个条件,此时强行终止光线的计算。跟踪深度越大,效果越逼真,计算量也越大。

 


      2.相交测试

在跟踪过程中需要计算光线与物体是否有交点,在本例中只计算了与球体及平面的交点,

    1. 球:

c为球的中心,p为光线在屏幕的发出点,u为光线的方向,r为圆的半径,qpq cq垂直的交点,得到一公式,alpha = -1 * (p - c) * u,此处有p + alpha * u = q. 然后计算qc的距离b. a * a = r * r – b * b, 求出aalpha = alpha – a;此处p + alpha * u即为射线与球的交点。

    1. 平面:

起点为pu为方向,q = p + alpha * u;

Alpha = (d – p * n) / (u * n), d为平面的常量 其中x * n = dn为法向。

 

 

 第2部分:程序设计

 

        程序的设计分为三部分:

        第一部分设计了常用的一个类Vector3,并作了常用的运算符重载。类部分代码如下

 

ContractedBlock.gifExpandedBlockStart.gifCode
  1 class Vector3
  2 
  3 {
  4 
  5 public:
  6 
  7     Vector3(double x, double y, double z) :
  8 
  9       m_x(x), m_y(y), m_z(z){}
 10 
 11 
 12 
 13       Vector3() :
 14 
 15       m_x(0), m_y(0), m_z(0){}
 16 
 17 
 18 
 19 
 20 
 21     Vector3 operator = (Vector3 Vector3)
 22 
 23     {
 24 
 25         this->m_x = Vector3.m_x;
 26 
 27         this->m_y = Vector3.m_y;
 28 
 29         this->m_z = Vector3.m_z;
 30 
 31 
 32 
 33         return *this;
 34 
 35     }
 36 
 37 
 38 
 39     bool operator ==(Vector3 b)
 40 
 41     {
 42 
 43         if(this->m_x == b.m_x && this->m_y == b.m_y && this->m_z == b.m_z)
 44 
 45             return true;
 46 
 47         else
 48 
 49             return false;
 50 
 51     }
 52 
 53 
 54 
 55     Vector3(Vector3& ax)
 56 
 57     {
 58 
 59         m_x = ax.m_x;
 60 
 61         m_y = ax.m_y;
 62 
 63         m_z = ax.m_z;            
 64 
 65     }
 66 
 67 
 68 
 69     Vector3 Normalize()
 70 
 71     {
 72 
 73         double result = sqrt( pow(m_x, 2)  + pow(m_y, 2+ pow(m_z, 2));
 74 
 75         m_x = m_x / result;
 76 
 77         m_y = m_y / result;
 78 
 79         m_z = m_z / result; 
 80 
 81         return *this;
 82 
 83     }
 84 
 85 
 86 
 87     double operator * (Vector3 v3)
 88 
 89     {
 90 
 91         double result = 0;
 92 
 93         result = this->m_x * v3.m_x +    this->m_y * v3.m_y + this->m_z * v3.m_z;
 94 
 95         return result;
 96 
 97     }
 98 
 99 
100 
101     Vector3 operator * (double f)
102 
103     {
104 
105         Vector3* vv3 = new Vector3();
106 
107         vv3->m_x = this->m_x * f;
108 
109         vv3->m_y = this->m_y * f;
110 
111         vv3->m_z = this->m_z * f;
112 
113 
114 
115         return *vv3;
116 
117     }
118 
119 
120 
121     Vector3 operator -(Vector3 v3)
122 
123     {
124 
125         Vector3* vv3 = new Vector3();
126 
127         vv3->m_x = this->m_x - v3.m_x;
128 
129         vv3->m_y = this->m_y - v3.m_y;
130 
131         vv3->m_z = this->m_z - v3.m_z;
132 
133 
134 
135         return * vv3;
136 
137     }
138 
139 
140 
141     Vector3 operator +(Vector3 v3)
142 
143     {
144 
145         Vector3* vv3 = new Vector3();
146 
147         vv3->m_x = this->m_x + v3.m_x;
148 
149         vv3->m_y = this->m_y + v3.m_y;
150 
151         vv3->m_z = this->m_z + v3.m_z;
152 
153 
154 
155         return * vv3;
156 
157     }
158 
159 
160 
161 public:
162 
163     double m_x, m_y, m_z;
164 
165 };
166 
167 

         第二部分设计了一个虚基类用于被各种物体继承,这样设计主要是为了光线跟踪时对物体的遍历方便,同时设计了材质属性类,球体类,平面类等。

 

ContractedBlock.gifExpandedBlockStart.gifCode
  1 class Primitive
  2 
  3 {
  4 
  5 public:
  6 
  7     enum{
  8 
  9         SPHERE = 1,
 10 
 11         BOARD
 12 
 13     };
 14 
 15     virtual int InterSect(Ray* ray, double& dis) = 0;
 16 
 17     Material* GetMaterial() { return &m_Material; }
 18 
 19     virtual Vector3 GetNormal(Vector3 Pos) = 0;
 20 
 21     virtual Color Get_Color(){return m_Material.Get_Color();}
 22 
 23     virtual void Light(bool light){ m_Light = light;}
 24 
 25     bool IsLight() { return m_Light; }
 26 
 27     virtual int GetType() = 0;
 28 
 29     void SetName(std::string& name){m_Name = name;}
 30 
 31     
 32 
 33 
 34 
 35 private:
 36 
 37     Material m_Material;
 38 
 39     bool m_Light;
 40 
 41     std::string m_Name;
 42 
 43 };
 44 
 45 
 46 
 47 
 48 
 49 
 50 
 51 //here is a sphere
 52 
 53 class Sphere : public Primitive
 54 
 55 {
 56 
 57 public:
 58 
 59     int GetType() {return SPHERE;}
 60 
 61     Sphere(Vector3 center, double radius){
 62 
 63         m_Center = center; 
 64 
 65         m_Radius = radius;
 66 
 67     }
 68 
 69 
 70 
 71     double GetRadius(){return m_Radius;}
 72 
 73     int InterSect(Ray* ray, double& dist);
 74 
 75     Vector3 GetCenter(){return m_Center;}
 76 
 77     Vector3 GetNormal(Vector3 pos){
 78 
 79         Vector3 v3 = pos - m_Center;
 80 
 81         NORMALIZE(v3)
 82 
 83         return v3;
 84 
 85     }
 86 
 87 
 88 
 89 
 90 
 91 private:
 92 
 93     Vector3 m_Center;
 94 
 95     double m_Radius;
 96 
 97 
 98 
 99 };
100 
101 
102 
103 //board such as walls , floors ceilings and so on
104 
105 class Board : public Primitive
106 
107 {
108 
109 public:
110 
111     int GetType(){return BOARD;}
112 
113     Board(Vector3 nor, double d)
114 
115     {
116 
117         m_Normal = nor;
118 
119         m_D = d;
120 
121     }
122 
123     int InterSect(Ray* ray, double& dist);
124 
125 
126 
127     
128 
129     double Get_D(){return m_D;}
130 
131     Vector3 GetNormal(Vector3 pos){
132 
133         m_Normal.Normalize();
134 
135         return m_Normal;
136 
137     }
138 
139 
140 
141 private:
142 
143     Vector3 m_Normal;
144 
145     double m_D;
146 
147 };

 

 
        第三部分渲染引擎的设计

 

ContractedBlock.gifExpandedBlockStart.gifCode
 1     class Engin
 2 
 3     {
 4 
 5     public:
 6 
 7         Engin();
 8 
 9         ~Engin();
10 
11         Scene* GetScene(){return m_Scene;}
12 
13         Primitive* RayTrace(Ray* ray, Color& color, int depth, double r_index, double& dist );
14 
15         void InitRender();
16 
17         bool Render();
18 
19         void SetTarget(int m_Width, int m_Height, int*** m_Buffer)
20 
21         {
22 
23             m_Width = m_Width;
24 
25             m_Height = m_Height;
26 
27             buffer = m_Buffer;
28 
29         }
30 
31 
32 
33     
34 
35     private:
36 
37         Scene* m_Scene;
38 
39         int m_Width, m_Height, m_CurrentLine, m_Pos;
40 
41         int*** buffer;
42 
43     };

 

        最终效果图如下:

 

 

 

转载于:https://www.cnblogs.com/superbigdog/archive/2009/06/22/1508641.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值