Reputation: 189
I am implementing a basic ray tracer so I am reading up on theory and other implementations. Here is the code that I am currently referring to
template<typename T>
void render(const std::vector<Sphere<T> *> &spheres)
{
int width = 800, height = 800;//define width and height of the screen
Vector3d<T> *image = new Vector3d<T>[width * height], *pixel = image;
T invWidth = 1 / T(width), invHeight = 1 / T(height);
T fov = 90, aspectratio = width / T(height);//defining field of view angle and aspect ratio
T fovDist = tan(M_PI * 0.5 * fov / T(180));//Calculates half screen width / perpendicular distance to the camer
a position
// For each ray crossing a pixel on the view screen.
for (int y = 0; y < height; ++y) //For each scan line
{
for (int x = 0; x < width; ++x, ++pixel) //for each pixel on a scan line
{
//Calculate the x position using centre of the pixel.
/*By simple trig (width/2)/perpendicular distance to camera = tan (fov/2)
=>width = distance * tan (fov/2)
*/
T xx = (2 * ((x + 0.5) * invWidth) - 1) * fovDist * aspectratio;
T yy = (1 - 2 * ((y + 0.5) * invHeight)) * fovDist;//Calculate the y position
Vector3d<T> raydir(xx, yy, -1);
raydir.normalize();
*pixel = trace(Vector3d<T>(0), raydir, spheres, 0);
}
}
I am putting in comments of what I understand but I am stuck on the calculation of xx and yy.
I understand that by simple trigonometry width = 2 * (perpendicular distance from camera to the view plane) * tan (fov / 2). But I am not able to figure out the expression for T xx and T yy.
Please can someone help clarify.
Regards, Moira
Upvotes: 1
Views: 3386
Reputation: 9967
Ok, so if I understand this, you've got your frame parallel to the XY plane, and sitting at Z=-1, with your camera/eye at the origin. Now you're trying to find the X and Y location of the center of each pixel. Is that right?
So x + 0.5
offsets you to the center of the current pixel, that's good. Dividing by the total number of pixels across gives you the percentage of the way across the frame: good. Multiply by two, then subtract one and you're in the range -1 to 1, which corresponds to 100% of the way from center to the left, and 100% of the way from the center to the right, respectively (or vice-versa). Now multiply by half the width (fovDist), so it puts you somewhere between one-half width to the left, and one-half width to the right. So that's all good. Lastly, you multiply by the aspect ratio because fovDist is really half the height, not necc. half the width. So if you have an aspect ratio of 2:1, it should be wider than it is tall, so you want to spread your pixels out horizontally, so you're all good there, too.
You've got yy set up the same way, except inverted because scanlines usually go the other way. So that looks fine, as well.
So does it work and you're just trying to understand it? Or is it not working correctly? If it's not working correctly, what kind of behavior are you seeing instead?
If it's not working correctly, the only thing that jumps out at me is all of the different numeric types. For instance your invWidth
and invHeight
variables both divide integer 1 by something. I can't remember how C++ handles this, but it's possible that you're getting truncated to 0 here by integer division. Similarly you've got a lot of integers in your expressions for xx and yy. Not sure if the compiler will work it out alright, but if it's not working correctly, I'd start there.
Upvotes: 1