While The Straits Times Digital Graphics Team has experimented with several 3D projects before, many of our past works featured scrollytelling scenes rendered as videos, which we then loaded on scroll.
However, for this project where we explained tips on how to maximise small spaces, we turned to WebGL (Web Graphics Library) – a technology that allows web browsers to render interactive 2D and 3D graphics directly on a webpage. This approach enables smoother interaction and dynamic rendering without the need to preload large video files, making the experience more lightweight and responsive across different screen sizes.
The 3D scene was built with assets modelled in-house using Blender, a free 3D program, supplemented by free stock furniture models that we customised to suit our needs. The animated 3D scenes were then exported in GLB format and embedded into the webpage.
While the sequences have different requirements, they all included one key step: ‘baking’ image textures.
In 3D graphics, the most common method to create a sense of materiality is by wrapping an image over the object.
An image texture could just be the base colour of an object. For example: adding stripes to a zebra. However, we can also pre-render additional details onto the same image, usually to overcome performance or aesthetic limitations.
This technique is known as “texture baking”. For this project, we “baked” lighting information to the 3D objects, so that we don’t have to rely on web-based, real-time lighting solutions, which could not accurately reflect real-life lighting.
Real-time lighting
Baked lighting
Bringing 3D Scenes to the web
Rendering 3D content in a browser is made straightforward with Three.js, a JavaScript library for displaying 3D graphics. Once we finalise the 3D assets, they are exported as GLB files. Then, we load them into the browser for further control and interactivity through Three.js.
Scrollytelling with 3D Scene
For scrollytelling, the GLB file must include camera animation data, with the camera configured to move and focus on different views within a defined duration. For objects that require animation (for example shelves and bed), the duration of the animation must be the same as the camera animation data to ensure synchronisation.
Without further manipulation, playing the camera animation on the web can feel much like watching a video play forward. To complete the scrollytelling experience, we convert the user’s scroll position into a value range between 0 and 100 per cent, this value is then mapped to the camera animation’s timeline, allowing the user to move through the animation in real time as they scroll.
Next, we break down how each sequence was built, showing how choices in lighting, texture baking and object animation came together to shape the look and feel of the final 3D scenes.
Sequence 1:
Introduction
The first sequence was the most straightforward. We set up the scene with sunlight coming in from the windows and some indoor lights, baked the lighting influence into the base colour in Cycles, a built-in rendering engine in Blender, and then cleaned up the textures in Photoshop.
Sequence 2:
Maximising storage
Using baked lighting works well when objects are static. However, for the second sequence, we had a lot of moving animation. In this case, picking a lighting scenario with a high level of directionality as we did with the previous sequence will not work as well.
Therefore, for this scene, we baked the lighting for each furniture separately while simulating a global illumination set-up (where lights are coming from all directions), making the lack of change in lighting when things are moving less obvious.
The method we used involved baking an ambient occlusion map, which we then combined with the base colour in Photoshop using the “multiply” blend mode.
Sequence 3:
Lighting
For the third sequence, we wanted to show the effects of some common home lighting set-ups.
While transitioning from one diffuse map (base colour image) with baked lighting influence to another could work in a purely linear sequence (lighting set-up A to B to C), we wanted to include an interactive function to allow readers to turn on and off light fixtures in different combinations. This presented some problems with the method as the different lights could not interact with one another in this case.
To solve this problem, we used a base colour map without baked lighting influence, a combination of what’s called a “light map” for the primary light sources, as well as some real-time lights added in code for the smaller accent lights.
Lighting Demo
In real-time lighting, the lighting is computed on the fly, shadows and shading are simplified, it is a trade-off between responsiveness and accurate simulation of how light interacts with surfaces.
Baked lighting, on the other hand, takes time to simulate how light bounces and diffuses across surfaces, resulting in more realistic shading.
See how different lighting set-ups can create noticeably different results.
Optimisation
During testing, we noticed a slow initial loading of the files, especially on iOS, which was unsurprising given the amount of 3D content featured on the page. To improve performance, we focused on two areas: optimising how assets are prepared and loading the page progressively as users scroll.
Optimising 3D assets
The preparation of 3D assets generally follows two principles: using texture variants optimised for different platforms and reducing 3D model complexity.
Multiple GLB versions are prepared with different texture resolutions, and only one is loaded at runtime based on the reader’s screen size and platform. Smaller screens and mobile devices are assigned lower-resolution versions.
As for the 3D model’s complexity, we were able to reduce it with the help of Blender’s Decimate modifier, which simplifies meshes while maintaining acceptable visual quality through side-by-side comparison.
Optimise lightmap HDR files
Among all 3D-related assets, lightmap HDR files have the largest file sizes and high resolutions. The high resolution is necessary to preserve lighting details across the 3D interior. A single 4K HDR file can be about 25MB, which slows loading and consumes enough memory to cause crashes on some iOS devices.
These issues are addressed with two approaches. Loading time is reduced by compressing HDR files using gainmap-js, which compresses the file size into 10 per cent of the original. Memory related crashes are mitigated by preparing smaller resolution lightmaps at 3K for desktop, 2K for tablet, and 1K for mobile devices.
Progressive loading of page sections
Instead of loading all sections upfront, the page progressively loads content as the user advances. This approach ensures content becomes available to viewers as quickly as possible. Each of the two types of 3D sections, scrollytelling and interactive, has its own trigger to load the next chunk of content.
As we explore new ways of telling stories, finding the balance between creative expression and technical feasibility remains an ongoing challenge to the team. Each project brings us a step closer to refining that balance, with the shared goal of telling stories that not only inform but also immerse readers in the worlds we build.
Read the interactive here.