richardjmoss's picture

Translucent overlay

Hello,

Is there a convenient method of doing a translucent overlay allowing you to dim out what you've already rendered, then draw "normal" stuff on top. My scenario is, I have drawn the game screen, but want to mask it out, still allowing it to be somewhat visible, while placing emphasis on a popup.

I should point out that I'm still using immediate mode, more or less - my 2D engine uses GL.DrawArrays for everything. I know I could probably draw a solid box blended over the scene, but while I'm sort of evil by still using immediate mode, I'm not so evil as to resort to drawing with primitives or GL.Begin/GL.End.

So... is there any way of doing this without using primitives? I guess you could use a shader, but I haven't even began to look at these, and I assume it won't work on GL.DrawArray commands that have already been executed. I also read that OpenGL has lighting built into it which sounds kind of cool, but again I haven't researched this yet either.

Any advice appreciated :)

Thanks;
Richard Moss


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
mOfl's picture
richardjmoss wrote:

So... is there any way of doing this without using primitives? I guess you could use a shader, but I haven't even began to look at these, and I assume it won't work on GL.DrawArray commands that have already been executed. I also read that OpenGL has lighting built into it which sounds kind of cool, but again I haven't researched this yet either.

You will always use primitives, because this is what the video card is able to process, you just don't do it in immediate mode but in a more performant fashion (VBO + VAO for example). A shader is not the magic fancy stuff, it just allows you to program and therefore modify the rendering pipeline - the thing you are just drawing your stuff with. Thus, everything that works in your current implementation can also work with shaders, if you just write the exact shader that is currently implicitly used by OpenGL. If you want to leave the sinful path of deprecated rendering, you should not take a look at the built-in lighting of OpenGL, as this is deprecated, too ;)

Generally, blending is the way to go here. There are two ways you can accomplish this (I don't know which one exactly you'd need):
- Draw your whole scene as usual, then blend over a semitranslucent black quad afterwards and draw your popup or whatelse. This is very easy to implement as you do not have to change anything but enabling blending and adding the new code for your popup, although it is a bit inefficient because you also draw all the other stuff first, which will be still updated each frame (which can also be desirable).
- Draw your whole scene in an off-screen framebuffer first, then stop drawing to it as soon as you show the popup. Draw a fullscreen quad with the off-screen framebuffer content first, then blend over your translucent quad and draw your popup on top. This way, you save performance because the original scene is not updated when showing the popup, but you'd have to mess with framebuffers.

Both ways, you do not need shaders to accomplish it, but it would of course be neat ;)

richardjmoss's picture

Hello,

Thanks for the response, that was helpful. And yes, I'd like to leave immediate behind but one thing at a time :) I'll not bother looking into the lighting then.

With regards to drawing a semi black quad, are you actually talking about using GL.Begin(BeginMode.Quads) / GL.End? I haven't used these since I first got my initial bits working with OpenGL and I figured they were pretty evil. But if it's "ok" (immediate mode caveats aside) to use these then I should just go ahead and do it.

With regards to your second statement, that does sound interesting! Can you give a few quick pointers on which parts of the API I can use for this?

I'll leave the shader work for another time I think :)

Thanks again for the response!
Richard Moss

mOfl's picture
richardjmoss wrote:

With regards to drawing a semi black quad, are you actually talking about using GL.Begin(BeginMode.Quads) / GL.End?

Actually, when referring to (fullscreen) quads, I did not mean actual quad primitives, but a plane that consists of two triangles, because today's hardware is optimized to work with triangles. http://www.john-chapman.net/content.php?id=6 sketches the usage of 4 vertices and 4 texture coordinates to accomplish this. Fullscreen quads are very common for advanced effects - you draw part of the scene into a framebuffer (the target of the framebuffer is a texture) and do fancy effects with it, then draw a plane consisting of 2 triangles into your back buffer and use the content of the off-screen framebuffer as texture. This way, you can compose the framebuffer contents with the rest of your scene very efficiently.
So, without changing too much of your code, you could draw the fullscreen quad using GL.Begin(BeginMode.TriangleStrip) / GL.End().

Quote:

With regards to your second statement, that does sound interesting! Can you give a few quick pointers on which parts of the API I can use for this?

For this, you'd have to render your whole scene into a framebuffer (http://www.opentk.com/doc/graphics/frame-buffer-objects, note that in the link, renderbuffer targets are also discussed, but you would use a texture target only) with a texture target. As you always render into a framebuffer (the default back buffer of OpenGL), you actually don't have to change a lot of code. You just need to create a texture, the framebuffer, then bind it at runtime, draw your geometry as usual, then unbind it by binding framebuffer 0.
If you only draw your scene, you bind the framebuffer, draw everything, unbind it, draw a fullscreen quad and use the framebuffer target texture to just display the framebuffer content - the result should be exactly the same as drawing to the back buffer directly.
If you are drawing the popup, you skip the scene rendering step, i.e. you draw the fullscreen quad with the framebuffer target texture without updating the contents of the framebuffer. This is possible as the texture still holds the data that was last rendered to it as long as you do not clear it explicitly. After drawing the fullscreen quad, you draw your popup as desired to the back buffer.

I hope that was clear :)

richardjmoss's picture

Thanks for the follow up! I think I'll be lazy and go with the quad for now, but I'll definitely look into this buffer stuff, seems to be silly redrawing the levels all the time if nothing has changed.

(No doubt I'll have more questions later :))

Thanks again;
Richard Moss