7

I need to do a limited form of ray tracing. I do not need reflections. I only need to change the color of a pixel, depending on how it passes by an object, and refraction. I also only need to test for intersections between the ray and spheres and disks, nothing else.

This is the main function in my shader:

void main(void)
{
    Ray ray;
    ray.origin=vec3(0.5,0.5,.75);

    ray.direction=vec3(gl_FragCoord.x/width,gl_FragCoord.y/height,-gl_FragCoord.z)-ray.origin;
    ray.direction=normalize(ray.direction);

    gl_FragColor=trace(ray);
}

My first question is regarding the origin of the ray. How do I get its location? Right now, I just fiddle around until it looks right, but if I change the width or height of the screen I have to play around until it looks right.

My second question is about the intersection between a ray and a disk. I do this by first checking to see if the ray intersects a plane and then if the intersection point is within the radius of the disk. My code looks like this

float intersectPlane(Ray ray,vec3 point,vec3 normal)
{
    return dot(point-ray.origin,normal)/dot(ray.direction,normal);
}
...

det=intersectPlane(ray,bodies[count].position,vec3(0,0,1));
if(det>0)
{
        if(distance(det*ray.direction,bodies[count].position)<=bodies[count].radius) 
        {
            return vec4(1.0,0.0,0.0,1.0);
        }
}

The problem is that if bodies[count].radius is less than or equal to the z-position of the ray's origin then nothing shows up. So

if(det>0)
{
        if(distance(det*ray.direction,bodies[count].position)<=.76) 
        {
            return vec4(1.0,0.0,0.0,1.0);
        }
}

results in visible disks, while using the actual radius results in nothing.

Paul Sonier
  • 36,435
  • 3
  • 72
  • 113
user467526
  • 507
  • 3
  • 19

3 Answers3

3

As to your second question: don't use a distance, use a squared distance. It's faster processing, and I suspect it may solve your problem.

Paul Sonier
  • 36,435
  • 3
  • 72
  • 113
1
  1. Origin of the ray really depends on you however I recommend you to specify the origin point such that the pixel positions are approximately equidistant from the origin and the objects.

  2. Be careful about the direction of the ray meaning that the objects you are trying to see must be in front of the camera. (The rays that are sent must hit the objects.)

phantasmagoria
  • 319
  • 1
  • 5
1

The intersection point of a ray and a plane is calculated as follows:

dist = dot( plane_origin - ray.origin, plane_NV ) / dot( ray.direction, plane_NV );
plane_isect = ray.origin + ray.direction * dist;

Your function intersectPlane calculates the distance from the origin of the ray to the intersection point at the plane correctly, but you do not calculate the intersection point before you compare it to the center of the disks.

To test if the intersection point is within the radius you have to do the following:

vec3 plane_isect = ray.origin + det * ray.direction;
if ( distance( plane_isect, bodies[count].position ) <= bodies[count].radius ) 

Adapt your code like this:

det = intersectPlane( ray, bodies[count].position, vec3(0,0,1) );
if ( det>0 )
{
    vec3 plane_isect = ray.origin + det * ray.direction;
    if ( distance( plane_isect, bodies[count].position ) <= bodies[count].radius ) 
    {
        return vec4(1.0,0.0,0.0,1.0);
    }
}
Rabbid76
  • 142,694
  • 23
  • 71
  • 112