# Using the update() and draw() loop properly in a multi-window application, while sharing some graphics between both windows

**URL:** <https://discourse.libcinder.org/t/using-the-update-and-draw-loop-properly-in-a-multi-window-application-while-sharing-some-graphics-between-both-windows/1664>\
**Category:** Using Cinder\
**Created:** [June 7, 2020, 3:01am UTC](https://discourse.libcinder.org/t/using-the-update-and-draw-loop-properly-in-a-multi-window-application-while-sharing-some-graphics-between-both-windows/1664 "2020-06-07T03:01:05Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![Gazoo](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.libcinder.org/gazoo/32/61_2.png) [@Gazoo](https://discourse.libcinder.org/u/Gazoo)\
**Post date:** [June 7, 2020, 3:01am UTC](https://discourse.libcinder.org/t/using-the-update-and-draw-loop-properly-in-a-multi-window-application-while-sharing-some-graphics-between-both-windows/1664/1 "2020-06-07T03:01:05Z")

</div>

Hey Embers,

I could use some experience/thoughts/opinions on using Cinder’s `update()` and `draw()` calls in a multi-window application. I’m a little fuzzy on certain details even in a simple context. Therefore, I thought I’d describe some scenarios from simple to complex, and state how I think things are generally supposed to work along with some questions.

One useful fact as I understand it upfront:

Cinder calls `update()` once per frame, and calls `draw()` once per frame, per window.

# Scenario 1: Single Window

- `update()` - All CPU related code should ideally be run here.
- `draw()` - All GPU related code should ideally be run here.

**Question 1:** It is my understanding that Cinder handles some graphics context matters around the `draw()` call, so even rendering graphics that will not immediately be shown on-screen (i.e. rendering something into a `FrameBufferObject`), should occur in `draw()`, is this true?

# Scenario 2: Multi-window, no shared graphics

Pretty much the same approach as above, as there is no shared graphics between the two windows.

I’ve noticed that the Cinder sample entitled `BasicAppMultiWindow` makes use of `setUserData()` and `getUserData()`, to tie data context to a given window. In my case I instead bind separate `draw()`, `resize()`, `close()` functions to the two windows, and each `drawWindowX()` call simply access its own data. E.g. Window 1 connects to `drawWindow1()`, where as window 2 connects to `drawWindow2()`.

**Question2 :** Are there any side-effects or problems with this approach? I.e. not using `setUserData()` and `getUserData()`, and instead just storing the individual window data in the application object.

# Scenario 3: Multi-window, shared graphics

This is my current use case. Window 1 has a unique scene to render which includes a scaled down render of Window 2’s scene. Since textures can be easily shared across graphics contexts, my approach is as follows:

Window 2’s scene is rendered in the `update()` call, into a `FrameBufferObject`. In `drawWindow1()` window 1’s scene is rendered, which uses the color texture of the `FrameBufferObject`. In `drawWindow2()` basically only the color texture from the `FrameBufferObject` is, again, rendered in its full resolution.

**Question 3:** Is this a bad approach? Should Window 2’s scene ideally be rendered in `drawWindow1()`? If so, how do I ensure that `drawWindow1()` is always called before `drawWindow2()` for every frame?

**Question 4:** What if a scene needs to be rendered every `n`-th frame into a texture, where `n` is higher than 1 but still drawn on-screen every frame (via the texture). Should the rendering still ideally occur in `draw()` or should it occur in `update()`, and merely be drawn in `draw()`?

I hope my questions make sense, and maybe the answer is ultimately “Do whatever you want.”, but I feel like there are probably some best practices to observe when it comes to these things.

Any thoughts are welcome.

Thanks in advance,  
Gazoo

## Related links

- [https://libcinder.org/docs/guides/tour/hello\_cinder\_chapter1.html](https://libcinder.org/docs/guides/tour/hello_cinder_chapter1.html)
- [https://forum.libcinder.org/topic/question-about-void-update-and-draw](https://forum.libcinder.org/topic/question-about-void-update-and-draw)

---

<div class="post-metadata">

**Author:** ![paul.houx](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.libcinder.org/paul.houx/32/31_2.png) [@paul.houx](https://discourse.libcinder.org/u/paul.houx)\
**Post date:** [June 12, 2020, 9:13pm UTC](https://discourse.libcinder.org/t/using-the-update-and-draw-loop-properly-in-a-multi-window-application-while-sharing-some-graphics-between-both-windows/1664/2 "2020-06-12T21:13:32Z")

</div>

Hi,

Here’s a few things I can tell you:

- The `update()` method will be called once per frame, regardless of the number of windows you have.
- The `draw()` method will be called once per _window_ per frame (to find out which window, simply call `getWindow()` from within `draw()`).
- When you create the window, a new OpenGL context is created. I believe this context will automatically be shared with the main context, but I could be wrong.
- The shared context allows you to use the same texture in every window, but some OpenGL objects can not be shared, most notably buffer objects like `Fbo` and `Vbo`.

Scenario 2 is a good solution, I can’t think of any side effects.

Question 3: it could be that Cinder makes sure windows are drawn in the order they were created, but I am not sure. Performing rendering in `update()` isn’t necessarily bad, just know that you’ll be using the main GL context in that case.

Question 4: in that case, it’s probably not very important when the frame is rendered, or in which method. Either of them would work, I guess. Personally, I would try not to render in `update()` just to keep logic separate from draw calls, but that’s just preference.

~Paul
