Implemeting alpha blending:
In order to display object file, I first needed to load object data in the program. So I wrote some code to load a wavefront(3D object file) file and store its vertex and triangle indices in a buffer.
I implemented the triangle rasterization algorithm, and wrote a function that could render a 2D triangle between any given 3 points.
When I used this function to render the faces, the object was was rendered with only single color and the curves on the surfaces were not apparent.
I decided to add light effects to make it more realistic. By using dot product between normal of each triangle and the difference between the position of the light source and the position of each triangle, I made an equation to calculate the brightness of each triangle.
I also implemented back-face culling to eliminate rendering triangles that face away from the camera. The images below are the result I got.
In the first picture above, there are some triangles that are rendered in the wrong order. To solve this problem I decided to sort each triangle based on their distance to the camera. I knew that it would not be accurately sort triangles since when they intersected, this method would fail. But I tried this method anyway to see that it wouldn’t work. Then I implemented the depth-buffering (z-buffering) technique which consists of recording the distance of each rendered pixel from the camera in a separate depth-buffer ,and using this buffer to only render the pixels that are closest to the camera. I implemented this and the result was magnificent without any error.
In the next step, I worked on rendering a perfect sphere without loading a sphere object. In the image below, the program calculates the normal vector at each pixel of the ball, and applies light calculations to determine the brightness of each pixel inside the ball. The light source is below the camera in this example, so the part of the ball that faces the light source is brighter.
Finally, I did lots of optimizations and the FPS rate tripled. I also tried tried using multi-threading by rendering triangles in separate threads. That increased the fps significantly, in fact it was so hard to debug, so I kept the program running at a single thread which was fast enough. It was always so easy to switch to multi-threading, so I decided to keep working using a single thread.
Used the dynamic Gerstner 3D ocean wave model to generate a dynamic ocean wave.
The program calculates the slope of the wave at the position of the boat by using 3 points that define a surface that are displayed in the video. Then it rotates the boat using the slope value.
Although this method worked well, it was not realistic enough; so I decided to change the program so that it could approximate the actual bouyant force vector, and use the result to keep the boat above the water level.
Calculating the Bouyant Force
To calculate the bouyant force, a triangle mesh data structure with greedy search was used for fast triangle intersection detection. Then the bouyant force was approximated by calculating the submerge distance of each triangle on the mesh boat.
Masking the water inside the boat:
One problem in the scene above is that the water was leaking inside the boat. I was expecting this problem since I programmed the rendering engine to only render the parts of each triangle that are closest to the camera.
To solve this problem, I drew a 3D mesh that exactly matched with the top of the boat and covered its top.
Instead of rendering this mesh as a 3D object, I changed the program to use this mesh to mask out the water pixels that are inside the boat. I got some pretty nice results:
I played with the with the parameters such as wave speed, inertia vectors , force multipliers ,and damping constants and got the following result:
- 3D rotational dynamics (3D rotational Inertia, 3D torque, 3D angular momentum)
- 3D transformation
- Triangles rasterization
- Painters algorithm as a partial solution for the visibility problem
- Z-buffering / depth buffering using ray-tracing
- Quaternion numbers for 3D rotation
- Gerstner Ocean wave simulation model
- Bouyant Force Approximation Technique
- 3D Simulation by using Euler’s method
- Importing Wavefront 3D object files
- Rendering a perfect sphere