By the end of this tutorial you will have learned how to draw coloured primitive two-dimensional shapes: LWJGL OpenGL drawing.
Immediate mode drawing
In this tutorial I will use the immediate drawing mode. The immediate drawing mode, as well as many other things, was deprecated in OpenGL 3.0, but many of the same principles still apply. This video covers alternate rendering methods.
Where to find the methods
All the OpenGL methods are static. You can find the OpenGL 1.1 methods in the org.lwjgl.opengl.GL11 class. Note that ’11’ stands for version ‘1.1’. Similarly, you can find the methods that were added in OpenGL 1.5 in the org.lwjgl.opengl.GL15 class. If you want to have some documentation, be sure to have a look at the OpenGL 2.1 manual pages.
import static org.lwjgl.opengl.GL11.*;
Setting up the projection matrix
The following code initialises a projection matrix where (0,0) is the upper-left corner of the drawing canvas and (640,480) the bottom-right corner of the drawing canvas:
glLoadIdentity(); // Resets any previous projection matrices
glOrtho(0, 640, 480, 0, 1, -1);
Clearing the canvas
To clear a 2D drawing canvas, you write:
To clear a 3D drawing canvas, you write:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
You tell OpenGL you want to start rendering by calling:
The parameter type is an OpenGL constant. This parameter stands for which shape to draw. IN LWJGL, constants are stored in the form of final integers. You can choose from GL_POINTS, GL_LINES, GL_TRIANGLES, GL_QUADS, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, and GL_POLYGONS.
For compliance with modern OpenGL (3.0 and higher), I recommend you avoid GL_QUADS and GL_POLYGONS, as they have been deprecated in OpenGL 3.0.
Each shape requires a set amount of vertices to be drawn. Triangles (GL_TRIANGLES) require three vertices, points (GL_POINTS) require one, and lines (GL_LINES) require two. Once you have sent the required amount of vertices for a shape, the following vertices will be used to assemble the next shape.
Now that OpenGL knows which shape to draw, you can give it the vertex data. Vertex data consists of the positions of the points in the coordinate space, and built-in attributes such as the colour and material.
After glVertex you can put a 2, 3, or a 4. This number tells OpenGL how many components the vertex will have. glVertex2 means that the method will take two values, x and y. After this component-indicator you can put an f, a d, or an i. These represent float, double, and integer types respectively. For 2D vertices you often use:
When you are done submitting vertex data to OpenGL, you can stop rendering by writing:
Submitting vertex colours is almost the same as submitting vertex position. Instead of xyzw, colours have rgba, which stand for red, green, blue, and alpha (tranparency). There is a global colour state; once you set the colour to a certain value, it will remain that value until it is changed again. Also, there is no i suffix with colours and, in order to use numerical values, the ub suffix must be used with arguments, typecast to bytes. If a vertex is sent to OpenGL, it links the current colour state to the vertex and draws it accordingly. Colour values for doubles and floats range from 0.0 to 1.0 and for unsigned bytes they range from 0 to 255.
Shapes, front-facing or back-facing?
In OpenGL each shape has a front and a back side. Which side is the front-facing one is determined from the order in which you send the vertices and where the camera is located. The side on which the vertices are counter-clockwise, is the front face. The side on which the vertices are clockwise, is the back face. A common performance optimisation known as face culling involves not drawing the back faces of shapes. In 3D this works if the back faces are always on the inside of a shape, and in 2D this works if all the shapes are front-facing.