Raycasting -- fisheye distortion?

Started by
16 comments, last by Eelco 19 years, 6 months ago
Alrighty. My raycaster has been coming along nicely, but I'm getting the evil fisheye distortion. I've heard mentionings of a sine or cosine correction, but I can't seem to find exactly what it is and how to apply it. I know it has something todo with applying a value to the distance of each ray, but that's it. Anyone care to shed some light on this for me? Thanks!
Advertisement
i guess your method of creating rays is borked.

the simplest way imho:

just create rays in the x-y plane in a rectangular grid.

transform them by your camera transform matrix.

normalize them if it has any relevance on the workings of your raytracer.

cant go wrong really.
If you have some artifacts that other renderers(OpenGL) don't have, it's mean, you just need to cast rays correctly. So, how to fix depends to how you currently do things.
If you assume screen is cylindric(so horisontal ray angle=x*a+b) or hemispherical, or something, you need to swich to assuming that screen is flat.
edit:as Eelco said.
Quote:Original post by Eelco
i guess your method of creating rays is borked.

the simplest way imho:

just create rays in the x-y plane in a rectangular grid.

transform them by your camera transform matrix.

normalize them if it has any relevance on the workings of your raytracer.

cant go wrong really.


I've got no matrices, no normals, nothing fancy like that. A good old fashioned raycaster, not raytracer. And how is my method of creating rays "borked"? I'm firing out rays that go out until they hit a solid block, and using the distance. I understand why the fisheye distortion is caused, but I don't know how to fix it.

Quote:If you assume screen is cylindric(so horisontal ray angle=x*a+b) or hemispherical, or something, you need to swich to assuming that screen is flat.


How do I switch to assuming that the screen is flat? I'm not using OpenGL or any library, just classic 2.5D.
Quote:Original post by HopeDagger
I've got no matrices, no normals, nothing fancy like that. A good old fashioned raycaster, not raytracer. And how is my method of creating rays "borked"? I'm firing out rays that go out until they hit a solid block, and using the distance. I understand why the fisheye distortion is caused, but I don't know how to fix it.

ah sorry my bad.

i know what youre doing wrong then.
your rays shouldnt be equally spaced in such a way that they have constant variation in angle, but so that they have a constant variation in distance in the line your projecting upon.

that ast bit is probably confusing, so lets add some code.

i guess what youre doing right now looks like this:

for (angle = -fov/2;angle<fov/2; angle+=deltangle){ rayx = cos(camangle+angle); rayy = sin(camangle+angle);}


what you should do is something along the lines of:
//construct a simple transformation matrixxx = cos(camangle); yx = sin(camangle);xy = -xy;        yy = xx;for (x = -screenwidth/2; x<screenwidth/2; x++){ //create rays in local coordinates tmprayx = x; tmprayy = screenwidth/2; //for a fov of 90 //transform them to worldcoordinates rayx = tmprayx * xx + tmprayy * yx; rayy = tmprayx * xy + tmprayy * yy; //normalize the ray if you want to.}
I appreciate your effort, but is there a way to do this without matrices? My math skills aren't top-notch, so I'm looking for a way to fix the fisheye in a way that I'd understand. :/
there is a way without matrices: that is, the same method with another interpretation. in effect youll be doing the same calculations though.

ill give a shot at explaining this same piece of code in other words, but learning about vectors, matrices and transforms and stuff is really usefull!

is suppose you understand the part where tmpray is constructed? is simply a fan of rays with the endpoints at regular intervals (as opposed to regular angles). it consists of an x and y component, with y being forward, and x being sideways (for no particular reason, just a convention i picked).

cos(angle), sin(angle) is the forward direction vector your camera is pointing towards. (basic trig right?)
-sin(angle), cos(angle) is the vector peripendicular to that, you can see it as a 'strafe' vector.

now we want the ouput ray to extend tmpray.y along this forward vector, and tmpray.x along the strafe vector. so we say:

ray = forward * tmpray.y + strafe * tmpray.x

if you write out the components of the vector 'ray' you get:

ray.x = forward.x * tmpray.y + strafe.x * tmpray.x
ray.y = forward.y * tmpray.y + strafe.y * tmpray.x

voila, the same thing!

(actually, its not 100% the same, but if you look closely youll notice its nothing more than some reversed signs that are not really important: simply reverse until it produces the desired behavior. thats what i always do is such situations anyway :P...)
I've heard of other methods mentioned in the past, like cosine/sine correction. It sounds much simpler. ;) Anyone got any info on that? :/
i can imagine what its about. instead of choosing a constant angle, vary it to correct the distortion.

however, i admit not being that good at explaining things, yet someone with the intention of writing a raytracer should really be able to understand the above, the most advanced piece of math in entrails is the unit circle and a bit of vector addition and multiplication.

i could derive this correction, but i dont feel like bothering, since if you dont (or dont even try to?) understand the above its highly unlikely youll be able to follow this.
Oh...just check

http://www.permadi.com/tutorial/raycast/index.html and
http://www.student.kuleuven.ac.be/~m0216922/CG/ and
http://www.sbdev.pwp.blueyonder.co.uk/ray.htm (explain the problem about fisheye distortion)

Hope this can help
Bruno B

This topic is closed to new replies.

Advertisement