Blog Archives

How to create a volume light effect

To generate volume light, you must use a direct light source. 3ds Max standard directional lights work well – but you can also use V-Ray plane lights by increasing the directional parameter.

Start by adding a target directional light into your scene and position the light source and the target so that the light passes through the opening or window. The target must go beyond the floor or wall so that the volume light continues throughout. Avoid angling the direct light towards the camera otherwise you may end up with a washed out render due to the volume light covering the camera.

The volume light will be contained within the direct light’s hotspot beam and falloff field. If you set the falloff field to be much greater than the hotspot beam, the volume light will start to lose density quite rapidly and fade out the further it travels from the centre of the light. If you want an even distribution of light, it is best to keep the falloff field value close to the hotspot beam value.

Start by adding a target directional light into your scene

By default, 3ds Max standard lights do not have any attenuation applied, so the light has continuous luminosity. This is incorrect. Light should start to lose luminosity by dispersing the further it travels away from the source. Within the decay parameters, set the type to Inverse Square. If the light decays too fast, you can tweak this by adjusting the Start Parameter.

3ds Max standard light multipliers do not behave in the same way that V-Ray lights do. When using Inverse Square falloff, the multiplier must be set to a very high value in order to appear within the scene. A good value to start from is 800, as this roughly equals a standard V-Ray light. The multiplier is also affected by the start decay parameter. The lower the decay, the lower the multiplier needs to be. You may end up setting the light multiplier up in the thousands to get the correct illumination in accordance to the decay.

Under shadow parameters, turn on atmosphere shadows and area shadows. This softens them as the shadow moves further away from the casting object. Increasing the subdivisions here will also improve the shadow quality and reduce noise.

3ds Max standard light multipliers do not behave in the same way that V-Ray lights do

Go to Environment Effects and add a V-Ray Environment Fog to atmosphere effects. Under V-Ray Environment Fog nodes, add the Direct Light. Turn off Use All Lights so the volume light effect is only applied to the lights you choose.

In the general parameters, you can either set the fog colour here or within the Directional Light. You cannot mix the colours, so one must remain white to be inactive. The Fog Distance controls the length the volume light will travel along the direct light, so set this distance to be the light’s entire length.

The fog height also affects the visibility. Therefore this setting must cover the entire height of the light. If the light is positioned 9,000mm above the floor, then this must be your minimum value. A good way to determine the value is to draw a rectangle that covers the height and length of the scene.

In order to get the correct volume light effect, exclude objects so that only the volume light is visible

V-Ray Environment Fog is an atmospheric effect that is calculated during rendering using a brute- force method. Therefore it is important to optimise the settings so that the render times are not too high. The subdivisions parameter controls the noise level. Lower values produce more noise, whereas higher values produce less at the cost of longer render time. Start with a value of 16 and increase in increments of 8 until you are satisfied with the results. Usually 50 subdivisions are adequate, but you may need to go up to 100 depending on the scene.

If the scatter GI parameter is enabled, the volume light will scatter throughout your scene, via Global Illumination illuminating surrounding objects. In addition to just direct light, this will add further realism but it can render very slowly. You may find that after a certain value the results are the same; try setting this to 8 and then 16. If not, then a value of 8 would be adequate.


Create a JavaScript bar chart with D3

Scott Murray, author of Interactive Data Visualization for the Web, demonstrates how to visualise data using the browser-based tool D3.js.

D3 (Data-Driven Documents), also known as D3.js, is a powerful tool for creating data visualisation within the browser. It’s a JavaScript library that leverages web standards that you already know to create future-proofed interactive visualisations that don’t rely on browser plug-ins. Start by downloading the code and opening up 00_page_template.html in a current browser. (You may need to view pages served through a web server, for example http://localhost/.)

Selection and creation

The page template provides only a reference to D3. Notice that the ‘body’ of the page is empty.

Open up the JavaScript console, and type in your first line:“body”)

Everything in D3 begins with a selection. You select something first; then you can tell D3 what you want to do with it.

D3’s select() and selectAll() methods both use CSS selector syntax (just like jQuery), so you can quickly identify any DOM element or elements you like. select() selects only the first element found, while selectAll() returns all matching elements.

We’ve selected the body; now let’s add something to it:“body”).append(“p”)

append() creates a new element inside the end of whatever selection you give it. So here, we create a new p paragraph at the end of the body.

