0
\$\begingroup\$

I've come here because I can't seem to find out what's wrong with my ray tracer.

I fixed the fish eye effect when looking straight on at walls, but the effect remains when the player is looking at walls to the side.

I think it's because most of the rays hit the surface close to the player, while fewer and fewer rays hit more distant walls, resulting in a curve. The only problem is I don't know how to make it appear linear.

    float dist = distance*cos(angle); //fix distorted distance
    float rat = (depth-(dis))/depth; //calculate ratio for wall height
    float h = 64*rat; //calculate height
    PImage slice = sprites[0].get((int)(inter/2),0,1,16); //get image slice
    image(slice,i*4,768-h/2,4,h); //display image slice

In this example, the top screen is the raw data while the bottom screen it the ray traced 2.5D image. I've made the rays visible.

Edit: I changes "rat" to be 192/dis. This seems to look a bit better, but is still slightly curved...

enter image description here

\$\endgroup\$
1
\$\begingroup\$

It appears to me that you're having a problem because you're not doing any ray tracing, you are trying to simplify the "all purpose calculation" into a "specific" calculation that can hit vertical walls.

First, obtaining a 3d ray direction should not come from an angle; but from the vector that links the current iterated pixel to the camera.

find a ray direction

After that, evaluating the closest intersection hit, per ray, should loop on all the scene objects, calculate all distances and keep the smallest one (with the associated object hit at that smallest distance.) to be able to shade it.

The hit in your case seems to be a plane equation with 2 vertical limits (ground and up).
So you need to solve ax+by+cz=-d with (abc) the normal vector of the wall, and d its smallest distance to the world's origin. Together as a system of 2 equations, the other one being your ray, expressed as ray=t*direction for t that makes it so that point-on-wall = camera + t * direction

That solution involves a division indeed, which you already sensed as necessary.
Here is what you need: https://nerdparadise.com/math/lineintersectsaplane (or that)
Presented as: solution of ray and place hit For code, Trillian's answer will do: https://stackoverflow.com/a/23976134/893406

For your case you can replace some 3d components by knowns, like your walls will always have 0 in y. If they are always aligned to the axis, they will always have either 0 or 1 in x or z. That creates 2 types of solutions, one solution for x aligned walls, and one solution for z aligned walls. (or you can keep the generic version for diagonal walls)

| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ Hello, I believe I accidently wrote "ray tracer" instead of "ray caster". I'm looking to reproduce the effect from Wolfenstein 3D. \$\endgroup\$ – benneyHacker May 25 at 11:36
  • \$\begingroup\$ @benneyHacker don't miss the forest for the trees. The core insight that you should fire your ray through each pixel (column) on your screen, not at evenly-spaced angles, solves the Wolfenstein version too. \$\endgroup\$ – DMGregory May 25 at 11:52
  • \$\begingroup\$ @ DMGregory I'll try this out, thanks for the insight! \$\endgroup\$ – benneyHacker May 25 at 11:55
  • \$\begingroup\$ So I replaced the evenly spaced angles with a series of pre-calculated pixel and camera angles... I'm not sure if this is what you meant, but it seems to be working a lot better now! \$\endgroup\$ – benneyHacker May 25 at 12:34
  • 1
    \$\begingroup\$ Ah I suspected it from the look, lol. Yeah ray cast will share the cost of one trace, for an entire pixel column. \$\endgroup\$ – v.oddou May 25 at 13:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.