【问题标题】:Optimizing a Ray Tracer优化光线追踪器
【发布时间】:2015-02-05 12:11:50
【问题描述】:

我的任务是优化以下光线追踪器:

void Scene::RayTrace() 
{

    for (int v = 0; v < fb->h; v++)  // all vertical pixels in framebuffer
    {
        calculateFPS(); // calculates the current fps and prints it

        for (int u = 0; u < fb->w; u++) // all horizontal pixels in framebuffer
        {

            fb->Set(u, v, 0xFFAAAAAA); // background color
            fb->SetZ(u, v, FLT_MAX);  // sets the Z values to all be maximum at beginning
            V3 ray = (ppc->c + ppc->a*((float)u + .5f) + ppc->b*((float)v + .5f)).UnitVector(); // gets the camera ray

            for (int tmi = 0; tmi < tmeshesN; tmi++)  // iterates over all triangle meshes
            {
                if (!tmeshes[tmi]->enabled) // doesn't render a tmesh if it's not set to be enabled
                    continue;
                for (int tri = 0; tri < tmeshes[tmi]->trisN; tri++) // iterates over all triangles in the mesh
                {
                    V3 Vs[3]; // triangle vertices
                    Vs[0] = tmeshes[tmi]->verts[tmeshes[tmi]->tris[3 * tri + 0]];
                    Vs[1] = tmeshes[tmi]->verts[tmeshes[tmi]->tris[3 * tri + 1]];
                    Vs[2] = tmeshes[tmi]->verts[tmeshes[tmi]->tris[3 * tri + 2]];
                    V3 bgt = ppc->C.IntersectRayWithTriangleWithThisOrigin(ray, Vs); // I don't entirely understand what this does

                    if (bgt[2] < 0.0f || bgt[0] < 0.0f || bgt[1] < 0.0f || bgt[0] + bgt[1] > 1.0f) 
                        continue;
                    if (fb->zb[(fb->h - 1 - v)*fb->w + u] < bgt[2])
                        continue;

                    fb->SetZ(u, v, bgt[2]);
                    float alpha = 1.0f - bgt[0] - bgt[1];
                    float beta = bgt[0];
                    float gamma = bgt[1];
                    V3 Cs[3]; // triangle vertex colors
                    Cs[0] = tmeshes[tmi]->cols[tmeshes[tmi]->tris[3 * tri + 0]];
                    Cs[1] = tmeshes[tmi]->cols[tmeshes[tmi]->tris[3 * tri + 1]];
                    Cs[2] = tmeshes[tmi]->cols[tmeshes[tmi]->tris[3 * tri + 2]];
                    V3 color = Cs[0] * alpha + Cs[1] * beta + Cs[2] * gamma;
                    fb->Set(u, v, color.GetColor()); // sets this pixel accordingly

                }

            }


        }
        fb->redraw();
        Fl::check();
    }

}

两件事:

  1. 我不完全理解ppc-&gt;C.IntersectRayWithTriangleWithThisOrigin(ray, Vs); 的作用。任何人都可以从光线追踪的角度向我解释这一点吗?这是我的“平面针孔相机”类中的函数(这个函数是给我的):

    V3 V3::IntersectRayWithTriangleWithThisOrigin(V3 r, V3 Vs[3]) 
    {
    
        M33 m; // 3X3 matrix class
        m.SetColumn(0, Vs[1] - Vs[0]);
        m.SetColumn(1, Vs[2] - Vs[0]);
        m.SetColumn(2, r*-1.0f);
        V3 ret; // Vector3 class
        V3 &C = *this;
        ret = m.Inverse() * (C - Vs[0]);
        return ret;
    
    }
    

基本步骤很明显,我只是看不出它实际上在做什么

  1. 我将如何从这里优化这个光线追踪器?我在网上找到了一些关于“kd 树”的东西,但我不确定它们有多复杂。有没有人有一些关于优化这个的简单解决方案的好资源?我在破译外面的东西时遇到了一些困难。

谢谢!

