Reputation: 1522
I'm starting to learn open GL in android (GL10) using java and I followed some tutorials to draw squares, triangles, etc.
Now I'm starting to draw some ideas I have but I'm really confused with the drawing vertexs of the screen. When I draw something using openGL ES, I have to specify the part of the screen I want to draw and the same for the texture...
So I started to make some tests and I printed a fullscreen texture with this vertexs:
(-1, -1, //top left
-1, 1, //bottom left
1, -1, //top right
1, 1); //bottom right
Why is this fullscreen? Isn't the center of OpenGL coordinates at top left (0, 0)? Why with that vertexs the draw is correct? It seems that the center is really the real center of the screen and the width and height is from -1...1, but I dont really understand it because I thought that the center was at the top left...
Another question... I read a lot of c++ code where they print using pixels. It seems really necesary in videogames using pixels because needs the exact position of the things, and with -1...1 I cant be really precise. How can I use pixels instead of -1...1?
Really thanks and sorry about my poor english. Thanks
Upvotes: 2
Views: 3184
Reputation: 162164
Why is this fullscreen? Isn't the center of OpenGL coordinates at top left (0, 0)? Why with that vertexs the draw is correct? It seems that the center is really the real center of the screen and the width and height is from -1...1, but I dont really understand it because I thought that the center was at the top left...
There are 3 things coming together. The so called viewport, the so called normalized device coordinates (NDC), and the projection from model space to eye space to clip space to NDC space.
The viewport selects the portion of your window into which the NDC range
[-1…1]×[-1…1]
is mapped to. The function signature is glViewport(x, y, width, height)
. OpenGL assumes a coordinate system with rising NDC x-coordinates as going to the right and rising NDC y-coordinates going up.
So if you call glViewport(0, 0, window_width, window_height)
, which is also the default after a OpenGL context is bound the first time to a window, the NDC coordinate (-1, -1) will be in the lower left and the NDC coordinate (1,1) in the upper right corners of the window.
OpenGL starts with all transformations being set to identity, which means, that the vertex coordinates you pass through are getting right through to NDC space and are interpreted like this. However most of the time in OpenGL you're applying to successive transformations:
and
The modelview transformation is used to move around the world in front of the stationary eye/camera (which is always located at (0,0,0)). Placing a camera just means, adding an additional transformation of the whole world (view transformation), that's the exact opposite of how you'd place the camera in the world. Fixed function OpenGL calls this the MODELVIEW matrix, being accessed if matrix mode has been set to GL_MODELVIEW.
The projection transformation is kind of the lens of OpenGL. You use it to set if it's a wide or small angle (in case of perspective) or the edges of a cuboid (ortho projection) or even something different. Fixed function OpenGL calls this the PROJECTION matrix, being accessed if matrix mode has been set to GL_PROJECTION.
After the projection primitives are clipped, and then the so called homogenous divide applied, which is creating the actual perspective effect, if a perspective projection has been applied.
At this point vertices have been transformed into NDC space, which then gets mapped to the viewport as explained in the beginning.
Regarding your problem: What you want is a projection that maps vertex coordinates 1:1 to viewport pixels. Easy enough:
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if( origin_lower_left ) {
glOrtho(0, width, height, 0, -1, 1);
} else {
glOrtho(0, width, 0, height, -1, 1);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
Now vertex coordinates map to viewport pixels.
OpenGL-2.1 and OpenGL ES-1
void fullscreenquad(int width, int height, GLuint texture)
{
GLfloat vtcs[] = {
0, 0,
1, 0,
1, 1,
0, 1
};
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, vtcs);
glTexCoordPointer(2, GL_FLOAT, 0, vtcs);
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 1, 0, 1, -1, 1);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
Upvotes: 9
Reputation: 5322
You need to read a bit more to get things clearer. In openGL, you specify a viewport. This viewport is your view of the OpenGL space, so if you set it so that the center of the screen is in the middle of your screen and the view to extend from -1 to 1, then this is your full view of the OpenGL prespective. Do not mix that with the screen coordinates in Android (these coordinates have the origin at the top left corner as you mentioned). You need to translate between these coordinates (for touchevents for e.g.) to match the other coordinate system.
Upvotes: 2
Reputation: 2470
By default opengl camera is placed at origin pointing towards negative z axis. Whatever is projected on the camera near plane is the what is seen on your screen. Thus the center of the screen corresponds to (0,0)
Depending on what you want to draw you have the option of using GL_POINT, GL_LINE and GL_TRIANGLE for drawing.
You can use GL_POINTS to color some pixels on the screen but in case you need to draw objects/mesh such as teapot, cube etc than you should go for triangles.
Upvotes: 2