Computer graphics -- 2008-2009 -- info.uvt.ro/Laboratory 3
From Wikiversity
Quick links: front; laboratories agenda, 1, 2, 3, 4, 5, JOGL template.
Contents |
[edit] (J)OGL BASICS (PART 2)
NOTE: Grab the application template from the following link: Computer graphics -- 2008-2009 -- info.uvt.ro/JOGL-Template
[edit] Antialising
Aliasing effects are induced due to discretization of images or to effects that cause different continuous signals to become indistinguishable.
Several antialiasing techniques ca be used in (J)OGL:
- Color blending -- means that two colors can be mixed together using various criteria. The next example shows how we can use it to obtain an antialiasing effect:
[...] public void init(GLAutoDrawable canvas) { [...] // Activate the GL_LINE_SMOOTH state variable. Other options include // GL_POINT_SMOOTH and GL_POLYGON_SMOOTH. gl.glEnable(GL.GL_LINE_SMOOTH); // Activate the GL_BLEND state variabe. Means activating blending. gl.glEnable(GL.GL_BLEND); // Set the blend function. For antialiasing it is set to GL_SRC_ALPHA for the source // and GL_ONE_MINUS_SRC_ALPHA for the destination pixel. gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA); // Control GL_LINE_SMOOTH_HINT by applying the GL_DONT_CARE behavior. // Other behaviours include GL_FASTEST or GL_NICEST. gl.glHint(GL.GL_LINE_SMOOTH_HINT, GL.GL_DONT_CARE); } public void display(GLAutoDrawable canvas) { GL gl = canvas.getGL(); [...] gl.glLineWidth(1.5f); gl.glColor3f(1.f, 0.f, 0.f); gl.glBegin(GL.GL_LINES); gl.glVertex2f(0.2f, 0.2f); gl.glVertex2f(0.9f, 0.9f); gl.glEnd(); gl.glColor3f(0.f, 1.f, 0.f); gl.glBegin(GL.GL_LINES); gl.glVertex2f(0.9f, 0.2f); gl.glVertex2f(0.2f, 0.9f); gl.glEnd(); [...] } [...]
We could play with the previous code by disabling GL_BLEND and/or GL_LINE_SMOOTH and notice the difference.
- Handling the accumulation buffer -- is the most simple OGL buffer and is handled by only one function (method) glAccum. It is an extended-range color buffer but instead of rendering images in it they are added to the contents of the accumulation buffer after rendering. It is used for creating antialiasing effects, motion blur, depth of field etc. This approach will be detailed in a later laboratory when will deal with buffers in more detail.
Links:
[edit] Polygons
Are made of a single line loop between several points.
[edit] Validity
Only convex polygons are valid in (J)OGL. If we want to draw concave polygons we should draw them by using lines with GL_LINE_LOOP. Alternatively we could divide our concave polygon into smaller convex ones by triangulation or tessallation (See bellow).
Link:
[edit] The building blocks of polyons
Polygons are made of smaller polygons. These building blocks can be either other triangles (triangulation) or other smaller polygons (tessellation).
The simplest polygon is a triangle.
[edit] Dimensionality
Polygons may lie in the same plane or not depending on whether all their vertices lie in the same plane or not.
[edit] Primitives
In (J)OGL we can create polygons by interpreting vertices in a broad way:
- polygons -- by using GL.GL_POLYGON
- quads -- by using GL.GL_QUADS
- quad strip -- by using GL.GL_QUAD_STRIP
- triangles -- by using GL.GL_TRIANGLES
- triangle strip -- by using GL.GL_TRIANGLE_STRIP
- triangle fan -- by using GL.GL_TRIANGLE_FAN
A particular polygon which has its own function (method) is the rectangle (by using glRect).
public class Main { [...] public void display(GLAutoDrawable canvas) { GL gl = canvas.getGL(); [...] gl.glBegin(GL.GL_POLYGON); gl.glColor3f(1.f, 0.f, 0.f); gl.glVertex2f(0.2f, 0.2f); gl.glColor3f(0.f, 1.f, 0.f); gl.glVertex2f(0.2f, 0.4f); gl.glColor3f(0.f, 0.f, 1.f); gl.glVertex2f(0.4f, 0.4f); gl.glColor3f(1.f, 1.f, 1.f); gl.glVertex2f(0.4f, 0.2f); gl.glEnd(); [...] } [...] }
Links:
[edit] Polygon filling and orientation
(J)OGL polygons can also be filled with a given color or just draw their contours or display the points (vertices) they are made of. The function (method) which enables you this operation is glPolygonMode(face, mode), where face could take the GL_FRONT, GL_BACK, GL_FRONT_AND_BACK values and mode can take the GL_POINT, GL_LINE or GL_FILL values. Polygons could be rendered differently depending on which side is facing the viewer.
An important feature when drawing polygons is the decision to draw only front or/and back faced ones. This action is specified by the glCullFace(face) where face is specified by GL_FRONT, GL_BACK, GL_FRONT_AND_BACK. This feature is called culling and is used for optimization reasons mostly.
Polygons having their vertices specified in clockwise order are back-faced, while polygons having vertices defined in trigonometric order are front-faced. You could change this default behavior by using the glFrontFace function (method). It receives two parameters: GL_CW (ClockWise) and GL_CCW (CounterClockWise - Trigonometric).
For example the following code will display the polygon:
public class Main { [...] public void display(GLAutoDrawable canvas) { GL gl = canvas.getGL(); [...] // Do not render front-faced polygons. gl.glCullFace(GL.GL_FRONT); // Culling must be enabled in order to work. gl.glEnable(GL.GL_CULL_FACE); gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL); // Define vertices in clockwise order (back-faced) gl.glBegin(GL.GL_POLYGON); gl.glColor3f(1.f, 0.f, 0.f); gl.glVertex2f(0.2f, 0.2f); gl.glColor3f(0.f, 1.f, 0.f); gl.glVertex2f(0.2f, 0.4f); gl.glColor3f(0.f, 0.f, 1.f); gl.glVertex2f(0.4f, 0.4f); gl.glColor3f(1.f, 1.f, 1.f); gl.glVertex2f(0.4f, 0.2f); gl.glEnd(); [...] } [...] }
while the next one will not:
public class Main { [...] public void display(GLAutoDrawable canvas) { GL gl = canvas.getGL(); [...] // Do not render back-faced polygons. gl.glCullFace(GL.GL_BACK); // Culling must be enabled in order to work. gl.glEnable(GL.GL_CULL_FACE); gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL); // Define vertices in clockwise order (back-faced). gl.glBegin(GL.GL_POLYGON); gl.glColor3f(1.f, 0.f, 0.f); gl.glVertex2f(0.2f, 0.2f); gl.glColor3f(0.f, 1.f, 0.f); gl.glVertex2f(0.2f, 0.4f); gl.glColor3f(0.f, 0.f, 1.f); gl.glVertex2f(0.4f, 0.4f); gl.glColor3f(1.f, 1.f, 1.f); gl.glVertex2f(0.4f, 0.2f); gl.glEnd(); [...] } [...] }
[edit] Polygon stipple
As for lines polygons can be filled with a stipple pattern by using the glPolygonStipple function (method):
public class Main { [...] byte mask[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, (byte)0x80, 0x01, (byte)0xC0, 0x06, (byte)0xC0, 0x03, 0x60, 0x04, 0x60, 0x06, 0x20, 0x04, 0x30, 0x0C, 0x20, 0x04, 0x18, 0x18, 0x20, 0x04, 0x0C, 0x30, 0x20, 0x04, 0x06, 0x60, 0x20, 0x44, 0x03, (byte)0xC0, 0x22, 0x44, 0x01, (byte)0x80, 0x22, 0x44, 0x01, (byte)0x80, 0x22, 0x44, 0x01, (byte)0x80, 0x22, 0x44, 0x01, (byte)0x80, 0x22, 0x44, 0x01, (byte)0x80, 0x22, 0x44, 0x01, (byte)0x80, 0x22, 0x66, 0x01, (byte)0x80, 0x66, 0x33, 0x01, (byte)0x80, (byte)0xCC, 0x19, (byte)0x81, (byte)0x81, (byte)0x98, 0x0C, (byte)0xC1, (byte)0x83, 0x30, 0x07, (byte)0xe1, (byte)0x87, (byte)0xe0, 0x03, 0x3f, (byte)0xfc, (byte)0xc0, 0x03, 0x31, (byte)0x8c, (byte)0xc0, 0x03, 0x33, (byte)0xcc, (byte)0xc0, 0x06, 0x64, 0x26, 0x60, 0x0c, (byte)0xcc, 0x33, 0x30, 0x18, (byte)0xcc, 0x33, 0x18, 0x10, (byte)0xc4, 0x23, 0x08, 0x10, 0x63, (byte)0xC6, 0x08, 0x10, 0x30, 0x0c, 0x08, 0x10, 0x18, 0x18, 0x08, 0x10, 0x00, 0x00, 0x08}; ByteBuffer bb = null; public void display(GLAutoDrawable canvas) { GL gl = canvas.getGL(); gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL); // Set the polygon mask. gl.glPolygonStipple (bb); // Enable polygon stipple. gl.glEnable (GL.GL_POLYGON_STIPPLE); // Define vertices in clockwise order (back-faced). gl.glBegin(GL.GL_POLYGON); gl.glColor3f(1.f, 0.f, 0.f); gl.glVertex2f(0.2f, 0.2f); gl.glColor3f(0.f, 1.f, 0.f); gl.glVertex2f(0.2f, 0.4f); gl.glColor3f(0.f, 0.f, 1.f); gl.glVertex2f(0.4f, 0.4f); gl.glColor3f(1.f, 1.f, 1.f); gl.glVertex2f(0.4f, 0.2f); gl.glEnd(); // Disable polygon stipple. gl.glDisable (GL.GL_POLYGON_STIPPLE); [...] } [...] }
[edit] Polygon normals
Normals are perpendicular lines on surfaces. They are important when dealing with lights as their effects are computed with regard to the angle between the light direction and the each vertex normal. More on them will be discussed when we will address lighting issues.
Normals can be specified by using the glNormal*() family functions (methods). The values of the arguments should be in the [-1,1] range.
public class Main { [...] public void display(GLAutoDrawable canvas) { GL gl = canvas.getGL(); [...] // Do not render front-faced polygons. gl.glCullFace(GL.GL_FRONT); // Culling must be enabled in order to work. gl.glEnable(GL.GL_CULL_FACE); gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL); // Define vertices in clockwise order (back-faced). gl.glBegin(GL.GL_POLYGON); // Define normal for vertex 1 gl.glNormal3f(0.f, 0.f, 1.f); gl.glColor3f(1.f, 0.f, 0.f); gl.glVertex2f(0.2f, 0.2f); // Define normal for vertex 2 gl.glNormal3f(0.f, 0.f, 1.f); gl.glColor3f(0.f, 1.f, 0.f); gl.glVertex2f(0.2f, 0.4f); // Define normal for vertex 3 gl.glNormal3f(0.f, 0.f, 1.f); gl.glColor3f(0.f, 0.f, 1.f); gl.glVertex2f(0.4f, 0.4f); // Define normal for vertex 4 gl.glNormal3f(0.f, 0.f, 1.f); gl.glColor3f(1.f, 1.f, 1.f); gl.glVertex2f(0.4f, 0.2f); gl.glEnd(); [...] } [...] }
Links:
[edit] Building Display Lists
Display lists can be seen (at first glance) as a C function which once defined can be used as many times we want in our code. Simply put they store batches of OGL commands which can then be used repeatedly in our code. They are also used for their performance.
OGL commands within them are precompiled and, if possible, stored in the graphics card memory. Therefore, in general the execution of a Display List is faster than the execution of the commands contained in it.
Display Lists IDs are generated by using the glGenLists function (method). All the OGL commands that we want to store in a Display List must be placed inside a function (method) block starting with glNewList(int id, int mode) (where mode can be GL_COMPILE - creates the list, or GL_COMPILE_AND_EXECUTE - creates the list and executes the commands contained inside of it) and ending with glEndList.
public class Main { [...] public void init(GLAutoDrawable canvas) { [...] // Generate a unique ID for our list. aCircle = gl.glGenLists(1); // Generate the Display List gl.glNewList(aCircle, GL.GL_COMPILE); drawCircle(gl, 0.5f, 0.5f, 0.4f); gl.glEndList(); } int aCircle; public void display(GLAutoDrawable canvas) { GL gl = canvas.getGL(); [...] gl.glColor3f(1.0f, 1.0f, 1.0f); // Call the Display List i.e. call the commands stored in it. gl.glCallList(aCircle); } // Here we define the function for building a circle from line segments. private void drawCircle(GL gl, float xCenter, float yCenter, float radius) { double x,y, angle; gl.glBegin(GL.GL_LINE_LOOP); for (int i=0; i<360; i++) { angle = 2 * Math.PI / 360 * i; x = radius * Math.cos(angle); y = radius * Math.sin(angle); gl.glVertex2d(xCenter + x, yCenter + y); } gl.glEnd(); } [...] }
Links:
[edit] API
[edit] Exercises
- Draw a house by using GL_LINES (GL_LINE_LOOP) without antialiasing. Enable it. What do you notice?
- Draw a circle by using GL_LINE_LOOP
- Draw a circle by using GL_TRIANGLE_FAN
- Draw a chess board made out of polygons with squares of white and black. Squares should alternate with one being black and one white. It is prohibited to draw a polygon using the black color. Instead you should draw them as back-faced and enable culling for them.