# Tag: opengl

Entries for tag "opengl", ordered from most recent. Entry count: 2.

Warning! Some information on this page is older than 3 years now. I keep it for reference, but it probably doesn't reflect my current knowledge and beliefs.

Pages: 1

21:12
Mon
27
Apr 2015

Watch out for reduced precision normalize/length in OpenGL ES

GLSL language for OpenGL ES introduces concept of precision. You can annotate variable declaration (both float and int/uint) with a precision qualifier: highp, mediump or lowp, like:

mediump float a = 3.0;

You can also specify default precision qualifier by using precision statement. Language specification defines minimum required range and precision for each precision qualifier.

• highp basically means normal, single-precision, 32-bit float (IEEE 754), as we know it from CPU programming.
• mediump is said to have have range of at least -2^14 ... 2^14 and relative precision 2^-10, so it can be, for example, implemented using a 16-bit, half-precision float.
• lowp is said to have range at least -2 ... 2 and absolute precision 2^-8, so basically it can be stored as a 10-bit, fixed-point number.

GPU vendors are free to use more precise data types, or even full 32-bit float for all of them. What exact precision is used depends on specific GPU and maybe even operating system or graphics driver version. Using smaller data types can occupy less memory, calculate faster and consume less battery power. But it comes at the price of reduced precision and range of these numbers. Tom Olson wrote interesting articles about this: "Benchmarking floating-point precision in mobile GPUs": Part I, Part II, Part III.

In this post I'd like to warn you against a specific problem related to it - usage of length(), normalize() and distance() functions. Using smaller data types not only limits precision in terms of number of significant digits, but also available range (over which the value will saturate to -INF/+INF). For mediump, this range is defined as +/-2^14, which is only 16384.

This may still look like a lot, but let's remember that calculating vector length involves intermediate value that it sum of squares of this components. This can grow very big before a square root is applied. For example, for 3D vector:

length(a) = sqrt(a.x*a.x + a.y*a.y + a.z*a.z)

If you do this operation on a mediump vector, the term a.x*a.x + a.y*a.y + a.z*a.z can exceed maximum value for vector as small as (74.0, 74.0, 74.0). It can be very dangerous if you do something like this in your fragment shader:

precision mediump float;
uniform vec3 light_pos;
...
void main()
{
...
vec3 dir_to_light = normalize(pos - light_pos);
// Calculate your lighting and so on...

You might ask: Why isn't this intermediate value stored in high precision before taking its square root to avoid this overflow problem? Obviously it could be, as precision in any place of the shader is free to be higher than the minimum allowed in that place, so some GPU vendors can do it this way, but you shouldn't rely on this. GLSL specification clearly says that the shader is free to use same, reduced precision for intermediate values.

The precision used to internally evaluate an operation, and the precision qualification subsequently associated with any resulting intermediate values, must be at least as high as the highest precision qualification of the operands consumed by the operation.

Conclusion is: When you write shaders for OpenGL ES, watch out for operations that involve calculating vector length (or dot product) like length(), normalize(), distance(), use highp precision for vectors involved and remember that what works on one GPU due to using precision higher than minimum required, may not work on another GPU and it’s still an application issue.

13:52
Thu
21
Oct 2010

Beginning with OpenGL ES on Android

I've started learning programming for Android. It's (probably) nothing commercial, I just love to learn new technologies and APIs while I have not much experience in either Java, OpenGL ES or mobile technologies at all. The first thing I did was... buying a phone - LG GT540 in my case. It has Android 1.6 (upgrade to 2.1 is scheduled for this year).

Android is a nice platform. Anyone can code for his phone in either Windows or Linux, using Java language (native code development is also possible). To start my coding, I needed to install JDK (SDK for Java), Android SDK, Java version of Eclipse 3.5 (they say Android SDK is not fully compatible with new Eclipse 3.6) and Eclipse JDT plugin to connect them all. Android Developers website does a great job explaining all the steps required to setup the whole development environment so I've came across not so many issues to get annoyed as I often get when installing some C/C++ stuff :)

I've read a bit about the fundamentals of developing applications for Android and I like the API. All these ideas like Activity, Service, Intent, View, Widget, Task etc. seem very well designed. But just like PC game developers learn WinAPI to only initialize an empty window and launch DirectX or OpenGL in it, I went straight to OpenGL on my Android. Android 1.6 has OpenGL ES 1.1, which in turn is the embedded equivalent for OpenGL 1.5. This 3D API has no shaders, so all the graphics has to be done using fixed function pipeline, including MODELVIEW and PROJECTION matrices, 2 textures with register combiners, 8 dynamic per-vertex lights, 1 user clip plane, fog etc. - something like on the old good GeForce 2 MX :)

It's easy to start using OpenGL for someone who has experience in DirectX because all the concepts that are so diffcult to understand at the beginning of the game programming adventure stay the same - like 3D coordinate system, vertex, triange, matrix, texture and so on. Some things are only reversed - textures are addressed from left-bottom corner in OGL, matrices are stored in column-major order, matrix multiplication is right-to-left like Point2 = Xform2 * Xform1 * Point1, post-projective space is -1..1, -1..1, -1..1, coordinate system is right-handed so Z points to the viewer, angles are given in degrees, counterclockwise oriented triangles are considered front-facing by default and so one. Some objects have also different names, so in OGL there is "model" not "world" matrix, "fragment" not "pixel" operation etc.

Here is the list of Internet sources I already know about and I've been learning from:

• Android Developers - the main documentation for Android, including developers guide and reference. Offline version is installed with Android SDK and can be found in docs\offline.html subdirectory.
• OpenGL ES 1.X at Khronos Group - here are the definitive documents about OpenGL. OpenGL ES 1.1.12 Full Specification can be downloaded as PDF, while Reference Pages have to be teleported with WinHTTrack or DownThemAll! if you want to have it offline.
• EGL - an auxilliary API
• Android 3D game tutorial on droidnova.com - some introductory tutorial to OGL on Android, but doesn't even cover texturing.
• NeHe Android Ports - some lessons from the famous NeHe OpenGL tutorials ported to Android. It's actually just the sample source code, but it's the best tutorial I've met so far.
• Writing Real-Time Games for Android - a 1 hour video from a lecture by Chris Pruett. There are probably some interesting things there but I had no patience to watch it all :)
• Developer blog of Robert Green, the author if Light Racer, Light Racer 2 and Light Racer 3D games for Android. Lots of valuable information and source code.

Now you can expect more entries about Android development on my blog :)

Comments (3) | Tags: android opengl mobile | Author: Adam Sawicki |

Pages: 1