In order to draw anything, we need to calculate the ray
based on the camera position and the current x, y
coordinate we currently on.
In ray tracing, a viewport
is a flat screen or window through which your camera looks at a 3D scene. Its where a 3D scene gets projected onto a 2D plane.
We will use the camera FOV
thats provided to calculate the following:
- Viewport height
- Viewport width
- Viewport vectors
- Lower left corner vector
- Camera direction
Some things to note:
- The
ray.origin
will always be the camera coordinates
ray.direction
will always depend which pixel coordinate we sending the ray to.
Calculations
Viewport height
![Image](https://private-user-images.githubusercontent.com/79513076/293456274-09b311fd-52d2-421c-9b04-e6af24b9513e.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjQwMDc1MjksIm5iZiI6MTcyNDAwNzIyOSwicGF0aCI6Ii83OTUxMzA3Ni8yOTM0NTYyNzQtMDliMzExZmQtNTJkMi00MjFjLTliMDQtZTZhZjI0Yjk1MTNlLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA4MTglMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwODE4VDE4NTM0OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWYwOWQxNzY1Zjg4ZTkwYzkxMDMzNDE1M2M1N2Q4M2RjZGI2NDIyYTA5ZDNkZGIwOTdlN2NiNzcyOWYwM2FhODgmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.FkoSrM3Yt1J9q4FKZdAO6TD5jTxAnSLtOHLM2_g8jd0)
This is directly calculated by the FOV
Here, FOV * (pi / 180)
converts the FOV from degrees to radians, since tan
functions requires radians to work properly.
Why do we do tan(FOV / 2)
?
It gives the ratio of half the viewports height to the distance from the camera.
Why do we multiply by 2?
After finding the tangent of half the FOV, we multiply by 2 to get the full viewport height.
Viewport width
![Image](https://private-user-images.githubusercontent.com/79513076/293457529-d9457f17-0ed0-4049-9a18-711552dd3b48.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjQwMDc1MjksIm5iZiI6MTcyNDAwNzIyOSwicGF0aCI6Ii83OTUxMzA3Ni8yOTM0NTc1MjktZDk0NTdmMTctMGVkMC00MDQ5LTlhMTgtNzExNTUyZGQzYjQ4LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA4MTglMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwODE4VDE4NTM0OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTNlMzk0MWZjMWY3NzE1NWEwNmFlOTVjODdiNTQyY2Y2MGI5ZTA1NmNhYzAyNTI0NzI2ZjE5MDlhZjY3MDQ0NDEmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.pck4JHA1T2Xby0jucyLyVZndr1XsWHuH_46qnNIPD6s)
Since we already have the height of the viewport we can simply scale the width according to the aspect ratio.
Camera direction
viewport.camera_direction = normalize_vector(scene->camera.or_vect);
Here we can just normalize the camera direction (adjust the length of the vector to 1
while keeping its direction the same). We do this for calculations involving directions.
Here is how we would normalize a given vector:
-
Take a given vector:
![Image](https://private-user-images.githubusercontent.com/79513076/293460065-3d06b5c2-ad49-4c1b-a29d-35370367c5f7.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjQwMDc1MjksIm5iZiI6MTcyNDAwNzIyOSwicGF0aCI6Ii83OTUxMzA3Ni8yOTM0NjAwNjUtM2QwNmI1YzItYWQ0OS00YzFiLWEyOWQtMzUzNzAzNjdjNWY3LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA4MTglMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwODE4VDE4NTM0OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTJhNTY5ODViZjJjZGQ1MmY3YTIwMzI0ZWM1NGFiNWM1YTgzNTZjNjJhZWNhNGIxN2M2ZmMxM2Q4ZmVjZDY5NGQmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.e3xDt91b6b8b_m8dgx-Pl0etiwN1UuNiWwM63agi6BI)
-
Calculate the length of V
above using:
![Image](https://private-user-images.githubusercontent.com/79513076/293460051-82afdfe5-4c42-4b83-aa38-0f218ecfa374.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjQwMDc1MjksIm5iZiI6MTcyNDAwNzIyOSwicGF0aCI6Ii83OTUxMzA3Ni8yOTM0NjAwNTEtODJhZmRmZTUtNGM0Mi00YjgzLWFhMzgtMGYyMThlY2ZhMzc0LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA4MTglMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwODE4VDE4NTM0OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWFjM2I0NTJiY2MyY2RiYjkzZDk2YTI3YjVlZTQyZmQ5ZjM5MzdmNGQwZmZmMjFiMjNmZjBkM2I5NjIxNjM3M2QmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.NPYywv4aIcj8nQo5pzsiKizcVg8QLLBvUcpecspPWKw)
-
Divide each vector element by the length which will give us the normalized vector:
![Image](https://private-user-images.githubusercontent.com/79513076/293460191-a9af3c53-67fc-414a-b8ff-41abc330f2ba.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjQwMDc1MjksIm5iZiI6MTcyNDAwNzIyOSwicGF0aCI6Ii83OTUxMzA3Ni8yOTM0NjAxOTEtYTlhZjNjNTMtNjdmYy00MTRhLWI4ZmYtNDFhYmMzMzBmMmJhLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA4MTglMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwODE4VDE4NTM0OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWEyOTY5YzY3Y2E3ZDU4NDJlZjcwMzljODc3MmMzZDMzNGRiYzdhMGE3ZmZmYjVlZDk0NGFkNzBjNGJhMzAzOTEmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.fpKTQSIHrzQijBzB6yWm36r-G2SsKzbXMgL0O7enUC8)
Viewports position
No need for calculation here, we already have everything we need, We can just store it for later calculations.
viewport.horizontal = (t_vector){vp_width, 0, 0};
viewport.vertical = (t_vector){0, vp_height, 0};
Lower left corner calculation:
This calculation gets the bottom left position of the viewport. We start at the camera position and move back and to the left based on viewport size and camera direction. We need this variable to generate rays correctly/
We can use the following formula:
- L = Lower left corner of the viewport
- C = Camera position vector
- H = Horizontal vector
- V = Vertical vector
- D = Camera direction vector
![Image](https://private-user-images.githubusercontent.com/79513076/293684973-4599f4ef-dd25-4e50-9bd6-24e54bf7a345.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjQwMDc1MjksIm5iZiI6MTcyNDAwNzIyOSwicGF0aCI6Ii83OTUxMzA3Ni8yOTM2ODQ5NzMtNDU5OWY0ZWYtZGQyNS00ZTUwLTliZDYtMjRlNTRiZjdhMzQ1LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA4MTglMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwODE4VDE4NTM0OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTAxMmU0ZDQwNmEyN2IzNmUzZmIyMGNjZjQ2YzU4NDI3MDJhZDk0MmZiZDViOTI1NmExMWI3MzNiZjQyOWM5MTYmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.XUpcGfHU49c4H5QBeji3bMk1NKpCYqdndLJV1wsa85o)
In Code:
viewport.lower_left_corner = vec_subtract(
vec_subtract(
vec_subtract(scene->camera.cords, vec_divide(viewport.horizontal, (t_vector){2, 2, 2})),
vec_divide(viewport.vertical, (t_vector){2, 2, 2})),
viewport.camera_direction);