How to find out how many units across the screen plane in OpenGL - c++

How would one get the relative size of the viewing plane in opengl's own units? I need to find out the width and height in "opengl units". Is there a function which will retrieve this information?
I assume that one unit (let us say 1.0f) in Z would be equivalent to one unit in X, even if conversion to a real measurement system in meaningless.
I know I can get the screen size either by use of GetSystemMetrics(SM_CXSCREEN) or glutGet(GLUT_SCREEN_WIDTH), but this is in pixels.
To handle the graphical window calls, I am using freeglut on non-windows OSes and the WinAPI on Windows.

Assuming you want to draw something like a UI, set your projection matrix to an Orthographic matrix with glOrtho, then you don't have any perspective and have a direct orthographic mapping between world coordinates and screen coordinates. The arguments to your glOrtho call determine how wide/high your view port is in world coordinates.
If you want to draw both a UI and a 3D scene, draw the UI with glOrtho and draw the scene with glPerspective using a clipping mask to make sure you don't ruin your UI.
If on the other hand you want to know the width of the view port in a 3D scene with perspective, so that you know how big to draw your object then you'll have to deal with the perspective projection. You need to know at which Z coordinate you want to know the witdh/height of the view port. You can use gluUnProject to calculate the world coordinate corresponding to a given screen coordinate and Z plane.
However it would probably be better to do it the other way around, always draw your object with a given size and then calculate what your projection matrix should be to have that object appear properly in your view port.

Related

Is it possible to separate normalized device coordinates and window clipping in openGL (glViewport)

