Tuesday, October 13, 2015

CGI Sphere

Over my fall break (which lasted 1 day), I wrote a JavaScript program that would render a sphere. I thought it would be a fun way to practice math and programming skills simultaneously. As usual, I used my FireTools.js library to help with graphics as well as some other functions.

To render the sphere, I wanted to take every pixel on the screen, and calculate the color of the pixel. The color would vary depending on which part of the sphere the pixel was displaying. If the part of the sphere was facing the light source, it would need to be brighter than a part of the sphere facing away from the light source.

To find the brightness of each point on the surface, I first calculated the XYZ coordinates of that part of the sphere. This is also equal to the normal vector at that point. I took the dot product between the light source's direction and the normal vector. This is a mathematical operation that tells me whether the surface is aligned with the light source, as well as the percentage of the light that is being received at that point on the surface. From this, I could easily calculate the brightness of the sphere's surface.

After anti-aliasing the edges of the sphere, I moved to the next step. I wanted to use Perlin noise to give the sphere some texture. I had already written a program that could generate 2-dimensional Perlin noise, so I just upgraded that to 3-dimensional (so I could generate noise based on the coordinates of the sphere's surface).

Finally, I made the light source change direction, and then set up a system to allow the user to look at the sphere from different angles. And then I was done. I think it turned out pretty well.

Here it is (click and drag the mouse to change the orientation):

New posts every month - subscribe for free!


  1. Is it like the ones you made on KA all that time ago?

    ( https://www.khanacademy.org/computer-programming/rotating-gas-giant-3d/5363614714167296 )

    1. This one is actually very different. The ones on KA didn't use 3D cloud mapping - I faked that with 2D Perlin noise. Also, for this program, I used a way to render the sphere much faster at a higher resolution, with the dot product instead of inverse trig functions. Another big difference is that I wrote the whole thing independently, with my FireTools library.