1
votes

So I decided to write a ray tracer the other day, but I got stuck because I forgot all my vector math. I've got a point behind the screen (the eye/camera, 400,300,-1000) and then a point on the screen (a plane, from 0,0,0 to 800,600,0), which I'm getting just by using the x and y values of the current pixel I'm looking for (using SFML for rendering, so it's something like 267,409,0)

Problem is, I have no idea how to cast the ray correctly. I'm using this for testing sphere intersection(C++):

bool SphereCheck(Ray& ray, Sphere& sphere, float& t)
{ //operator * between 2 vec3s is a dot product
    Vec3 dist = ray.start - sphere.pos; //both vec3s
    float B =  -1 * (ray.dir * dist);
    float D = B*B - dist * dist + sphere.radius * sphere.radius; //radius is float
    if(D < 0.0f)
        return false;
    float t0 = B - sqrtf(D);
    float t1 = B + sqrtf(D);
    bool ret = false;
    if((t0 > 0.1f) && (t0 < t))
    {
        t = t0;
        ret = true;
    }
    if((t1 > 0.1f) && (t1 < t))
    {
        t = t1;
        ret = true;
    }
    return ret;
}

So I get that the start of the ray would be the eye position, but what is the direction?

Or, failing that, is there a better way of doing this? I've heard of some people using the ray start as (x, y, -1000) and the direction as (0,0,1) but I don't know how that would work.

On a side note, how would you do transformations? I'm assuming that to change the camera angle you just adjust the x and y of the camera (or the screen if you need a drastic change)

3
I think that's what it should be, but I forgot everything I know about vector math, so I'm not quite sure.Chris
Basically what I'm trying to say is, how should I cast the ray, because I think I might be doing it wrong.Chris
@Chris: like Nocturn said, you cast the ray from the eye through the pixel. The direction is given by subtracting one point from the other.R. Martinho Fernandes
I think my code might be wrong for calculating intersections, can anyone check it? (It's in the original post)Chris

3 Answers

1
votes

The parameter "ray" in the function,

bool SphereCheck(Ray& ray, Sphere& sphere, float& t)
{
    ...
}

should already contain the direction information and with this direction you need to check if the ray intersects the sphere or not. (The incoming "ray" parameter is the vector between the camera point and the pixel the ray is sent.)

Therefore the local "dist" variable seems obsolete.

0
votes

One thing I can see is that when you create your rays you are not using the center of each pixel in the screen as the point for building the direction vector. You do not want to use just the (x, y) coordinates on the grid for building those vectors.

I've taken a look at your sample code and the calculation is indeed incorrect. This is what you want.

http://www.csee.umbc.edu/~olano/435f02/ray-sphere.html (I took this course in college, this guy knows his stuff)

Essentially it means you have this ray, which has an origin and direction. You have a sphere with a point and a radius. You use the ray equation and plug it into the sphere equation and solve for t. That t is the distance between the ray origin and the intersection point on the spheres surface. I do not think your code does this.

0
votes

So I get that the start of the ray would be the eye position, but what is the direction?

You have camera defined by vectors front, up, and right (perpendicular to each other and normalized) and "position" (eye position).

You also have width and height of viewport (pixels), vertical field of view (vfov) and horizontal field of view (hfov) in degrees or radians.

There are also 2D x and y coordinates of pixel. X axis (2D) points to the right, Y axis (2D) points down.

For a flat screen ray can be calculated like this:

startVector = eyePos;
endVector = startVector 
    + front
    + right * tan(hfov/2) * (((x + 0.5)/width)*2.0 - 1.0)
    + up * tan(vfov/2) * (1.0 - ((y + 0.5f)/height)*2.0);

rayStart = startVector;
rayDir = normalize(endVector - startVector);

That assumes that screen plane is flat. For extreme field of view angles (fov >= 180 degreess) you might want to make screen plane spherical, and use different formulas.

how would you do transformations

Matrices.