Lighting is one of the most important tools for making 3D scenes feel believable. A simple model can look convincing with well-designed lighting, while a high-resolution asset can appear flat without it. In web-based 3D this is no different, but lighting comes with a big caveat, a possibly big hit to performance.
Every extra light and reflection typically translates into additional calculations in shaders, so understanding how lighting is implemented helps developers decide where to spend the performance budget.
Types of Lights
Most real time engines for the web support several types of lights. Directional lights, point lights, spot lights and ambient lights among others. Directional lights represent the most common light source – the sun, with light rays moving parallel to one another. They are often used to define a main light direction for outdoor scenes. Point lights emit light equally in all directions starting from a single point, similar to a light bulb. Spot lights on the other hand emit light in the form of a cone, similar to stage lights. Ambient lights emit lights evenly everywhere, providing a base level of brightness so that shadows are not 100% black. Additionally there are HDRI maps that can be used to simulate real lighting scenarios without the use of a single “physical” light. HDRI maps are most important for reflections and physically based rendering.
How do Lights light?
Lights are implemented in shaders as mathematical models. The vertex or fragment shader takes the light positions, directions and colors, combines them with surface normals and material properties, and computes a lighting contribution at each pixel. For directional lights, this often involves a simple dot product between the light direction and the surface normal. Point and spot lights add distance-based falloff, which are more expensive on performance because of the additional equations. Environment lighting relies on a preprocessed environment texture, which is more costly that a single directional light but can dramatically increase realism.
To add shadows, the renderer needs to determine which parts of the scene are blocked from the light. The most common real-time technique is shadow mapping. In a shadow map pass, the scene is rendered from the light’s point of view into a depth texture, which stores how far each visible point is from the light. Then this map is transformed into the light’s coordinate space and compared do the depth value. If the fragment is farther away then the stored depth, it is considered occluded and rendered in shadow. This technique is widely used in WebGL and other real time APIs as it works with any geometry and doesn’t require a special kind of processing.
For global illumination, many modern engines use Image-Based Lighting (IBL). IBL relies on environment maps (HDRI) that represent the lighting of a full 360 degree environment. For web development, these HDR maps are often converted into specular and diffuse textures that can be applied to the environment to provide both reflections and indirect light.
Because lighting affects performance so much, many real-time pipelines use a mix of baked and dynamic techniques. Baked lighting is a precomputed light interaction that is stored in lightmap textures. These lightmaps are then sampled at runtime, with shaders performing minimal calculations. Dynamic lighting on the other hand, is computed every frame and is necessary for moving objects or lights. A common strategy is to use baked lightmaps for static indirect light and large-scale ambient effects while reserving the performance heavy real-time shadows for characters, moving props or user-driven interactions. Baked lightmaps consume some texture memory but almost no runtime completion, making them a good fit for low end devices such as mobile.
Good lighting design for the web starts with restraint. Often, a single directional light with shadows and an environment map can provide enough richness for product visualization. More complex setups should be justified by clear visual needs, such as interactive environments or game-like experiences. When targeting a wide range of devices, it is wise to provide different lighting tiers depending on the available hardware.
SOURCES
1: https://webglfundamentals.org/webgl/lessons/webgl-shadows.html
2: https://sbcode.net/threejs/environment-maps/
3: https://dev.to/joseph7f/tutorial-building-a-simple-pbr-scene-with-shadows-and-fps-controls-in-threejs-19oj
4: https://star.global/posts/introduction-to-webgl/
5: https://www.chinedufn.com/webgl-shadow-mapping-tutorial/
6: https://pingpoli.de/sparrow-9-shadows
7: https://docs.godotengine.org/en/stable/tutorials/3d/global_illumination/using_lightmap_gi.html