Let’s throw some text into that paragraph:“body”).append(“p”).text(“Hello, world!”)

Now you should see “Hello, world!” rendered in the browser.

Well, hello!

All your data are belong to arrays

Switch to 01_data.html for a refresher on storing data in JavaScript. The simplest storage is one value in a single variable:

var value = 5;

Arrays can store multiple values. In JavaScript, arrays are defined with hard brackets:

var arrayOfValues = [ 5, 6, 7, 8, 10, 12, 22 ];

D3 is supremely flexible about data — as long as it’s in an array. Within an array, mix and match as you please. Instead of single values (as above), you could use objects.

Objects store arbitrary key/value pairs, and are defined with curly brackets. Here’s an array of objects:

var arrayOfObjects = [
{ plant: “fern”, color: “green”, number: 23 },
{ plant: “rose”, color: “pink”, number: 7 },
{ plant: “dandelion”, color: “white”, number: 185 }

Binding data to elements

I’ll use a straightforward array as our data set:

var dataset = [90, 45, 29, 88, 72, 63, 51, 35, 26, 20];

And I’ll set up some variables for our chart’s dimensions:

var width = 500;
var height = 200;
var barHeight = 20;

This doesn’t look like much yet, but as you can see, we’ve created one rectangle for each value in the data set — 10 in all

The Scalable Vector Graphics image format is amazing because its code is markup, just like HTML.

This simple SVG image contains a square and a circle.

<svg width=”100″ height=”100″>
<rect x=”0″ y=”0″ width=”50″ height=”50″></rect>
<circle cx=”50″ cy=”50″ r=”25″></circle>

Styling SVG

Because SVG markup is HTML-compatible, all SVG elements will exist in the DOM.

As a result, they can be styled with CSS and manipulated dynamically with JavaScript.

I dare you to try that with JPGs!

Before we can draw anything, we have to create the SVG element inside which all the visual elements will reside:

var svg =“body”).append(“svg”)
.attr(“width”, width)
.attr(“height”, height);

This selects the body and appends a new svg element. Then we use D3’s attr() method to set width and height attributes.

The selection of the new SVG element is passed back into a new variable called svg.

Storing selections this way allows us to reference elements later without having to re-select them.

Finally, brace yourself for D3’s most mind-bending pattern:

.attr(“x”, 0)
.attr(“y”, 0)
.attr(“width”, width)
.attr(“height”, barHeight);

Ack, what is this? First, within the SVG element, we select all the rect elements. Of course, there are none yet, but we’re about to create them!

Next, we call data(), which binds our data set to the selection. This is the fundamental process of D3: driving documents with data by linking one data value to one element.

For multiple values, we need multiple elements — say, one circle for each number. In this case, since there are more data values than matching DOM elements, data() not only binds the data, but creates an enter selection which represents all the incoming elements that do not yet exist.


We use enter() to access the enter selection. Finally, append() fills each empty element with a new rect: these are the elements to which the data values are linked. Finally, several attr() statements set the properties of each new rect.

Open up 02_binding_data.html and inspect the DOM. We see there are 10 rectangles, but they’re all positioned on top of each other.

Here we’ve succeeded in creating a working horizontal bar chart, with 10 bars generated from 10 different data values

This is happening because we set the same x, y, width, and height values for each rect.

To prove that the data is now bound to elements, type d3.selectAll(“rect”) into the console. You’ll see an array of 10 SVG rect elements. Expand each one, and you’ll find a __data__ property, in which lives a data value!

The elements’ values are 90, 45, 29, and so on, just as specified in our original dataset array.

Setting attributes

Let’s rewrite the last four lines of the code above as:

