光线追踪算法的实现

    为了演示光线追踪是如何运行的,现在要编写一个光线追踪算法,来说明其工作原理。

    在我们身边有无数的光线,只有那些进入我们眼睛,并且在视网膜投下像的光线才能被我们看到。因此,我们人眼对光线的追踪是非常自然的事情,因为只要看到光人类的眼睛就能自然而然地顺着光线的来源进行光线追踪。

光线追踪算法的实现_第1张图片

图A:在光线追踪算法中,会通过像素中心发射一条主光线,然后检查是否与对象相交,当其与对象相交时,再投射一条阴影光线,进而确定该点是否被照亮。

    光线追踪算法利用像素构成图像,对于构成图像的每一个像素,该算法都会向场景中发射出一条主光线。主光线的方向由眼睛到像素的中心线来确定,当设置好主光线的方向后,就可以检查场景中的每一个对象,看这些对象是否与主光线相交。在一些情况下,主光线会与多个对象相交,此时将从交叉点向光源发射阴影光线。如果该光线在到达光源过程中没有与对象相交,则判定照亮相交点,如果与对象相交,则会判定为阴影。

    光线追踪算法的实现_第2张图片

图B:小球在大球上方,阴影光线在到达光源之前与小球体相交,因此判定为阴影。

   

光线追踪算法的实现_第3张图片

图C:为了渲染一个帧,需要为帧缓冲区的每个像素拍摄一个主光线。

    如果对每个像素都重复上述操作,则会获得三维物体的二维表示。

以下是该算法的伪代码:

for (int j = 0; j < imageHeight; ++j) { 
    for (int i = 0; i < imageWidth; ++i) { 
        // compute primary ray direction
        Ray primRay; 
        computePrimRay(i, j, &primRay); 
        // shoot prim ray in the scene and search for intersection
        Point pHit; 
        Normal nHit; 
        float minDist = INFINITY; 
        Object object = NULL; 
        for (int k = 0; k < objects.size(); ++k) { 
            if (Intersect(objects[k], primRay, &pHit, &nHit)) { 
                float distance = Distance(eyePosition, pHit); 
                if (distance < minDistance) { 
                    object = objects[k]; 
                    minDistance = distance; // update min distance 
                } 
            } 
        } 
        if (object != NULL) { 
            // compute illumination
            Ray shadowRay; 
            shadowRay.direction = lightPosition - pHit; 
            bool isShadow = false; 
            for (int k = 0; k < objects.size(); ++k) { 
                if (Intersect(objects[k], shadowRay)) { 
                    isInShadow = true; 
                    break; 
                } 
            } 
        } 
        if (!isInShadow) 
            pixels[i][j] = object->color * light.brightness; 
        else 
            pixels[i][j] = 0; 
    } 
} 

    由此可见,光线追踪其明显优点在于只需少量代码便可实现,相比于其他算法光线追踪更加容易实现。

    光线追踪算法最早由Arthur Appel在1969年发表的论文《Some Techniques for Shading Machine Renderings of Solids》中提出,但时至今日该算法依旧没能取代其他渲染算法,主要原因也在当年的论文中有所提及,引用Arthur Appel原话:“光线追踪算法非常耗时,一般来说想产生有效计算结果所需时间是一般算法绘图所需时间的几千倍,其中有超过一半时间用来确定投影和场景的点对点关系。”

    同时,计算机图形学的先驱Jim Kajiya说过:“ray tracing is not slow - computers are”“光线追踪不慢—慢的是计算机”。

    总而言之,渲染的过程可以看做是两个独立的进程,一是确定某一个点在特定的像素位置是否可见,第二是对该点进行着色。但非常不幸的是这两个步骤都需要消耗大量宝贵的时间进行光线与几何物体之间的相交判定。虽然光线追踪算法非常强大,却不得不消耗大量时间来换取图像的准确性。自从Arthur Appel发表论文以来,无数的人做了大量研究来想办法加快光线与物体间的判定算法,时至今日大量改进的算法使光线追踪变得更容易。

你可能感兴趣的:(算法)