WOWCube Docs logo
WOWCube Docs
Mission Control
Section Shortcuts
APIExamplesSourceWOWConnectChangelog
Filters
SDK and language defaults persist in cookies.
SDK version
Navigation Tree
Collapsed by default, focused on the active path.
Made byMcKay Seamons
GitHub
  1. Home
  2. Docs
  3. Examples
  4. Gfx Engine - Offscreen Render Targets
Mission NodeSDK 6.3C++renderingProject Included

Gfx Engine - Offscreen Render Targets

Gfx Engine Offscreen Render Target An offscreen render target , also known as an offscreen framebuffer, is a technique used in computer graphics to render im...

Examples / SDK 6.3 / C++ / rendering

Gfx Engine - Offscreen Render Target

An offscreen render target, also known as an offscreen framebuffer, is a technique used in computer graphics to render images or scenes to a location in memory that is not directly visible on the screen. Instead of rendering it directly on the screen, the graphics engine renders the scene to a buffer in memory

Using offscreen render targets can speed up rendering of multiple sprites by minimizing the number of draw calles required to render them on the screen. Here is how it works:

  1. Batching: When rendering sprites individually, each sprite requires a separate draw call. Each draw call incurs overhead in the form of CPU-GPU communication and setup time. By rendering multiple sprites to an offscreen render target in a single draw call, you can batch together the rendering of multiple sprites into one operation, significantly reducing the overhead associated with individial draw calls.

  2. Efficient Rendering: Rendering sprites to an offscreen render target allows for more efficient rendering techniques. For example, sprites can be sorted and grouped before rendering to minimize overdraw (the process of rendering pixels that will later be covered by other objects), leading to imporved performance.

  3. Caching: Once multiple sprites are rendered to an offscreen render target, the resulting image can be cached and reused if the sprites don't change frequently. This means that if the same set of sprites needs to be rendered again in a subsequent frame, the cached image can be quickly drawn onto the screen without the need for recomputation, saviung valuable device resources.

Overall, by consolidating the rendering of multiple sprites into a single operation and optimizing the rendering process, offscreen render targets can significantly improve rendering performance when dealing with large numbers of sprites in a scene.

So, in order to creaate and use an offscreen render target whth GFX Engine, we need to do the following:

  • Create an OffscreenRenderTarget object and register it in the scene
  • Add visual objects to the render target inside its own Begin()-End() block

then

  • Add the render target object to the screen inside the Begin()-End() block in the on_Render() function
  • Dispose the render target object when it's not needed anymore to free system resources

Let's look at each step separately.

Step 1 - Initialization

The OffscreenRenderTarget class has just one constructor:

Gfx Engine - Offscreen Render Targets
CPP
1OffscreenRenderTarget(u32_t width, u32_t height, Cubios::GFX_PixelFormat_t format);
2
Wrapped for easier reading. Turn wrap off to inspect exact line lengths.

As you can see from the source above, the render target can be creted with different resolutions and pixel formats. The pixel format parameter defines how many bits per color definition of one pixel of a render targets must be used. The "higher" pixel format is, more memory is required for creation of an offscreen render target.

  • u32_t width
    Render target width, in pixels

  • u32_t height
    Render target height, in pixels

  • Cubios::GFX_PixelFormat_t format
    Render target pixel format. Please see GFX Engine documentation for available formats

Please pay attention, none of these parameters can be changed on-the-fly once the render target object is created. In order to change render target parameters, you will have to dispose current render target object and create a new one from scratch.

Registering an offscreen render target object in a scene can be done this way:

Gfx Engine - Offscreen Render Targets
CPP
1OffscreenRenderTarget* rt = new OffscreenRenderTarget(240,240,Cubios::GFX_PixelFormat_t::FORMAT_RGB565);
2rt->Begin();
3....
4rt->End();
5
6this->Scene.CreateObjectWithID(GfxObjects::myRT,rt);
7
Wrapped for easier reading. Turn wrap off to inspect exact line lengths.

Step 2 - Adding visuals to the render target

Once your render target is created, you would want to add (or to "draw") some objects onto it before rendering the render target image on the screen.

The process of adding visual objects to a render target is no different to the way you add objects to a screen directly: a render target object has its own Begin and End methods, and the objects should be simply added inside the Begin-End block:

Gfx Engine - Offscreen Render Targets
CPP
1rt->Begin(true);
2
3 rt->Add(this->Scene[GfxObjects::myBackground]);
4
5 rt->Add(this->Scene[GfxObjects::mySprite1]);
6 rt->Add(this->Scene[GfxObjects::mySprite2]);
7 rt->Add(this->Scene[GfxObjects::mySprite3]);
8
9rt->End();
10
Wrapped for easier reading. Turn wrap off to inspect exact line lengths.

