Help set up OpenGL for 2D

I am writing my first 2D Android app using OpenGL. I write this on my Desire, so my screen coordinates should be from 0.0 to 799,479 in landscape mode. I am trying to get OpenGL to use this range in world coordinates.

The application, for example, still works, but I had to adjust the numbers so that something appeared on the screen, and I was disappointed by my inability to understand the relationship between the projection matrix, and texture rendering in this regard.

Setting the projection matrix:

gl.glViewport(0, 0, width, height); float ratio = (float) width / height; float size = .01f * (float) Math.tan(Math.toRadians(45.0) / 2); gl.glMatrixMode(GL10.GL_PROJECTION); gl.glLoadIdentity(); gl.glFrustumf(-size, size, -size / ratio, size / ratio, 0.01f, 100.0f); // GLU.gluOrtho2D(gl, 0,width, 0, height); 

I want to understand 0.01f and 100.0f here. What do I use to describe the 2D world 0,0 → 799,479 with z value of zero?

Also, I'm not sure what is “best” - using glFrustumF or GLU.gluOrtho2D. The latter has simpler parameters - only the size of the viewport, but I have not found this anywhere. (Some sites have a height and 0 vice versa, but that doesn't matter.) But shouldn't that be a natural choice for using OpenGL 2D? Do I have to say something somewhere to say OpenGL "I do it in 2D - please ignore the third dimension everywhere, in the interest of speed"?

Drawing my textures:

I draw material using 2 textured triangles. Relevant parts of my init (let me know if I need to edit my question in more detail):

 gl.glMatrixMode(GL10.GL_MODELVIEW); gl.glLoadIdentity(); gl.glTranslatex(nXpos, nYpos, nZoomin); gl.glRotatef(nRotZ, 0, 0, 1); gl.glScalef((float)nScaleup,(float)nScaleup, 0.0f); ... ... gl.glVertexPointer(2, GL10.GL_FIXED, 0, mVertexBuffer); gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTextureBuffer); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); mVertexBuffer is an IntBuffer and contains: int vertices[] = { -1, -1, 1, -1, -1, 1, 1, 1 }; 

I do not intend to ultimately go to nZoomin - I did it this way, because that’s how I found the “magic numbers” necessary to see something! Currently, I need to use -1000, with smaller numbers resulting in smaller images. Do I think that there must be some way to have a value of zero for nZoomin when the projection matrix is ​​set correctly?

My textures are currently 128x128 (but may have different sizes, possibly always square). I do not know when they will be displayed in real size. I would like to be able to pass a value of, say, 128 to nScaleup so that it is built to the actual size. Is this related to the projection matrix, or do I have two separate problems?

+4
source share
2 answers

If you are working in 2D, you do not need glFrustum , just use glOrtho . Something like that:

 void glOrthof(0, 800, 0, 480, -1, 1); 

This will start in the lower left. If you want in the upper left corner, use:

 void glOrthof(0, 800, 480, 0, -1, 1); 

For 480 and 800, you must explicitly replace the actual size of your view, so your application will be portable for different screen sizes and configurations.

I pass -1 and 1 for the z range, but that doesn't really matter, because the orthogonal projection puts (x, y, z) in the same place on the screen, regardless of the z value (should not be close and far away equal). This is the only way to tell OpenGL to ignore the z-coordinate; there is no specific “2D” mode, your matrices are still 4x4, and two-dimensional vertices will get the z coordinate from 0.

Please note that your coordinates do not range from 0 to 799, but really from 0 to 800. The reason is that OpenGL interprets the coordinates as lying between the pixels, and not from them. Think of it as a 30 cm ruler: there are 30 centimeter intervals on it, and the ticks are numbered 0-30.

The vertex buffer that you use does not work because you use the GL_FIXED format. This means that 16 bits before the decimal point and 16 bits after it, so to indicate a 2x2 square around the origin, you need to multiply each value by 0x10000 :

 int vertices[] = { -0x10000, -0x10000, 0x10000, -0x10000, -0x10000, 0x10000, 0x10000, 0x10000 }; 

This is probably the reason you need to scale it so much. If you use this array without scaling, you should get a 2x2 pixel square. Turning this into a 1x1 square, so the size can be controlled directly by a scale factor, remains as an exercise for the reader;)

+8
source

Do I need to say something in OpenGL "I do it in 2D

I think the problem is that you are using a projection matrix for perspective projection. Instead, you should use parallel projection. To get this matrix, you can use the glOrtho () function.

 gl.glMatrixMode(GL10.GL_PROJECTION); ... gl.glOrtho(0, width, 0, height, 0, 128); 

Now the value of z no longer affects the size of the object.


I want to understand 0.01f and 100.0f here. What do I use to describe the 2D world 0,0 → 799,479 with z value of zero?

It is true that in the 2D world you really have no z values. But you must decide which of your objects you want to draw first. There are two ways to decide what:

  • Deactivate GL_DEPTH_TEST , and everything will be drawn in the order you GL_DEPTH_TEST .
  • Activate GL_DEPTH_TEST and let OpenGL decide
+1
source

Source: https://habr.com/ru/post/1338643/


All Articles