.attr(“x”, 0)
.attr(“y”, function(d, i) {
return i * barHeight;
.attr(“width”, function(d) {
return d;
.attr(“height”, barHeight – 1);

All bars will be aligned along the left edge, so we can keep x at zero. But the y values must be spaced out to prevent overlap. To calculate dynamic values, we can specify an anonymous function instead of a static value.

Parameters Notice this function takes d and i as parameters, into which D3 will pass the current datum (the current value in the array) and its index position (0, 1, 2…). Although we don’t reference d yet, we must include it as a parameter so i is given the right value.

To get to grips with D3, check out Scott Murray’s forthcoming book Interactive Data Visualization for the Web, published by O’Reilly

Within this function, i * barHeight is calculated and returned as the y value, thereby pushing each successive rect further down the image.

For the width, we take d, the raw data value. And for height, we don’t need a function to calculate a dynamic value, since all bars will be the same height (barHeight – 1).

Now check out 03_setting_attributes.html!

Each bar gets a unique vertical position and a width that corresponds to the original array’s data value: a true visualisation!

Scaling data to pixels

This looks better, but the bars are too short. Our SVG is 500 pixels wide, yet the bars cover only a quarter of that.

Say hello to D3’s scales. Scales are customisable functions that map values from an input domain to an output range. We’ll use a scale to map values from the data’s domain (0 to 90) to pixel values (0 to 500).

To define our first scale:

var xScale = d3.scale.linear()
.domain([0, d3.max(dataset)])
.range([0, width]);

domain() takes an array with two values. The first value is the low end of the domain, while the second is the high values. d3.max() is a quick way to get the largest value from an array (90, in this case).

range() also takes as an array of two values, one low and one high. For us, these are pixel units, so we set them to zero and width.

One last thing: when setting each bar’s width, now we need to wrap d in our new scale function:

.attr(“width”, function(d) {
return xScale(d);

Brilliant! The data values have been mapped to visual pixel values, and therefore our bars now automatically scale to fit the image width.

In the screengrab above, the horizontal bars have been scaled to fit the width of the image

One step further

Taking this idea one step further, we can use an ordinal scale for the vertical axis.

This keeps our bars’ spacing and height flexible, so they can scale should our data set change in the future. Ordinal scales expect categories, not linear quantitative values, as input.

In this case, the ‘categories’ will be simply the position of each value in the data set: 0, 1, 2, and so on.

var yScale = d3.scale.ordinal()
.rangeRoundBands([0, height], 0.05);

d3.range() is a handy sequential integer generator, so the input domain here is set to [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], since dataset.length is 10.

rangeRoundBands() sets a banded output range that lines up nicely with pixel values — just what we need to space out the bars evenly, between 0 and height. The 0.05 tells D3 to add 5% for padding between bands.

D3 can handle more than bar charts, including zoomable geographic data, sortable tables and other interactive elements, like this map

Later, when setting the bars’ y and height values, instead of calculating those values from barHeight, we now reference our new ordinal scale:

.attr(“y”, function(d, i) {
return yScale(i);

.attr(“height”, yScale.rangeBand());

To specify basic interactions, bind the event listeners to elements using on():

.on(“click”, function() {
//Do something when this element is clicked

on() takes two arguments: first, the name of the DOM event that should trigger the function. This can be any standard JavaScript event. Let’s use mouseover and mouseout to highlight each bar on mouse hover:

.on(“mouseover”, function() {“highlight”, true);
.on(“mouseout”, function() {“highlight”, false);

Bar chart with mouse hover interaction. On mouseover, rects are assigned the ‘highlight’ class. On mouseout, the class is removed

Within each anonymous function, this represents “the current element,” so we can select it with classed() adds or removes a class from any element. If true, the class will be added. If false, it is removed. Finally, we need a CSS style to recolour the bars when the highlight class is applied:

rect.highlight {
fill: purple;

(A colour change on hover like this could be achieved with CSS alone, but event listeners are needed for more complex interactions, like transitions.) Open up 05_interactivity.html: you’ve made a simple interactive bar chart!

Words: Scott Murray

Interactive Data Visualization for the Web: An Introduction to Designing with D3 by Scott Murray is available to buy from O’Reilly.

This article originally appeared in .net magazine issue 237. Thanks to Mike Bostock for his peer review of this tutorial

Liked this? Read these!

Build a custom HTML5 video player

Media players that are built in to browsers vary in design. Ian Devlin explains how to use HTML5’s media API to build a custom player with a UI that stays consistent no matter what browser you use.

  • Knowledge needed: Intermediate HTML, intermediate JavaScript, intermediate CSS
  • Requires: Text editor, HTML5-enabled browser
  • Project time: 2-3 hours

Download the source files for this HTML5 tutorial

It’s common knowledge that with HTML5 websites you can play audio and video files directly in the browser without the need for third-party plug-ins, via the <audio> and <video> elements. But since the specification doesn’t define how the controls for audio and video files should look, each browser vendor has designed its own interface for its player, which of course provides a different user experience for each browser.

Read the rest of this entry

%d bloggers like this: