Sunday, May 18, 2014

Video course review: Building Android Games with OpenGL ES

Packt publishing invited me to do a review for their video course Building Android Games with OpenGL ES. Here is my complete review. I have broken it down chapter by chapter so lets get started.

The Review:
Chapter 1:
Section 1.1 starts up with an introduction to the development environment Eclipse and Android ADt plugin. The author details all the steps rather briskly to show the URLs from where the libraries are to be downloaded and how they are setup. He also shows how to setup the Android SDK manager as well as the eclipse IDE to load the ADT plugin.It concludes with the creation of an emulator for OpenGL ES code debugging/testing.

Section 1.2 gets our hand dirty with basic clear screen program that outputs a blue coloured screen on the Android emulator. The author starts with saying "add this code to the Activity class". As a beginner, I dont know what an activity is in the first place and why do I use Activity for? Why should I add the GLSurfaceView? There is no mention of what a Toast popup is? Another thing is about the overriden methods in our Renderer implemented class. When are they called and is it necessary to implement each of these functions? What if I am only interested in some of them?

Section 1.3 gives an overview of shaders and defines two shaders, vertex shader which simply assigns the per-vertex position to the gl_Position register. The fragment shader outputs the given uniform u_Color to the output. One thing to note here is that the author mentions that the fragment shader is sometimes also called pixel shader. This is only correct in the context of DirectX. In OpenGL, we never use the term pixel shader because in OpenGL, there is clear distinction between a fragment and a pixel. The fragment carries more information not just colour. So after the color is assigned in the fragment shader, the fragment travels through the raster ops to its final destination in the frame buffer. The output color of the eventual pixel is subject to the depth test/stencil test/blending outcome. So clearly in OpenGL parlance we cannot work on pixels we can only work on fragments thats why the term fragment shaders.

Section 1.4 shows how to compile and link shader programs. The author mentions the steps required to compile and link shader programs. He also details how to get the location of the attributes and upload data to GPU. One thing that I did not understand is the 4th parameter of glVertexAttribPointer which is given as false. What does it do? The author skipped this parameter without detailing what it does and what happens if we set it to true. Another thing that i dont understand is that the output looks more like a rectangle than a square to me. Why is that so even though we input coordinates for a square. I think this should have been discussed in detail. The reason is the viewport which is on a non-square window. If we were to draw a correct square geometrically, we must take the aspect ratio of the window/viewport into account when passing in vertex coordinates to OpenGL rather than passing in constant values.

Chapter 2:
Section 2.1 shows how to implement two basic classes, one for matrix and other for vector. Basic function definitions like identity matrix and vector addition, subtraction, multiplication and division were implemented. This section appears to be the shallowest of all the sections in the course.

Section 2.2 explains how to implement the dot and cross product functions in the vector class. The author first implements the normalization routine. One thing that should have been emphasized and discussed was the special case when the length of the vector is 0. The code shown does not handle this special case hence if the code is run on a zero vector (0,0,0), it will surely crash with a divide by zero arithmetic exception at runtime. The proper code should be this

static final float EPSILON = 0.0001f;
public void normalize() {
   float length = Math.sqrt(x*x + y*y + z*z);
   if(Math.abs(length) <= EPSILON)
      return;
   x /= length;
   y /= length;
   z /= length;
}


In addition to the normalization code, the lecture also covers how to implement the dot and cross product functions.

Section 2.3 shows how to implement orthographic and perspective projection matrices. In addition it also details how to implement the camera transform matrix. I find the projection matrix discussion to be very concise but the camera transform matrix is hardly detailed. More information should have be given about the orthonormal vectors that are obtained from the camera position, target and up vectors. Details should have been given on the elements stored in the camera matrix.

Section 2.4 shows how to create the scaling and translation matrices. The details about their implementation are given along with the definition of a Pipeline class that store the required properties and transforms.

Section 2.5 details how to implement the rotation and combined model view projection matrices. Although the author shows how the functions are implemented in detail, however, the analysis part is missing completely.

Section 2.6 covers Quaternions. It shows how to implement the quaternion class to do transformation using an axis and an angle. It also details how to find the conjugate of a quaternion as well as other required functions.

