Single OpenGL context, multiple views - windows

I have a Windows app which can create several view windows which can render some models using OpenGL (3.2+). Each window can either render it's own independent object, or two (or more) windows can render the same object (but for example from different camera perspectives):
After reading various posts here on stackoverflow I decided to create a single OpenGL context (HGLRC), and for each window that I am rendering to (HDC) I switch with
wglMakeCurrent(targetWindowHDC, m_deviceContext)
As you can see in the screenshot, that principally seems to work fine (the window code is happening on the main thread, and for Rendering I have my own RenderThread to which all the OpenGL operations are limited to). For each of the windows I render to an FBO (which has MSAA support if the user activates it), which only gets updated in case something in the scene changes, otherwise it will just draw it to the window as is.
My question is now, what states do I have to set every time I switch to drawing to another window? And is my approach reasonable in terms of performance?
This is what I now set every time after I make the context current for another HDC:
glClearDepth( 1.0f );
glClearColor( color.r, color.g, color.b, 1.0f );
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glDepthFunc(GL_LEQUAL);
glDepthRange(0.0f, 1.0f);
glPointSize(3.0f);
glEnable(GL_BLEND);
glBlendFunc( srcBlend, dstBlend );
glPolygonMode( GL_FRONT_AND_BACK, targetType );
glEnable( GL_CULL_FACE );
glCullFace( GL_BACK );
glViewport( 0, 0, vp.width, vp.height );
These are basically all the settings that could be changed when the user sets up the render windows, so I need to be sure they are set correctly before rendering each window.
But is it really necessary to do all those calls? It means in the above example with 4 render windows I need to call those 4 times each frame. Is there a better way? Would it be more efficient with several GL contexts?

The absolute minimum set of state you need to track between windows is the viewport, clearing color, color and depth masks, depth test function and depth range; you've got those covered in your code snippet already, so you're good.
Most other OpenGL state should be set on-demand right before it's needed anyway (and also cleaned up when no longer needed). So I'd say setting blend modes, face culling and so on actually is superfluous in your snippet.
Using the same context for multiple windows makes sense if the kind of rendering is the same for all the windows. For example in a typical 3D modeler there's a "quad view". If those subviews are implemented using multiple windows, then reusing a single context makes sense.
I'm one of those guys who keeps reminding people, that there's no need to have a separate OpenGL context for each window. That doesn't mean doing this is a bad thing if it makes your life simpler.
If your concern is about multiple windows with largely different rendering settings, then using separate render contexts is sensible.
So how do you decide if to use multiple context or a single one. Well, that's easy:
If the windows are sharing much of the render code and conceptually show the same thing (the same scene from different vantage points, different objects that make use of the same texture and are rendered using the same code) then context reuse it is.
If the contents of the windows differ a lot, then multiple contexts.

Related

what is the recommended way, in three js, to render (mostly) static scene

I have a scene that is mostly static, i.e. without user interaction it doesn't change (animations).
The user interacts with the scene. For example:
when the user clicks on certain location in a map, another image opens in another pane
the user may move the camera by moving the mouse
etc...
Originally I implemented the rendering via animate(), which calls:
function animate() {
requestAnimationFrame( animate );
render();
controls.update();
}
This works fine (in terms of response) except that
the rendering happens constantly, which is not necessary.
for one of the admin pages, which does not show the scene, I'm getting runtime errors when the scene does not exist, but the rendering still goes on...
So I re-implemented the rendering by calling, explicitly, after user action which change the scene
render();
controls.update();
This requires more work, because I have to cover all the cases where the scene changes.
In one of the cases, the behaviour is not as expected (the rendered scene is black and explicit call to render does not fix the problem).
The link here says that if your scene is static, there is no reason for an animation loop.
The link here suggests to use animate().
My questions:
Is explicit render, a good pattern to use in three js for static scenes?
Are there pros to render only when needed, instead of calling animate which renders constantly, when this is not needed?
In terms of resource load in general
The link here says that if your scene is static, there is no reason for an animation loop.
The answer of the respective stackoverflow question is also the correct one. The second link is unrelated to question whether to use on-demand rendering or not.
In general, having an animation loop requires more resources since you constantly render no matter if the scene changes or not. However, certain application like 3D viewers (without animation playback) do not need to do this. It's sufficient to render only when certain events happen (e.g. user interaction).
Is explicit render, a good pattern to use in three js for static scenes?
Yes, it is. It is a good pattern for 3D applications in general.
Are there pros to render only when needed, instead of calling animate which renders constantly, when this is not needed? In terms of resource load in general
The app requires less resources which is always a good thing. E.g. mobile device will save a lot of battery and laptops or desktops will be more quiet.

Qt Quick: Can I use the layout components for item layout, without the overhead of rendering the items to the window?

I want to render a QML subtree manually to a Canvas3D by having all the subtree's items' be-texture-source flag (layer.enabled) enabled, and taking the geometry (x, y, width, height) of each item from the corresponding QML properties of each item (calculated by layouts, anchors, etc), so I know how to position and size each item with OpenGL calls.
I have no problems with implementing this, except for a performance issue: since I'm drawing the items in OpenGL, I don't want Qt to also draw them to the window (this would be doing the same work twice). I could achieve that easily by setting opacity: 0 on the items, but that would probably only fix the visual problem, it wouldn't save performance. I could also set visible: false but then I think the layout components wouldn't be able to do their job correctly.
The reasons I want to implement the described architecture are:
I want to implement custom rendering for some of the items in the subtree, but still use their positions and sizes (calculated by the layout for me) for the custom rendering. This custom rendering is complex enough that it can't be done with QML features alone, and I don't want to use Qt3D.
I could use use another approach: use a separate Canvas3D for every item that I want to render customly. And let Qt Quick render the rest of the items for me normally. That's what I've been doing until now. The problem, however, is that:
The different Canvas3Ds can't share GL resources, so I need to initialize and keep copies of the GL resources in each Canvas3D. This increases load time and memory usage.
The creation time of each Canvas3D (even without my GL init code) is significant, I think
So instead I want to use a single, big Canvas3D.

Multi-window support for opengles2

Recently I am writting game editor in my project. I want to implement a editor which has four viewport like 3ds max or other 3D software.
So, how to use opengles2 to render context on multi-window?
You can usually have multiple views with each having its own frame buffer. In this case all you need to do is bind the correct frame buffer before drawing to each of the views. You might also need to have different contexts for each view and setting them as current before drawing (also before binding the frame buffer). If you need multiple contexts you will need to find a way to share resources between them though.
Another approach is having a single view and simply using glViewport to draw to different parts. In this case you need to set glViewport for a specific part, setting ortho or frustum (if view segments are of different size) and that is it. For instance if you split the view with buffer having dimensions bWidth and bHeight into 4 equal rectangles and you want to refresh the top right:
glViewport(bWidth*.5f, .0f, bWidth*.5f, bWidth*.5f);
glOrthof(.0f, bWidth*.5f, bHeight*.5f, .0f, .1, 1.0); //same for each in this case
//do all the drawing
and when you are finished with all you want to update just present the frame buffer.

EaselJS and multi layered canvas system: performance tuning, game developing, event handling

