Двунаправленная трассировка пути

Я делаю двунаправленную трассировку пути, и у меня есть некоторые проблемы.

Для ясности: 1) Один точечный свет 2) Все объекты рассеянны 3) Все объекты являются сферами, даже стенами (они очень большие) 4) НЕТ НЕПРАВИЛЬНОГО ВЕСА

Излучение света является трехмерным вектором. BRDF сферы - это трехмерный вектор. Жестко закодировано.

В основной функции ниже я генерирую EyePath и LightPath, затем соединяю их. По крайней мере, я стараюсь.

В этом посте я расскажу об основной функции, затем о EyePath, а затем о LightPath. Разговор о функции подключения появится, когда EyePath и Light будут хорошими.

  1. Первые вопросы:
    • Хороша ли генерация первой светлой точки?
    • Нужно ли вычислять эту точку в соответствии с излучением источника света? или это просто эмиссия? Строка прокомментирована, где я заполняю структуру Vertices.
    • Нужно ли переводить с света? Для того, чтобы положить его на сферу

Код ниже взят из основной функции. Над ним есть две петли for, проходящие через все пиксели. Camera.o это глаз. CameraRayDir - это направление к текущему пикселю.

//The path light starting point is at the same position as the light Ray fromLight(Vec(0, 24.3, 0), Vec()); Sphere light = spheres[7];

#define PDF 0.15915494309 // 1 / (2 * PI)    

for(int i = 0; i < samps; ++i)
{
    std::vector<Vertices> PathEye;
    std::vector<Vertices> PathLight;

    Vec cameraRayDir = cx * (double(x) / w - .5) + cy * (double(y) / h - .5) + camera.d;

    Ray rayEye(camera.o, cameraRayDir.norm());              

    // Hemisphere oriented towards the top
    fromLight.d = generateRayInHemisphere(fromLight.o,Vec(0,1,0)).d;

    double f = clamp(n.dot(fromLight.d.norm()));

    Vertices vert;
    vert.d = fromLight.d;           
    vert.x = fromLight.o;
    vert.id = 7;
    vert.cos = f;
    vert.n = Vec(0,1,0).norm();

    // this one ?
    //vert.couleur = spheres[7].e * f / PDF;

    // Or this one ?
    vert.couleur = spheres[7].e;

    PathLight.push_back(vert);

    int sizeEye = generateEyePath(PathEye, rayEye, maxDepth);
    int sizeLight = generateLightPath(PathLight, fromLight, maxDepth);

    for (int s = 0; s < sizeLight; ++s)
    {
        for (int t = 1; t < sizeEye; ++t)
        {
          int depth = t + s - 1;
          if ((s == 0 && t == 0) || depth < 0 || depth > maxDepth)
            continue;

          pixelValue = pixelValue + connectPaths(PathEye, PathLight, s, t);
        }
     }
}

Для EyePath я пересекаю геометрию, затем вычисляю освещение в соответствии с расстоянием со светом. Цвет черный, если точка находится в тени.

Второй вопрос: хорошо ли вычисление для траектории глаза и прямого освещения? Я видел во многих кодах, люди используют PDF даже при прямом освещении. Но я использую только точечный свет и сферы.

int generateEyePath(std::vector<Vertices>& v, Ray eye, int maxDepth)
{
  double t;
  int id = 0;

  Vertices vert;

  int RussianRoulette;

  while(v.size() <= maxDepth)
  {

    if(distribRREye(generatorRREye) < 10)
      break;

    // Intersect all the geometry
    // id is the id of the intersected geometry in an array
    intersect(eye, t, id);

    const Sphere& obj = spheres[id];

    // Intersection point
    Vec x = eye.o + eye.d * t;

    // normal
    Vec n = (x - obj.p).norm();  

    Vec direction = light.p - x;   

    // Shadow ray
    Ray RaytoLight = Ray(x, direction.norm());        

    const float distance = direction.length();

    // shadow
    const bool visibility = intersect(RaytoLight, t, id);

    const Sphere &lumiere = spheres[id];

    float degree = clamp(n.dot((lumiere.p - x).norm()));

    // If the intersected geometry is not a light, then in shadow
    if(lumiere.e.x == 0)
    {
      vert.couleur = Vec(); 
    }
    else // else we compute the colour
       // obj.c is the brdf, lumiere.e is the emission
       vert.couleur = (obj.c).mult(lumiere.e / (distance * distance)) * degree;    

    vert.x = x;
    vert.id = id;
    vert.n = n;
    vert.d = eye.d.normn();
    vert.cos = degree;

    v.push_back(vert);

    eye = generateRayInHemisphere(x,n);
  }

  return v.size();
 }

Для LightPath, для данной точки, я вычисляю ее в соответствии с предыдущей и значениями в этой точке. Как в обычной трассировке пути. \ N

Третий вопрос: хорошо ли вычисление цвета?

int generateLightPath(std::vector<Vertices>& v, Ray fromLight, int maxDepth)
{
   double t;
   int id = 0;

   Vertices vert;

   Vec previous;

   while(v.size() <= maxDepth)
   {
    if(distribRRLight(generatorRRLight) < 10)
      break;

    previous = v.back().couleur;

    intersect(fromLight, t, id);

    // intersected geometry
    const Sphere& obj = spheres[id];

    // Intersection point
    Vec x = fromLight.o + fromLight.d * t;

    // normal
    Vec n = (x - obj.p).norm();   

    double f = clamp(n.dot(fromLight.d.norm()));

    // obj.c is the brdf
    vert.couleur = previous.mult(((obj.c / M_PI) * f) / PDF);  

    vert.x = x;
    vert.id = id;
    vert.n = n;
    vert.d = fromLight.d.norm();
    vert.cos = f;

    v.push_back(vert);

    fromLight = generateRayInHemisphere(x,n);
  }

  return v.size();
 }

На данный момент я получаю этот результат.

введите описание изображения здесь

Функция подключения появится, когда EyePath и LightPath будут хорошими.

Спасибо вам всем

1 ответ

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

https://www.researchgate.net/publication/221546261_Testing_Monte-Carlo_Global_Illumination_Methods_with_Analytically_Computable_Scenes

Это сэкономит ваше время на внедрение и проверку вашего понимания сначала с помощью трассировки пути и трассировки света, а затем попытается объединить их с весами.

Другие вопросы по тегам