Screenshot of dynamic overshadowing app

Figure 1: A screenshot of the Dynamic Overshadowing app running inside a web browser.

Launch app in new tab...

The aim of this app was to investigate the possibility of generating real-time interactive shading masks using WebGL and JavaScript. A shading mask is simply a map of which parts of the sky dome are visible from a particular point and which are obstructed by opaque objects in and around a site. This is very useful information as it affects daylighting, solar incidence and photovoltaic collection, as well as shading and overshadowing.

The other key aim of this app was to see if I could implement dynamic sky luminance mapping at the same time. The degree of shading at any point is usually quantified based on the percentage of the sky that is occluded. However, this is not really that informative as the luminous distribution over the sky dome is typically quite uneven and can vary significantly over even short time periods. With this app, I can now experiment with a range of different sky conditions, based on the 16 CIE General Standard Sky types, and begin to quantify shading based on the percentage of actual sky luminance that is occluded.

From here, the next steps are to add dynamic time-varying skies based on real weather data and the ability to aggregate luminance and/or radiance over time to look at quantifying seasonal and annual shading effects.

Why a Simple Block Model

Actually you can import any type of 3D model as an OBJ file. The app only starts out with simple rectilinear blocks as a way of illustrating the process and providing an interactive site that you can play around with. To load a 3D model, use either the button that looks like a building or drag/drop the OBJ file anywhere in the app window.

Screenshot of a detailed 3d shading model

Figure 2: An example of a more complex 3D shading model loaded from an OBJ file.

With large and complex models, the app automatically detects when a calculation is taking too long to be interactive and will try to degrade appropriately. For example, if the detailed shading takes longer than 200ms to complete, it will try to use a simpler method to maintain the dynamic feedback. If the simpler method takes longer than 200ms, it will stop trying to dynamically update until you finish dragging and release the pointer. Sometimes the browser or system might be busy with something else when you drag, causing it to temporarily stop dynamic updates even on a relatively simple model. However, as soon as the calculations return back to speed, the dynamic update will resume automatically.


I started out using pretty straightforward ray-tracing for occlusion testing, which is pretty flexible and allows it to work with any type of triangulated geometry. Whilst there is some scope for optimising both the model and the intersection testing techniques used, and maybe WebGL2 or WebGPU could assist in the future, at this stage it seems unlikely that such an approach will be fast enough for highly dynamic feedback on anything other than the simplest of sites.

However, by simplifying the obstructions to just rectilinear boxes, it can run in very close to real-time - try it out for yourself. Using highly optimised axially-aligned bounding box intersections works astoundingly well, even with several hundred boxes and on a reasonably good phone or tablet.

This is particularly interesting as it suggests that the voxelisation of complex models into tiny rectilinear cells might just be the way forward, allowing for real-time dynamic shading calculations on geometry of any complexity. Why this is interesting is because many fluid dynamics calculation engines require a similar approach to complex geometry. Perhaps there is some synergy there to be exploited.

It turns out that the real bottleneck in terms of speed is dynamically updating the SVG sky segments in the 2D Sun-path chart. You can see this for yourself by choosing a small angle for the sky subdivision (say 2 degrees), closing the SHADING MASK overlay by clicking on its title bar (it ignore update requests when closed), and then dragging the 3D Sun-path around the site. After a second or so, the updating should become significantly faster and smoother (it takes the JavaScript compiler time to re-adjust its run-time optimisations). I will look into this further, but it may be that I have to use WebGL for the 2D chart as well.

Interesting Features

Apart from the actual shading, the first potentially interesting feature of this app is the ability to select and interactively manipulate the obstruction blocks and the shading mask.

To change the size of any block, simply click/tap on any of its bounding surfaces and then drag the appropriate arrow in the direction you want. To adjust the shading mask position, first click/tap on the small red dot at its center and then drag any of the manipulator arrows.

The circular manipulator in the center of a block allows you to change its position. When you position a block such that it is close to the face of another block, it will snap to a position which aligns with that face. By default, this only happens with other blocks that are physically near the block being manipulated. If you wish to snap to other blocks further away, make sure the toggle button with the picture of a magnet inside a globe is selected. Similarly, you can toggle center snapping on or off or even all snapping.