I'm an engineer and we are currently porting our Red5 + Flash game into a Node.js + Easeljs html5 application.
Basicly: it's a board game, not an rpg. The layer system means we have multiple canvasses, based on functionally. For example there is a static background stage, with images. There is a layer for just the timers.
At default, all canvas size is 1920x1080, if needed we downscale to fit to the resolution.
The first approach used kinetic.js, but the performance fallen when the game got complex. Then we switched to easel, because it's abstraction level is lower, so we can decide how to implement some more function, not just use the provided robust one.
I was optimistic, but now it's starting to show slowness again, that's why I want to look deeper inside and do fine performance tuning. (Of course everything is fine in Chrome, Firefox is the problem, but the game must run smoothly on all modern browser).
The main layer (stage) is the map, contains ~30 containers, in each there is a complex custom shape, ~10 images. The containers are listening to mouse events, like mouseover, out, click. Currently, for example on mouseover I refill the shape with gradient.
Somehow, when I use cache, like the way in the tuts the performance get even worse, so I assume I'm messing up something.
I collected some advanced questions:
In the described situation when can I use cache and how? I've already tried cache on init, cacheUpdate after fill with other color or gradient, then stage.update(). No impact.
If I have a static, never changing stage cache doesn't make sense on that layer, right?
What stage.update() exactly do? Triggering the full layer redraw? The doc mentions some kind of intelligent if changed then redraw effect.
If I want to refill a custom shape with new color or gradient I have to completely redraw its graphics, not just use a setFill method, right?
In easel there is no possibility to redraw just a container for example, so how can I manage to not update the whole stage, but just the one container that changed? I thought I can achieve this with caching, cache all containers the just update the one that changed, but this way didn't work at all for me.
Does it make sense to cache bitmap images? If there are custom shapes and images in a container what is better? Cache the container or just the shape in container.
I found a strange bug, or at least an interesting clue. My canvas layers totally overlapping. On the inferior layers the mouseover listening is working well, but the click isn't on the very same container/object.
How can I produce a click event propagation to overlapped layers those have click listeners? I've tried it with simple DOM, jquery, but the event objects were far away from what canvas listeners wanted to get.
In brief, methods and props I've already played with bare success when tried tuning: cache(), updateCache(), update(), mouseEnabled, snapToPixel, clear(), autoClear, enableMouseOver, useRAF, setFPS().
Any answer, suggestion, starting point appreciated.
UPDATE:
This free board game is a strategy game, so you are facing a world map, with ~30 territories. The custom shapes are the territories and a container holds a territory shape and the icons that should be over the territory. This container overlapping is minimal.
An example mouse event is a hover effect. The player navigate over the territory shape then the shape is getting recolored, resized, etc and a bubble showing up with details about the place.
Basically, maximum amount of 1-3 container could change at once (except the init phase -> all at this time). Not just the animations and recoloring slow in FF, but the listener delay is high too.
I wrote a change handler, so I only stage.update() up on tick the modified stages and the stages where an animation is running (tweenjs).
In my first approach I put every image to the container that could be needed at least once during the game, so I only set visible flags on images (not vectors).
Regarding caching:
There are some strange caching-issues, somehow the performance can drop with certain sizes of the caching rectangle: CreateJS / EaselJS Strange Performance with certain size shapes
(2) Depending on how often you call stage.update();
(3)
Each time the update method is called, the stage will tick any
descendants exposing a tick method (ex. BitmapAnimation) and render
its entire display list to the canvas. Any parameters passed to update
will be passed on to any onTick handlers.
=> Afaik it rerenders everything if not cached
(4) Yes.
(5) No. (I don't know of any)
(6) If the content's of the container don't change often, I'd cache the whole container, otherwise the container will be reconstructed every frame.
I have a question though: Why do you use multiple canvases? How many do you use? I could imagine that using multiple canvases might slow down the game.
How many sprites do you use in total?
2: if your layer or stage doesn't change, don't call stage.update() for that layer (so it doesn't gets rerendered, gives me a much lower cpu!)
For example, keep a global "stagechanged" variable and set this to true when something has changed:
createjs.Ticker.addEventListener("tick",
function() {
if (stagechanged)
{
stagechanged = false;
stage.update();
}
});
(or do you already use this, as stated in your "update"?)
4: I found a way to update for example the fill color :)
contaier1.shape1.graphics._fillInstructions[0].params[1] = '#FFFFFF';
(use chrome debugger to look at the _fillInstructions array to see which array position contains your color)
5: I found a way to just paint one container :)
//manual draw 1 component (!)
var a = stage.canvas.getContext("2d");
a.save();
container1.updateContext(a); //set position(x,y) on context
container1.draw(a);
a.restore();

Does Direct2D use back-buffer?

Reading https://learn.microsoft.com/en-us/windows/win32/direct2d/comparing-direct2d-and-gdi :
Presentation Model
When Windows was
first designed, there was insufficient
memory to allow every window to be
stored in its own bitmap. As a result,
GDI always rendered logically directly
to the screen, with various clipping
regions applied to ensure that it did
not render outside of its window. In
contract, Direct2D follows a model
where the application renders to a
back-buffer and the result is
atomically “flipped” when the
application is done drawing. This
allows Direct2D to handle animation
scenarios much more fluidly that GDI
can.
The author says Direct2D uses back-buffer and by 'flipped' he meant swap-chain I guess. I created a simple demo that draw a rectangle at random location on mouse click. But previous rectangles are not cleared so it seems that it is drawn directly to the screen and does not use any back-buffer.
When you initialize the RenderTarget for your Direct2D operations you can specify in the second parameter the D2D1_PRESENT_OPTIONS option.
I think what confuses you is the D2D1_PRESENT_OPTIONS_RETAIN_CONTENTS and the fact that the buffer isn't swapped but copied.
That doesn't disprove the existence of back-buffers, it only means the back-buffer isn't cleared between redraws. Right observation, wrong conclusion!
If you increase the number of back-buffers in the chain, you'll start noticing flickering rectangles as you keep clicking, so you should always clear your back-buffer between redraws.
Direct2D indeed uses back-buffer.
Perhaps you forgot to clear your render target, which is the back-buffer, right after calling begindraw and so previous draws stayed there?

Resources