GuidesReferenceIssuesSupportGet API Key


Physically-based rendering


Physically-based rendering, or PBR, is a collection of rendering techniques that produces more realistic lighting results for your scenes by incorporating an advanced model of real-world lights and materials. The theory behind PBR closely matches the physics of real-world lighting and surfaces (though not exactly, it is still an approximation).

In addition to looking better, PBR offers an artist workflow that's far more intuitive: lighting and surface materials are based on physical parameters, so things naturally "look right" without having to resort to random tweaks.

Viro fully supports physically-based rendering. This guide covers the three constructs you need for creating great PBR scenes -- materials, direct lighting, and image-based lighting -- and offers some sample code to get you started.


The first step to creating PBR scenes is to configure Materials. There are four PBR properties in each Material.

  • Diffuse texture: The diffuse or albedo texture defines the base color of the material. This can be set by setDiffuseTexture(Texture).

  • Metalness: The metalness value or texture defines how "metallic" the surface is, which influences the degree to which light refracts and reflects off the surface, the level of sharpness in the reflections, and more. This can be set by setMetalnessMap(Texture), or, if a uniform value is preferred, setMetalness(float).

  • Roughness: The roughness value or texture defines the roughness of the microfacets on the surface. The rougher a surface is, the more light will scatter along completely different directions, resulting in larger and more muted specular reflections. Smoother surfaces, meanwhile, exhibit a sharper specular reflection as light rays are more likely to reflect in a uniform direction. Roughness can be set by setRoughnessMap(Texture), or, if a uniform value is preferred, setRoughness(float).

  • Ambient Occlusion: The ambient occlusion texture approximates how exposed the surface is to ambient lighting. This has no effect on direct lights (it does not result in clear shadows) but it darkens enclosed and sheltered areas. These textures are typically authored using modeling tools along with roughness and metalness. Ambient occlusion can be set by setAmbientOcclusionMap(Texture).

These properties are best understood with images. Below is a grid of spheres that are illuminated by four direct lights. The spheres have no diffuse texture, but are colored red. Each sphere has a unique roughness and metalness value: roughness increases from left to right, and metalness increases from bottom to top. You can see that increasing metalness creates a shinier, more reflective sphere, and increasing roughness makes the spheres scatter incoming light more, creating a less sharp and more diffuse effect.

In the image above, no textures are used: the diffuse color, the roughness, and the metalness are all uniform across each sphere. However, using modeling software, artists can create texture maps for these properties, so that each pixel on a surface has its own roughness and metalness value. Viro supports loading such models through OBJ and FBX. The image below shows spheres with diffuse, roughness, and metalness texture maps.

To learn more about using modeling software to create Viro-compatible PBR models, check out our guide on the PBR asset pipeline.

Direct Lighting

Accurate physically-based rendering requires not only that material surface models are accurate, but also that the lights themselves behave physically. Viro supports two forms of physically-based lights, and two forms of stylized lights.

Physically-based Lights

Physically-based lights attenuate naturally, using a distance-squared falloff, which closely matches lights in the real-world. Note this means that the attenuation start distance for such lights is ignored -- but the attenuation end distance is still adhered to. Furthermore, these lights also have their intensity set as luminous flux (in lumens).

Spotlight and OmniLight behave physically when illuminating physically-based materials (that is, materials whose lighting model is set to LightingModel.PhysicallyBased.

Stylized Lights

Not all lights are physically-based; you may want to tweak lighting to achieve a cinematic effect in your Scene that can't be easily achieved by tuning realistic light sources. For this purpose we have stylized lights.

For stylized lights, the intensity is not set in lumens: instead it is simply divided by 1,000 and multiplied by the light's color. In other words, intensity acts a scalar multiplier on the color, affecting the light's brightness. Furthermore, stylized lights do not attenuate naturally: instead their attenuation can be set via the start, end, and (coming soon) falloff exponent to achieve the desired effect.

When PBR is enabled, AmbientLight and DirectionalLight remain as stylized lights. When PBR is disabled, all lights behave as stylized lights.

Image-Based Lighting

Image-based lighting (IBL) refers to the techniques used to physically simulate ambient light. Whereas the lights described above simulate direct lights -- for example, bulbs and spotlights -- image-based lighting simulates the softer illumination from the environment.

Viro handles IBL through the use of lighting environment maps. The lighting environment is a Texture that acts as a global light source, illuminating surfaces with diffuse and specular ambient light. Each pixel in the lighting environment is treated as a light emitter, thereby capturing the environment's global lighting and general feel. This gives objects a sense of belonging to their environment. For this reason it is common to use the scene's background texture as the lighting environment, but this is not necessary.

For these lighting environment textures, Viro expects an image in HDR Radiance format (.hdr). These can be loaded into a Texture object with Texture.loadRadianceHDRTexture(Uri).

Below are two examples of lighting environment maps. Notice how even the less reflective spheres (those on the bottom right, with high roughness and low metalness) capture a sense of belonging in their environment.

The code to produce the image above is shown below. This code sample combines material properties, direct lighting, and IBL lighting. The HDR image used in this example can be found here. The code below loads the image from the application's assets folder.

Scene scene = new Scene();
Node rootNode = scene.getRootNode();

int rows = 7;
int columns = 7;
float spacing = 2.5f;
Node sphereContainerNode = new Node();

// Render an array of spheres, varying roughness and metalness
for (int row = 0; row < rows; ++row) {
    float radius = 1;
    float metalness = (float) row / (float) rows;

    for (int col = 0; col < columns; ++col) {
        float roughness = Math.max((float) col / (float) columns, 0.05f);

        Sphere sphere = new Sphere(radius, 20, 20, true);
        Material material = new Material();
        material.setDiffuseColor(Color.rgb(128, 128, 128));

        Node sphereNode = new Node();
        sphereNode.setPosition(new Vector((float)(col - (columns / 2)) * spacing,
                                          (float)(row - (rows    / 2)) * spacing,


// Configure and add the direct lights to the scene
List<Vector> lightPositions = new ArrayList<Vector>();
lightPositions.add(new Vector(-10,  10, 1));
lightPositions.add(new Vector(10,  10, 1));
lightPositions.add(new Vector(-10, -10, 1));
lightPositions.add(new Vector( 10, -10, 1));

float intensity = 300;
List<Integer> lightColors = new ArrayList<Integer>();

for (int i = 0; i < lightPositions.size(); i++) {
    OmniLight light = new OmniLight();

// Load an HDR Radiance texture and set it as both the screen background
// and lighting environment
Texture environment = Texture.loadRadianceHDRTexture(Uri.parse("file:///android_asset/ibl_mans_outside.hdr"));

To see the full effect of physically-based rendering it's best to use FBX models authored for PBR. Below is one example: an FBX model of a canister, featuring a metalness map, a roughness map, diffuse textures, and ambient occlusion textures. The model is placed in an HDR environment. Observe how the lighting around the model subtly matches its environment lighting, and notice the sharp specular reflections on the metallic regions of the canister.

Finally, the slightly different cylinder below, seen from all angles, showcases the effects of PBR more vividly.