双向路径跟踪

时间:2016-03-03 19:37:06

标签: rendering raytracing

我正在制作双向路径追踪器,我遇到了一些麻烦。

要明确:     1)一点光     2)所有对象都是漫反射的     3)所有物体都是球体,甚至是墙壁(它们非常大)     4)没有MIS加权

光发射是3D矢量。球体的BRDF是3D矢量。硬编码。

在下面的主要功能中,我生成EyePath和LightPath,然后连接它们。至少我试试。

在这篇文章中,我将讨论主要功能,然后是EyePath,然后是LightPath。一旦EyePath和Light很好,就会出现关于连接功能的讨论。

  1. 第一个问题:
    • 第一个亮点的产生是否良好?
    • 我是否需要根据光源的发射来计算这一点?还是只是排放?在我填充顶点结构的地方注释了该行。
    • 我需要翻译来自光明吗?为了把它放在球体上
  2. 以下代码在main函数中进行采样。在它上面有两个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();
     }
    

    目前我得到了这个结果。

    enter image description here

    一旦EyePath和LightPath很好,连接功能就会出现。

    谢谢大家

1 个答案:

答案 0 :(得分:0)

尝试本文中提到的球形参考场景。我想你可以自己解决大部分问题,因为它有分析解决方案。

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

首先,您可以节省时间来实现和验证您对路径追踪和灯光追踪的理解,然后尝试将它们与权重相结合。