Computer graphics/2013-2014/Laboratory 4

(J)OGL BASICS (PART 3)
NOTE: Grab the application template from the following link: Computer graphics -- 2013-2014 -- info.uvt.ro/JOGL-Template

Textures
A texture is a rectangular array of data containing information about color, luminance, color and alpha. Each element in this array is called a texel.

Textures can be 1D, 2D or 3D (used to simulate certain characteristics in the material they depict)

Texture mapping allows one to glue together an image of an object on a polygon. For example images of walls, vegetation, landscapes, etc. NOTE: besides being applied to polygons textures could be also applied to other primitives such as points, lines, polygons, bitmaps and images. It implies mapping texture coordinates to geometric coordinates.

NOTE: you can download textures from the following link:.

Links:


 * Texturing
 * 3D Textures

Creating and displaying 2D textures
The steps involved in generating a 2D texture are as follows:


 * Generate a name for our texture using glGenTextures function (method)
 * Bind (select) our texture in a target. The target is in our case GL_TEXTURE_2D but can also take other values such as GL_TEXTURE_3D or GL_TEXTURE_1D. The binding is accomplished by using the glBindTexture function (method)
 * Specify the pixel storage mode by using the glPixelStorei function (method). This affects how the pixels stored in memory are read
 * Define the filters used when the texture is scaled (resized) during the drawing by using the glTexParameteri function (method)
 * Construct the texture with the representation of the picture file by using either glTexImage2D or gluBuild2DMipmaps functions (methods) depending on whether we want mipmaps (multiple levels of detail in our texture) or not
 * Enable GL_TEXTURE_2D by using the glEnable function (method)
 * Render the texture by assigning vertex coordinates to texture coordinates. The texture coordinates are usually given inside the [0, 1] interval. One can specify a texture coordinate by using the glTexCoord2* family functions (methods)

NOTE: an alternate method for generating textures by using the Texture and TextureIO classes is presented at the following link: Computer graphics -- 2007-2008 -- info.uvt.ro/Laboratory 5.

Important: texture size must be a power of 2 (32x32, 64x64, 512x128, etc) for the texture loader to work properly. Failing to provide a power of 2 texture size will result in an error.

The following code fragments exemplifies the previous steps (IMPORTANT - Please be sure to download and copy the classes found inside the following arhive: http://www.info.uvt.ro/~mfrincu/textureManager.zip):

NOTE: While the previous code reads textures from image files, the textures can also be generated by specifying the pixel matrix. This (uses glTexImage2D) and this (uses glDrawPixels) exemplifies how you can achieve this.

Textures can also be repeated or clamped:
 * repeated - copies of the texture map tile the surface
 * clamped - a single copy of the image appears on a large surface

The previous techniques are useful when one decides to give texture coordinates outside the [0, 1] interval.

Links:


 * Texturing
 * Mipmapping
 * Texturing tutorial
 * Texturing tutorial based on the NeHe examples

Replacing parts of a texture with another
(J)OGL allows one to replace parts of a texture with another. This technique is also used for improving performance as replacing a texture is much faster than rebuilding it each time.

The following code fragment shows how one can replace a texture with another. Be sure to generate 2 textures inside init, and change NO_TEXTURES = 1 with NO_TEXTURES = 2 inside your code before testing it.

NOTE arguments 3,4,5 and 6 from the glTexSubImage2D represent the position in pixels (arguments 3 and 4) from where a portion of given width (argument 5) and height (argument 6) will be replaced by the pixel data given as last argument. The width and height need to be smaller than the initial image size (tex[0].getWidth, tex[0].getHeight - in our example). The coordinate center (0,0) is situated in the lower left corner of the image.

Links:


 * Texture replacement
 * Multiple views
 * Texture replacement based on Nehe examples

Anisotropic Fitering
Mipmapping often produces blurred images for distant textures viewed at oblique angles. This is due to the fact that texture mapping mode assumes the texture space is a square (isotropic) while in reality it is rather long and narrow (anisotropic). To overcome this problem one could apply anisotropic filtering as detailed in the following code fragment:

Texture transparency and blending
Blending means combining two or more textures by mixing their components.

Transparency means making some pixels transparent. The transparency factor can range from opaque to fully transparent.

Steps for blending

 * Enable blending by using the glEnable(GL.GL_BLEND) function (method)
 * Set the blend function by using the glBlendFunc(mode, mode) function (method)
 * Draw the object(s)
 * disabling blending by using the gl.glDisable(GL.GL_BLEND) function (method)

Note: (for 3D graphics) there are cases when you need to disable the depth test while blending, by using the glEnable(GL_DEPTH_TEST) and glDisable(GL_DEPTH_TEST) functions (methods)

Steps for transparency (alpha testing)

 * Enable alpha testing by using the glEnable(GL_ALPHA_TEST) function (method)
 * Set alpha testing by using the glAlphaFunc(GL_GREATER, 0.7f) function (method) which tells OGL to discard the pixels with an alpha value greater then 0.7 (for example)

IMPORTANT: In order to enable blending we need two textures. As a result the code fragment in the init method for creating a texture needs to be duplicated:

NOTE: The previous method is inefficient as it requires one to copy several lines of code multiple times. A better approach would be to create a class for handling texture creation and manipulation (binding, enabling, disabling).

Links:


 * OpenGL Programming Guide -- Blending, Antialiasing, Fog, and Polygon Offset
 * NeHe blending and transparency
 * OpenGL FAQ -- Transparency, Translucency, and Blending
 * glBlendFunc

API

 * JOGL JavaDoc;

Exercises

 * Create a separate class called TextureHandler for generating a texture and test it by loading and displaying two textures. The class should have the following methods:
 * a method called bind for binding (selecting) the texture. Wrapper for gl.glBindTexture(GL.GL_TEXTURE_2D, texture[0]);.
 * a method called enable for enabling the texture. Wrapper for gl.glEnable(GL.GL_TEXTURE_2D);.
 * a method called disable for disabling the texture. Wrapper for gl.glDisable(GL.GL_TEXTURE_2D);.
 * a method called getTexture for retrieving the TextureReader.Texture object.
 * a constructor called TextureHandler(GL gl, GLU glu, String filename, boolean mipmapped) for generating the texture. Much of the code in the init method presented at the beginning of this lab goes in there. The constructor should receive as argument a reference to the GL and GLU objects, the path to the image and a boolean argument which specifies whether mipmapping should be used or not.
 * a private method makeRGBTexture(...) as the one presented in this laboratory.
 * Create a chessboard by replacing parts of a large white texture with smaller black textures.
 * Create two squares on top of each other, apply two textures to them and set up blending. Use 5 different blending options and compare them. Make the squares move on the X axis and let them bounce of the wall (screen margin)

NOTE: Use the TextureHandler that you implemented for the first assignment in the rest of the exercises!