# Performance Optimization

This document provides a collection of useful hints on how to optimize the performance of an OpenGL ES 2.0 application created with CGI Studio.  
Many of these hints will apply to any graphic chip; these are listed first. Later sections describe properties and corresponding hints specific to some given hardware.  
Some information is based on the document Optimizing OpenGL Applications1 , while the document at hand focuses more on possible performance optimizations for applications based on the CGI Studio Candera Engine instead of native OpenGL applications.

# Quick Guide

This chapter aggregates recommendations concerning major points explained very shortly.

# Optimize Number of Nodes

A reduced number of nodes lead to fewer node-related render state activations that have to be processed. Thus, whenever geometry can be safely combined to a single node like e.g. a mesh, then this way should be favoured. For instance a tire and a rim form a logical group sharing the same transformation. In that case the designer can unify separate geometries in a single mesh with the aid of a digital content creation (DCC) tool.   
Consequently, the rim and tire do their texture lookup in a single texture, which further leverages performance gains by texture caching.

<div drawio-diagram="1801"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676619365.png" alt=""/></div>

<div class="contents" id="bkmrk--0"><div class="contents"><div class="textblock"></div></div></div>See below crucial prerequisites for combining Nodes:

<div class="contents" id="bkmrk-nodes-share-same-tra"><div class="contents"><div class="textblock">- Nodes share same transformation (position, rotation, scale).
- Nodes share the same Appearance (textures, shaders, material, render-mode, render-order)
- Nodes are within the same render-order bin.

</div></div></div><div drawio-diagram="1803"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676619452.png" alt=""/></div>

<div class="contents" id="bkmrk--2"><div class="textblock"></div></div>

# Avoid Buffer Clearing

Clear only buffers that need to be cleared.

<div class="contents" id="bkmrk-color-buffer%3A-the-co"><div class="textblock">- Color buffer: The color buffer does not have to be cleared if the scene is known to cover all of it.   
    For instance, this is the case if the background image or a sky map covers the whole surface.
- Stencil buffer: Only needs to be cleared if it is actually used.
- Depth buffer: If depth test is enabled.

</div></div>

# Disable Depth Test and Adjust Depth Range

#### <a class="anchor" id="bkmrk-"></a>Disable Depth Test if Not Required

If it can be easily predicted that an object is not occluded by other objects then disable depth test (See Render-Mode).

#### <a class="anchor" id="bkmrk--0"></a>Adjust Depth Range

As the float resolution in depth buffer is highly limited, the depth range should be as small as possible to reduce depth-fighting artifacts. Further, geometry beyond the near and far plane can be discarded in the clipping stage

# Vertex Buffer Optimization

#### <a class="anchor" id="bkmrk-"></a>Vertex Buffer Editor

Loading of vertex geometry has impact on the bandwidth and on the performance of the caching mechanism for vertices. Scene Composer offers a Vertex Buffer Editor that can be used to remove the unused/unneeded vertex buffer attributes so the performance increase.