Chapter 3
Section 3.1 starts with an introduction to the lighting model, in particular it details about the ambient light calculation. It then shows how to create new wrapper classes to represent the new LightingProgram by inheriting a class from the abstract ShaderProgram class. One thing that is
more a design decision that I cannot digest is why the location variables are not stored in the parent class as protected variables. That way all inheriting class could use the same variables without any modification. If implemented the way it is shown, the user will have to provide new location variables for each shader when instead the basic variable locations (like MVP location, a_pos etc. which we are certain will always be in all shaders) could be stored as protected base class members. Another thing that is more a performance note is that the glUniform4f call in the onDrawFrame function could also be move in the onSurfaceCreated function. It is not a good idea to pass a constant uniform variable each frame and this could cause performance loss.

Section 3.2 list diffuse lighting model. It adds additional attributes both in the LightShader program as well as shaders. One thing that is really strange is that the example given in this video does not show diffuse lighting. Rather it simply outputs the interpolated colour from the rasterizer as the fragment colour. Considering that the section was on diffuse lighting, the given code example should have shown diffuse lighting.

Section 3.3 details specular lighting model theory. It then details how to add the Camera and Pipeline object in the exisiting class to allow positioning of camera and setting up of the projection transformation for the camera.

Section 3.4 shows how to implement the directional light. It creates a new class DirectionalLight and then modifies shader program to contain structs similar to the DirectionalLight class. Then it details how to bind attributes from the class to the shader program. While the details and implementation of the light are very good, the given example merely shows any lighting effect at all. To me it appears the same as the output from the last section. Clearly a much better example would have been to show a light circling around the object.

Section 3.5 describes implementation of a point light with attenuation. The author adds in aadditional attributes, classes and struct to implement a point light as in the previous sections. The details are very hastily given without giving the reader time to digest. The output render shown from the code does not show the lighting effect at all. I cannot distinguish between the result shown in section 3.3, 3.4 and 3.5. There are no visual cues like light position visible nor are there any light shades anywhere. The author is in such a hurry he just blinks the result on screen and leaves in a flash. See the reader wants to understand this stuff, he is new to OpenGL ES and Android please hold his hand rather than leaving him in the wild.

Section 3.6 implement a spot light using a new class. While the explanation of the shader is nicely done, in the introductory part (0:25-0:38) the author says that "we compare dotproduct to the cutoff value, and if it is larger than the cutoff value, then we light the pixel" This is wrong we light the pixel if dotproduct is less than the cutoff value as shown later in the video. The details are given on how to add the class and required attribute and uniform variables in the shaders. The final snapshot shows the light spot but honestly it would have been better to give a more distinct example.

Chapter 4
Section 4.1 shows how to create a simple Texture class that loads the given texture file from the resource and creates an OpenGL texture object from it. I uses the BitmapFactor.DecodeResource function to load the image. The required OpenGL texture functions, their parameter values and image loading functions are introduced without any further details about them.

Section 4.2 details the required changes to pass the texture object from the android application to the OpenGL shader. It details the required additional per-vertex attribute the texture coordinate. It also details the sampler that represents the loaded texture in the shader. One thing that I would like to rectify here. In the code sample shown in the video, in the setUniform function, the glUniform1i function is passed two parameters, first is the location of the texture sampler unit in the shader, the second parameter passed to glUniform1i function is the loaded texture id that was returned by OpenGL when the texture loading function was called. This is wrong. The glUniform1i second parameter is the texture unit where the texture is bound. It is not the texture id. The correct call then is to pass 0 as second parameter since the texture was bound to texture unit 0.

glUniform1i(uTexUnitLocation, 0);

Section 4.3 details how to draw the texture. It details how to pass the additional attributes (the texture coordinates) along with each vertex and then how they are passed in the draw function. Quite surprisingly, the main shader texture sampling function is not discussed at all.

Section 4.4 shows how to add filtering parameters to the loaded texture to improve the texture quality/performance.It details how to set the OpenGL texture parameters to enable bi-linear, tri-linear, nearest neighbor and mipmap filtering. These are just basic OpenGL texture states so the contents of this chapter in particular are very shallow.