Obviously, the visual objects to add must be created and registered in a scene beforehand.

Step 3 - Rendering

All renderable GFX Engine objects are drawn by adding them to the current screen, and an OffscreenRenderTarget is not an exclusion. The addition is done inside the Begin()-End() block, which is used to inform the engine about the start and end of the process of adding objects, as well as about the orientation control mode and automatic rotation.

An elementary example looks like this:

Gfx Engine - Offscreen Render Targets
CPP
1for(auto it = screens.begin(); it != screens.end(); ++it)
2 {
3 //Start adding objects to a screen
4 it->Begin(TOPOLOGY_orientation_mode_t::ORIENTATION_MODE_GRAVITY,true);
5
6 it->Add(this->Scene[GfxObjects::myRT]);
7
8 //Finish adding objects
9 it->End();
10 }
11
Wrapped for easier reading. Turn wrap off to inspect exact line lengths.

The Screen::Add() function returns a pointer to the object that was added. Therefore, if it is necessary to dynamically change any object parameters (for example, the position on the screen), in-place setters are used, as shown below:

Gfx Engine - Offscreen Render Targets
CPP
1for(auto it = screens.begin(); it != screens.end(); ++it)
2 {
3 //Start adding objects to a screen
4 it->Begin(TOPOLOGY_orientation_mode_t::ORIENTATION_MODE_GRAVITY,true);
5
6 it->Add(this->Scene[GfxObjects::myRT])->SetPosition(xOffset,120);
7
8 //Finish adding objects
9 it->End();
10 }
11
Wrapped for easier reading. Turn wrap off to inspect exact line lengths.

Step 4 - Disposing render target object

When the offscreen render target object is not needed anymore, the object MUST be deleted. Although there is a dedicated native function GFX_removeBakedImage, an OffscreenRenderTarget object can be simply disposed with

Gfx Engine - Offscreen Render Targets
CPP
1delete(rt);
2
Wrapped for easier reading. Turn wrap off to inspect exact line lengths.

as its descructor performs the neccessary cleanup automatically.

The Example

In this example, we will create and render an offscreen render target bitmap.

The first step, as always, is the initialization of resources in the InitializeResources() function. We create some tile sprites that will then be used to compose a complex scene rendered onto the offscreen render target:

Gfx Engine - Offscreen Render Targets
CPP
1void RenderTarget::InitializeResources()
2{
3 ...
4//Create tile sprites
5 this->Scene.CreateObjectWithID(GfxObjects::terrain,new Sprite("terrain.png",Transform(120,120,0)));
6
7 this->Scene.CreateObjectWithID(GfxObjects::pit,new Sprite("pit.png",Transform(120,120,0)));
8 this->Scene.CreateObjectWithID(GfxObjects::plant,new Sprite("plant.png",Transform(120,120,0)));
9 this->Scene.CreateObjectWithID(GfxObjects::plant2,new Sprite("plant2.png",Transform(120,120,0)));
10 this->Scene.CreateObjectWithID(GfxObjects::plant3,new Sprite("plant3.png",Transform(120,120,0)));
11 this->Scene.CreateObjectWithID(GfxObjects::plant4,new Sprite("plant4.png",Transform(120,120,0)));
12
13 this->Scene.CreateObjectWithID(GfxObjects::rock,new Sprite("rock.png",Transform(120,120,0)));
14 this->Scene.CreateObjectWithID(GfxObjects::rock2,new Sprite("rock2.png",Transform(120,120,0)));
15 this->Scene.CreateObjectWithID(GfxObjects::rock3,new Sprite("rock3.png",Transform(120,120,0)));
16
17 this->Scene.CreateObjectWithID(GfxObjects::myBackground,new Background(Cubios::Gfx::Colors::black));
18
19 //Create offscreen render target
20 this->prepareOffscreenResource();
21}
22
Wrapped for easier reading. Turn wrap off to inspect exact line lengths.

Note the last funcion, prepareOffscreenResource(). In that function, the offscreen render target object is created and the composition of tile sprites is done.

