I have a problem using glOrtho in a program that uses GLMDraw() function of GLM library to draw Google SketchUp 3D images. I wanted to see the image for only certain values of z in Projection mode and glOrtho() didn't seem to work so I made the following code to test it:
glOrtho(0.0f, 2.0f, 0.0f, 2.0f, 0.0f, 0.0f);
Since near and far planes are the same I thought I should see no image but I see the whole image.
What I am missing?
If you call glOrtho with znear=zfar, it generates a GL_INVALID_VALUE error, and probably just discards the call.
http://www.opengl.org/sdk/docs/man/xhtml/glOrtho.xml
Try giving it a range greater than zero.
Related
After searching many pages, glm documentation, tutorials...etc, I'm still confused on some things.
I'm trying to understand why I need to apply the following transformations to get my 800x600 (fullscreen square, assume the screen of the user is 800x600 for this minimal example) image to draw over everything. Assume I'm only drawing CCW triangles. Everything renders fine in my code, but I have to do the following:
// Vertex data (x/y/z), using EBOs
0.0f, 600.0f, 1.0f,
800.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
800.0f, 600.0f, 1.0f
// Later on...
glm::mat4 m, v, p;
m = scale(m, glm::vec3(-1.0, 1.0, 1.0));
v = rotate(v, glm::radians(180.0f), glm::vec3(0.0f, 1.0f, 0.0f));
p = glm::ortho(0.0f, 800.0f, 600.0f, 0.0f, 0.5f, 1.5f);
(Note that just since I used the variable names m, v, and p doesn't mean they're actually the proper transformation for that name, the above just does what I want it to)
I'm confused on the following:
Where is the orthographic bounds? I assume it's pointing down the negative z-axis, but where do the left/right bounds come in? Does that mean [-400, 400] on the x-axis maps to [-1.0, 1.0] NDC, or that [0, 800] maps to it? (I assume whatever answer here applies to the y-axis). Then documentation just says Creates a matrix for an orthographic parallel viewing volume.
What happens if you flip the following third and fourth arguments (I ask because I see people doing this and I don't know if it's a mistake/typo or it works by a fluke... or if it properly works regardless):
Args three and four here:
_____________
| These two |
p1 = glm::ortho(0.0f, 800.0f, 600.0f, 0.0f, 0.5f, 1.5f);
p2 = glm::ortho(0.0f, 800.0f, 0.0f, 600.0f, 0.5f, 1.5f);
Now I assume this third question will be answered with the above two, but I'm trying to figure out if this is why my first piece of code requires me flipping everything on the x-axis to work... which I will admit I was just messing around with it and it happened to work. I figure I need a 180 degree rotation to turn my plane around so it's on the -z side however... so that just leaves me with figuring out the -1.0, 1.0, 1.0 scaling.
The code provided in this example (minus the variable names) is the only stuff I use and the rendering works perfectly... it's just my lack of knowledge as to why it works that I'm unhappy with.
EDIT: Was trying to understand it from here by using the images and descriptions on the site as a single example of reference. I may have missed the point.
EDIT2: As a random question, since I always draw my plane at z = 1.0, should I restrict my orthographic projection near/far plane to be as close to 1.0 as possible (ex: 0.99, 1.01) for any reason? Assume nothing else is drawn or will be drawn.
You can assume the visible area in a orthographic projection to be a cube given in view space. This cube is then mapped to the [-1,1] cube in NDC coordinates, such that everything inside the cube is visible and everything outside will be clipped away. Generally, the viewer looks along the negative Z-axis, while +x is right and +Y is up.
How are the orthographic bounds mapped to NDC space?
The side length of the cube are given by the parameters passed to glOrtho. In the first example, parameters for left and right are [0, 800], thus the space from 0 to 800 along the X axis is mapped to [-1, 1] along the NDC X axis. Similar logic happens along the other two axes (top/bottom along y, near/far along -z).
What happens when the top and bottom parameters are exchanged?
Interchanging, for example, top and bottom is equivalent to mirroring the scene along this axis. If you look at second diagonal element of a orthographic matrix, this is defined as 2 / (top - bottom). By exchanging top and bottom only the sign of this element changes. The same also works for exchanging left with right or near with far. Sometimes this is used when the screen-space origin should be the lower left corner instead of upper left.
Why do you have to rotate the quad by 180° and mirror it?
As described above, near and far values are along the negative Z-axis. Values of [0.5, 1.5] along -Z mean [-0.5, -1.5] in world space coordinates. Since the plane is defined a z=1.0 this is outside the visible area. By rotating it around the origin by 180 degrees moves it to z=-1.0, but now you are looking at it from the back, which means back-face culling strikes. By mirroring it along X, the winding order is changed and thus back and front side are changed.
Since I always draw my plane at Z = 1.0, should I restrict my orthographic projection near/far plane to be as close to 1.0 as possible?
As long as you don't draw anything else, you can basically choose whatever you want. When multiple objects are drawn, then the range between near and far defines how precise differences in depth can be stored.
I'm having a hard time figuring out what's going on with my texture:
Basically I am fetching a webcam stream as my underlying 2d texture canvas in OpenGL, and in my paintGL() I'm drawing stuff on it (as RGBA images with GL_BLEND).
Since I'm using a Kinect as a data source, I'm also getting the depth values from a tracked skeleton (a person), and converting them into GL values (XYZ varying between 0.0f and 1.0f).
So my goal is that, for instance, a loaded 2D Texture like a shirt, is now properly tracking the person in my RGB output display. But it seems my understanding of orthographic projection is wrong:
I'm constantly loading the 4 converted vertices into a VBO, but whenever I put the texture on top of this dynamic quad, it's always facing the screen.
I thought that putting this dynamic quad between the "background" canvas and the camera would result in a proper projection of the quad onto the canvas, which would give me the impression of a warping 2D texture, that seems to "bend" whenever the person rotates.
But the texture is always facing the camera and doesnt rotate.
I've also tried to manually rotate via a matrix and set that into my shader, but again, it only rotates the vertice quad itself (as: rotation simply makes the texture smaller) , and THEN puts the texture on top, instead of rotating the texture with it.
So, is it somehow possible to properly apply this to the texture?
I've thought about mixing a perspective projection in, but actually have no idea how to implement this...
EDIT:
I've actually already set my projection matrix up like the following:
In resizeGL():
projection.setToIdentity();
projection.ortho(0.0f, 1.0f, 0.0f, 1.0f, 2.0f, -5.0f);
projection.translate(0.0f, 0.0f, 3.0f);
In paintGL():
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_DEPTH_TEST); // turning this on/off makes no difference
glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, &textureID);
program.setUniformValue("mvp_matrix", projection);
program.setUniformValue("texture", 0);
//draw 2d background quad
drawQuad();
glClear(GL_DEPTH_BUFFER_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// switch to frustum to give perspective view
projection.setToIdentity();
projection.frustum(0.0f, 1.0f, 0.0f, 1.0f, 2.0f, -5.0f);
projection.translate(0.0f, 0.0f, 3.0f);
// bind cloth texture and draw ontop 2d quad
clothTexture->bind();
program.setUniformValue("mpv_matrix", projection);
drawShirtQuad();
// reset to ortho view
projection.setToIdentity();
projection.ortho(0.0f, 1.0f, 0.0f, 1.0f, 2.0f, -5.0f);
// release texture
clothTexture->release();
glDisable(GL_BLEND);
clothTexture is a QOpenGLTexture that has successfully loaded an RGBA image from a file.
Result: whenever I activate the frustum perspective, it results in a black screen. I think everything is correctly set up: POV is traversed towards positive z-axis in resizeGL(), and all the cloth vertices vary between 0 and 1 in XYZ, while the background is positioned at:
(0.0f, 0.0f, -1.0f), (1.0f, 0.0f, -1.0f), (1.0f, 1.0f, -1.0f), (0.0f, 1.0f, -1.0f).
So the cloth object is always positioned between background plane and POV. Am i missing something in the frustum setup ? I've simply set it up the same way as ortho...
EDIT:
Sorry for not mentiong; the matrix I'm using is a QMatrix4x4 type:
Frustum
These functions multiply the current matrix with the one you define as an argument, which should yield the same result as if I define a View matrix for instance, and then define my shader uniform "mvp_matrix" as projection * view, if I'm not mistaken. Maybe something like lookAt will do the trick; I'll just try messing around more. :)
You need to use a perspective projection to achieve desired result. Look here for example code for perspective projection matrix creation with glm.
Moving vertices wouldn't be needed as you will get proper positions with rotation applied in your model matrix.
EDIT: in your code where can i look at .frustum and .translate methods or from what library projection object is? It doesn't look like you are doing Projection * View by moving frustum matrix. Some info about roles of standard matrices.
Considering debugging if you get on screen black color instead of GL_COLOR_BUFFER_BIT color problem is not with matrix but earlier. Also i recommend to console.log your perspective matrix and compare it to correct one (which you can get for example in glm library).
Using WIN32_FIND_DATA and FindFirstFile I'm searching for files in a directory an with fileName.find(".jpg") != std::string::npos I filter the jpg images out.
I'm using OpenGL for creating Boxes with a red color:
glBegin( GL_QUADS );
glColor4f( 1.0f, 0.0f, 0.0f, 0.0f ); glVertex2f( 0.35f, 0.7f );
glColor4f( 1.0f, 0.0f, 0.0f, 0.0f ); glVertex2f( -0.35f, 0.7f );
glColor4f( 1.0f, 0.0f, 0.0f, 0.0f ); glVertex2f( -0.35f, -0.3f );
glColor4f( 1.0f, 0.0f, 0.0f, 0.0f ); glVertex2f( 0.35f, -0.3f );
This is the box in the center with a red color.
My Question is how can I load the Images each in a Cube instead of the Red color (glColor4f)?
I think this is not the best way to make this, but this code is not my own Code, I'm trying to make this better for a friend.
Thank you!
You need to learn about texturing. See NeHe's tutorial on the subject as an example.
However, that tutorial is a bit old (as is your code, since you use glVertex(), so it might not matter to you right now... :).
Anyway, starting from OpenGL 3.1 and OpenGL ES 2.0, you should do it with using GLSL, fragment shaders and samplers instead. See another tutorial for that. It's actually simpler than learning all the fixed function stuff.
It's not really a good practice to use WinAPI together with OpenGL applications unless you really have reasons to - and loading textures from the disk is not a good reason.
Think this way: OpenGL is a platform-independent API, why to dimnish this advantage by using non-portable subroutines when portable alternatives exist and are more convenient to use in most cases?
For the loading textures, I recommend the SOIL library. This is likely to be much better a solution than what the NeHe tutorials recommend.
For finding files on the disk, you might want to use boost::filesystem if you want to get rid of the WinAPI dependency. But that's not a priority now.
When you have the texture loaded by SOIL (a GLuint value being the texture ID), you can do the following:
enable 2D texturing (glEnable(GL_TEXTURE_2D)),
bind the texture as active 2D texture (glBindTexture(GL_TEXTURE_2D,tex);),
set the active color to pure white so that the texture image will be full-bright,
draw the vertices as usual, but for each vertex you'll need to specify a texture coordinate (glTexCoord2f) instead of a color. (0,0) is upper left coord of the texture image, (1,1) is the lower right.
Note that the texture image must have dimensions being powers of two (like 16x16 or 256x512). If you want to use any texture size, switch to a newer OpenGL version which supports GL_TEXTURE_RECTANGLE.
Not really a lot of explaining, as far as the basics are concerned. :)
BTW- +1 for what Marcus said in his answer. You're learning an outdated OpenGL version right now; while you can do a lot of fun things with it, you can do more with at least OpenGL 2 and shaders... and it's usually easier with shaders too.
I try to use the following code to draw a square-shaped pixel with opengl
glPointSize(5.0f);
glBegin(GL_POINTS);
glVertex3f(1.0f, 1.0f, 1.0f);
glEnd();
However, the final result is a circle-shaped pixel.
Please take a look the reference http://risknfun.com/compform/w1.html
See the "Problem 4. A Grid". On the right side, the display image has square-shaped pixel.
It's partly up to the OpenGL implementation (i.e., it can vary with your graphics driver), but with a bit of luck, you can turn this on or off with glEnable(GL_POINT_SMOOTH); or glDisable(GL_POINT_SMOOTH); With point smoothing turned on, you'll normally get round points, but with it turned off you'll get square points.
You can also try to tell OpenGL not to spend time making GL_POINTS nice and round by calling:
glHint(GL_POINT_SMOOTH_HINT, GL_FASTEST);
But keep in mind that's just an hint. The OpenGL driver has ultimately the last word.
I know OpenGL itself is a frequently asked question, but I couldn't find a solution to this specific problem I'm having. I've been following NeHe's tutorials, and I've ran into some issues which I don't think should be happening:
When calling glRotatef, where the first parameter being the angle, it appears to be the speed of rotation instead.
Example:
glRotatef(0, 0.0f, 1.0f, 0.0f); // despite the constant numbers, the object rotates infinitely
I am using an NSTimer to loop through the drawing method, which I may think be part of the issue.
Instead of the object rotating 360 degrees around like it should, the object's angle will increment to 180 then decrement back to 0. This is the same with 2D and 3D objects.
I saw example code from Apple and other places that didn't have the same problem as I did, but I was never able to figure out what exactly I am doing wrong that gives me these issues.
The code you have there glRotatef(0,0.0f,1.0f,0.0f); does not change the rotation at all, it simply requests a rotation of 0 degrees around the Y axis. If you want an object to rotate smoothly as time progresses I would suggest the following:
Keep a counter that increments every time your timer triggers, then, before you draw whatever object you are displaying, reset the transformation matrix with glLoadIdentity() and then call glRotatef( counter , 0.0f, 1.0f , 0.0f )