Chapter 5
Chapter 5 is all about creating a very basic particle system class and associated classes like Emitter and Explosion to create some particle effects. The chapter starts with Section 5.1 which details how to create a particle system shader program class to hold the required attributes and uniforms to create a stateless particle system. The relevant changes and the class generated is detailed. Section 5.2 shows how to create two classes a particle system class to create and manage particles and a particle emitter class to add/remove particles from the particle system at a particular position in a particular direction.Section 5.3 shows how to draw the particle system the output shown displays a stream of particles. Section 5.4 refines the particle system to look more like an explosion.The output generated from the example is not that impressive but it serves the purpose well showing a bunch of particles that are simulated and that respond to gravity.

Chapter 6
Section 6.1 shows how to create the background asset for the Breakout game. The required image is copied into android drawable folder and then the necessary changes are made in the xml file. Next a new activity is created on which the background image and buttons are added. Then, the activity manifest file is modified to load the background activity at start up rather than the main activity.

Section 6.2 details how to add UI elements like the score and lives of player. For these text elements, TextView is used and corresponding member variable for score and lives are read from the main activity class. The final change is to add the UI elemens to the layout rather than the contents view.

Section 6.3 shows how to load the bricks for the game. The details about the required additions are given but the important information like the space in which the brick vertex positions are defined are not discussed.

Section 6.4 details how to create the ball and paddle objects. There are some design decision which I question. First, the values of limits are given as contant literals and it is very hard to discern which space these are given in. I also personally feel that defining the ball class with two triangle lists is overkill considering that this code will be run on a mobile device. I was hoping that the author would use a single particle to render as a ball. This can be easily achieved using shaders.

Section 6.5 adds sound effects and music to the game. The author creates a wrapper class that uses system services to play sound files stored in the res folder of the project.

Chapter 7
Section 7.1 is on ball movement in particular how to create frame rate independent movement. For this, the author creates tow variables, currentTime and elapsedTime. At startup, he initializes the current time and in the render function, he subtracts the current time from the currentTime variable value and divide by 10^9 to get the time value in seconds. Next, the ball movement direction is multiplied to the elapsed time and the resulting movement is frame rate independent.

Section 7.2 shows how to handle touch events to enable paddle movement. To enable listening of touch events, a custom function is hooked into the onTouchListener. The function forwards the event to the appropriate class of the OpenGL renderer. The function determines the touch event properties to see if the screen was pressed or released. Based on the result, the paddle is moved.

Section 7.3 details how to handle accelerometer input. This is done by requesting sustem service. Relevant changes are detailed and the code adjusted to accommodate the new input.

Section 7.4 provides information on how to handle broad phase collision data structure a spatial hash grid which is first populated and then queries for possible narrow phase collisions. Details of the sptial grid are not given.

Section 7.5 describes narrow phase collision to check the bounding boxes of the two game entities that might collide. This is done after each movement to ensure that there are no collisions. The potential colliders list is updated and then the ball is checked for collision with all entities in the same cell as the ball. If there is collision, the ball is rebound.

Section 7.6 details how to adjust scores and lives based on the outcome of narrow phase collision. the explosion and scores are handled in the collision code. The lives are handles based on the ball position if it is lower than the paddle's y value. Based on available lives, if they fall to zero, a new activity called Gameover activity is created and launched. The ontouchlistener is handled to allow game to return to the main menu.

Chapter 8
Section 8.1 adds final touches to the created game. It first creates a local high scores table. Section 8.2 details how to publish the game on the Google Play store. The required settings and options are detailed nicely. Section 8.3 describes some optimizations that are possible for the game for example removing useless variables and making constants as static final. The final section is on how to enable in app purchases for game related stuff like extra lives etc.

Summary:
Now that i have gone through the videos. I can say that the author has done a commendable job with these video tutorials. The breadth of the topics covered is tremendous. I feel the depth of the topics is severely lacking. Following are my main concerns about these video lectures.
1) I was hoping that the videos would cover OpenGL ES 3.0 but they are covering OpenGL ES 2.0.
2) I find that the vdos are a bit brisk. The author is dumping loads of code to the viewer. Even though I have programmed on Android before but for me too it is very difficult to follow along with the author. In addition, the way he is referring to the code is rather vague most of the times for e.g. he says "add this line after this line and you will see ..." why should I add that line and what will happen if I dont put those in. 
3) It seems that the author is merely dumping information without explaining the reasons why a particular code is written that way. I find the why to be missing from most of the videos.

