   Ray Tracer: Generating Rays
  Hello, I have learned that given a point x,y,z in 3D I can find its corresponding 2D point by this math:x' = (d*x)/zy' = (d*y)/zz' = 0this makes sense. However, I'm not sure how I can implement this in my ray tracer. Currently I have a camera positioned at (0,0,0) and an image plane with size 800x800. At each iteration a ray is assigned origin (400,400,0), which is the middle of the screen, and the direction is the difference between the current image plane's pixel location and the origin. Here is an image that describes my technique:http://www.devmaster.net/articles/raytracing_series/part1.2.jpgHowever, I think there is a better way I can determine the ray's direction by using the theory I stated earlier in the post. Is there?Thank You.   
  I'm not sure I understand what you mean, but it seems to me that you want to project your scene in a plane.If you do that, you're not doing ray tracing anymore, you're just simulating what your hardware does, using software. You cannot project reflections, refractions or shadows this way, because they don't have vertices, and this effects are the point in ray tracing.The subtraction is good enough.   ;  I'm simply asking how to do perspective projection. I have a camera that generates rays but I don't know how to properly calculate the ray's direction.   ;  Not sure if this one is correct ... but I used it some time ago for ray tracing. (Hope that I'm not posting some buggy version :-/)// about variables - screenWidth and screenHeight should be clear// M_PI is approximately 3.14159265358979424 (ah... you know that of course)// FOV is angle of view (in degrees here), often 45 or 60 degrees// rayD are directions of rays (x, y and z are components - 3 component vectorsfloat halfWidth = (float)screenWidth / 2.0f;float halfHeight = (float)screenHeight / 2.0f;// Perform some triangle math here ... we need to compute our Zfloat planeDistance = halfWidth / (float)tan(M_PI * (180.0f - (FOV / 2.0f)) / 180.0f);// and now lets just calculate directions, must be normalized!for(int i = 0; i < screenWidth; i++){for(int j = 0; j < screenHeight; j++){rayD.x = (<span class="cpp-keyword">float</span>)i - halfWidth;<br>rayD.y = (<span class="cpp-keyword">float</span>)j - halfHeight;<br>rayD.z = planeDistance;<br><br>rayD.normalize();<br>}<br>}<br><br><br></pre></div><!–ENDSCRIPT–> ;Quote:Original post by subfloodCurrently I have a camera positioned at (0,0,0) and an image plane with size 800x800. At each iteration a ray is assigned origin (400,400,0), which is the middle of the screen, and the direction is the difference between the current image plane's pixel location and the origin. The eye is the origin.  A ray starts at the eye and passes through a point on the image plane this is how you know the direction of the ray. Note the image plane shouldn't be co planar with the eye. Say you have the eye at 0,0,0 then the image plane could be z = 1 and x\y from -400 to 400.   ;  Vilem Otte and stonemetal, what you describe is what I'm doing. However, when I render the image the spheres are somewhat distorted. In the image below the bottom right sphere seems distorted, just like in my ray tracer:I figured that maybe this is normal but other images such as the one below don't seem to suffer from this problem: ;  Don't use your formula to project from scene space into screen space, that's rasterisation, and it kinda defeats the purpose of doing raytracing in the first place.Looking at the two images you posted, I can see that in the smaller one the little diffuse-only circle in the bottom left is slightly squished.The second image you posted has a much smaller view angle, so it is hard to say whether or not the circles are distorted because the distortions would be too small to notice anyway. Try reducing the view angle for your scene.;  This is my camera class:class QLCamera{protected:std::string name;unsigned int samplesPP;public:QLCamera() : name("No Name (QLCamera)"), samplesPP(1) {}QLCamera(const std::string &n) : name(n), samplesPP(1) {}virtual ~QLCamera() {}//Accessorsvoid SetSamplesPerPixel(unsigned int samples) {samplesPP = samples;}unsigned int GetSamplesPerPixel() const{return samplesPP;}virtual void PreProcess() {}virtual void SetTransformation(const matrix4<real> &toWorld) { }//Samples coordinates range [0-1[ for x and [0-(aspect ratio)[ for y//Some camera may also accept coordinates outside this range, but this is not guaranteedvirtual const ray<vector4<real>> GenerateRay(const vector2<real> &sample, real time = real(0)) const = 0;};/*The following class defines a very simple pinhole camera. The samples are all taken on the focus plane, so that no DOF can be generated.*/class QLPinholeCamera : public QLCamera{protected:matrix4<real> cameraToWorld, worldToCamera;real horizontalHAngle;real verticalHAngle;real aspectRatio;real viewPlaneW;real viewPlaneH;vector4<real> position;vector4<real> direction;real nearPlane; //nearPlane and farPlane are distances from the positionreal farPlane;public:QLPinholeCamera(const matrix4<real> &toWorld, real hFov, real aRatio, real nearP = real(0), real farP = Q_INF) : QLCamera("No Name (Pinhole Camera)") {SetTransformation(toWorld);Init(hFov, aRatio, nearP, farP);}QLPinholeCamera(const std::string &name, const matrix4<real> &toWorld, real hFov, real aRatio, real nearP = real(0), real farP = Q_INF) : QLCamera(name) {SetTransformation(toWorld);Init(hFov, aRatio, nearP, farP);}//Accessorsvoid SetHorizontalFov(real fov){horizontalHAngle = fov / real(2);verticalHAngle = horizontalHAngle / aspectRatio;viewPlaneW = tan(horizontalHAngle) * real(2);viewPlaneH = tan(verticalHAngle) * real(2);}real GetHorizontalFov() const { return horizontalHAngle * real(2); }const vector4<real> GetPosition() const { return position; }const vector4<real> GetDirection() const { return direction; }//Interface implementationvoid SetTransformation(const matrix4<real> &toWorld){cameraToWorld = toWorld;worldToCamera = toWorld.Inverse();position = toWorld * vector4<real>(real(0), real(0), real(0), vector4<real>::POINT);direction = toWorld * vector4<real>(real(0), real(0), real(-1), vector4<real>::VECTOR);}const ray<vector4<real>> GenerateRay(const vector2<real> &sample, real time = real(0)) const{vector4<real> dir((sample.x - real(0.5)) * viewPlaneW, (sample.y - real(0.5)) * viewPlaneH, real(-1), vector4<real>::VECTOR);dir.Normalize();vector4<real> o = vector4<real>(real(0), real(0), -nearPlane, vector4<real>::POINT);return ray<vector4<real>>(cameraToWorld * o, cameraToWorld * dir, farPlane, real(1), time);}protected:void Init(real hFov, real aRatio, real nearP, real farP){aspectRatio = aRatio;nearPlane = nearP;farPlane = farP;SetHorizontalFov(hFov);}};What I do is generating rays in camera space and the transforming them with the camera to world transformation matrix. To generate the directions I use a few informations about the view plane (width and height calculated with the FOV) and then construct a ray using (p - cameraPosition).Normalize();In my case, camera position is always (0,0,0) because I use the matrix to move the ray in world space.The effect you are refering is intrinsic in ray generation: the view plane where you sample the points is planar, and this leads to equally spaced points. But if you 'look' from the camera POV, then they are no longer equally distant because the distance between them and the ray origin is not constant.The strenght of this effects is related to the size of the view plane, wich in turn is bound to the FOV. In your second image the fov is really small (like you used a zoom lens) so this effect is unnoticeable.I don't know if sampling a curved viewplane instead than a planar one can resolve this, but usually this is how things work (also photographs exibhit sometimes this effect, expecially when using older devices).Keep your FOV relatively small (60 degrees, for example).   ;  Ok, I changed the field of view to a much smaller value and now the image looks a lot less distorted.Here is a screenshot of my ray traced image, still in the early stages:Thanks you all for helping.   ;  Maybe what you want is orthographic projection; see here