h1

Boost your raytracer

June 5, 2008

You can speed up a bit (6-10% maybe) your current raytracer by changing simple linear pixel rendering order into hilbert curve (in that case data are more coherent and there are less cache misses). I did not believe that until I try it.

Hilbert curves

Here is my Hilbert curve class (drop me a line if you find it usefull):


#ifndef HILBERT_H_
#define HILBERT_H_

class Hilbert
{
public:
    Hilbert(int dx,int dy)
    {
        nXDim  = dx;
        nYDim  = dy;
        int m  = dx>dy ? dx : dy;
        int nOrder = 1;
        while ((1<<nOrder)<m) nOrder++;        

        pPointsX = new int[dx*dy];
        pPointsY = new int[dx*dy];
        nX = 0;
        nY = 0;
        nPoints = 0;

        hilbert(nOrder, NORTH, EAST, SOUTH, WEST);
    }

    ~Hilbert()
    {
        if (pPointsX) delete []pPointsX;  pPointsX = NULL;
        if (pPointsY) delete []pPointsY;  pPointsY = NULL;
    }

    int *GetX() { return pPointsX; }
    int *GetY() { return pPointsY; }
    int Count() { return nPoints;  }

private:
    int nXDim,nYDim;

    int *pPointsX;
    int *pPointsY;
    int  nPoints;

    int curvesize(int ord) {    return (1<<ord) - 1;    }

    static const int NORTH=0, EAST=1, SOUTH=2, WEST=3;
    int nX,nY;

    void move(int d)
    {
        // Move one unit in direction d from point lastpoint.
        switch (d)
        {
          case NORTH: nY--;  break;
          case EAST:  nX++;  break;
          case SOUTH: nY++;  break;
          case WEST:  nX--;  break;
        }
    }

    void hilbert (int i,      // order of Hilbert curve to be drawn
                  int front,  // direction at front
                  int right,  // direction at right
                  int behind, // direction at back
                  int left)   // direction at left
    {
        if (i == 0)
        {
            if (nX<nXDim && nY<nYDim) // cut to image only
            {
                pPointsX[nPoints  ] = nX;
                pPointsY[nPoints++] = nY;
            }
        }
          else
        {
          hilbert(i-1, left , behind, right , front );    move(right );
          hilbert(i-1, front, right , behind, left  );    move(behind);
          hilbert(i-1, front, right , behind, left  );    move(left  );
          hilbert(i-1, right, front , left  , behind);
        }
    }
};

#endif

There are a lot of changes in the project I will write more about it soon, lightcuts works great,
some new images generated (including our new kitchen visualization designed by my wife):

Leave a Comment

You must be logged in to post a comment.