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.
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.
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.
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.
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.)
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);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With