TLDR: three.js is amazing, go to http://codercat.club/photospheres.html and play.
However, once I started pushing some of my projects online, this black box seemed to be presenting itself to me more frequently. I don’t particularly enjoy having black boxes in my development processes. The need to begin was there, but motivation was still missing…
I had fantasies of being a 3D graphics programmer at some point, and played around with openGL in C++, but shortly lost enthusiasm as the learning curve was so high. It took me a few days to even get my code to compile and render the well known teapot in a window.
ThreeJS, on the other hand, has fantastic documentation and an example page that has a number of demo’s of what you can do with the library. Copy and paste the source code into your own HTML and voila, you have a working rainbow rotating cube with lighting in like 30 seconds! This fueled my motivation and I was excited to finally have a user-friendly interface to explore the world of 3D programming.
The home page is a hub of inspiration, with links to real applications made with three.js.
Diving into photospheres.
There’s a thing called an equirectangular photo, and it looks like this:
The equirectangular photo is exactly 2x wide as it is tall and suitable for spherical projections. The horizontal coordinate is longitude, and the vertical coordinate is latitude. All verticals remain vertical, and the horizon becomes a straight line across the middle of the image.
My first step was to find a way to take my own equirectangular photos.
Google street view maps equirectangular photos onto spheres, and puts you inside, allowing you to get a 360 view of a location. I downloaded the Google street view app, and was excited to see that they allow you to generate your own equirectangular photo without a 360 camera! The process includes taking a series of photos at a location, which are stitched together by the app to form the resulting 360 image.
I highly recommend trying this, it’s really fun.
Creating the photosphere.
I started this project by simply adding one sphere to the scene with an equirectangular photo mesh material, and built in orbitControls. Three.js has an amazing module called orbitControls that essentially enables high level camera controls from user mouse input, supporting controls such as orbit, pan, and zoom. This would have taken weeks with openGL.
I wanted to be able to enter the sphere, so I implemented my own camera zoom function that moves the camera along the z-axis until it reaches the center of the sphere. I also added a function to synchronously change the opacity of the sphere to create a fade in and fade out effect, enhancing the sphere entering experience (lol).
One photosphere was not enough!
This was cool, but then I had the idea of making the page a sort of portfolio of photospheres. This would require major refactoring. I suddenly needed arrays of rotating spheres. I would also have to abandon the convenient OrbitControls module, because the camera now needed to do much more than rotate around one sphere.
Controlling the camera.
I started by having millions of booleans determining the state of camera movement, but this got messy very fast (what if the user clicks to zoom in and clicks next before the zooming in is finished??).
Instead, I created my own Camera Controller class holding 5 different states. The Camera Controller would update on each render call, and move the camera if a state had been triggerred. I modeled a state for
- Zoom into current sphere
- Zoom out of current
- Move to the next sphere
- Reset to the first sphere
- Control opacity of spheres during transition
Much more maintainable.
(the wireframes represent the mysterious sphere that is ahead of you)
ThreeJS also provides a Stats DOM which allows you to see the rendering speed of your application, measured in frames per second. I noticed that the fps was very low around 6 fps on Safari, but 60 fps on Chrome.
I tried making the code more efficient by loading all photos when opening the browser, and only applying the photo mesh onto the sphere that is currently in view. Also, tried using slightly lower resolution images.
This made a difference, but nothing significant..
Turns out I was using the canvasRenderer instead of the webGLRenderer…. and this made all the difference.
Just the beginning.
Currently, the 360 photos included are from random adventures around the city, taken with a RICOH Theta 360 Camera. There is a small description and link to location included as well.
I hope to develop the photosphere idea into more of a storytelling project, where the user can flip through spheres into immersive scenes that together will tell a narrative.
Basically taking a picture book to a 3D experience.
I was also thinking of doing a 360 photoshoot with a model, because having a subject in the sphere will create a more emotional dynamic scene.
It would also be cool to illustrate scenes from poems… But yeah, hit me up if you have any feedback or ideas~
You can view the project online @ http://codercat.club/photospheres.html
And the source code @ https://github.com/sneha-belkhale/photospheres-threejs