go to: [part 3 ][home]


Implementing Ray Tracing on GPU
Part 2


Calculating Primary Rays


Calulating primary rays can be easily mapped to a fragment/pixel shader: for each pixel a ray is calculated. If the ray hits the axis aligned bounding box (AABB) of the scene then it will be used for further processing, otherwise the pixel is “rejected” from further processing using early Z-culling.

Uniform Variables

vec3    _upvec;     // camera: up-vector
vec3    _right;     // camera: vector to the right 
vec3    _tl;        // camera: vector to the "virtual screen" top left 
float   _pixelsize; // pixel size of the "virtual screen"
vec3    g1,g2;      // Axis Aligned Bounding Box (AABB) of the scene
float   psize;      // Size of a pixel in texture coordinates  (i.e. 1/256 for a 256x256 image)
vec3    camera_pos; // camera position

Function: calculate primary ray for current pixel position:
vec3 raydir(vec2 pixelpos)
{ 
   vec3 direction = _tl + _right*(_pixelsize/2.0) - _upvec*(_pixelsize/2.0);
   direction = direction + _right*(pixelpos.x*_pixelsize) - _upvec*(pixelpos.y*_pixelsize);
   
   return direction;
}

For every pixel calculate corresponding ray. There are 2 cases:

pixel2 create_primary_rays( PixelShaderInput IN )
{
pixel2 OUT;

Ray r;
vec3 hit = vec3(0,0,0);
float tmin, tmax;

r.startpoint = camera_pos;

// In Pixel Shader 3.0 (HLSL) it is possible to use the
//
position register to get the screen coordinate directly.
#ifdef USE_PS_3
r.direction = raydir(IN.screencoord.xy);
#else
// In PixelShader 2.0 and GLSL the pixel position is calculated
// using the texture coordinate.

r.direction = raydir(IN.texCoord.xy / psize);
#endif

OUT.color0 = vec4(r.direction.x,r.direction.y,r.direction.z,1);

// test is camera is withing AABB, in this case start point = camera position
if (inbox(r.startpoint, g1,g2))
{
   hit = r.startpoint;
}
else
{
   if (hitbox(r, g1,g2, tmin, tmax)) // test if ray hits AABB
   
{
     if (tmin <=0) // tmin must be > 0, or the hit is on wrong side
     {
        OUT.color0 = vec4(1,1,1,10.5);  // set reject flag: w=10.5

     }
     else
     {
        hit = r.startpoint + (tmin+_EPSILON_)*r.direction; // calculate hit point
     }
   }
   else
   {
      // Ray doesn't hit AABB: Set reject flag: w=10.5

      OUT.color0 = vec4(1,1,1,10.5);
   }
}
OUT.color1 = vec4(hit,-0.5);

return OUT;
}


go to: [part 3 ][home]