<div class="contents" id="bkmrk-read-more..."><div class="contents"><div class="textblock"><table class="doxtable"><tbody><tr><td bgcolor="#f5e7b6"><span style="color: rgb(230, 126, 35);">[Read more...](https://doc316en.candera.eu/books/scene-design/page/vertex-buffer-editor)</span></td></tr></tbody></table>

</div></div></div>#### <a class="anchor" id="bkmrk--0"></a>Shader Consistency Checker

The information contained in the vertex buffer and the shader attributes should match otherwise conversion is needed and that costs performance. Scene Composer validates the shader parameters, the attributes and the uniforms defined in shaders and gives warnings that can indicate performance issues.

<div class="contents" id="bkmrk-read-more...-0"><div class="contents"><div class="textblock"><table class="doxtable"><tbody><tr><td bgcolor="#f5e7b6"><span style="color: rgb(230, 126, 35);">[Read more...](https://doc316en.candera.eu/link/146#bkmrk-shader-consistency-c)</span></td></tr></tbody></table>

</div></div></div>#### <a class="anchor" id="bkmrk--1"></a>Node Attachment Optimization

The more node attachments are shared the more performance increases because of reusing the data instead of loading it. SceneComposer provides a wizard to automatically detect node attachments which could be replaced by shared node attachments templates.

<div class="contents" id="bkmrk-read-more...-1"><div class="textblock"><table class="doxtable"><tbody><tr><td bgcolor="#f5e7b6"><span style="color: rgb(230, 126, 35);">[Read more...](https://doc316en.candera.eu/link/132#bkmrk-cube-map-texture-0)</span></td></tr></tbody></table>

</div></div>

# Startup Time

#### <a class="anchor" id="bkmrk-"></a>Loading Data

<span style="color: rgb(230, 126, 35);">[Asset Tool](https://doc316en.candera.eu/books/asset-tool)</span> can be used to partition an asset for a startup scene in a faster flash memory.

An another option would be to load a small startup scene and use <span style="color: rgb(230, 126, 35);">[asynchronous asset loading](https://doc316en.candera.eu/books/candera/page/asynchronous-asset-loading)</span> to load next scene in background.

Loading a lot of data at startup is generally a bad idea. Distribute loading tasks over time.

Also avoid to copy the whole asset from NAND flash to RAM. A better solution would be to implement a paging and caching mechanism using a custom Asset Repository.

#### <a class="anchor" id="bkmrk--0"></a>Persist Pre-compiled Shaders

Use this feature by enabling CANDERA\_SHADER\_PROGRAM\_PERSIST\_INTERFACE\_ENABLED flag in the CMake project.

#### <a class="anchor" id="bkmrk--1"></a>Scope Masks

Upload data to VRAM using Scope Masks as presented in the <span style="color: rgb(230, 126, 35);">[documentation](https://doc316en.candera.eu/link/537#bkmrk-uploading-to-multipl)</span> and in the <span style="color: rgb(230, 126, 35);">[example](https://doc316en.candera.eu/link/537#bkmrk-uploading-to-multipl-0)</span>.

#### <a class="anchor" id="bkmrk--2"></a>Startup Animation

Here are some hints for the startup animation:

<div class="contents" id="bkmrk-avoid-large-images-u"><div class="textblock">- Avoid large images
- Use image compression
- Restrict the frame rate (e.g. 30 fps)
- Realize a flipbook startup animation with asynchronous image fetching

</div></div>

# Optimization at Application Design Level

This section discusses performance optimizations in the scope of 3D scene modelling and application design based on CGI Studio Candera Engine.

# Simplify Meshes

Reduce the number of vertices in a mesh in order to improve runtime and memory performance. If viewing angle to a mesh is rather steady, it is a preferred approach to maintain higher amount of vertices at the silhouette and mainly reduce vertices in front view.

<div drawio-diagram="1806"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676620086.png" alt=""/></div>

<div class="contents" id="bkmrk-a-strongly-simplifie"><div class="textblock"><dl class="note"><dt></dt><dd><p class="callout info">A strongly simplified mesh does not necessarily lead to a diminished quality of visual appearance, if the level of detail matches the use case rendered (See also <span style="color: rgb(230, 126, 35);">[LOD Management](https://doc316en.candera.eu/books/performance-optimization/page/use-lodlevel-of-detail-management)</span>).</p>

</dd></dl></div></div>

# Optimize Number of Nodes

A reduced number of nodes lead to fewer node-related render state activations that have to be processed. Thus, whenever geometry can be safely combined to a single node like e.g. a mesh, then this way should be favoured. For instance a tire and a rim form a logical group sharing the same transformation. In that case the designer can unify separate geometries in a single mesh with the aid of a digital content creation (DCC) tool.   
Consequently, the rim and tire do their texture lookup in a single texture, which further leverages performance gains by texture caching.

<div drawio-diagram="1807"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676620178.png" alt=""/></div>

<div class="contents" id="bkmrk--0"><div class="contents"><div class="textblock"></div></div></div>See below crucial prerequisites for combining Nodes:

<div class="contents" id="bkmrk-nodes-share-same-tra"><div class="contents"><div class="textblock">- Nodes share same transformation (position, rotation, scale).
- Nodes share the same Appearance (textures, shaders, material, render-mode, render-order)
- Nodes are within the same render-order bin.

</div></div></div><div drawio-diagram="1808"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676620232.png" alt=""/></div>

<div class="contents" id="bkmrk--2"><div class="textblock"></div></div>

# Draw Visible Objects Only

Nodes, even when attempting to render them, might be not be visible in various circumstances. Nevertheless, if no countermeasures are taken, they have to pass the render pipeline and are quite often discarded at a very late stage. To minimize computations within the render pipeline, geometry shall be discarded as soon as possible, if it is not visible at all.

Use following [Candera](http://dev.doc.cgistudio.at/APILINK/namespace_candera.html "[DataBinding_RefTypeSample]") concepts to exclude invisible objects from effective rendering earliest possible:

<div class="contents" id="bkmrk-disable-rendering-of"><div class="textblock">- Disable rendering of nodes manually (see `Node::SetRenderingEnabled(false)`).   
    Example: Consider to disable nodes with a very low alpha value from rendering.
- Enable Viewing Frustum Culling in the Camera, to cull objects out of viewing frustum
- Use Backface Culling in the RenderMode to cull faces not visible.
- Use custom defined visibility and light culling via [Candera](http://dev.doc.cgistudio.at/APILINK/namespace_candera.html "[DataBinding_RefTypeSample]") scopes.
- Use [Candera](http://dev.doc.cgistudio.at/APILINK/namespace_candera.html "[DataBinding_RefTypeSample]") RenderOrder to sort opaque objects from near to far distance to the camera, which increases number of fragment culling according to depth-test-fails.

</div></div>

# Use LOD(Level of Detail) Management

Performance gains can be achieved by using simplified models with less complex geometry, texture, materials and shaders for objects that need less perceptional detail level. E.g. objects that appear farer from the camera may reduce richness of detail without a noticeable decrease in visual perception.   
The same applies for instance to objects that are less illuminated, moving, or in peripheral viewing frustum.

<div drawio-diagram="1809"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676620378.png" alt=""/></div>

<div class="contents" id="bkmrk--0"><div class="contents"><div class="textblock">  
</div></div></div><div drawio-diagram="1810"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676620433.png" alt=""/></div>

<div class="contents" id="bkmrk--2"><div class="contents"><div class="textblock">  
</div></div></div>[Candera](http://dev.doc.cgistudio.at/APILINK/namespace_candera.html "[DataBinding_RefTypeSample]") supports comprehensive, multi-purpose level-of-detail functionality including discrete and blending transitions.   
Please refer to the <span style="color: rgb(230, 126, 35);">[Tutorials](https://doc316en.candera.eu/books/candera)</span> CGI Studio Application Development Tutorial

# Imposters

Billboards or point sprites are quite often used as "imposters" pretending to be a 3D geometry by showing a 2D image that is always facing the camera.   
[Candera](http://dev.doc.cgistudio.at/APILINK/namespace_candera.html "[DataBinding_RefTypeSample]") supports both, Billboards and Point Sprites to achieve three-dimensional impressions by showing camera aligned two-dimensional images.

In order to relief distinction between Billboards and Point Sprites see following comparison:

<div class="contents" id="bkmrk-billboards-support-r"><div class="contents"><div class="textblock">- Billboards support rectangular dimension and non-uniform scale.
- Billboards support different rotation techniques (see Alignment), whereas Point Sprites are always screen aligned.
- Point Sprites have a performance advantage due to less geometry (one instead of 4 vertices).

</div></div></div>Overall recommendation: Use Point Sprites for spherical shapes like particles, lens flares, sparkles, dust which are screen aligned. \\ Further, use Billboards for world up oriented clouds, text, or yaw axis aligned trees, and signs, etc.

# Lighting

Use as few *dynamic* light sources as possible. Light sources in order of their impact on rendering performance (fastest first):

<div class="contents" id="bkmrk-ambient-light-direct"><div class="contents"><div class="textblock">- ambient light
- directional light
- point light
- spot light

</div></div></div>Often the ambient light computation can be omitted by already including the ambient light factor in the ambient material of the affected node. Bake light into texture for static lighting. Use multi-texture effects like *lightmaps*, *spheremaps* for certain light effects to achieve high detailed pixel lighting on simple surfaces without dynamic light sources.

# Avoid Buffer Clearing

Clear only buffers that need to be cleared.

<div class="contents" id="bkmrk-color-buffer%3A-the-co"><div class="textblock">- Color buffer: The color buffer does not have to be cleared if the scene is known to cover all of it.   
    For instance, this is the case if the background image or a sky map covers the whole surface.
- Stencil buffer: Only needs to be cleared if it is actually used.
- Depth buffer: If depth test is enabled.

</div></div>

# Disable Depth Test and Adjust Depth Range

<div class="header" id="bkmrk-disable-depth-test-i"><div class="headertitle"><div class="title"><span style="color: rgb(34, 34, 34); font-size: 1.666em; font-weight: 400;">Disable Depth Test if Not Required</span>  
</div></div></div>If it can be easily predicted that an object is not occluded by other objects then disable depth test (See Render-Mode).

#### <a class="anchor" id="bkmrk-"></a>Adjust Depth Range

As the float resolution in depth buffer is highly limited, the depth range should be as small as possible to reduce depth-fighting artifacts. Further, geometry beyond the near and far plane can be discarded in the clipping stage.

# Disable Blending If Not Required

Disable blending for opaque objects, as blending is a demanding computation (See Render-Mode).

Further, if blending for translucent objects does not require separate alpha blending (common case), set source blend factor to One, destination blend factor to Zero, and operator to Add (default settings in RenderMode). This setting allows modern GPUs to ignore the alpha blending equation.

<div class="contents" id="bkmrk-within-the-lifetime-"><div class="textblock"><dl class="note"><dt></dt><dd><p class="callout info">Within the lifetime of an object, there may be periods where blending is needed (fade-in/out) and periods where blending is not needed. In such cases take care to enable / disable blending dynamically as appropriate.</p>

</dd></dl></div></div>

# Minimize Render State Changes

Minimize render state changes within a single frame. A render state change often comes with a performance penalty, as a render state change can require complete rendering pipeline to be flushed.

Following subchapters explain how render state settings and changes can be minimized when using [Candera](http://dev.doc.cgistudio.at/APILINK/namespace_candera.html "[DataBinding_RefTypeSample]").

#### <a class="anchor" id="bkmrk-"></a>Enable Candera Render State Caching

Enabling this [Candera](http://dev.doc.cgistudio.at/APILINK/namespace_candera.html "[DataBinding_RefTypeSample]") feature in the CMake build system configuration means that redundant render state settings are not propagated to graphic device driver.  
Another benefit is that render state queries are not processed by graphic device driver, either.

#### <a class="anchor" id="bkmrk--0"></a>Render Objects with same Rendering State

Render objects together that use the same rendering state, e.g.:

<div class="contents" id="bkmrk-objects-using-the-sa"><div class="contents"><div class="textblock">- Objects using the same texture (avoids flushing the texture cache)
- Objects using the same shader program (avoids changing shader programs)
- Objects using similar render modes

</div></div></div>Use the [Candera](http://dev.doc.cgistudio.at/APILINK/namespace_candera.html "[DataBinding_RefTypeSample]") render order concept to take influence on the sequence of render operations according to custom criteria. For further details refer to <span style="color: rgb(230, 126, 35);">[Tutorials](https://doc316en.candera.eu/books/candera)</span> CGI Studio Application Development Tutorial

#### <a class="anchor" id="bkmrk--1"></a>Scoping

If using scopes, scene graph nodes can form conceptual groups independent of the scene graph hierarchy, according to arbitrary

# Textures

#### <a class="anchor" id="bkmrk-"></a>Draw Objects Sorted by Texture

This way the texture cache isn't flushed between objects. See also above, "Render Objects with Same Rendering State".

#### <a class="anchor" id="bkmrk--0"></a>Texture Cache

Consider the size of the texture cache when defining textures. Cache misses can slow performance down appreciably. The total size needed by textures depends on their number, dimensions, and bit-depth; ideally, this size should be smaller than the cache size.

#### <a class="anchor" id="bkmrk--1"></a>Use Texture Compression

If a texture compression feature is available, turning it on and using it is likely to improve performance.

Etc2/Eac compressed textures are typically uncompressed during texture lookups by the GPU for free. They save memory and increase the performance of the texture cache by reducing bandwidth. The following Etc2/Eac formats are supported by [Candera](http://dev.doc.cgistudio.at/APILINK/namespace_candera.html "[DataBinding_RefTypeSample]") on OpenGL ES3.0 platforms:

<div class="contents" id="bkmrk-compressed-bitmap%3A%3Ap"><div class="contents"><div class="textblock"><table class="doxtable" style="width: 98.3951%; height: 344.563px;"><tbody><tr style="height: 29.7969px;"><th style="width: 34.0005%; height: 29.7969px;">**Compressed Bitmap::PixelFormat**</th><th style="width: 29.1994%; height: 29.7969px;">**Uncompressed generic format**</th><th style="width: 36.7295%; height: 29.7969px;">**size ratio compressed to uncompressed**</th></tr><tr style="height: 29.7969px;"><td style="width: 34.0005%; height: 29.7969px;">Etc2CompressedRgbPixelFormat</td><td style="width: 29.1994%; height: 29.7969px;">RGB</td><td style="width: 36.7295%; height: 29.7969px;">1/6</td></tr><tr style="height: 29.7969px;"><td style="width: 34.0005%; height: 29.7969px;">Etc2CompressedSrgbPixelFormat</td><td style="width: 29.1994%; height: 29.7969px;">sRGB</td><td style="width: 36.7295%; height: 29.7969px;">1/6</td></tr><tr style="height: 29.7969px;"><td style="width: 34.0005%; height: 29.7969px;">Etc2Alpha1CompressedRgbaPixelFormat</td><td style="width: 29.1994%; height: 29.7969px;">RGBA</td><td style="width: 36.7295%; height: 29.7969px;">1/8</td></tr><tr style="height: 46.5938px;"><td style="width: 34.0005%; height: 46.5938px;">Etc2Alpha1CompressedSrgbaPixelFormat</td><td style="width: 29.1994%; height: 46.5938px;">sRGBA</td><td style="width: 36.7295%; height: 46.5938px;">1/8</td></tr><tr style="height: 29.7969px;"><td style="width: 34.0005%; height: 29.7969px;">Etc2EacCompressedRgbaPixelFormat</td><td style="width: 29.1994%; height: 29.7969px;">RGBA</td><td style="width: 36.7295%; height: 29.7969px;">1/4</td></tr><tr style="height: 29.7969px;"><td style="width: 34.0005%; height: 29.7969px;">Etc2EacCompressedSrgbaPixelFormat</td><td style="width: 29.1994%; height: 29.7969px;">sRGBA</td><td style="width: 36.7295%; height: 29.7969px;">1/4</td></tr><tr style="height: 29.7969px;"><td style="width: 34.0005%; height: 29.7969px;">EacCompressedUnsignedRPixelFormat</td><td style="width: 29.1994%; height: 29.7969px;">A</td><td style="width: 36.7295%; height: 29.7969px;">1/2</td></tr><tr style="height: 29.7969px;"><td style="width: 34.0005%; height: 29.7969px;">EacCompressedSignedRPixelFormat</td><td style="width: 29.1994%; height: 29.7969px;">signed A</td><td style="width: 36.7295%; height: 29.7969px;">1/2</td></tr><tr style="height: 29.7969px;"><td style="width: 34.0005%; height: 29.7969px;">EacCompressedUnsignedRGPixelFormat</td><td style="width: 29.1994%; height: 29.7969px;">LA</td><td style="width: 36.7295%; height: 29.7969px;">1/2</td></tr><tr style="height: 29.7969px;"><td style="width: 34.0005%; height: 29.7969px;">EacCompressedSignedRGPixelFormat</td><td style="width: 29.1994%; height: 29.7969px;">signed LA</td><td style="width: 36.7295%; height: 29.7969px;">1/2</td></tr></tbody></table>

</div></div></div>Note: 'A' stands for Alpha (uncompressed equivalent format: AlphaUnsignedBytePixelFormat), and 'LA' for Luminance Alpha (uncompressed equivalent format: LuminanceAlphaUnsignedBytePixelFormat).

If texture compression is supported, avoid uncompressed textures as much as possible. E.g. 1 uncompressed RGB texture takes as much space as 6(!) Etc2CompressedRgb textures. Plus uncompressed textures decrease performance.

There a several compressed RGBA formats to choose from, which primarily affect the quality of the Alpha channel. If the alpha channel is only used to indicate fully opaque/transparent regions, then Etc2Alpha1Compressed formats are the best fit. If quality of transparency in Etc2EacCompressed textures is lacking, a combination of a compressed RGB texture together with a compressed single channel Alpha texture (EacCompressedUnsignedR/EacCompressedSignedR) should be favored over an uncompressed texture, because the 2 compressed textures need less memory and bandwidth than an uncompressed one.

Signed compressed textures have the capability to express 0 exactly in every pixel of the compressed texture. This is useful for sharp transparent edges, or for normal maps that are encoded in the EacCompressedUnsignedRG format.

#### <a class="anchor" id="bkmrk--2"></a>Use Mip Maps

For objects that occupy static screen size, try to fit texture to rendered object size. For objects that change size on screen use Mip-Mapping to avoid texture aliasing effects and to improve runtime performance. Mip-Mapping consumes little more memory (max 1/3 more than the biggest bitmap).

Texture filter MipMapNearest consumes less time than MipMapLinear, which processes a trilinear filtering.

#### <a class="anchor" id="bkmrk--3"></a>Combine Textures

Associated segments, for example rims and tires, should be combined into one texture. The different segments (nodes) share the same texture, but each of them refers to a different area within the texture. This way, the texture only needs to be activated once for multiple nodes.

# CGI Studio Optimization Techniques

This chapter describes performance optimization techniques for Candera based applications.

# Rendering Only Updated Content

#### <a class="anchor" id="bkmrk--6"></a>Description

This chapter briefly describes how to achieve performance optimization by rendering only updated content.

#### **Introduction**

##### <a class="anchor" id="bkmrk--8"></a>Invalidation Introduction

Basic principles for composing graphical content:

<div class="contents" id="bkmrk-place-content-which-"><div class="contents"><div class="textblock">- Place content which is never changed in an own scene and render it to an own layer.
- Partition content which is frequently changed by widgets or animations. Use several cameras for this purpose.
- If rarely modified graphical content is part of a dynamic scenery then think about using <span style="color: rgb(230, 126, 35);">[Texture Render Targets](https://doc316en.candera.eu/books/candera/page/multiple-render-targets)</span>.

</div></div></div>##### <a class="anchor" id="bkmrk--9"></a>How is it done?

In the render loop of the application all Widgets are updated by calling [Candera::WidgetBase::Update()](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_widget_base.html#ad7891efa29f51b34e2566ff4804c59e3). The basic render loop looks like this:

```
  // 3D Render Loop

    // handle input events
    // ...

    // update animations by calling AnimationDispatcher::DispatchTime()
    if (m_animationDispatcher3D != 0) {
      m_animationDispatcher3D->SetWorldTimeMs(nowMs);
      m_animationDispatcher3D->DispatchTime();
    }

    // update all widgets
    CgiApp::GetInstance().Update();

    Renderer::RenderAllCameras();

  // end 3D Render Loop
```

The widgets must now implement a mechanism to tell the application whether associated graphical content needs to be rendered. The following pages explain two ways to achieve this:

<div class="contents" id="bkmrk-use-candera%3A%3Acamera%3A"><div class="textblock">- <span style="color: rgb(230, 126, 35);">[Use Candera::Camera::SetRenderingEnabled() / Candera::Camera2D::SetRenderingEnabled()](https://doc316en.candera.eu/link/375#bkmrk-use-setrenderingenab)</span>
- <span style="color: rgb(230, 126, 35);">[Explicitely Pick Camera to Render](https://doc316en.candera.eu/link/375#bkmrk-pick-camera-to-rende)</span>

</div></div>####   
**Use SetRenderingEnabled()**   


##### <a class="anchor" id="bkmrk--10"></a>Use Candera::Camera::SetRenderingEnabled() / Candera::Camera2D::SetRenderingEnabled()

The example below shows how in CGIApplication all 3D cameras are turned off in first step of render loop.

```
void CgiApp3dGc::Update() {
    Base::Update();
   
  // Turn off all cameras
    UInt32 cameraCount = Renderer::GetCameraCount();
    for (UInt32 i = 0; i < cameraCount; i++)
    {
        Camera* cam = Renderer::GetCamera(i);
        cam->SetRenderingEnabled(false);
    }

    // Update widgets in all visible scenes
    WidgetBase* widget = 0;
    Vector<SceneContext*>::ConstIterator it = m_sceneContexts.ConstBegin();
    for (; it != m_sceneContexts.ConstEnd(); it++) {
        if ((*it) != 0 && (*it)->GetScene() != 0 && (*it)->GetScene()->IsRenderingEnabled()) {
            widget = (*it)->GetFirstWidget();
            while (widget != 0) {
                widget->Update();
                widget = (*it)->GetNextWidget();
            }
        }
    }
}
```

The [Candera::Widget::Update()](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_widget_base.html#ad7891efa29f51b34e2566ff4804c59e3) method needs to be implemented such that the recently turned off camera is turned on again whenever rendering is required. The [Candera::Camera](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_camera.html "A Camera provides Modelview and Projection matrices. Camera is a Transformable.* The eye point is set...") can be either set as a widget property or retrieved inside the scene by masking the widget and the associated camera with the same [Candera::ScopeMask](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_scope_mask.html "The class ScopeMask allows scene graph nodes to form conceptual groups independent of the scene graph...") value.

```
void SampleBaseWidget3D::InvalidateCamera(bool value)
{
  m_camera->SetRenderingEnabled(true);
}
```

```
void MyWidget::Update()
{
  // update graphical content from cached property value(s)
  //...

  Base::InvalidateCamera(true);
}
```

#### **Pick Camera to Render**

##### Explicitly Pick Camera to Render

Another method is to maintain a list of cameras by the application.

The render loop has to be changed

<div class="contents" id="bkmrk-to-call-candera%3A%3Aren"><div class="textblock">- to call Candera::Renderer::RenderCamera( Camera \* camera )
- instead of [Candera::Renderer::RenderAllCameras()](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_renderer.html#aed822ba1d66620f2d1e794973e30f354).

</div></div><div class="contents" id="bkmrk-the-application-need"><div class="textblock"><dl class="note"><dd><p class="callout info">The application needs to take care on <span style="color: rgb(230, 126, 35);">[Render Buffer Swapping](https://doc316en.candera.eu/link/1050#bkmrk-render-buffer-swappi)</span>.</p>

</dd></dl></div></div>

# Multi Frequency Rendering

#### <a id="bkmrk--9"></a>Description

This chapter briefly describes the Multi Frequency Rendering technique supported by [Candera](http://dev.doc.cgistudio.at/APILINK/namespace_candera.html "[DataBinding_RefTypeSample]").   
It allows to split rendering of complex parts to several frames, to achieve an overall higher frame rate.

#### **Introduction**

##### <a class="anchor" id="bkmrk--10"></a>Multi Frequency Rendering Introduction

Multi Frequency Rendering allows using different update rates for multiple render targets. For example

<div class="contents" id="bkmrk-fix-framerate-for-tu"><div class="contents"><div class="contents"><div class="textblock">- Fix framerate for tubes.
- Adaptive framerate for center use case.
- Details of entire content are preserved.

</div></div></div></div><div drawio-diagram="1945"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676868292.png" alt=""/></div>

<div class="contents" id="bkmrk--1"><div class="contents"><div class="textblock">  
</div></div></div>##### <a class="anchor" id="bkmrk--12"></a>Workflow

<div class="contents" id="bkmrk-cgi-analyzer-sceneco"><div class="contents"><div class="textblock"><table border="0"><tbody><tr><td align="center">**CGI Analyzer**</td><td align="center">**SceneComposer**</td><td align="center">**Application**</td></tr><tr><td style="vertical-align: middle;">[![09_mfranalyzer.png](https://doc316en.candera.eu/uploads/images/gallery/2023-02/scaled-1680-/nIy09-mfranalyzer.png)](https://doc316en.candera.eu/uploads/images/gallery/2023-02/nIy09-mfranalyzer.png)

</td><td style="vertical-align: middle;">[![09_mfrscenecomposer.png](https://doc316en.candera.eu/uploads/images/gallery/2023-02/scaled-1680-/09-mfrscenecomposer.png)](https://doc316en.candera.eu/uploads/images/gallery/2023-02/09-mfrscenecomposer.png)

</td><td style="vertical-align: middle;">[![09_mfrapplication.png](https://doc316en.candera.eu/uploads/images/gallery/2023-02/scaled-1680-/09-mfrapplication.png)](https://doc316en.candera.eu/uploads/images/gallery/2023-02/09-mfrapplication.png)

</td></tr><tr><td align="left">CGI Analyzer determines benchmark values for each node of a scene given. The benchmarks are exported to a \*.crsms file.</td><td align="left">The benchmarks are assigned to nodes benchmark property. SceneComposer stores nodes incl. benchmark values in Asset File.</td><td align="left">The Application renders multiple cameras with different framerates with help of Benchmark-CameraRenderStrategy.</td></tr></tbody></table>

</div></div></div>##### <a class="anchor" id="bkmrk--13"></a>Candera::CameraRenderStrategy

The following sections explain how an application can use the [Candera::CameraRenderStrategy](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_camera_render_strategy.html "The abstract class CameraRenderStrategy is intended to be derived in order to tell the Renderer...") to implement multi frequency rendering based on given benchmark values within the scene tree.

##### <a class="anchor" id="bkmrk--14"></a>References

For details about how to calculate benchmark values and how to assign them to a scene tree, please refer to:

<div class="contents" id="bkmrk-cgi-analyzer_user_ma"><div class="textblock">- **CGI-Analyzer\_User\_Manual.pdf**: Calculate benchmark values and export to a \*.crsms file.
- <span style="color: rgb(230, 126, 35);">**[SceneComposer Help](https://doc316en.candera.eu/books/import-of-resources/page/import-benchmarks)**</span>: Import benchmark values from a \*.crsms file into a given solution.

</div></div>####   
**Candera - Camera Render Strategy**

##### <a class="anchor" id="bkmrk--15"></a>Partitioning Render Passes

A Camera render pass renders all scene nodes in one sweep.  
[Candera::CameraRenderStrategy](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_camera_render_strategy.html "The abstract class CameraRenderStrategy is intended to be derived in order to tell the Renderer...") enables to partition a Camera render pass, if e.g. complete processing in one frame is not possible.

##### <a class="anchor" id="bkmrk--16"></a>Examples of Usage

<div class="contents" id="bkmrk-omit-rendering-of-no"><div class="contents"><div class="contents"><div class="textblock">- Omit rendering of nodes with low priority like decorations.
- Multi Frequency Rendering: Suspend and continue Camera render pass next time Camera renders. Unless render pass is complete, render target is not swapped.

</div></div></div></div><div drawio-diagram="1950"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676868435.png" alt=""/></div>

<div class="contents" id="bkmrk--3"><div class="contents"><div class="textblock">  
</div></div></div>Both, [Candera::BreakNodeCameraRenderStrategy](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_break_node_camera_render_strategy.html "The BreakNodeCameraRenderStrategy is an implementation of the abstract class CameraRenderStrategy. The rendering of the nodes is done until it reaches a node that is in the list of break nodes (See function AddBreakNode).") and [Candera::BenchmarkCameraRenderStrategy](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_benchmark_camera_render_strategy.html "The class BenchmarkCameraRenderStrategy is an implementation of the abstract class CameraRenderStrate...") are concrete implementations of the interface [Candera::CameraRenderStrategy](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_camera_render_strategy.html "The abstract class CameraRenderStrategy is intended to be derived in order to tell the Renderer...") to cover most typical Camera render pass partitioning.

####   
**Candera - Break Node Camera Render Strategy**

##### <a class="anchor" id="bkmrk--18"></a>Splitting Render Pass on specific Break Nodes

The [Candera::BreakNodeCameraRenderStrategy](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_break_node_camera_render_strategy.html "The BreakNodeCameraRenderStrategy is an implementation of the abstract class CameraRenderStrategy. The rendering of the nodes is done until it reaches a node that is in the list of break nodes (See function AddBreakNode).") is populated with a list of arbitrary break nodes.  
Defined by RenderPassAction a break node can pause or stop a Camera render pass, if encountered.

```
breakNodeStrategy = new BreakNodeCameraRenderStrategy();
breakNodeStrategy->AddBreakNode(node4);
breakNodeStrategy->AddBreakNode(node7);
breakNodeStrategy->SetRenderPassActionOnBreakNode(renderPassAction);
camera->SetCameraRenderStrategy(breakNodeStrategy);
```

<div drawio-diagram="1952"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676868541.png" alt=""/></div>

<div class="contents" id="bkmrk-back-to-the-menu-1"></div>####   
**Candera - Benchmark Camera Render Strategy**

##### <a class="anchor" id="bkmrk--20"></a>Splitting Render Pass on Benchmark Threshold Values

Each node has a benchmark property that describes a custom reference value for render duration.  
During Camera render pass benchmarks are accumulated until threshold of [Candera::BenchmarkCameraRenderStrategy](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_benchmark_camera_render_strategy.html "The class BenchmarkCameraRenderStrategy is an implementation of the abstract class CameraRenderStrate...") is reached. RenderPassAction defines to suspend or stop render pass.

```
benchmarkStrategy = new BenchmarkCameraRenderStrategy(); 
node1->SetRenderBenchmark(250.0f); 
node2->SetRenderBenchmark(330.0f); 
node3->SetRenderBenchmark(220.0f); 
node4->SetRenderBenchmark(400.0f); 
node5->SetRenderBenchmark(390.0f); 
benchmarkStrategy->SetThreshold(1000.0f);
benchmarkStrategy->SetRenderPassActionOnThreshold(renderPassAction);
camera->SetCameraRenderStrategy(benchmarkStrategy);
```

<div drawio-diagram="1953"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676868597.png" alt=""/></div>

<div class="contents" id="bkmrk--7"><div class="textblock">  
</div></div>####   
**Candera - Render Pass Actions**

##### <a class="anchor" id="bkmrk--22"></a>Render Pass Actions

<div class="contents" id="bkmrk-proceed-render-pass-"><div class="textblock"><table border="0" cellpadding="5"><tbody><tr><td align="center" valign="top" width="33%">[![09_mfrrenderpassaction1.png](https://doc316en.candera.eu/uploads/images/gallery/2023-02/scaled-1680-/09-mfrrenderpassaction1.png)](https://doc316en.candera.eu/uploads/images/gallery/2023-02/09-mfrrenderpassaction1.png)

</td><td align="center" valign="top" width="33%">[![09_mfrrenderpassaction2.png](https://doc316en.candera.eu/uploads/images/gallery/2023-02/scaled-1680-/09-mfrrenderpassaction2.png)](https://doc316en.candera.eu/uploads/images/gallery/2023-02/09-mfrrenderpassaction2.png)

</td><td align="center" valign="top" width="33%">[![09_mfrrenderpassaction3.png](https://doc316en.candera.eu/uploads/images/gallery/2023-02/scaled-1680-/09-mfrrenderpassaction3.png)](https://doc316en.candera.eu/uploads/images/gallery/2023-02/09-mfrrenderpassaction3.png)

</td></tr><tr><td align="center">**Proceed Render Pass**</td><td align="center">**Pause Render Pass**</td><td align="center">**Stop Render Pass**</td></tr><tr><td align="left">Proceeds Rendering. Rendering is not interrupted. Break nodes are ignored.</td><td align="left">Pauses rendering. The next time the Camera is rendered it restarts from the node that has been paused. Swaps render target when Camera completes.  
Usage: Entire content captured by Camera shall be displayed</td><td align="left">Stops rendering. The next time the Camera renders it restarts from the very first node in render order. Swaps render target at each render cycle.  
Usage: Nodes with lower priority shall be omitted.</td></tr></tbody></table>

</div></div>####   
**Example - Multi Frequency Rendering**

##### <a class="anchor" id="bkmrk--23"></a>Example: Different Frame Rates for several Cameras

<div class="contents" id="bkmrk-fix-framerate-for-sp"><div class="contents"><div class="textblock">- Fix framerate for speedometer.
- Adaptive framerate for car.
- Details of entire content is preserved.

</div></div></div>##### <a class="anchor" id="bkmrk--24"></a>Cycle 1

<div class="contents" id="bkmrk-camera-1-%3A-renders-t"><div class="contents"><div class="textblock"><table border="0"><tbody><tr><td>[![09_mfrcycle1.png](https://doc316en.candera.eu/uploads/images/gallery/2023-02/scaled-1680-/09-mfrcycle1.png)](https://doc316en.candera.eu/uploads/images/gallery/2023-02/09-mfrcycle1.png)

</td></tr><tr><td>Camera 1 : Renders the speedometer and swaps render target.  
Camera 2 : Renders car until benchmark threshold is exceeded. Render target is not swapped.</td></tr></tbody></table>

</div></div></div>##### <a class="anchor" id="bkmrk--25"></a>Cycle 2

<div class="contents" id="bkmrk-camera-1-%3A-renders-t-0"><div class="textblock"><table border="0"><tbody><tr><td>[![09_mfrcycle2.png](https://doc316en.candera.eu/uploads/images/gallery/2023-02/scaled-1680-/09-mfrcycle2.png)](https://doc316en.candera.eu/uploads/images/gallery/2023-02/09-mfrcycle2.png)

</td></tr><tr><td>Camera 1 : Renders the speedometer and swaps render target.  
Camera 2 : Completes render pass and swaps render target. Thus Camera2 renders with half frames per second (FPS) than Camera1.</td></tr></tbody></table>

</div></div>####   
**Multi Frequency Rendering in 2D**

Analogous to [Candera::CameraRenderStrategy](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_camera_render_strategy.html "The abstract class CameraRenderStrategy is intended to be derived in order to tell the Renderer..."), there is an abstract class [Candera::Camera2DRenderStrategy](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_camera2_d_render_strategy.html "The abstract class Camera2DRenderStrategy is intended to be derived in order to tell the Renderer2D...") available.

This class is intended to be derived to tell the [Candera::Renderer2D](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_renderer2_d.html "The class Renderer2D represents the unique Candera 2D render interface to the application. Each render call shall be triggered via the Renderer2D interface."), if rendering shall proceed, pause, or stop for a given node in a camera's render pass.

##### <a class="anchor" id="bkmrk--26"></a>BreakNodeCamera2DRenderStrategy

In difference to 3D, [Candera](http://dev.doc.cgistudio.at/APILINK/namespace_candera.html "[DataBinding_RefTypeSample]") 2D Engine only provides a [Candera::BreakNodeCamera2DRenderStrategy](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_break_node_camera2_d_render_strategy.html "The BreakNodeCamera2DRenderStrategy is an implementation of the abstract class Camera2DRenderStrategy...") to split a 2D render pass along specific break nodes.

####   
**Limitations**

##### <a class="anchor" id="bkmrk--27"></a>MFR animation issue

Using an AnimationReq-Message in combination with MFR results in an wrong output since the animation progresses during each partial drawn frame. One idea is to check if the view uses MFR and if used the view would provide it's own AnimationTime-Dispatcher which only gets updated during the Update call. The animation for this view would then be added to this time dispatcher. This allows to use animations as long as they only affect a single scene.

##### <a class="anchor" id="bkmrk--28"></a>MFR transition issue

Using a Scene-Transition in combination with MFR results in an wrong output since the transition progresses during each partial drawn frame. Transitions should check the status of the camera and only perform a modification if the Render-Pass is complete. This would allow transitions to be used if only one Scene is active per Render-Target. To allow multiple scenes per Render-Target (more common case) all Cameras in the transition need to be "synced".

# VRAM Upload Culling

#### <a class="anchor" id="bkmrk--1"></a>Description

This chapter briefly describes how to use scope masks for uploading only dedicated content to VRAM.

#### **VRAM Upload using Scope Masks**

content to VRAM in succeeding steps.

##### <a class="anchor" id="bkmrk--3"></a>VRAM Upload Policies

Refer to <span style="color: rgb(230, 126, 35);">[Startup and Asset Management](https://doc316en.candera.eu/books/candera/page/startup-and-asset-management-LUu)</span> for how to load scenes from assets and upload to VRAM with the default upload policy [Candera::ContentLoader::DefaultUploadPolicy](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_content_loader.html#aeac726ed65d6cdb88644422ec9c5b0d2a374ada9b6b3da92611ff8e707530b68f "creates scene data in System RAM and uploads the asset data to VRAM").

To implement VRAM upload culling with scopes, use [Candera::ContentLoader::NoVramUploadPolicy](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_content_loader.html#aeac726ed65d6cdb88644422ec9c5b0d2a8646da23e8199f2db5a21b82b1ae1978 "creates scene data in System RAM but does not upload anything to VRAM") and upload dedicated content based on scope masks later.

##### <a class="anchor" id="bkmrk--4"></a>Scoping Concept

Refer to <span style="color: rgb(230, 126, 35);">[Scoping](https://doc316en.candera.eu/books/scene-design/chapter/scoping)</span> how to use and configure scope masks in SceneComposer.

####   
**Code Example**

The following scene graph is a simple example where two parts of the scene have different scopes. Think about a use case where one part of the scene has to be displayed immediately after loading the scene and the second part has to be displayed only later in some special situations. To save time for uploading the content to VRAM not all of the content has to be uploaded immediately.

<div drawio-diagram="1944"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676867547.png" alt=""/></div>

<div class="contents" id="bkmrk--0"><div class="contents"><div class="textblock">  
</div></div></div>##### <a class="anchor" id="bkmrk--6"></a>Using NoVramUploadPolicy

Loading the scene from the asset has to be triggered without loading the content to VRAM.

```
using namespace Candera;

<a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_content_loader.html" title="Encapsulates routines for scene content handling.">ContentLoader</a>& contentLoader = <a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_content_loader.html#a8d2faf2ac0af84444a4de43845c2e03e">ContentLoader::GetInstance</a>();
<a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_content_loader.html#abcb5725d1db1cae643a7d2e9fed85b91">ContentLoader::BuildState</a> buildState = contentLoader.BuildSceneContext("Scene", <a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_content_loader.html#aeac726ed65d6cdb88644422ec9c5b0d2a8646da23e8199f2db5a21b82b1ae1978" title="creates scene data in System RAM but does not upload anything to VRAM">ContentLoader::NoVramUploadPolicy</a>);
if (buildState == <a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_content_loader.html#abcb5725d1db1cae643a7d2e9fed85b91ac464d449fddc8a968cacd4f660dbd097" title="Completed.">ContentLoader::Completed</a>) {
    <a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_scene_context.html" title="Encapsulates main objects that define a scene context an application can operate on. These objects are:">SceneContext</a>* sceneContext = contentLoader.GetSceneContext("Scene");
    <a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_scene.html" title="The class Scene represents a top level scene graph node. Multiple Scenes are allowed. A Scene can not be part of any other Scene. To render a Scene, at least one Camera must be part of this Scene and the Camera must have rendering enabled. A Scene can have more than one Camera. Note: Lights added to a Scene apply for that Scene only and do not affect 3D objects in any other Scene.">Scene</a>* scene = sceneContext-><a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_scene_context.html#a895f11e8ee586e4e10649838cfd12dd7">GetScene</a>();
}
```

##### <a class="anchor" id="bkmrk--7"></a>Upload Nodes with Scope 1

```
using namespace Candera;

<a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_scope_mask.html" title="The class ScopeMask allows scene graph nodes to form conceptual groups independent of the scene graph...">ScopeMask</a> scopeMask1(false);            // all scopes are disabled...
scopeMask1.SetScopeEnabled(1, true);    // ...and only scope 1 gets enabled.
scene-><a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_scene.html#a324480706f8e985675e5fea454381150">Upload</a>(scopeMask1);
```

The scene can be rendered now as long as those nodes with scope 2 are not needed (e.g. rendering is disabled).

##### <a class="anchor" id="bkmrk--8"></a>Deferred Upload of Nodes with Scope 2

```
using namespace Candera;

<a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_scope_mask.html" title="The class ScopeMask allows scene graph nodes to form conceptual groups independent of the scene graph...">ScopeMask</a> scopeMask2(false);
scopeMask2.SetScopeEnabled(2, true);
scene-><a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_scene.html#a324480706f8e985675e5fea454381150">Upload</a>(scopeMask2);
```

Now the whole scene is uploaded to VRAM and can be rendered completely.

<div class="contents" id="bkmrk-in-that-simple-use-c"><div class="textblock"><dl class="note"><dt>  
</dt><dd><p class="callout info">In that simple use case the scopes are already set to the nodes e.g. during design phase in SceneComposer. The scopes can also be set during runtime by calling [Candera::Node::SetScopeMask()](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_node.html#a96af0d7869cd7b35b7f2a0a35a70a1f1) or [Candera::Node::SetScopeEnabled()](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_node.html#abefd359cba7184aec9f2ebd7b9ab31e0).</p>

<p class="callout info">This example is written for [Candera](http://dev.doc.cgistudio.at/APILINK/namespace_candera.html "[DataBinding_RefTypeSample]") 3D, for 2D please refer to [Candera::Scene2D::Upload()](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_scene2_d.html#a1d21f1e09ea51bd1ac741fc5ae8d2e3b), [Candera::Node2D::SetScopeMask()](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_node2_d.html#af111a4667a3507d78b01814c6e132281) and [Candera::Node2D::SetScopeEnabled()](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_node2_d.html#aaa166796aff943249b32e4c2ad7e20ae).</p>

</dd></dl></div></div>

# Occlusion Queries and Occlusion Culling

#### <a class="anchor" id="bkmrk--1"></a>Description

In scenes containing nodes with lots of vertices or expensive fragment shaders, the rendering speed can be drastically improved by avoiding to render occluded objects. For this purpose [Candera](http://dev.doc.cgistudio.at/APILINK/namespace_candera.html "[DataBinding_RefTypeSample]") offers the Occlusion Queries and Occlusion Culling, which are described on this page.

#### **Occlusion Queries**

##### <a class="anchor" id="bkmrk--2"></a>Overview

Occlusion queries are the collective name for a particular type of queries, which are useful to detect whether an object is visible or not. They interrogate asynchronously the Render Device to determine whether the scoped rendering commands pass the depth test and if so, how many samples pass. Occlusion queries are typically used to enable features like occlusion culling and varying lens flare or bloom intensity.

<div class="contents" id="bkmrk-queries-are-related-"><div class="contents"><div class="textblock"><dl class="note"><dt></dt><dd><p class="callout info">Queries are related to one specific rendering context and must not be uploaded to multiple contexts.</p>

</dd><dd></dd></dl></div></div></div>##### <a class="anchor" id="bkmrk--3"></a>Occlusion Query Types

There are three types of occlusion queries:

<div class="contents" id="bkmrk-query%3A%3Aqueryanysampl"><div class="contents"><div class="textblock">- [Query::QueryAnySamplesPassed](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_query.html#aeef30513e21344092b50c82f7ddf6ccda7141400f708d270e4f8b95b4ca3f5a7f "Query determines if any sample passes the depth test."): query determines, if any sample passes the depth test.
- [Query::QueryAnySamplesPassedConservative](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_query.html#aeef30513e21344092b50c82f7ddf6ccdaa69721a27042afb9796561f3a7d17099 "Similar to QueryAnySamplesPassed type, but less precise for queries performance's sake..."): similar to QueryAnySamplesPassed type except that the implementation may use a less accurate algorithm, which may be faster, but at the cost of more false positives.
- [Query::QueryTransformFeedbackPrimitivesWritten](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_query.html#aeef30513e21344092b50c82f7ddf6ccda9d24a7bd8b750118dc44517bc7b82cba "Query determines how many vertices have been written into bound transform feedback buffer(s)..."): query determines how many vertices have been written into bound transform feedback buffer.

</div></div></div>##### <a class="anchor" id="bkmrk--4"></a>Conditional Rendering Example

The figure below depicts the demand for occlusion queries to determine and subsequently discard occluded objects in a highly populated scene:

<div drawio-diagram="1943"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676863030.png" alt=""/></div>

<div class="contents" id="bkmrk--0"><div class="contents"><div class="textblock">  
</div></div></div>Find below an abstract code sample for occlusion queries to obtain information whether any pixels have been rendered or not:

```
SharedPointer<Query> query;
query = <a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_query.html#ad85249a37de10608cb92612c8c7784e6">Query::Create</a>(<a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_query.html#aeef30513e21344092b50c82f7ddf6ccda7141400f708d270e4f8b95b4ca3f5a7f" title="Query determines if any sample passes the depth test.">Query::QueryAnySamplesPassed</a>);
query.Upload();
query.Begin(); 

// Do some rendering here.

query.End(); 

// Process other operations to provide GPU with sufficient time to complete query or skip query evaluation, if result is not available yet.

if (query.IsResultAvailable()) {
    if (query.GetResult() > 0)) {
        // Samples have been written to framebuffer while query was active, this is between query.Begin() and query.End().
        // In case low resolution model was rendered, render next frame with high resolution model.
    }
    else {
        // No sample has been written to framebuffer while query was active.
        // In case high resolution model was rendered, render next frame with low resolution model.
    }
}
```

####   
**Occlusion Culling**

##### <a class="anchor" id="bkmrk--6"></a>Overview

Occlusion Culling is a feature that disables rendering of objects when they are not currently seen by the camera because they are obscured by other objects. The feature can be enabled by setting the render strategy for camera to [OcclusionCullingCameraRenderStrategy](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_occlusion_culling_camera_render_strategy.html "The class OcclusionCullingCameraRenderStrategy is an implementation of the abstract class CameraRende..."). During the rendering, all nodes initialized by the strategy will issue occlusion queries. If query results are available from the previous frame, they are evaluated and all nodes deemed occluded will have their bounding box rendered invisibly instead of the node itself. Visible nodes, or nodes not having a QueryProperty attached, will be rendered as usual. A new query to determine visibility for the next frame will be issued regardless the result of the previous query.

<div class="contents" id="bkmrk-a-performance-increa"><div class="contents"><div class="textblock"><dl class="note"><dd><p class="callout info">A performance increase by using occlusion culling can only be expected when objects occlude each other, and occluded objects consist of lots of vertices, have expensive fragment shaders, or both.</p>

</dd></dl></div></div></div>##### <a class="anchor" id="bkmrk--7"></a>Workflow

<div class="contents" id="bkmrk-attach-an-occlusionc"><div class="contents"><div class="contents"><div class="textblock">- Attach an [OcclusionCullingCameraRenderStrategy](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_occlusion_culling_camera_render_strategy.html "The class OcclusionCullingCameraRenderStrategy is an implementation of the abstract class CameraRende...") to the camera.

<div class="fragment">  
</div></div></div></div></div>```
    m_occlusionCullingStrategy = CANDERA_NEW(OcclusionCullingCameraRenderStrategy)();
    m_camera->SetCameraRenderStrategy(m_occlusionCullingStrategy);
```

<div class="contents" id="bkmrk-initialize-the-rootn"><div class="contents"><div class="contents"><div class="textblock"><div class="fragment">  
</div>- Initialize the rootNode's subtree for use by the render strategy.

<div class="fragment">  
</div></div></div></div></div>```
    m_occlusionCullingStrategy->Initialize(m_group, <a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_query.html#aeef30513e21344092b50c82f7ddf6ccdaa69721a27042afb9796561f3a7d17099" title="Similar to QueryAnySamplesPassed type, but less precise for queries performance's sake...">Query::QueryAnySamplesPassedConservative</a>);
```

<div class="contents" id="bkmrk-this-camera-render-s"><div class="contents"><div class="textblock"><dl class="note"><dd><dl class="note"><dd><p class="callout info">This camera render strategy requires nodes to have a valid bounding box. This camera render strategy reaches its full potential when nodes were sorted front to back first.</p>

</dd></dl></dd><dd></dd></dl></div></div></div><div class="contents" id="bkmrk-render-camera-m_gdu-"><div class="contents"><div class="contents"><div class="textblock">- Render camera ```
        m_gdu->ToRenderTarget3D()->Activate();
        RenderDevice::ClearDepthBuffer(1.0f);
        <a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_renderer.html#aed822ba1d66620f2d1e794973e30f354">Renderer::RenderAllCameras</a>();
    ```

- [OcclusionCullingCameraRenderStrategy](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_occlusion_culling_camera_render_strategy.html "The class OcclusionCullingCameraRenderStrategy is an implementation of the abstract class CameraRende...") interface provides also methods to get the number of occluded and non-occluded nodes since last render pass by using the methods [OcclusionCullingCameraRenderStrategy::GetOccludedNodesCount()](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_occlusion_culling_camera_render_strategy.html#a11ffc92413b74687427d05eee20be52c) and [OcclusionCullingCameraRenderStrategy::GetVisibleNodesCount()](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_occlusion_culling_camera_render_strategy.html#a26d3bf20b6c9bc588efe5e4aa52e29a5).

- Before destroying the render strategy remove the association with nodes by calling the [OcclusionCullingCameraRenderStrategy::Reset()](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_occlusion_culling_camera_render_strategy.html#a214a77f084e490f73e74eb107f7556e0) method

<div class="fragment">  
</div></div></div></div></div>```
    m_occlusionCullingStrategy->Reset(m_group);
    CANDERA_DELETE(m_occlusionCullingStrategy);
```

<div class="contents" id="bkmrk-the-nodes-removed-fr"><div class="contents"><div class="textblock"><dl class="note"><dd><p class="callout info">The nodes removed from the subtree are automatically detached from the render strategy</p>

</dd></dl></div></div></div>##### <a class="anchor" id="bkmrk--8"></a>Occlusion Culling in SceneComposer

Refer to chapter<span style="color: rgb(230, 126, 35);"> [Occlusion Culling](https://doc316en.candera.eu/link/130#bkmrk-%C2%A0occlusion-culling-0)</span> to see how to configure occlusion culling in SceneComposer.

# Bitmap Compression

#### Introduction

Bitmap compression aims to improve the application performance by reducing the bandwidth consumption and asset size and also by speeding up the bitmaps load and upload.

Candera supports following formats for compressing bitmaps, that are described in detail on this page:

- <span style="color: rgb(0, 0, 0);">Run-legth Encoding </span>
- <span style="color: rgb(0, 0, 0);">Color Look-Up Table </span>
- <span style="color: rgb(0, 0, 0);">Erricson Texture Compression </span>

#### **Run-legth Encoding**

##### <a class="anchor" id="bkmrk--1"></a>Description

**Run-length encoding** (RLE) is a simple form of data compression in which runs of data are stored as a single data value and count, rather than as the original run. This is most useful on data that contains many such runs so, the content of the data will affect the compression ratio achieved by RLE. Although most RLE algorithms cannot achieve the high compression ratios of the more advanced compression methods, RLE is both easy to implement and quick to execute, making it a good alternative to either using a complex compression algorithm or leaving the image data uncompressed.

##### <a class="anchor" id="bkmrk--2"></a>RLE compression example

For example, consider an image containing plain black text on a solid white background. There will be many long runs of white pixels in the blank space, and many short runs of black pixels within the text. A hypothetical scan line, with B representing a black pixel and W representing white, might read as follows:

```
    WWWWWWWWWWBBWWWWWBWWWWWWWWWWW

```

With a run-length encoding (RLE) data compression algorithm applied to the above hypothetical scan line, it can be rendered as follows:

```
    10W2B5W1B11W

```

The run-length code represents the original 30 characters in only 13.

##### <a class="anchor" id="bkmrk--3"></a>RLE Compression in SC

You can take advantage of using the RLE compression on a bitmap by setting an appropriate pair of converter and format for its bitmap profile as described in the SceneComposer documentation in the <span style="color: rgb(230, 126, 35);">[Bitmap Profile](https://doc316en.candera.eu/books/solution-handling/page/bitmap-profile)</span> chapter.

####   
**Color Look-Up Table**

##### <a class="anchor" id="bkmrk--4"></a>Description

A **color lookup table** (CLUT) is a table which associates a numeric pixel value with a color to be displayed on the output device. The color is typically specified as a mixture of varying levels of alpha, red, green, and blue, and thus a color lookup table will usually contain three or four components for each possible pixel value. The number of entries in the palette determines the maximum number of colours which can appear simultaneously in the bitmap. Changes to the palette affect the whole image at once and can be used to produce special effects which would be much slower to produce by updating pixels.

##### <a class="anchor" id="bkmrk--5"></a>CLUT Example

For instance, if a CLUT bitmap has a palette of 256 available colors, the index can be represented by an 8-bit value. The color table is then used to lookup a corresponding 24-bit color value (eight bits of red, green, and blue). Thus, comparing to a full RGB color bitmap, the CLUT bitmap size is roughly one-third.

<div drawio-diagram="1858"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676624256.png" alt=""/></div>

<div class="contents" id="bkmrk--0"><div class="contents"><div class="textblock">  
</div></div></div>The key to the efficiency of the indexed color approach is limiting the number of colors that can be represented.

##### <a class="anchor" id="bkmrk--7"></a>CLUT Compression in SC

In order to use CLUT compression, set the bitmap with a bitmap profile that uses an appropriate converter and one of the 72 preset CLUT compressions as format. Please consult in the SceneComposer documentation the <span style="color: rgb(230, 126, 35);">[Bitmap Profile](https://doc316en.candera.eu/books/solution-handling/page/bitmap-profile)</span> chapter for more details.

####   
**Erricson Texture Compression**

##### <a class="anchor" id="bkmrk--8"></a>Description

**Ericsson Texture Compression** (ETC) is a lossy texture compression scheme which was mandated as part of the OpenGL ES specification for the versions **3.0** and **4.3**. The original 'ETC1' compression scheme provides 6x compression of 24-bit RGB data and it does not support the compression of images with Alpha components. 'ETC2' is an updated version of 'ETC1' which offers higher quality than its predecessor and also introduces support for alpha pixels and R-/RG- textures.

ETC2 allows for more textures to fit in video memory, leads to less traffic on the bus for higher performance and lower power consumption, and it becomes cheaper to transit textures over networks.

The following ETC2 codecs are supported in [Candera](http://dev.doc.cgistudio.at/APILINK/namespace_candera.html "[DataBinding_RefTypeSample]"):

<div class="contents" id="bkmrk-candera%3A%3Abitmap%3A%3Aetc"><div class="contents"><div class="textblock">- [Candera::Bitmap::Etc2CompressedRgbPixelFormat](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_bitmap.html#a0028006b9fd5b6e630bc6aca572603cba46051977a6b00299db944cb2b398fd2f "4 bpp compressed RGB") : Compresses RGB888 data.
- [Candera::Bitmap::Etc2EacCompressedRgbaPixelFormat](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_bitmap.html#a0028006b9fd5b6e630bc6aca572603cba1e1416879d629186bb86392df53fb873 "8 bpp compressed RGBA") : Compresses RGBA8888 data with full alpha support.
- [Candera::Bitmap::Etc2Alpha1CompressedRgbaPixelFormat](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_bitmap.html#a0028006b9fd5b6e630bc6aca572603cba7d473bd019630a4cfd4153ccb30e4521 "4 bpp compressed RGBA with binary Alpha values") : Compresses RGBA data where pixels are either fully transparent or fully opaque.

</div></div></div>sRGB variants of the above codecs are also available.

EAC is built on the same principles as ETC1/ETC2 but is used for one- or two-channel data. The following EAC codecs are supported:

<div class="contents" id="bkmrk-candera%3A%3Abitmap%3A%3Aeac"><div class="contents"><div class="textblock">- [Candera::Bitmap::EacCompressedUnsignedRPixelFormat](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_bitmap.html#a0028006b9fd5b6e630bc6aca572603cba447be8300c1f43a03411c80e5ed302cf "4 bpp compressed single channel unsigned R format") : 4 bpp compressed single channel unsigned R format
- [Candera::Bitmap::EacCompressedSignedRPixelFormat](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_bitmap.html#a0028006b9fd5b6e630bc6aca572603cbac2fb78a1508e725fcbc20ceb8d57d7cc "4 bpp compressed single channel signed R format (can preserve 0 exactly)") : 4 bpp compressed single channel signed R format (can preserve 0 exactly)
- [Candera::Bitmap::EacCompressedUnsignedRGPixelFormat](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_bitmap.html#a0028006b9fd5b6e630bc6aca572603cba1082969c6760b1bac6f2b8293e861283 "8 bpp compressed two channel unsigned RG format") : 8 bpp compressed two channel unsigned RG format
- [Candera::Bitmap::EacCompressedSignedRGPixelFormat](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_bitmap.html#a0028006b9fd5b6e630bc6aca572603cbaf0c9b02e215af0f20d0b6089433f8ce8 "8 bpp compressed two channel signed RG format (can preserve 0 exactly)") : 8 bpp compressed two channel signed RG format (can preserve 0 exactly)

</div></div></div>##### <a class="anchor" id="bkmrk--9"></a>ETC2/EAC Compression in SC

Please consult in the SceneComposer documentation the chapter <span style="color: rgb(230, 126, 35);">[Import .KTX Image Format](https://doc316en.candera.eu/link/1101#bkmrk-import-file-formats)</span>, to find out how to generate and import ETC2/EAC compressed textures.

# Drawcall Batching/Geometry Instancing

#### <a class="anchor" id="bkmrk--7"></a>Description

This chapter describes how Candera's Drawcall Batching utilizes Geometry Instancing and how to set it up.

#### **Introduction**

OpenGL ES3.0 introduced a feature called Geometry Instancing. With this feature, a vertex buffer can be drawn several times using a single draw call. This single draw call uses exactly one shader and render state for all instances of that vertex buffer. The instances can have different shader parameters to individually customize their appearance on screen. Basically, this feature renders multiple copies of the same mesh at once, with the ability to parameterize each copy.

##### <a class="anchor" id="bkmrk--8"></a>Use Case

Whenever objects share a mesh, render state, shader and textures, these are potential candidates for geometry instancing. E.g. trees that only have a different size and color, houses which share the same shader using a uniform as an offset for a shared texture atlas, street lamps, or any other recurring or repeating geometry that only differs in shader parameters is a use case for geometry instancing.

##### <a class="anchor" id="bkmrk--9"></a>Motivation

Submitting drawcalls to the GPU is a relatively slow operation due to the necessary overhead caused by OpenGL and the driver. When drawing thousands of small objects individually, chances are that this overhead is leaving the GPU underutilized, and thus becoming a bottleneck. In such a scenario, batching several objects together to be submitted in a single drawcall decreases the total CPU overhead to be performed, which in turn increases overall performance.

<div class="contents" id="bkmrk-the-gpu-still-has-to"><div class="textblock"><dl class="note"><dt></dt><dd><p class="callout info">The GPU still has to perform the same amount of work, so if the bottleneck of your application is the GPU (e.g. pixel or vertex operations are the limiting factor), don't expect significant performance gains by using geometry instancing.</p>

</dd></dl></div></div>####   
**Geometry Instancing and Shaders**  


Dedicated shaders are required to utilize geometry instancing. In a shader the reserved keyword *gl\_InstanceID* represents the index of the instance currently being rendered. This index can be used to fetch instance specific parameters from arrays of uniforms.

Example of a geometry instancing vertex shader:

```
/* Uniforms */
#define MAX_INSTANCE_COUNT 100                 // Used for the size of the uniform arrays
uniform mat4 u_MVPMatrix[MAX_INSTANCE_COUNT];  // Model-View-Projection matrices for each instance
uniform vec4 u_Color[MAX_INSTANCE_COUNT];      // Color for each instance

/* Attributes */
in vec4 a_Position;

/* Varyings */
out mediump vec4 v_Color;

void main(void)
{
    /* Transform vertex into world space using the MVP matrix of the instance indexed by gl_InstanceID */
    gl_Position = u_MVPMatrix[gl_InstanceID] * a_Position;

    /* Pass the color of the instance indexed by gl_InstanceID to the pixel shader */
    v_Color = u_Color[gl_InstanceID];
}
```

The pixel shader for the vertex shader above:

```
in mediump vec4 v_Color;
out mediump vec4 FragColor;

void main(void)
{    
    FragColor = v_Color;
}
```

<div class="contents" id="bkmrk-opengl-es3.0-pixel-s"><div class="contents"><div class="textblock"><div class="fragment">  
</div><dl class="note"><dt></dt><dd><p class="callout info">OpenGL ES3.0 pixel shaders can only index uniform arrays using a constant index. Therefore the vertex shader has to index and pass any uniforms required by the pixel shader.</p>

</dd></dl></div></div></div>This shader uses a different color and model view projection matrix for each instance of the mesh. It supports drawing of up to 100 (MAX\_INSTANCE\_COUNT) instances. Therefore the model view projection matrix array and the color array have a size of 100 to hold the individual values for each instance. The maximum array size that can be used depends on the total number of uniforms in the shader as well as the target platform.

<div class="contents" id="bkmrk-array-sizes-that-are"><div class="contents"><div class="textblock"><dl class="note"><dt></dt><dd><p class="callout info">Array sizes that are too big for the platform will not throw an error during shader compilation, but only during linking the shader. Therefore you have to export shader binaries to verify if the shader can be used on your target platform.</p>

</dd></dl></div></div></div>#### **Geometry Instancing in Candera**  


Candera does not expose geometry instancing explicitly, instead it is used automatically (if possible). This approach is called **Drawcall Batching**.   
After renderable objects have been culled and sorted (ideally by the BatchOrderCriterion to produce as big sequences of batchable objects as possible), the Renderer identifies sequences of objects that can be batched, and submits those objects in a single drawcall using geometry instancing. Each such sequence is a batch. Each batch corresponds to one draw call.

##### <a class="anchor" id="bkmrk--10"></a>Prerequisites for Drawcall Batching

The following list of prerequisites must be met to facilitate draw call batching in [Candera](http://dev.doc.cgistudio.at/APILINK/namespace_candera.html "[DataBinding_RefTypeSample]"):

<div class="contents" id="bkmrk-the-target-platform-"><div class="contents"><div class="textblock">- The target platform must support geometry instancing (i.e. OpenGL ES3.0 or better).
- The object must be a Mesh or PointSprite (Billboard, LineList, MorphingMesh are currently not supported).
- The object must have an Appearance.
- The Appearance must not be a multi-pass appearance.
- The Appearance must have a Shader with a maximum instance count bigger than 1. I.e. the shader supports instancing.
- The Appearance must have a ShaderParamSetter.
- The ShaderParamSetter must support instancing. (Candera's ShaderParamSetter and GenericShaderParamSetter support instancing. Existing custom AbstractShaderParamSetter implementations will need to be adapted to support instancing.) 
    - If a GenericShaderParamSetter is used with lights activation enabled, the light coordinate space must be World space.
- Objects to be batched must share: 
    - the VertexBuffer
    - the RenderMode
    - the Shader
    - the Textures

</div></div></div><div class="contents" id="bkmrk-if-objects-share-an-"><div class="contents"><div class="textblock"><dl class="note"><dd><p class="callout info">If objects share an Appearance, they automatically share the RenderMode, Shader, and Textures, too.</p>

</dd></dl></div></div></div>##### <a class="anchor" id="bkmrk--11"></a>How to increase the Drawcall Batching rate.

Share as much vertex buffers and appearances between objects as possible. If sharing the appearance is not possible (e.g. because different materials, and/or shader parameter setters have to be used, which results in different appearances), share as much shaders, render modes and textures as possible.

The Renderer does not alter the order of contents of RenderOrderBins. In order to maximize the drawcall batching rate (i.e. the amount of objects that are batched versus the total amount of objects), objects have to be sorted by the criteria matching the prerequisites listed above. Candera'a BatchOrderCriterion offers two sorting modes to facilitate batching:

<div class="contents" id="bkmrk-sort-by-appearance-s"><div class="contents"><div class="textblock">- Sort by Appearance
- Sort by Shader and RenderMode

</div></div></div>Both modes sort by the Batchable flag (used by Mesh and PointSprite), the VertexBuffex, and either Appearance or Shader plus RenderMode to produce batches.

#### **Drawcall Batching in SceneComposer**

To configure SceneComposer solutions for drawcall batching, the following steps have to be performed:

##### <a class="anchor" id="bkmrk--12"></a>Use an instanceable shader

The shader of an object must support instancing. See <span style="color: rgb(230, 126, 35);">[this section](https://doc316en.candera.eu/link/380#bkmrk-geometry-instancing--0)</span> for a detailed explanation.

If a shader was recognized as instanceable by SceneComposer, "Max Instance Count" listed in the Properties of the Shader is bigger than one. The shader in the following example is able to draw batches of up to 50 instances.

<div drawio-diagram="1848"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676622527.png" alt=""/></div>

<div class="contents" id="bkmrk--0"><div class="contents"><div class="textblock"><div class="image">  
</div></div></div></div>##### <a class="anchor" id="bkmrk--14"></a>Configure the Uniform Setter

If the shader uses lighting, the Light Coordinate Space must be set to World.

<div drawio-diagram="1849"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676622549.png" alt=""/></div>

<div class="contents" id="bkmrk--2"><div class="contents"><div class="textblock"><div class="image">  
</div></div></div></div>##### <a class="anchor" id="bkmrk--16"></a>Share Assets

To utilize drawcall batching, vertex buffers, shaders, render modes and textures have to be shared as detailed in <span style="color: rgb(230, 126, 35);">[this section](#bkmrk-geometry-instancing--0)</span>.

SceneComposer offers the option to optimize asset usage by identifying assets that are identical and substituting these assets by a single shared instance. After selecting a node or a group, and pressing the right mouse button, the following context menu will appear:

<div drawio-diagram="1850"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676622577.png" alt=""/></div>

<div class="contents" id="bkmrk-selecting-%22node-atta"><div class="contents"><div class="textblock"><div class="image">Selecting "Node Attachment Optimization" will launch the following window, where you can select which assets should be optimized, and initiate the optimization:  
</div><div class="image"><div drawio-diagram="1851"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676622590.png" alt=""/></div>

</div></div></div></div><div class="contents" id="bkmrk--4"><div class="contents"><div class="textblock"><div class="image">  
</div></div></div></div>##### <a class="anchor" id="bkmrk--19"></a>Sort Render Order Bins using the Batch Order Sort Criterion

To maximize the [batching rate](http://dev.doc.cgistudio.at/APILINK/_p_i_d__a_p_p_d_e_v_t_u_t_chapter_09_drawcall_batching_03.html#BatchingRate), use "Batch Order" as the Render Order Bin's sort criterion.

<div drawio-diagram="1852"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676622607.png" alt=""/></div>

<div class="contents" id="bkmrk-if-the-scene-uses-a-"><div class="contents"><div class="textblock">If the scene uses a lot of different appearances (e.g. with different Materials), that share a shader, render mode, and textures, the batch order criterion "SortByShaderAndRenderMode" might achieve a better batching rate then "SortByAppearance". Use the Renderer Statistics to verify which criterion works best with the given content.  
</div></div></div><div class="contents" id="bkmrk-a-render-strategy-se"><div class="contents"><div class="textblock"><dl class="note"><dd><p class="callout info">A Render Strategy set on a camera can influence batching. E.g. the Occlusion Culling, and the Benchmark Render Strategy do not utilize drawcall batching due to their specific needs.</p>

</dd><dd></dd></dl></div></div></div>#####   


##### <a class="anchor" id="bkmrk--21"></a>Renderer Statistics

The Renderer Statistics window (which can be opened via View-&gt;Renderer Statistics), provides per frame information about what is being drawn by the cameras in the current scene. The values are updated in realtime, and directly correspond to the rendering performed in the "Display" window.

<div drawio-diagram="1853"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676622641.png" alt=""/></div>

<div class="contents" id="bkmrk-in-this-example-231-"><div class="contents"><div class="textblock"><div class="image">In this example 231 cubes are rendered using 5 draw calls. All 231 cubes are batched (i.e. instanced), therefore they are counted as "batched draw calls".  
</div></div></div></div>

# Courier Specific

#### **MFR - Multi-Frequency Rendering in Courier**   


Multi-Frequency rendering in [Courier](http://dev.doc.cgistudio.at/APILINK/namespace_courier.html) can be used to create custom sort criteria for the render jobs.

By default, the [Courier::RenderJobStrategy](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_render_job_strategy.html) sorts them like this:

<div class="contents" id="bkmrk-offscreen-render-job"><div class="contents"><div class="textblock">- offscreen render jobs before Display render jobs.
- 2d render jobs before 3d render jobs
- clear render jobs before normal view render jobs
- lower camera sequence number before higher camera sequence number

</div></div></div>One can create a custom sort criteria, simply by deriving from [Courier::RenderJobStrategy](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_render_job_strategy.html) and then use the [Courier::Renderer::SetRenderJobStrategy()](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_renderer.html#a2f24a34cfa676ab7fd71ca48edc4f5f3 "Set a custom RenderJobStrategy.") method to use this custom one.IE: SampleApp.cpp mRenderer.SetRenderJobStrategy(CANDERA\_NEW(PriorityRenderJobStrategy)(1000));

For example, PriorityRenderStrategy class uses such a custom sort criteria.

In this sample, the PriorityRenderStrategy demonstrates the ability to use the Renderer to sort the render targets depending on the layer they are on, and the sequence number of the associated camera.

```
bool PriorityRenderJobStrategy::IsPriorityRenderJob(const <a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_render_job.html">Courier::RenderJob</a>& renderJob) const
{
    bool res;
    if (renderJob.IsClear()) {
        res = IsPriorityRenderTarget(renderJob.GetGdu());
        return res;
    }
    res = GetRenderJobCameraSequenceNumber(renderJob) <= m_lastPriorityCameraSequenceNumber;
    return res;
}

// ------------------------------------------------------------------------
bool PriorityRenderJobStrategy::IsPriorityRenderTarget(<a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_gdu.html">Courier::Gdu</a>* gdu) const
{
    for (FeatStd::Int i = 0; i < m_priorityRenderTargets.Size(); ++i) {
        if (gdu == m_priorityRenderTargets[i]) {
            return true;
        }
    }
    return false;
}
```

Also as you can see in RenderTargetPerformanceData class, we can compute the cost of rendering a frame and see how many frame drops we had.

The PriorityRenderStrategy uses two other classes, PriorityCamera2DRenderStrategy and PriorityCamera3DRenderStrategy which are derived from RendererListenerBase, and [Candera::Camera2DRenderStrategy](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_camera2_d_render_strategy.html "The abstract class Camera2DRenderStrategy is intended to be derived in order to tell the Renderer2D...") and these classes compute the render cost for each node.

Example of the application running:

<div drawio-diagram="1824"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676621611.png" alt=""/></div>

<div class="contents" id="bkmrk--0"><div class="contents"><div class="textblock"><div class="image">  
</div><div class="image">  
</div></div></div></div>As you can see, the FPS is kept the same for all the layers, but the drops vary depending on the Layer/Nodes/Camera Sequence Number of each render target, some of the render jobs being skipped by the custom sort criteria in the PriorityRenderStrategy class.

In the sample output, red arrows mark skipped render jobs:

<div drawio-diagram="1825"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676621631.png" alt=""/></div>

<div class="contents" id="bkmrk--2"><div class="contents"><div class="textblock"><div class="image">  
</div></div></div></div>##### <a class="anchor" id="bkmrk--17"></a>SceneComposer solution

In this demo application, there are three layers: Layer0, Layer1 and Layer2 displayed bellow:

<div drawio-diagram="1827"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676621655.png" alt=""/></div>

<div class="contents" id="bkmrk--4"><div class="contents"><div class="textblock"><div class="image">  
</div></div></div></div>For Layer 2 – which has the most content – the backgrounds, the respective cameras have the highest Sequence Number to have priority being rendered.

<div drawio-diagram="1828"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676621683.png" alt=""/></div>

<div class="contents" id="bkmrk--6"><div class="textblock"><div class="image">  
</div></div></div>#### **Invalidation**   


##### <a class="anchor" id="bkmrk--20"></a>Description

[Courier](http://dev.doc.cgistudio.at/APILINK/namespace_courier.html) introduces an invalidation mechanism by providing [Courier::FrameworkWidget::Invalidate](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_framework_widget.html#a40c3fcf4c499f73e8e9156bef1f78a79 "Invalidates the parent view.") and [Courier::View::Invalidate](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_view.html#ab0c2b9e33adfb550d0ad840d082b1955) methods, which shall be called if ViewScenes Candera::Camera(s) shall be rendered. Only enabled and invalidated cameras will be rendered. Cameras can be enabled/disabled by sending the appropriate [Courier::ActivationReqMsg](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_activation_req_msg.html) or by manually maintaining the state of the cameras via widget implementation.

The invalidation of the cameras causes appending a [Courier::RenderJob](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_render_job.html) to a [Courier::RenderJobs](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_render_jobs.html) array inside the [Courier::Renderer](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_renderer.html). This array is then used for rendering the cameras when [Courier::RenderComponent](http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___f_o_u_n_d_a_t_i_o_n.html#ga111beafd1fd94fe52d99eda8c752bcbf "RenderComponent renders both 2D and 3D Views.") executes the Render method. If the render counter of a RenderJob reaches 0 then the RenderJob is removed from the array of RenderJobs. If a new RenderJob is appended with an already existing RenderJob for this camera, the older entry will be removed.

2D and 3D RenderJobs are processed in their own arrays. This is necessary because of above threading configuration scenarios.   
Every Candera::Rendertarget used by a rendered camera will be swapped once after rendering the cameras.

A more specific method of invalidation is the usage of the methods:

<div class="contents" id="bkmrk-courier%3A%3Aviewscene2d"><div class="contents"><div class="textblock">- [Courier::ViewScene2D::Invalidate](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_view_scene2_d.html#aa5d29150c17c8b7c3029229f323c20d3)([Candera::Camera2D](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_camera2_d.html "A camera defines the view to the scene. At least one Camera2D has to be added to a 2D scene graph and...") \* invalidatedCamera, UInt8 renderCounter = cDefaultRenderCounter)
- [Courier::ViewScene3D::Invalidate](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_view_scene3_d.html#afe6364fea300839ec5c7147212cc8fb2)([Candera::Camera](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_camera.html "A Camera provides Modelview and Projection matrices. Camera is a Transformable.* The eye point is set...") \* invalidatedCamera, UInt8 renderCounter = cDefaultRenderCounter)

</div></div></div>Those methods allow invalidating the specified cameras (not necessarily all cameras of a view) and might also be used in the widget implementations. The widget has therefore use method [Courier::FrameworkWidget::GetParentView](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_framework_widget.html#a54ff7d5327313cf9350937c0b2868c0c "Returns the parent view."), cast the returned pointer to ViewScene2D or ViewScene3D and then call the appropriate 2D or 3D Invalidation method.

##### <a class="anchor" id="bkmrk--21"></a>Update &amp; Invalidation Sample

For example the BindeableValueWidget in our GettingStarted App invalidates if the bound value has changed and it shall be redrawn.

```
void <a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_bindable_value_widget_base.html#a5da105c5b7bcdbde7322baa16b036906">BindableValueWidget::OnChanged</a>(Candera::UInt32 propertyId)
{
    if(!mBuffered) {
        if(propertyId == ValuePropertyId) {
            UpdateValue(GetValue());
        }
        <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___v_i_s_u_a_l_i_z_a_t_i_o_n.html#ggaf0e93dc4242f607c3c8d13dafd036af9a7e58b417e215e88881554ef892d19906">Invalidate</a>();
    }
}
```

<div class="contents" id="bkmrk--7"><div class="contents"><div class="textblock"><div class="fragment">  
</div>---

</div></div></div>##### <a class="anchor" id="bkmrk--22"></a>Invalidation in General

Most views are not overlapping, so there is no dependency between the displayed view. However, depending on the design, this may not always be the case.

The following examples demonstrate various combinations of overlapping views and their dependencies regarding invalidation:

##### <a class="anchor" id="bkmrk--23"></a>Example 1

<div class="contents" id="bkmrk-whenever-view2-is-in"><div class="contents"><div class="contents"><div class="textblock"><table border="0" style="width: 100%;"><tbody><tr><td style="width: 37.3334%;">[![invalidation1.png](https://doc316en.candera.eu/uploads/images/gallery/2023-02/scaled-1680-/invalidation1.png)](https://doc316en.candera.eu/uploads/images/gallery/2023-02/invalidation1.png)

</td><td style="vertical-align: top; width: 62.6666%;" valign="top">Whenever View2 is invalidated, View1 must be invalidated too, because they are overlapping. View3 has to be invalidated as well, because it is overlapping with View2.

<table border="0"><tbody><tr><td colspan="3">View2 is invalidated</td></tr><tr><td>-&gt;</td><td colspan="2">Overlap with View1</td></tr><tr><td>-&gt;</td><td colspan="2">View 1 must be invalidated</td></tr><tr><td>  
</td><td>-&gt;</td><td>Overlap with View3</td></tr><tr><td>  
</td><td>-&gt;</td><td>View3 must be invalidated</td></tr></tbody></table>

</td></tr></tbody></table>

</div></div></div></div><div drawio-diagram="1836"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676621892.png" alt=""/></div>

<div class="contents" id="bkmrk--9"><div class="contents"><div class="textblock">  
</div></div></div>When a ViewContainer ("Folder" in SceneComposer) is invalidated, all its child views are invalidated.  
View1-3 can set an invalidation dependency to the ViewGroup "Folder" to implement the mutual invalidation.

##### <a class="anchor" id="bkmrk--25"></a>Example 2

This is a possible solution for a shared background: Split the background into multiple views.

<div class="contents" id="bkmrk-view2-is-invalidated"><div class="contents"><div class="contents"><div class="textblock"><table border="1" style="border-collapse: collapse; width: 100%; border-width: 0px;"><tbody><tr><td style="width: 42.507%; border-width: 0px;">[![invalidation3.png](https://doc316en.candera.eu/uploads/images/gallery/2023-02/scaled-1680-/invalidation3.png)](https://doc316en.candera.eu/uploads/images/gallery/2023-02/invalidation3.png)

</td><td style="vertical-align: top; width: 57.493%; border-width: 0px;" valign="top">View2 is invalidated  
-&gt; Overlap with View 1.1  
-&gt; View 1.1 must be invalidated  
  
View 3 is invalidated  
-&gt; Overlap with View 1.2  
-&gt; View 1.2 must be invalidated  
</td></tr></tbody></table>

</div></div></div></div><div drawio-diagram="1838"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676621966.png" alt=""/></div>

<div class="contents" id="bkmrk--11"><div class="contents"><div class="textblock">  
</div></div></div>##### <a class="anchor" id="bkmrk--27"></a>Example 3

Sometimes overlap can not be avoided because of the design.

<div class="contents" id="bkmrk-an-invalidation-depe"><div class="contents"><div class="textblock"><table border="1" style="border-collapse: collapse; width: 100%; border-width: 0px;"><tbody><tr><td style="width: 41.1797%; border-width: 0px;">[![invalidation5.png](https://doc316en.candera.eu/uploads/images/gallery/2023-02/scaled-1680-/invalidation5.png)](https://doc316en.candera.eu/uploads/images/gallery/2023-02/invalidation5.png)

</td><td style="vertical-align: top; width: 58.8203%; border-width: 0px;" valign="top">An invalidation dependency between all 3 views exists.

**Possible solution:**  
Use multiple hardware layers if available.

If only 1 hardware layer is available, invalidation dependencies must be set.

</td></tr></tbody></table>

</div></div></div><div drawio-diagram="1840"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676622017.png" alt=""/></div>

<div class="textblock" id="bkmrk--13"></div><div class="textblock" id="bkmrk--14"></div>#### **Wakeup Render Mechanism** 

##### <a class="anchor" id="bkmrk--29"></a>Description

[Courier::RenderConfiguration::UseWakeUpRenderMechanism](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_render_configuration.html#a0d6faf01325c97dd10e92aaf12fc9815): The default value for this is false. If this is set to true, each widget should call WakeUpAllRenderComponents() whenever a property setter is called. Otherwise the Update method will not be called if the RenderComponent is currently in sleep mode. If implemented correctly this setting will result in the best possible performance optimization, therefore it can be recommended.

# CGI Analyzer

# Overview

#### <a class="anchor" id="bkmrk-"></a>Description

Analyzer is an application which provides several measurement and analysis tools. These tools can be used in connection to CGI Studio projects.

<p class="callout info">This section provides an overview of Analyzer features. For a more detailed explanation, please click <span style="color: rgb(230, 126, 35);">[here](https://doc316en.candera.eu/books/analyzer)</span>.</p>

<div class="contents" id="bkmrk-read-more..."><div class="contents"><div class="textblock">  
</div></div></div>#### <a class="anchor" id="bkmrk--0"></a>First steps

Analyzer is an invaluable tool for diagnosing applications when it comes to improving performance. One of the first things to be determined is whether the application is CPU or GPU bound.

Following will explain shortly the necessary steps to achieve this.

#### <a class="anchor" id="bkmrk--1"></a>Configuration

First build your application with monitor enabled (as explained <span style="color: rgb(230, 126, 35);">[here](https://doc316en.candera.eu/link/276#bkmrk-preparations-for-ana)</span>).

Run the Analyzer and configure the monitor module so it accepts connections from the application and then start the server (read <span style="color: rgb(230, 126, 35);">[here](https://doc316en.candera.eu/link/276#bkmrk-connecting-with-a-ca)</span> how to do it).

If everything was configured correctly when the application is started it will connect automatically to the Analyzer.

#### <a class="anchor" id="bkmrk--2"></a>Global Experiments

Now we will use the use the <span style="color: rgb(230, 126, 35);">[Global Experiments](https://doc316en.candera.eu/link/276#bkmrk-global-experiments%C2%A0)</span> as follows:

1\. Enable "Ignore Draw Calls"

Draw calls will not be submitted anymore thereby simulating an infinitely fast GPU so the swapping will be instantaneous. If the performance improves dramatically the problem is **GPU-bound** (draw calls bound).

If the frame rate does not rise significantly, the problem may be **CPU-bound**. In this case you should have a look on the number of widgets the application is using and also run the application in host simulation with some profiling tools (like the ones from Visual Studio).

2\. Disable "Ignore Draw Calls" and enable the use of "Null Fragment Shader Program" and "2x2 textures".

In this case CPU will submit draw calls but the GPU burden is almost zero. If performance is bad that means there are too many draw calls or textures in use are too big or maybe the fragment shader is to complex.

<div class="contents" id="bkmrk-there-are-situations"><div class="contents"><div class="textblock"><dl class="note"><dt></dt><dd><p class="callout info">There are situations when the problem could be both GPU and CPU bound (for example in the case of hundred of nodes to render).</p>

</dd></dl></div></div></div>Please refer to the <span style="color: rgb(230, 126, 35);">[Quick Guide](https://doc316en.candera.eu/books/performance-optimization/chapter/quick-guide)</span> to get troubleshooting information for any performance degradation issue.

# Optimizing Shader Programs

The goal of shader optimizations is to increase its throughput (vertices/sec, fragments/sec) without impacting visual appearance.

# Surface Effects and Combinations

#### <a class="anchor" id="bkmrk-"></a>Draw Objects Sorted by Texture

Spherical Environment mapping for static surface reflections is supported by [Candera](http://dev.doc.cgistudio.at/APILINK/namespace_candera.html "[DataBinding_RefTypeSample]"). The texture coordinate of the Spheremap will be calculated dynamically in the Shader depending on the position of the camera. Furthermore the spheremap texture can still be mixed with additional textures (multitexturing) like specular maps for shiny surfaces.

Consider using textures for storing (intermediate) results of expensive shader calculations. Texture lookups might be faster than arithmetic calculations.

# Use Specialized Shaders

#### <a class="anchor" id="bkmrk-"></a>Texture Cache

Use Shaders that are customized to fit exactly your special situation.

Reference shaders are full featured and functional code examples to demonstrate the interoperability with [Candera](http://dev.doc.cgistudio.at/APILINK/namespace_candera.html "[DataBinding_RefTypeSample]"). They are not optimized for performance. A great performance improvement can be achieved by reducing the lighting calculation to support only the light sources that are actually used. They should be used for reference, but later be replaced by optimized and more specialized shaders.

# Carefully Design your Lighting

#### <a class="anchor" id="bkmrk--0"></a>Use Texture Compression

<div class="contents" id="bkmrk-per-vertex-lighting-"><div class="textblock">- Per-vertex lighting is less expensive than per-fragment lighting.
- Use as few lighting sources as possible (usually one light source is enough).
- Use simplified, tailored lighting calculations.
- Use light ranges to reduce the illumination area.
- Pre-calculate your lighting effects by putting them into textures.

</div></div>---

# Optimize Shader Program Coding

#### <a class="anchor" id="bkmrk-"></a>Avoid if-else Constructs in the Shader

The use of if-else statements for non-constant variables (attributes, varyings and local variables) should generally be minimized or avoided in shaders, as they might lead to synchronization penalties due to different processing times while parallel processing.

#### <a class="anchor" id="bkmrk--0"></a>Reduce Calculations in the Shader Program

Reduce complex calculations in shader. Uniform calculations can be done outside of the shader. Attribute calculation must be done in the shader anyway.

For example rather give a pre-calculated model-view-projection matrix to the shader than combining the model view projection matrices within a shader, as each calculation is done for each vertex in the vertex shader. [Candera](http://dev.doc.cgistudio.at/APILINK/namespace_candera.html "[DataBinding_RefTypeSample]") pre-calculates uniforms set by [Candera](http://dev.doc.cgistudio.at/APILINK/namespace_candera.html "[DataBinding_RefTypeSample]") ShaderParamSetters automatically before given to the shader (like model-view-projection transformation, light vectors, reflection matrix, etc...).

#### <a class="anchor" id="bkmrk--1"></a>Minimize the Number of (temporary) Variables

#### <a class="anchor" id="bkmrk--2"></a>Remove Superfous Assignments

Consider that each assignment to a variable in a shader is executed for each vertex (in vertex shader) or fragment (in fragment shader). Thus, reduce the number of assignments to a right-minded minimum.

#### <a class="anchor" id="bkmrk--3"></a>Minimize Variable Lifetime

Don't allocate variables across a large code range. Instead minimize their lifetime by scopes or by instantiation directly before usage.

#### <a class="anchor" id="bkmrk--4"></a>use Lowest Precision Possible

Choose the lowest precision possible (without rendering artifacts) on vertices, normal, color and texture coordinates. Lower precision data requires less bandwidth to be transferred from VRAM to the graphics chip.

The shader performs most of the arithmetic calculations much faster in mediump than in highp precision. When using mediump precision for vertex attributes, make sure the data in memory is stored in half-float format as well. Otherwise the driver has to convert the precision every time the object is drawn. Mediump precision should be the default precision in the fragment shader and for varyings.

#### <a class="anchor" id="bkmrk--5"></a>Perform Vector Based Operations

If possible, make use of vector based operations like in the following example.

```
    vec2 x1 = (in1 + in1) / 2;
    vec2 x2 = (in2 + in2) / 2;
```

Better:

```
    vec4 x.xy = in1;
    x.zw = in2;
    x = (x+x) * 0.5;
```

#### <a class="anchor" id="bkmrk--6"></a>Use Multiplication instead of Division

Better rephrase division by x as multiplication by 1.0/x, as this can be computed faster, generally.

# PowerVR GPU Specific Best Practices

The following rules are a set of performance recommendations that developers should seek to implement to help produce well-behaved, high performance graphics applications using the PowerVR device.

#### <a class="anchor" id="bkmrk-"></a>Do Profile Your Application

Identify the bottlenecks in your application and determine whether there are opportunities for improvement.

#### <a class="anchor" id="bkmrk--0"></a>Do Not Use Alpha Blend Unnecessarily

Be sure Alpha Blending is used only when required to make the most of deferred architectures and to save bandwidth.

<div class="contents" id="bkmrk-alpha-blending-in-cg"><div class="contents"><div class="textblock"><table class="doxtable"><tbody><tr><td style="background-color:#f5e7b6;"><span style="color:rgb(230,126,35);">[Alpha blending in CGI Studio...](https://doc316en.candera.eu/books/2d-effects/page/blending)</span></td></tr></tbody></table>

</div></div></div><div class="contents" id="bkmrk-for-2d-scenes-when-h"><div class="contents"><div class="textblock"><dl class="note"><dt></dt><dd><p class="callout info">For 2D scenes when having the default settings the alpha blending will not be performed.</p>

</dd></dl></div></div></div>#### <a class="anchor" id="bkmrk--1"></a>Perform Clear

Perform a clear on a framebuffer's contents to avoid fetching the previous frame's data on tilebased graphics architectures, which reduces memory bandwidth.

<div class="contents" id="bkmrk-for-3d-scenes-the-cl"><div class="contents"><div class="textblock"><dl class="note"><dt></dt><dd><p class="callout info">For 3D scenes the clearing should be performed not only for the color buffer but also for the depth buffer and for the stencil buffer. This can be achieved in Scene Composer by ticking the corresponding checkboxes on the properties panel of the Camera.</p>

</dd></dl></div></div></div>There are situations when the clearing is not necessary:

<div class="contents" id="bkmrk-in-complex-solutions"><div class="contents"><div class="contents"><div class="textblock">- In complex solutions with multiple scenes and cameras it is recommended that only one camera performs the clear. For instance, in the case of several scenes overlapping and having cameras with partial viewports it is recommended to add an extra empty scene and a camera with the sole purpose to clear the complete viewport.
- In the situation when the drawing of an item from the scene clears the color buffer. For example if the solution contains several scenes and a background image that covers entirely the viewport the clearing is not necessary because the background image will be drawn first and will do implicitly the clear.

</div></div></div></div>