In additional to physically dragging things around, you can edit both the position and size of the currently selected block by clicking in the SELECTION: BLOCK overlay panel or the small button with a pencil in it. This will display the EDIT SELECTION panel, as shown in Figure 3.

Screenshot of the edit selection panel

Figure 3: Using the 'EDIT SELECTION' panel to numerically edit the size of the selected block.

Sky Luminance

You can use the Luminance tab in the SKY SETTINGS panel to select from a range of different sky distributions. These are all based on the CIE General Standard Sky types. As sky luminance values can vary a huge amount across different sky conditions, the value that is displayed is actually the luminance ratio between the zenith of the sky and each sky segment. Such a scale most clearly displays the nature of the distribution across the sky dome, if not its absolute value.

Screenshot of sky settings panel

Figure 4: Selecting the sky luminous distribution.

This means that the scale changes each time the sky changes. You can temporarily lock the scale by setting a value in the Luminance Ratio Scale section. The selected scale value will be retained across all subsequent date, time and location changes, but will reset if the sky type changes.

Show Obstruction Color

This feature makes the various shading relationships in the model immediately obvious and understandable. It basically colors each shaded segment based on the color of the object(s) that obstruct it.

Screenshot of model showing colored shading

Figure 5: Coloring shading regions based on the color of the obstructing object.

I added this feature because I have found this technique very useful in the past when explaining shading masks and how they relate to a particular site. Being able to isolate one or more parts of a 3D model in a different color makes the relationships much clearer.

Shading Rays

Another useful tool for checking a model or trying to understand a particular shading pattern is to actually see the shading rays used to detect obstruction. Only rays that actually hit something are displayed. Each ray terminates at the closest obstructing object.

Screenshot of shading rays within the model

Figure 6: The shading rays used to determine sky occlusion can be displayed in order to check a model and understand shading patterns.

If you turn on the Show Obstruction Color option, the arrow end of each ray will also be colored based on the object it intersected.

Change Log

0.0.6 2017-03-19

  • Fixed an issue where snapping was being performed on the center point of a block when its position was being dragged which seemed logical, but meant that the extents of blocks that were not some even multiple of the snap grid would never align with the ground grid. Snapping is now performed on the minimum position of the block in each axis which works much better.

  • Added a more descriptive dialog box for saving data within the app, containing a collapsible explanation as to why web pages can’t invoke the system File Save As dialog when saving a remotely generated file locally.

  • Proximate interactive snapping now hi-lights the aligned faces of the moving block as well as the aligned block.

  • Added keyboard shortcuts for toggling interactive snapping - ‘O’ for turning snapping on or off, ‘B’ for bounds snap, ‘C’ for center snap and ‘V’ for model-wide alignment snapping.

0.0.5 2017-03-15

  • Added an option to have the color of the shaded sky segment reflect the color of the obstructing object. This also applies to generated shading rays.

0.0.4 2017-03-07

  • Added ability to select one of the 16 CIE General Standard Sky types and map the resulting luminous distribution over the sky dome. I was able to get this fast enough for both the 2D chart and 3D diagram to update reasonably dynamically whenever you change the date, time or location.

  • Added a ‘View from Sun’ button to the projections within the ‘VIEW SETTINGS’ panel.

0.0.3 2017-03-01

  • Added interactive alignment snapping to the faces and centers of proximate blocks. This highlights the aligned face in red and the center line in orange.

  • Added a ‘Snap to All’ button that aligns with any block in the model, regardless of proximity. When snapped, highlights all aligned faces or centers across the whole model. Use the SHIFT key whilst dragging to temporarily toggle this option.

  • Added a position/size editor panel which you can display by clicking the selection information overlay.

  • Added ability to set imperial/metric units as well as the cursor snap value within the ‘Units’ tab of the position/size editor panel.

0.0.2 2017-02-20

  • Added a dynamic 2D Sun-path chart overlay that mirrors current shading.

  • Added ability to choose different sky subdivision methods and the subdivision angle. To display these options, click the 2D Sun-path chart or the ‘SKY SETTINGS’ button.

  • Added North Offset slider and a redesigned ‘SUN-PATH SETTINGS’ panel.

  • Fixed problem of some imported OBJ models not generating shadows.

0.0.1 2016-11-28

  • Initial release.

Click here to comment on this page.