Computer graphics/2013-2014/Laboratory 8

Quering the status of state variables
(J)OGL allows one to query the status of several state variables such as GL_BLEND, GL_LIGHTING, GL_VIEWPORT, GL_MAX_LIGHTS etc. The methods (functions) which facilitate these operations are: glGetBooleanv, glGetDoublev, glGetFloatv and glGetIntegerv. Each of them receives two variables: the desired state variable and a variable which will hold the result. In addition some state variables have their own methods (functions): glGetLight*, glGetError, or glGetPolygonStipple

Links:


 * http://linux.die.net/man/3/glgetfloatv

Buffers
(J)OGL uses four buffers to handle each window (canvas):


 * Color buffer - specified by GL_COLOR_BUFFER_BIT is responsible for storing the colors of the pixels
 * glColorMask is a nice example of how one can restrict the modification of any of the RGBA color components of the pixels

For instance the following code snippet disables coloring, draws a triangle and enables coloring again:


 * Depth buffer - specified by GL_DEPTH_BUFFER_BIT is responsible for storing the distance from each pixel to the observer's position. It is used by the z-buffer algorithm to eliminate the hidden surfaces
 * glDepthFunc can be used to specify the function used to compare each incoming pixel depth value with the depth value present in the depth buffer
 * the operators which can be used to compare the value stored in the buffer with the current pixel value are: GL_NEVER, GL_ALWAYS, GL_EQUAL, GL_NOTEQUAL, GL_LESS, GL_GREATER, GLGEQUAL. They can be specified by using the glDepthFunc method (function)
 * Stencil buffer - specified by GL_STENCIL_BUFFER_BIT is used for generating shadows from multiple light sources, restricting drawing to a particular area, etc. One can draw into the stencil planes using GL drawing primitives, then render geometry and images, using the stencil planes to mask out portions of the screen
 * it is activated by using glEnable(GL_STENCIL_TEST)
 * there are four main functions for handling it: glClearStencil, glStencilFunc, glStencilOp and glStencilMask.

The following example shows how the stencil buffer can be used to create a custom shaped viewport:


 * Accumulation buffer - specified by GL_ACCUMULATION_BUFFER_BIT is the simplest buffer and is used for effects such as anti-aliasing, motion blur, depth of field, etc.
 * it only has one method (function) attached to it: glAccum. Its first parameter can be one of the following:
 * GL_ACCUM - adds (in the buffer) the color from the color buffer multiplied by the second parameter
 * GL_LOAD - replaces (in the buffer) the color from the color buffer multiplied by the second parameter
 * GL_ADD - adds to all the values stored in the buffer the value of the second parameter
 * GL_MULT - multiplies all the values stored in the buffer the value of the second parameter
 * GL_RETURN - copies the values from the buffer to the color buffer

The following example shows a simple use of the accumulation buffer:

Links:


 * http://www.cs.unm.edu/~angel/CS433/LECTURES/CS433_24.pdf

OBJECT PICKING
Picking is used in interactive scenes where the user can select an object or click on it to obtain more information.

Rendering modes
Before proceeding it is good to know that there (J)OGL has three possible rendering states. Until now we have only used GL_RENDER (implicitly):


 * GL_RENDER - used for rendering the objects in the frame buffer (on the screen)
 * GL_SELECT - used for rendering objects in the select buffer - this is what will use for picking
 * GL_FEEDBACK - used for displaying a lot of information without actually rendering anything

Changing the rendering mode is accomplished by using the glRenderMode(mode) method (function). It takes as arguments one of the above listed parameters.

Picking
The glRenderMode method (function) returns a value which depends on the previously used rendering mode. The value contains the number of visible objects drawn in the buffer. So for example if you restrict drawing in GL_SELECT mode to a window of NxN pixels it will count the number of objects drawn in that particular area. Now if you only use an area of one pixel around your mouse pointer and switch to GL_SELECT mode each time you click a button the previously mentioned method (function) will return to you the number of objects which were drawn (and thus visible) in that region. You therefore can count in this way how many objects you've selected.

The previous is not enough as you need to know which object you clicked on. For this (J)OGL provides us with methods (functions) (glPushName(name) and glPopName) for naming objects and pushing them in the name stack. Before you draw the object you need to push its name on the stack. In the same way you pop it after drawing is complete:

NOTE: the name stack is only used in selection mode (GL_SELECT). It will have no effect in the default GL_RENDER mode.

Important: be sure to initialize the name stack by using the glInitNames method (function) right after entering selection mode.

One should add the following it the code in order to handle picking:


 * define a drawing function which draws the objects. Before drawing each object you define it's name by calling glLoadName(name)
 * define an event handling function which can handle mouse clicks:
 * call a selection handling method (function) each time a click happens
 * define a selection method (function) where you need to:
 * initialize the selection buffer. It will contain data about selected objects
 * save the info about the current view-port
 * switch to GL_SELECT mode
 * initialize the name stack
 * restrict the drawing area around the mouse position (a 1x1 pixels or 5x5 should suffice). Is accomplished by reseting the view-volume (from the Projection Matrix). It can be done by using the gluPickMatrix method (function).
 * draw the objects with their names
 * get the number of hits, handle them and retrieve the picked object

The following fragment of code exemplifies all of the previous by drawing a sphere and allowing the user to pick it.

Links:


 * http://jerome.jouvie.free.fr/OpenGl/Tutorials/Tutorial27.php#RenderMode
 * http://www.lighthouse3d.com/opengl/picking/
 * http://gpwiki.org/index.php/OpenGL:Tutorials:Picking
 * http://user.cs.tu-berlin.de/~schabby/

API

 * javax.media.opengl:
 * GL:
 * glClearStencil(int)
 * glStencilFunc(int, int, int)
 * glStencilOp(int, int, int)
 * glStencilMasc(int)
 * glAccum(int, float)
 * glRenderMode(int)
 * glPushName(int)
 * glPopName
 * glGetBooleanv(int, bytev, int)
 * glGetDoublev(int, doublev, int)
 * glGetFloatv(int, floatv, int)
 * glGetIntegerv(int, intv, int)
 * glInitNames
 * glSelectBuffer(int, java.nio.IntBuffer)
 * glMultMatrixf(floatv, int)
 * javax.media.opengl.glu:
 * GLU;
 * gluPickMatrix(double, double, double, double, intv, int)

Exercise

 * Create a hexagon shaped viewport. Make it rotate.
 * Starting from the exercise in the previous laboratory add support for picking the three spheres present in the scene.