Gfx Engine - Offscreen Render Targets
CPP
1void RenderTarget::prepareOffscreenResource()
2{
3 OffscreenRenderTarget* rt = new OffscreenRenderTarget(240,240,Cubios::GFX_PixelFormat_t::FORMAT_RGB565);
4 rt->SetPosition(120,120);
5
6 Sprite* terrain = (Sprite*)this->Scene[GfxObjects::terrain];
7 Sprite* rock3 = (Sprite*)this->Scene[GfxObjects::rock3];
8 Sprite* plant3 = (Sprite*)this->Scene[GfxObjects::plant3];
9
10 rt->Begin(true);
11
12 rt->Add(this->Scene[GfxObjects::myBackground]);
13
14 rt->Add(terrain);
15 rt->AddCopy(new Sprite(*terrain))->SetPosition(120-79,120-47);
16 rt->AddCopy(new Sprite(*terrain))->SetPosition(120+79,120-47);
17 rt->AddCopy(new Sprite(*terrain))->SetPosition(120+79,120+47);
18 rt->AddCopy(new Sprite(*terrain))->SetPosition(120-79,120+47);
19
20 rt->AddCopy(new Sprite(*terrain))->SetPosition(120,120-47*2);
21 rt->AddCopy(new Sprite(*terrain))->SetPosition(120,120+47*2);
22
23 rt->AddCopy(new Sprite(*terrain))->SetPosition(120-79*2,120-47*2);
24 rt->AddCopy(new Sprite(*terrain))->SetPosition(120-79*2,120+47*2);
25
26 rt->AddCopy(new Sprite(*terrain))->SetPosition(120+79*2,120-47*2);
27 rt->AddCopy(new Sprite(*terrain))->SetPosition(120+79*2,120+47*2);
28
29 rt->AddCopy(new Sprite(*terrain))->SetPosition(120+79*2,120);
30 rt->AddCopy(new Sprite(*terrain))->SetPosition(120-79*2,120);
31
32 rt->Add(this->Scene[GfxObjects::pit]);
33
34 rt->Add(rock3)->SetPosition(120-79,120-47);
35 rt->Add(this->Scene[GfxObjects::rock])->SetPosition(120-79,120-47);
36 rt->Add(this->Scene[GfxObjects::rock2])->SetPosition(120,120-47*2);
37
38 rt->AddCopy(new Sprite(*rock3))->SetPosition(120+79,120-47);
39 rt->AddCopy(new Sprite(*plant3))->SetPosition(120+79,120-47);
40
41 rt->AddCopy(new Sprite(*rock3))->SetPosition(120-79,120+47);
42 rt->AddCopy(new Sprite(*rock3))->SetPosition(120,120+47*2);
43 rt->AddCopy(new Sprite(*plant3))->SetPosition(120,120+47*2);
44
45 rt->Add(this->Scene[GfxObjects::plant])->SetPosition(120+79,120+47);
46 rt->Add(this->Scene[GfxObjects::plant4])->SetPosition(120-79,120+77);
47
48 rt->Add(this->Scene[GfxObjects::plant2])->SetPosition(120-39,120+7);
49
50 rt->End();
51
52 this->Scene.CreateObjectWithID(GfxObjects::myRT,rt);
53}
54
Wrapped for easier reading. Turn wrap off to inspect exact line lengths.

Now that the images are loaded and the render target is prepared and assigned with GfxObjects::myRT identifier, we can simply render it same way we render ordinary sprites. This is done in on_Render() function:

Gfx Engine - Offscreen Render Targets
CPP
1void RenderTarget::on_Render(std::array<Cubios::Screen, 3>& screens)
2{
3 for(auto it = screens.begin(); it != screens.end(); ++it)
4 {
5 //Start adding objects to a screen
6 it->Begin(TOPOLOGY_orientation_mode_t::ORIENTATION_MODE_GRAVITY,true);
7
8 it->Add(this->Scene[GfxObjects::myRT]);
9
10 //Finish adding objects
11 it->End();
12 }
13}
14
Wrapped for easier reading. Turn wrap off to inspect exact line lengths.

Done!

Context Rail

Project files

GfxRenderTarget.cpp
project/src/GfxRenderTarget.cpp
GfxRenderTarget.h
project/src/GfxRenderTarget.h
wowcubeapp-build.json
project/wowcubeapp-build.json
Jump Grid

On This Page

Gfx Engine Offscreen Render TargetStep 1 InitializationStep 2 Adding visuals to the render targetStep 3 RenderingStep 4 Disposing render target objectThe Example
Context Rail

Related nodes

info.json
Examples / SDK 6.3 / C++ / rendering / Gfx Engine - Offscreen Render Targets
GfxRenderTarget.cpp
Examples / SDK 6.3 / C++ / rendering / Gfx Engine - Offscreen Render Targets / project / src
GfxRenderTarget.h
Examples / SDK 6.3 / C++ / rendering / Gfx Engine - Offscreen Render Targets / project / src
wowcubeapp-build.json
Examples / SDK 6.3 / C++ / rendering / Gfx Engine - Offscreen Render Targets / project
Previous Node
wowcubeapp-build.json
Examples / SDK 6.3 / C++ / rendering / Gfx Engine - Bitmaps / project
Next Node
info.json
Examples / SDK 6.3 / C++ / rendering / Gfx Engine - Offscreen Render Targets