<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 消費(fèi)電子 > 設(shè)計應(yīng)用 > 光線追蹤技術(shù)的理論和實(shí)踐(面向?qū)ο?

          光線追蹤技術(shù)的理論和實(shí)踐(面向?qū)ο?

          作者: 時間:2013-07-23 來源:網(wǎng)絡(luò) 收藏

          CGObject類成員變量有五個,分別表示物體表面環(huán)境光反射系數(shù)(m_Ka),漫反射系數(shù)(m_Kd),鏡面反射系數(shù)(m_Ks),鏡面反射強(qiáng)度(m_Shininess)和環(huán)境反射強(qiáng)度(m_Reflectivity)。前四個變量是計算光照所需要的最基本量,而環(huán)境反射強(qiáng)度表示該物體能反射環(huán)境的能力。這些成員變量都的類型都是protected,因?yàn)槲覀円袰GObject最為物體的基類,這些protected成員變量可以被該類的子類所繼承。該類的所有g(shù)et方法和set方法都能被子類繼承,而且所有繼承了該類的子類的方法都相同。該類還有兩個虛成員函數(shù),分別是getNormal()和isIntersected()。getNormal()函數(shù)的作用是獲取物體表面一點(diǎn)的法線,它接受一個GVector3類型的參數(shù)_Point,并返回物體表面點(diǎn)_Point處的法線。當(dāng)然不同物體表面獲得法線的方法是不一樣的。比如,對于平面來說,平面上所有點(diǎn)的法線都是一樣的。而對于球來說,球面上每一個的法線是球面上的該交點(diǎn)p和球心的c的差向量。

          本文引用地址:http://www.ex-cimer.com/article/164673.htm

          NSphere = p - c

          所以將getNormal()設(shè)置為虛成員函數(shù)就可以實(shí)現(xiàn)類的多態(tài)性,凡是繼承了該方法的子類,都可以實(shí)現(xiàn)自己的getNormal()方法。同樣的道理,函數(shù)isInserted也是虛成員函數(shù),該方法接受參數(shù)射線CRay

          和距離Distance,CRay是輸入?yún)?shù),用于判斷射線和該物體的交點(diǎn),Distance是輸出參數(shù),如果物體和射線相交,則返回相機(jī)到該交點(diǎn)的距離。Distance還應(yīng)該有個很大初始值,表示在無限遠(yuǎn)處物體和射線相交,這種情況用于判斷物體和射線沒有交點(diǎn)。函數(shù)isIntersected()還返回一個枚舉類型INTERSECTION_TYPE,定義如下:

          enum INTERSECTION_TYPE {INTERSECTED_IN = -1, MISS = 0, INTERSECTED = 1};

          其中INTERSECTED_IN表示射線從物體內(nèi)部出發(fā)并和物體有交點(diǎn),MISS射線和物體沒有交點(diǎn),INTERSECTED表示射線從物體外部出發(fā)并且和物體有交點(diǎn)。射線和不同物體交點(diǎn)的計算方法不同,于是該函數(shù)為虛函數(shù),繼承該函數(shù)的子類可以實(shí)現(xiàn)自己的isIntersected()方法。下面的代碼就可以判斷一條射線和場景中所有物體的是否有交點(diǎn),并且返回離相機(jī)最近的一個。

          double distance = 1000000; // 初始化無限大距離

          GVector3 Intersection; // 交點(diǎn)

          for(int i = 0; i

          {

          CGObject *obj = objects_list[i];

          if( obj->isIntersected(ray, distance) != MISS) // 判斷是否有交點(diǎn)

          {

          Intersection = ray.getPoint(distance); //如果相交,求出交點(diǎn)保存到Intersection

          }

          }

          為了計算方便,這里就以球?yàn)槔瑒?chuàng)建一個CSphere的類,該類繼承于CGObject。

          作為球,只需要提供球心Center和半徑Radius就可以決定它的幾何性質(zhì)。所以CSphere類只有兩個私有成員變量。在所有成員函數(shù)中,我們重點(diǎn)來看看isIntersected()方法。

          INTERSECTION_TYPE CSphere::isIntersected(CRay _ray, double _dist)

          {

          GVector3 v = _ray.getOrigin() - m_Center;

          double b = -(v * _ray.getDirection());

          double det = (b * b) - v*v + m_Radius;

          INTERSECTION_TYPE retval = MISS;

          if (det > 0){

          det = sqrt(det);

          double t1 = b - det;

          double t2 = b + det;

          if (t2 > 0){

          if (t1 0) {

          if (t2 _dist) {

          _dist = t2;

          retval = INTERSECTED_IN;

          }

          }

          else{

          if (t1 _dist){

          _dist = t1;

          retval = INTERSECTED;

          }

          }

          }

          }

          return retval;

          }

          如果射線和球有交點(diǎn),那么交點(diǎn)肯定在球面上。球面上的點(diǎn)P都滿足下面的關(guān)系,

          | P – C | = R

          很明顯球面上的點(diǎn)和球心的差向量的大小等于球的半徑。然后將射線的參數(shù)方程帶入上面的公式,再利用求根公式判斷解的情況。具體的方法這里就不詳述了,有興趣的同學(xué)可以參考另一篇文章“利用OpenGL實(shí)現(xiàn)RayPicking”,這篇文章詳細(xì)講解了射線和球交點(diǎn)的計算過程。

          現(xiàn)在我們實(shí)現(xiàn)了射線CRay,球體CSphere,還差一個重要的角色——光源。光源也是物體的一種,完全可以從我們的基類CGObject類繼承。這里做一點(diǎn)區(qū)別,我們單獨(dú)創(chuàng)建一個所有光源的基類CLightSource,然后從它在派生出不同的光源種類,比如平行光源DirectionalLight,點(diǎn)光源CPointLight和聚光源CSpotLight。本文中只詳細(xì)講解平行光源的情況,其他兩種光源有興趣的同學(xué)可以自己實(shí)現(xiàn)。

          類CLightSource的成員變量有四個,分別表示光源的位置,光源的環(huán)境光成分,漫反射成分和鏡面反射成分。同樣地,所有的set和get方法都為該類的子類提供相同的功能。最后也有三個虛成員函數(shù),EvalAmbient(),EvalDiffuse()和EvalSpecular(),它們名字分別說明它們的功能,并且都返回GVector3類型的值——顏色。由于對于不同種類的光源,計算方法可能不同,于是將它們設(shè)置為虛函數(shù)為以后的擴(kuò)展做準(zhǔn)備。筆者這里將光照計算放在了光源類里面,當(dāng)然你也可以放在物體類CGObject里,也可以單獨(dú)寫一個方法,將光源和物體作為參數(shù)傳入,計算出顏色后最為返回值返回。具體使用哪一種好還是要根據(jù)具體情況具體分析。

          上面的平行光源類CDirectionalLight是CLightSource的子類,它繼承了父類三個虛函數(shù)方法。下面來看看這三個函數(shù)的具體實(shí)現(xiàn)。

          環(huán)境光的計算是最簡單的,將物體材質(zhì)環(huán)境反射系數(shù)和光源的環(huán)境光成分相乘即可。

          ambient = Ia•Ka

          計算環(huán)境光的代碼如下

          GVector3 CDirectionalLight::EvalAmbient(const GVector3 _material_Ka)

          c++相關(guān)文章:c++教程




          評論


          相關(guān)推薦

          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();