I am painting on a large opengl canvas. At times I need to draw onto some small framebuffers (tiles) and then go back to paint to my canvas. The problem is that when I draw the framebuffers, I obviously change the viewport of the context, so when I go back painting on my canvas obviously the viewport needs to modified. What I am looking for is a way to save and restore the glViewport settings. Something like this in pseudocode:
saveViewport();
drawFramebuffers(); // this change the viewport
restoreViewport();
Is something like this possible?
For Compatibility contexts glPushAttrib()/glPopAttrib() with GL_VIEWPORT_BIT will save/restore the depth range & viewport state.
In addition to #genpfault 's answer, the following also works:
// save viewport
GLint aiViewport[4];
glGetIntegerv(GL_VIEWPORT, aiViewport);
// do your stuff and then restore viewport
glViewport(aiViewport[0], aiViewport[1], (GLsizei)aiViewport[2], (GLsizei)aiViewport[3]);
This was taken from here
Related
Suppose you have some objects which are rendered based on camera position and then you have side pannels (some buttons, text, etc.) which are always at the same position on the screen.
How could I achieve this effect with opengl?
I'm not sure what I should be looking for but I have two ideas how this could be done. The first is to draw semi-transparent texture after applying view and projection matrix. The second is to render to texture like here and then draw it on a plane and render also the pannels.
What method is the most efficient and/or what method is usually used by game developers?
glViewport(full_window);
set_projection_and_modelview_for_scene();
draw_scene();
glViewport(sidebar_position);
glScissor(sidebar_position);
glEnable(GL_SCISSOR_TEST);
set_projection_and_modelview_for_sidebar();
draw_sidebar();
glDisable(GL_SCISSOR_TEST);
I am using OpenGL for a 2D-based game which has been developed for a resolution of 640x480 pixels. Thus, I setup my OpenGL doublebuffer like this:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 640, 480, 0, 0, 1);
glDisable(GL_DEPTH_TEST);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
This works really well and I can draw all my sprites and background scrollers using hardware accelerated GL textures. Now I'd like to support other window sizes as well, i.e. the user should be able to run the game in 800x600, 1024x768, etc. So all graphics should be scaled to the new resolution. Of course I could do this by simply applying scaling factors to all my vertices when drawing the textures as quads. But I don't think that I'd be able to achieve pixel-perfect positioning that way.... but pixel-perfect positioning is of course very important for 2D games!
Thus, I'd like to ask if there's a possibility to work with a static 640x480 doublebuffer have it scaled only just before it is drawn to the screen, i.e. something like this:
1) My doublebuffer will always be 640x480 pixels, no matter what the real output window size is.
2) Once I call glfwSwapBuffers() the 640x480 doublebuffer should be scaled to the actual window size which can be smaller or larger than 640x480.
Is this possible somehow? I think this would be the easiest solution for my game because manually scaling all vertices is likely to give me some problems when it comes to pixel-perfect positioning, isn't it?
Thanks!
I setup my OpenGL doublebuffer like this:
I think you don't know what "doublebuffer" means. It means that you perform drawing on a invisible buffer which is then revealed to the user once the drawing is finished, so that the user doesn't see the drawing process.
The code snippet you have there is the projection setup. And hardcoding the dimensions in pixel units there is just wrong.
but pixel-perfect positioning is of course very important for 2D games!
No, not really. Instead of "pixel" units (which don't really exist in OpenGL except for texture image indexing and the viewport) you should use something like world unit. For example in a simple jump-and-run platformer like SMW
you could say, that each block is one unit high. The Yosi-sprite would be 2 units high, Mario 1.5 and so on.
The important thing is, that you can keep your sprite rendering dimensions independent of screen resolution. This is especially important with respect to all the varying screen resolutions and aspect ratios out there. Don't force the user on resolutions you think are appropriate. People have computers with big screens and they want to use them.
Also the appearance of your sprites depends largely on the texture images and filtering method you use. If you want to achieve a pixelated look, just make the texture images low resolution and use a GL_NEAREST magnification filter, OpenGL will do the rest (however you should provide minification mipmaps and use GL_LINEAR_MIPMAP_LINEAR for minification, so that things don't look awful on small resolutions).
Thus, I'd like to ask if there's a possibility to work with a static 640x480 doublebuffer have it scaled only just before it is drawn to the screen, i.e. something like this:
Yes, you can use a framebuffer object for this. Create a set of textures (color and depth-stencil) of the rendering dimensions (like 640×480) render to that, then when finished draw the color texture to a viewport filling quad on the main framebuffer.
Like before, render at 640x480 but to an offscreen texture. Then render a screen-sized (800x600, 1024x768,...) quad with this texture applied to it.
I draw a tile map on screen and each tile light(grayscale) in a FBO. All are quads.
I store the view in a Rect. To move I change de Rect, then I do this...
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(getViewRect().left,
getViewRect().left + getViewRect().width,
getViewRect().top + getViewRect().height,
getViewRect().top,
-1,
1);
glMatrixMode(GL_MODELVIEW);
I only draw the tiles inside the Rect.
The problem is the FBO. I have to draw the same tiles( the lights of the tiles), that are visible.
I want to know if there is a better way than, drawing the same tiles to the fbo with the offset of the tiles, drawing a smaller quad on the borders when is not completly visible, and changing texcoord, because when I draw outside the FBO, it draw on the opposite side.
I use FBO, because I apply shader to the lights.
It works perfect if I dont move the view, but if I move I dont know how to draw on the FBO.
You ought to be able to use glScissor to restrict all drawing within the FBO. Perform this operation after calling glBindBuffer(...) each time you bind it.
Hope this helps!
I'd like to try and implement some HCI for my existing OpenGL application. If possible, the menus should appear infront of my 3D graphics which would be in the background.
I was thinking of drawing a square directly in front of the "camera", and then drawing either textures or more primatives on top of the "base" square.
While the menus are active the camera can't move, so that the camera doesn't look away from the menus.
Does this sound far feteched to anyone or am I on the right tracks? How would everyone else do it?
I would just glPushMatrix, glLoadIdentity, do your drawing, then glPopMatrix and not worry about where your camera is.
You'll also need to disable and re-enable depth test, lighting and such
There is the GLUI library to do this (no personal experience)
Or if you are using Qt there are ways of rendering Qt widgets transparently on top of the OpenGL model, there is also beta support for rendering all of Qt in opengl.
You could also do all your 3d Rendering, then switch to orthographic projection and draw all your menu objects. This would be much easier than putting it all on a large billboarded quad as you suggested.
Check out this exerpt, specifically the heading "Projection Transformations".
As stated here, you need to apply a translation of 0.375 in x and y to get pixel perfect alignment:
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, width, 0, height);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.375, 0.375, 0.0);
/* render all primitives at integer positions */
The algorithm is simple:
Draw your 3D scene, presumably with depth testing enabled.
Disable depth testing so that your GUI elements will draw over the 3D stuff.
Use glPushMatrix to store you current model view and projection matrices (assuming you want to restore them - otherwise, just trump on them)
Set up your model view and projection matrices as described in the above code
Draw your UI stuff
Use glPushMatrix to restore your pushed matrices (assuming you pushed them)
Doing it like this makes the camera position irrelevant - in fact, as the camera moves, the 3D parts will be affected as normal, but the 2D overlay stays in place. I'm expecting that this is the behaviour you want.
I am rendering an OpenGL scene that include some bitmap text. It is my understanding the order I draw things in will determine which items are on top.
However, my bitmap text, even though I draw it last, is not on top!
For instance, I am drawing:
1) Background
2) Buttons
3) Text
All at the same z depth. Buttons are above the background, but text is invisible. It I change the z depth of the text, I can see it, but I then have other problems.
I am using the bitmap text method from Nehe's Tutorials.
How can I make the text visible without changing the z depth?
You can simply disable the z-test via
glDisable (GL_DEPTH_TEST); // or something related..
If you do so the Z of your text-primitives will be ignored. Primitives are drawn in the same order as your call the gl-functions.
Another way would be to set some constant z-offset via glPolygonOffset (not recommended) or set the depth-compare mode to something like GL_LESS_EQUAL (the EQUAL is the important one). That makes sure that primitives drawn with the same depth are rendered ontop of each other.
Hope that helps.
You can also use glDepthFunc (GL_ALWAYS).