【问题讨论】:

  • 由于某种原因,我无法让第二个函数正确地“代码块”。对此感到抱歉。
  • 似乎您需要对列表内的代码块进行两级缩进。否则对于一般格式帮助 html cmets &lt;!-- --&gt; 总是作为中断工作。 (对于分隔两个紧随其后的代码块很有用。
  • 关于该函数的用途,您将获得的最佳答案可能是询问您正在为其优化此代码的人。就我个人而言,如果他们没有做任何文档记录,我不会用 10 英尺长的杆子触碰别人的代码,尤其是在像光线追踪器这样复杂的程序中。
  • 问题是这是我们大学的最后一个项目,教授写了代码。至于通过电子邮件向他寻求帮助……通常会遇到“弄清楚”。虽然我相信这个函数可能与计算从眼睛到当前三角形的光线有关?
  • 啊,大学。如果您的教授要在现实世界的工作中提供这种混乱,他的同事会当场谋杀他。无论如何是的,它似乎是射线/三角形碰撞检测代码。

标签: c++ optimization graphics rendering raytracing


【解决方案1】:

到目前为止,最大的优化可能是使用某种bounding volume hierarchy。现在,代码将所有光线与所有对象的所有三角形相交。使用 BVH,我们会问:“给定这条射线,哪些三角形相交?”这意味着对于每条光线,您通常只需要测试与少数图元和三角形的交集,而不是场景中的每个三角形。

【讨论】:

  • 您认为解决方案有多复杂?正如我正在阅读的那样,它似乎只是对象周围的一个边界框。我的场景只有一个对象,所以我认为这很容易?
  • 这种结构的实现难度与场景的复杂程度无关。我建议使用octree 以方便实施,尽管k-d trees 如果实施得当,性能往往会更好。
  • 我想我当时有点困惑。如果我错了,请纠正我,但似乎 BVH 基本上在每个对象周围放置了一个 2D 边界框,然后将其插入到八叉树(或 k-d 树)中。如果只有一个对象,八叉树/k-d树不是不必要的吗?
  • 插入 BVH 的原语是 三角形,而不是对象。所以它是场景中三角形的层次细分。
  • 嗯。那你能详细解释一下吗?看来我只能找到将整个对象存储在树中的引用,例如:3dmuve.com/3dmblog/?p=182
【解决方案2】:
  1. IntersectRayWithTriangleWithThisOrigin

    • 从外观上看
    • 它从三角形边创建逆变换矩阵(三角形基向量为 X,Y)
    • 没有得到 Z 轴,我希望那里的光线方向而不是像素的位置(光线原点)
    • 但可能会误解某些内容
    • 反正逆矩阵计算是最大的问题
    • 您正在为每个像素的每个三角形计算它很多
    • 在光线追踪(一次)之前计算每个三角形的逆变换矩阵会更快
    • 其中 X、Y 是基础,Z 垂直于它们的展位,始终朝向相机的同一方向
    • 然后将你的光线转换成它并检查相交的限制
    • 这只是matrix*vector 和少数ifs,而不是逆矩阵计算
    • 另一种方法是代数求解射线与平面的交点
    • 这应该会导致比矩阵求逆更简单的方程
    • 之后就是基向量边界检查的一个主题

【讨论】:

  • 这真的很有帮助,谢谢! “没有得到 Z 轴,我希望那里的光线方向而不是像素的位置(光线原点)”是什么意思?以及你将如何只进行一次逆矩阵计算?它需要不同的光线,如上面这一行所示:V3 ray = (ppc-&gt;c + ppc-&gt;a*((float)u + .5f) + ppc-&gt;b*((float)v + .5f)).UnitVector();
  • @Jestus 现在您的 Z 轴由 r*-1.0f 设置,如果您使用相对于三角形而不是相对于三角形的矩阵,这对我来说毫无意义(这很可能是某种代数方法的结果) ray 那么矩阵对于所有光线都是恒定的(Z轴是正常的)。但是您需要添加结果计算,因为这样的逆矩阵只是从世界坐标转换为三角形。所以只需计算 z=0 的 x,y 值(均在三角形坐标中)并检查 x,y 是否在内部
猜你喜欢
  • 2020-07-28
  • 2018-11-19
  • 2021-04-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多