Is there a way to set a transformation for NDC to window, but separately specify the clipping region so it matches the actual window size?
Background: I have a bunch of openGL code that renders a 2D map to a window. It's a lot of complex code, because I use both the GPU and the CPU to draw on the map, so it's important that I keep to a consistent coordinate system in both places. To keep that simple, I use glViewport(0,0,mapSizeX, mapSizeY), and now map coordinates correspond well to pixel coordinates in the frame buffer, exactly what I need. I can use GLSL to draw some of the map, call glReadPixels and use the CPU to draw on top of that, and glDrawPixels to send that back to the frame buffer, all of that using the same coordinate system. Finally I use GLSL to draw a few final things over that (that I don't want zoomed). That all works, except...
The window isn't the same size as the map, and glViewport doesn't just set up the transformation. It also sets up clipping. So now when I go to draw a few last items, and the window is larger than the map, things I draw near the top of the screen get clipped away. Is there a workaround?
glViewport doesn't just set up the transformation. It also sets up clipping.
No, it just sets up the transformation. By the time the NDC-to-window space transform happens, clipping has already been done. That happened immediately after vertex processing; your vertex shader (or whatever you're doing to transform vertices) handled that based on how it transformed vertices into clip-space.
You should use the viewport to set up how you want the NDC box to visibly appear in the window. Your VS needs to handle the transformation into the clipping area. So it effectively decides how much of the world gets put into the NDC box that things get clipped to.
Basically, you have map space (the coordinates used by your map) and clip-space (the coordinates after vertex transformations). And you have some notion of which part of the map you want to actually draw to the window. You need to transform the region of your map that you want to see such that the corners of this region appear in the corners of the clipping box (for orthographic projections, this is typically [-1, 1]).
In compatibility OpenGL, this might be defined by using glOrtho for othographic projections to transform from you. In a proper vertex shader, you'll need to provide an appropriate orthographic matrix.

How to draw a rectangle overlay with fixed aspect ratio that represents a render region?

I have a small custom ray tracer that I am integrating in an application. There is a resizable OpenGL window that represents the camera into the scene. I have a perspective matrix that adjusts the overall aspect ratio when the window resizes (basic setup).
Now I would like to draw a transparent rectangle over the window representing the width x height of the render so a user knows exactly what will be rendered. How could this be done? How can I place the rectangle accurately? The user can enter different output resolutions for the ray tracer.
If I understand well your problem, I think that your overlay represents the new "screen" in your perspective frustum.
Redefine then a perspective matrix for the render, in which the overlay 4 corners define the "near" projection plane.

OpenGL drawing 2D and 3D at the same time

I have a 3D scene I'm drawing and I want to draw a rectangle for a dialogue text that will be stretched for all the screen's width, what's the best way to achieve this, having performance in mind?
I found about glOrtho() that I can use for exact pixel placing, but since it's a matrix multiplication task, won't my app feel much heavier during scenes with dialogues?
If yes, should I try to find a math solution to find the X position of my left window corner according to some Z distance and draw a QUAD from there? (Is this even possible?)
glOrtho() is the way to go.
In the course of OpenGL's rendering Pipeline, during the Primitive Assembly stage, every vertex will be transformed (projected) from eye coordinates to clip coordinates. Whether your projection matrix is used for 3D perspective or 2D orthogonalization, it's still one matrix multiplication per vertex before Rasterization starts.
glOrtho() will change your projection matrix to an orthographic one but the matrix only needs to be generated once per frame and the equations required to do so are very simple:
(image credit: MSDN)
Once you have a projection matrix, don't let the thought of matrix multiplication scare you. It's exactly what video cards are designed to do and it's hardly a frightening task for any processor or GPU these days.

OpenGL define vertex position in pixels

I've been writing a 2D basic game engine in OpenGL/C++ and learning everything as I go along. I'm still rather confused about defining vertices and their "position". That is, I'm still trying to understand the vertex-to-pixels conversion mechanism of OpenGL. Can it be explained briefly or can someone point to an article or something that'll explain this. Thanks!
This is rather basic knowledge that your favourite OpenGL learning resource should teach you as one of the first things. But anyway the standard OpenGL pipeline is as follows:
The vertex position is transformed from object-space (local to some object) into world-space (in respect to some global coordinate system). This transformation specifies where your object (to which the vertices belong) is located in the world
Now the world-space position is transformed into camera/view-space. This transformation is determined by the position and orientation of the virtual camera by which you see the scene. In OpenGL these two transformations are actually combined into one, the modelview matrix, which directly transforms your vertices from object-space to view-space.
Next the projection transformation is applied. Whereas the modelview transformation should consist only of affine transformations (rotation, translation, scaling), the projection transformation can be a perspective one, which basically distorts the objects to realize a real perspective view (with farther away objects being smaller). But in your case of a 2D view it will probably be an orthographic projection, that does nothing more than a translation and scaling. This transformation is represented in OpenGL by the projection matrix.
After these 3 (or 2) transformations (and then following perspective division by the w component, which actually realizes the perspective distortion, if any) what you have are normalized device coordinates. This means after these transformations the coordinates of the visible objects should be in the range [-1,1]. Everything outside this range is clipped away.
In a final step the viewport transformation is applied and the coordinates are transformed from the [-1,1] range into the [0,w]x[0,h]x[0,1] cube (assuming a glViewport(0, w, 0, h) call), which are the vertex' final positions in the framebuffer and therefore its pixel coordinates.
When using a vertex shader, steps 1 to 3 are actually done in the shader and can therefore be done in any way you like, but usually one conforms to this standard modelview -> projection pipeline, too.
The main thing to keep in mind is, that after the modelview and projection transforms every vertex with coordinates outside the [-1,1] range will be clipped away. So the [-1,1]-box determines your visible scene after these two transformations.
So from your question I assume you want to use a 2D coordinate system with units of pixels for your vertex coordinates and transformations? In this case this is best done by using glOrtho(0.0, w, 0.0, h, -1.0, 1.0) with w and h being the dimensions of your viewport. This basically counters the viewport transformation and therefore transforms your vertices from the [0,w]x[0,h]x[-1,1]-box into the [-1,1]-box, which the viewport transformation then transforms back to the [0,w]x[0,h]x[0,1]-box.
These have been quite general explanations without mentioning that the actual transformations are done by matrix-vector-multiplications and without talking about homogenous coordinates, but they should have explained the essentials. This documentation of gluProject might also give you some insight, as it actually models the transformation pipeline for a single vertex. But in this documentation they actually forgot to mention the division by the w component (v" = v' / v'(3)) after the v' = P x M x v step.
EDIT: Don't forget to look at the first link in epatel's answer, which explains the transformation pipeline a bit more practical and detailed.
It is called transformation.
Vertices are set in 3D coordinates which is transformed into a viewport coordinates (into your window view). This transformation can be set in various ways. Orthogonal transformation can be easiest to understand as a starter.
http://www.songho.ca/opengl/gl_transform.html
http://www.opengl.org/wiki/Vertex_Transformation
http://www.falloutsoftware.com/tutorials/gl/gl5.htm
Firstly be aware that OpenGL not uses standard pixel coordinates. I mean by that for particular resolution, ie. 800x600 you dont have horizontal coordinates in range 0-799 or 1-800 stepped by one. You rather have coordinates ranged from -1 to 1 later send to graphic card rasterizing unit and after that matched to particular resolution.
I ommited one step here - before all that you have an ModelViewProjection matrix (or viewProjection matrix in some simple cases) which before all that will cast coordinates you use to an projection plane. Default use of that is to implement a camera which converts 3D space of world (View for placing an camera into right position and Projection for casting 3d coordinates into screen plane. In ModelViewProjection it's also step of placing a model into right place in world).
Another case (and you can use Projection matrix this way to achieve what you want) is to use these matrixes to convert one range of resolutions to another.
And there's a trick you will need. You should read about modelViewProjection matrix and camera in openGL if you want to go serious. But for now I will tell you that with proper matrix you can just cast your own coordinate system (and ie. use ranges 0-799 horizontaly and 0-599 verticaly) to standarized -1:1 range. That way you will not see that underlying openGL api uses his own -1 to 1 system.
The easiest way to achieve this is glOrtho function. Here's the link to documentation:
http://www.opengl.org/sdk/docs/man/xhtml/glOrtho.xml
This is example of proper usage:
glMatrixMode (GL_PROJECTION)
glLoadIdentity ();
glOrtho (0, 800, 600, 0, 0, 1)
glMatrixMode (GL_MODELVIEW)
Now you can use own modelView matrix ie. for translation (moving) objects but don't touch your projection example. This code should be executed before any drawing commands. (Can be after initializing opengl in fact if you wont use 3d graphics).
And here's working example: http://nehe.gamedev.net/tutorial/2d_texture_font/18002/
Just draw your figures instead of drawing text. And there is another thing - glPushMatrix and glPopMatrix for choosen matrix (in this example projection matrix) - you wont use that until you combining 3d with 2d rendering.
And you can still use model matrix (ie. for placing tiles somewhere in world) and view matrix (in example for zooming view, or scrolling through world - in this case your world can be larger than resolution and you could crop view by simple translations)
After looking at my answer I see it's a little chaotic but If you confused - just read about Model, View, and Projection matixes and try example with glOrtho. If you're still confused feel free to ask.
MSDN has a great explanation. It may be in terms of DirectX but OpenGL is more-or-less the same.
Google for "opengl rendering pipeline". The first five articles all provide good expositions.
The key transition from vertices to pixels (actually, fragments, but you won't be too far off if you think "pixels") is in the rasterization stage, which occurs after all vertices have been transformed from world-coordinates to screen coordinates and clipped.

How to clip rendering in OpenGL (C++)

How to clip rendering in OpenGL (simple rectangle area)?
Please post a C++ example.
What you probably need is OpenGL's scissor mechanism.
It clips rendering of pixels that do not fall into a rectangle defined by x, y, width and height parameters.
Note also that this OpenGL state when enabled, affects glClear command by restricting the area cleared.
If you only want to display a specific rectangle, you need a combination of something like glFrustrum or glOrtho along with glViewPort. It's actually glViewPort that sets the clipping rectangle. glFrustrum, glOrtho (gluPerspective, etc.) then map some set of real coordinates to that rectangle. Typically you hardly notice the glViewPort, because it's normally set to the entire area of whatever window you're using, and what you change is the mapping to get different views in the window.
If you just adjust glFrustum (for example) by itself, the display area on the screen will stay the same, and you'll just change the mapping so you'll still fill the entire window area, and basically just move the virtual camera around, so you zoom in or out (etc.) on the "world" being displayed. Conversely, if you just adjust glViewPort, you'll display exactly the same data, but into a smaller rectangle.
To "clip" the data to the smaller rectangle, you need to adjust both at once, in more or less the "opposite" directions so as your view-port rectangle gets smaller, you zoom in your view frustum to compensate.