2012-04-04 2 views
4

Может кто-нибудь помочь мне с реализацией глубины резкости в Ray Tracer, пожалуйста?Как реализовать глубину резкости в Ray Tracer?

Я использую простую модель камеры с отверстиями, как показано ниже. Мне нужно знать, как мы можем генерировать эффект DOF, используя модель камеры с отверстиями? (Изображение взято из wikipedia)

enter image description here

Мой основной рэйтрэйсер в работе штрафа.

У меня глаза в (0,0,0,1) с направлением в точке (Dx, Dy, 1.0f, 0.0f), где

поплавка дх = (х * (1,0/Imgwidth)) - 0,5;
float dy = (y * (1.0/Imgheight)) - 0,5;

Теперь, где бы я ни читал, речь идет о взятии объектива, который должен быть расположен между плоскостью изображения и сценой. например, как показано ниже (изображение взято из википедии):

Как я могу представить объектив перед плоскостью изображения, если лучи исходят из одного положения точки (камеры или глаза)?

Если кто-то может помочь, это будет здорово!

спасибо

ответ

10

Есть 3 способа сделать это:

  1. Физически-корректный DOF потребовал бы многократные рендеров сцены. Камеры имеют глубину поля, потому что они не являются моделью обскуры. Вместо этого они имеют диафрагму, которая допускает свет в пределах определенного диаметра. Это эквивалентно съемке камеры с отверстиями и съемке большого количества изображений внутри этой апертуры и усреднению их.

    Так что в основном вам нужно несколько раз вращать камеру вокруг своей точки фокусировки, отображать всю сцену, накапливать выходной цвет в буфере и делить все значения на количество рендерингов.

  2. Простой эффект обработки сообщений - визуализирует не только цвет сцены, но и ее глубину, затем используйте эту глубину для управления силой размытия. Обратите внимание, что это техника требует некоторых трюков для получения плавных переходов между объектами на разных уровнях размытия.

  3. Более сложный эффект пост-обработки - создайте буфер глубины, как и раньше, а затем используйте его для рендеринга частицы в форме диафрагмы для каждого пикселя исходной сцены. Используйте глубину, чтобы контролировать размер частиц так же, как вы использовали бы его для силы размытия.

(1) дает наилучшие результаты, но является самой дорогой техникой; (2) является самым дешевым, (3) довольно сложным, но обеспечивает хороший баланс затрат и затрат.

+0

Не похоже ли на несколько точек отсчета вокруг моей камеры (или глаз). А затем отрисуйте мою сцену со всех этих позиций. Отправка луча из каждой точки выборки в точку фокусировки для каждого пикселя в плоскости изображения путем определения точки фокусировки где-то в сцене. – sinner

+0

Ну, да, это на самом деле то же самое - конечно, вы можете накапливать цвет на основе пикселя, вместо того, чтобы накапливать рендеринг всей сцены. – IneQuation

+0

Я имею в виду: Разве это не похоже на взятие: -Приблизительное количество точек вокруг моей камеры (или глаза). - И затем визуализируйте мою сцену из всех этих положений, отправив луч от каждой точки выборки до точки фокусировки через каждый пиксель в плоскости изображения. Прошу прощения, но если вы можете объяснить с точки зрения положения глаз, плоскости изображения, фокальной плоскости и сцены, это заставит меня понять довольно легко. – sinner

2

Вот код, который я написал для создания DOF.

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

Разве это не должно быть частью вопроса? –