2012-04-04 54 views
4

有人可以幫助我在Ray Tracer中進行景深實現嗎?如何在Ray Tracer中實現景深?

我正在使用一個簡單的針孔相機模型,如下所示。我需要知道如何使用針孔相機模型生成DOF效果? (圖片由wikipedia拍攝)在做工精細

enter image description here

我的基本的射線追蹤。

我有眼在(0,0,0,1),在(DX,DY,1.0F,0.0F)其中

浮子DX =(X *(1.0/Imgwidth))方向 - 0.5;
float dy =(y *(1.0/Imgheight)) - 0.5;

現在無處不讀,他們正在談論採樣應該放置在圖像平面和場景之間的鏡頭。例如如下圖所示(圖片來源於維基百科):

如果光線來自單點位置(相機或眼睛),如何在鏡像平面前引入鏡頭?

如果有人能幫上忙,那就太棒了!

謝謝

回答

10

有3種方法來做到這一點:

  1. 物理糾正自由度需要多次渲染的場景。相機具有景深,因爲它們不是真正的針孔模型。相反,他們有一個光圈,允許光線在一定的直徑內。這相當於拍攝針孔照相機並在該光圈內拍攝大量照片並對其進行平均處理。因此,基本上,您需要在您的焦點周圍多次旋轉相機,渲染整個場景,將輸出顏色累積在緩衝區中,並將所有值除以渲染數量。

  2. 簡單的後期處理效果 - 不僅渲染場景的顏色,還渲染其深度,然後使用此深度控制模糊效果強度。請注意,這是技術需要一些技巧,以獲得不同模糊級別的對象之間的無縫過渡。

  3. 更復雜的後期處理效果 - 先創建一個深度緩衝區,然後用它爲原始場景的每個像素渲染一個光圈形狀的粒子。就像使用模糊效果強度一樣,使用深度來控制粒子大小。

(1)給出最好的結果,但是是最昂貴的技術; (2)是最便宜的,(3)相當棘手,但提供良好的成本效益平衡。

+0

這與在我的相機(或眼睛)位置周圍取少量採樣點並不相似。然後從所有這些位置渲染我的場景。通過在場景中的某個地方定義一個焦點,從每個採樣點發送一個光線到圖像平面中每個像素的焦點。 – sinner 2012-04-04 14:03:53

+0

嗯,是的,這實際上是相同的 - 當然,您可以在每個像素的基礎上累積顏色,而不是累積整個場景的渲染。 – IneQuation 2012-04-04 14:10:28

+0

我的意思是: 是不是採取相似: - 我的相機(或眼睛)位置周圍的樣本點很少。 - 然後通過從圖像平面中的每個像素向每個採樣點發送一個光線到焦點,從所有這些位置渲染場景。 對不起,但如果你可以解釋眼睛的位置,圖像平面,焦平面和場景,它會讓我很容易理解。 – sinner 2012-04-04 14:13:44

2

這裏是我寫的代碼生成自由度。

void generateDOFfromEye(Image& img, const Camera& camera, Scene scene, float focusPoint) 
{ 
    float pixelWidth = 1.0f/(float) img.width; 
    float pixelHeight = 1.0f/(float) img.height; 

    for (int y = 0; y < img.height; ++y) 
     { 
     for (int x = 0; x < img.width; ++x) 
      { 
      Color output(0,0,0,0); 
      img(x, y) = Color(0,0,0,0); 

      //Center of the current pixel 
      float px = (x * pixelWidth) - 0.5; 
      float py = (y * pixelHeight) - 0.5; 

      Ray cameraSpaceRay = Ray(Vector(0,0,0,1), Vector(px, py, 1.0f, 0.0f)); 

      Ray ray = camera.Transform() * cameraSpaceRay; 

      int depth = 0; 
      int focaldistance = 2502; 
      Color blend(0,0,0,0); 



      //Stratified Sampling i.e. Random sampling (with 16 samples) inside each pixel to add DOF 
       for(int i = 0; i < 16; i++) 
       { 
       //random values between [-1,1] 
       float rw = (static_cast<float>(rand() % RAND_MAX)/RAND_MAX) * 2.0f - 1.0f; 
       float rh = (static_cast<float>(rand() % RAND_MAX)/RAND_MAX) * 2.0f - 1.0f; 
       // Since eye position is (0,0,0,1) I generate samples around that point with a 3x3 aperture size window. 
       float dx = ((rw) * 3 * pixelWidth) - 0.5; 
       float dy = ((rh) * 3 * pixelHeight) - 0.5; 

       //Now here I compute point P in the scene where I want to focus my scene 
       Vector P = Vector(0,0,0,1) + focusPoint * ray.Direction(); 
       Vector dir = P - Vector(dx, dy, 0.0f, 1.0f); 


       ray = Ray(Vector(dx,dy,0.0f,1.0f), dir); 
       ray = camera.Transform() * ray; 

       //Calling the phong shader to render the scene 
       blend += phongShader(scene, ray, depth, output); 

       } 
      blend /= 16.0f; 

      img(x, y) += blend; 
      } 
     } 
} 

現在我在代碼中看不到任何錯誤。但我得到的結果是隻爲focuspoint > 500價值模糊圖像,如下圖所示: enter image description here

如果你能告訴什麼是錯的這個代碼,那麼這將是非常有益的:) 謝謝!

+1

這不應該成爲問題的一部分嗎? – 2017-06-08 01:28:25