From the way they are done, these video lectures assume that you have already programmed in Android before. For a complete beginner, I would not recommend him/her to follow these as these lectures are severely lacking analysis and reasoning. You should have some basic android development experience to appreciate the course content.

All in all these tutorials are great to get you up and running with android development. The author details the entire process from  creation of game to hosting of the game on Google play store as well as in app purchases. Overall I will rate these video tutorials 4 out of 5 stars. Thanks to the author for sharing his insights and to Packt publishing for giving me this opportunity to review this video course.

Friday, May 16, 2014

A new course on Building Android Games with OpenGL ES

Packt publishing has launched a new course Building Android Games with OpenGL ES I will be reviewing this course in a couple of days on my blog. Looks like an interesting course to me. Here is the Table of Contents from the course.
  1. Getting Started with OpenGL ES [14:53 minutes]
    • Setting Up OpenGL ES in Eclipse
    • Creating an OpenGL ES Environment
    • Creating Your First Shaders
    • Loading and Compiling the Shaders

  2. OpenGL ES Math [16:23 minutes]
    • OpenGL ES Matrix System
    • Vector Math
    • Projection Matrix and Camera View
    • Transformation Matrix - Scale and Translate
    • Transformation Matrix - Rotation and Final
    • Theory - Quaternions

  3. Lighting [16:28 minutes]
    • Ambient Lighting
    • Diffuse Lighting
    • Specular Lighting
    • Directional Light
    • Point Light
    • Spot Light

  4. Texturing [08:46 minutes]
    • Loading Textures
    • Creating New Shaders for Texturing
    • Drawing the Texture
    • Texture Filtering

  5. Particle Systems [07:34 minutes]
    • Shaders for a Particle System
    • Adding a Particle System
    • Drawing the Particle System
    • Customizing the Particles

  6. Breakout – Assets and UI [12:25 minutes]
    • Menu Screens
    • Game Interface
    • Creating the Bricks
    • Creating the Ball and Paddle
    • Sound Effects

  7. Breakout – Gameplay [14:46 minutes]
    • Ball Movement
    • Paddle Input - Touch
    • Paddle Input - Accelerometer
    • Collisions - Broad Phase
    • Collisions - Narrow Phase
    • Scoring and Lives

  8. Breakout – Finishing Touches [11:21 minutes]
    • Creating a Local HighScores Table
    • How to Publish Your Game
    • Optimization Techniques
    • How to Add In-App Purchases

Tuesday, May 6, 2014

SIBGRAPI 2012 Tutorials (The most up to date course on Modern OpenGL development with Qt)

I am utterly impressed at the quality and applied nature of tutorials presented at SIBGRAPI 2012. I particularly like Tutorial T3-Interactive Graphics Applications with OpenGL Shading Language and Qt . The course slides as well as course survey paper are worth checking out. The tutorial teacher Joao Paulo Gois has has maintained the source codes of this tutorial for older and newer Qt versions on his own web site.

This is by far the best and the most reachable tutorial I have ever read on modern OpenGL development on Qt. Have a look at it yourself.

Thursday, May 1, 2014

Qt loading shaders from resource files (call qmake after creating the resource file)

I was recently playing with Qt and its support of shaders. Qt provides a bunch of useful classes for shader handling. So I thought of making my hands dirty. The first thing I did was try to load my simple triangle demo using shaders. I started out with using the QGLShaderProgram class with loading shaders as resource. I kept getting errors saying that the shader files cannot be loaded from the specified path. So then I realized I had to create a Qt resource file and manually add my shaders into the resource file. 

After doing all this, once again when I tried to run the demo, it still told me that the shader did not exist on the specified path. After many tries I came to know the reason for why the path could not be found. Once the resource file is created and the shader files are added to the resource file, we need to call qmake on the project. Without calling it, I kept getting the file not found error. I could not find any information on this so I thought I would include it here on my blog for others who fall into the same trap.

Popular Posts

Copyright (C) 2011 - Movania Muhammad Mobeen. Awesome Inc. theme. Powered by Blogger.