Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A few questions about ray tracing with opengl

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.

like image 420
user467526 Avatar asked Jul 26 '11 20:07

user467526


People also ask

Will OpenGL support ray tracing?

OpenGL currently does not support hardware boosted Ray tracing. DirectX 12 on windows does have support for it. It is recommended to wait a few more years before creating a Ray tracing only renderer although it is possible using DirectX 12 with current desktop and laptop hardware.


3 Answers

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.

like image 142
Paul Sonier Avatar answered Oct 03 '22 19:10

Paul Sonier


  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.)

like image 27
phantasmagoria Avatar answered Oct 03 '22 19:10

phantasmagoria


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);
    }
}
like image 30
Rabbid76 Avatar answered Oct 03 '22 18:10

Rabbid76