All posts by Admin

Kevin is the author of OpenGL ES 2 for Android: A Quick-Start Guide. He also has extensive experience in Android development.

OpenGL ES Resources and Best Practices

The first place to start for OpenGL documentation on the various mobile platforms is straight at the source:

  • Google’s Android documentation has a small amount of info about OpenGL, though not too much. You’ll get an overview of the APIs and learn how to exclude your application from unsupported devices. According to the OpenGL Dashboard, most devices out there now support OpenGL ES 2.0.
  • Apple’s OpenGL documentation is much better and goes into a lot more depth and detail. At their OpenGL ES for iOS website, you can learn more about best practices and the specifics of using OpenGL on their platform, and they also have videos and sample projects to download.

It’s also worth checking out what the various GPU vendors have to say about best practices and guidelines:

Each GPU vendor also often provides their own SDKs, tools, and IDEs for developing on their GPUs, which can help a great deal with tracing and finding performance issues.

Hope this helps out on your journey ahead!

Share

Beginning Android Games, to Learn More About Game Development for Android

I’m happy to announce that my book, OpenGL ES 2 for Android: A Quick-Start Guide, is now being readied to be sent off to the printers! I owe a special thanks to the publishers, to you guys, my readers and reviewers, and I also owe a special thanks to Mario Zechner, the creator of libgdx, for writing a great foreword and generously helping to promote the book on his end!

Mario has also co-authored ”Beginning Android Games” with Robert Green;  I think that his book can be the perfect complement to my own, as you’ll also learn about many of the additional aspects of game development that I didn’t get the chance to cover in my own book, such as:

  • How to develop 2D games, from beginning to end.
  • How to publish to the market, support your users, and deal with crash reports.
  • Using the Native Development Kit (NDK) to support C and C++ code.

If you’re looking to hit additional platforms, libgdx also has you covered. You can port your Java-based Android game to the desktop, to the web via WebGL, and even to iOS with a few nifty tricks. I plan to cover cross-platform development using libgdx in some subsequent posts, as well as going by the C / C++ route which I will also be covering in future posts.

If you use Reddit, you can also visit our respective Reddit threads here:

I just completed my first book: “OpenGL ES 2 for Android: A Quick-Start Guide” for beginners (EDIT: It seems someone removed my Reddit thread! Oh well :()

My book “Beginning Android Games, 2nd Edition” is out, and i’m super happy

I’m glad that the book is finally starting to head out the door; it feels like the end of a journey. It was a journey that was well worth it. :)

Share

Developing a Simple Game of Air Hockey Using C and OpenGL ES 2 for Android, iOS, and the Web

Some of you have been curious about what the air hockey game from the book would be like if we brought it over to other platforms. I would like to find out, myself. :) In the spirit of my last post about cross-platform development, I want to port the air hockey project over to a native cross-platform code base that can be built for Android and iOS, and even the web by using emscripten and WebGL. Everything will be open-source and available on GitHub.

Here are some of the things that we’ll have to figure out and learn along the way:

  • Setting up a simple build system for each platform.
  • Initializing OpenGL.
  • Adding support for basic touch and collision detection.

In the next post, we’ll take a look at setting up a simple build system to initialize OpenGL across these different platforms. Here are all of the posts for the series so far:

Setting up a simple build system

Adding support for PNG loading into a texture

Adding a 3d perspective, mallets, and a puck

Adding touch events and basic collision detection

The code is available on Github, with each section organized by tags.

Share

Site Updates, and Thoughts on Native Development for the Web

I’ve recently been spending time travelling overseas, taking a bit of a break after reaching an important milestone with the book, and also taking a bit of a rest from working for myself! The trip has been good so far, and I’ve even been keeping up to date with items from the RSS feed. Here is some of the news that I wanted to share with y’all, as well as to get your thoughts:

Book nearing production

OpenGL ES for Android: A Quick-Start Guide reached its final beta a couple of weeks ago, and is now being readied to be sent off to the printers. I would like to thank everyone again for their feedback and support; I am so grateful for it, and happy that the book is now going out the door. I’d also like to give a special thanks to Mario Zechner, the creator behind libgdx and Beginning Android Games, for generously contributing his foreword and a lot of valuable feedback!

Site news

Not too long ago, I decided to add a new forums section to the site to hopefully build up some more community involvement and get a two-way dialogue going; unfortunately, things didn’t quite take off. The forums have also suffered from spam and some technical issues, and recently I was even locked out of the forum administration. I have no idea what happened or how to fix it, so since the posting rate was low, I am just putting the forums on ice for now.

I’d still love to find a way to have some more discussions happening on the site. In which other ways do you believe that I could improve the site so that I could encourage this? I’d love to hear your thoughts.

Topics to explore further

I’ve also been thinking about new topics to explore and write about, as a lot of exciting things are happening with 3D on the mobile and web. One big trend that seems to be taking place: Native is making a comeback.

For many years,  C and C++ were proclaimed to be dead languages, lingering around only for legacy reasons, and soon to be replaced by the glorious world of managed languages. Having started out my own development career in Java, I can agree that the Java world does have a lot of advantages. The language is easier to learn than a behemoth like C++, and, at least on the desktop, the performance on the JVM can even come close to rivalling native languages.

So, why the resurgence in C and C++? Here are some of my thoughts:

  • The world is not just limited to the desktop anymore, and there are more important platforms to target than ever before. C and C++ excel at cross-platform portability, as just about every platform has a C/C++ compiler. By contrast, the JVM and .NET runtimes are limited to certain platforms, and Android’s Dalvik VM is not as good as the JVM in producing fast, efficient JIT compiled code. Yes, there are bytecode translators and commercial alternatives such as Xamarin’s Mono platforms for mobile, but this comes with its own set of disadvantages.
  • Resource usage can be more important than programmer productivity. This is true in big, expensive data centers, and it’s also true on mobile, where smaller downloads and lower battery usage can lead to happier customers.
  • C and C++ are still king when it comes to fast, efficient compiled code that can be compiled almost anywhere. Other native would-be competitors lose out because they are either not as fast or not as widely available on the different platforms. When productivity becomes more important than performance, these alternatives also get squeezed out by the managed and scripting languages.

As much as C and C++ excel at the things they’re good at, they also come with a lot of legacy cruft. C++ is a huge language, and it gets larger with each new standard. On the other hand, at least the compilers give you some freedom. Don’t want to use the STL? Roll out your own custom containers. Don’t want the cost/limitations of exception handling and RTTI? Compile with -fno-exceptions and -fno-rtti. Undefined behavior is another nasty issue which can rear its head, though compilers like Clang now feature additional tools to help catch and fix these errors. With data-oriented design and sensible error handling, C++ code can be both fast and maintainable.

Compiling C and C++ to the web

With tools like emscripten, you can now compile your C/C++ code to JavaScript and run it in a browser, and if you use the asm.js subset, it can actually run with very good performance, enough to run a modern 3D game using JavaScript and WebGL. I’ve always been skeptical of the whole “JavaScript everywhere” meme, because how can the web truly become an open computing platform by forcing the use of one language for everything? There’s no way a single language can be equally suitable for all tasks, and why would I want to develop a second code base just for the web? For this reason, I used to believe that Google’s Native Client held more promise, since it can run native code with almost no speed loss. Why use JavaScript when you can just execute directly on the CPU and bring your existing code over?

Now I see things a bit differently and I think that the asm.js approach has a lot of merit to it. NaCl has been around for years now, and it still only runs in Google Chrome, and then only on certain platforms and only if the software is distributed through the Chrome store, or if the user enables a developer flag. The asm.js approach, on the other end, can run on every browser that supports modern JavaScript. This approach is also portable, meaning it will work into the foreseeable future, even on new device architectures. NaCl, on the other hand, is limited to what was compiled. Portable NaCl is supposed to fix this, but it’s been a work-in-progress for years now, and given the experience with NaCl, it may never find its way to another browser besides Google Chrome. Combined with WebGL, compiling to JavaScript really opens up the web to a lot of new possibilities, one where you can deploy across the web without being tied to a single browser or plugin. The BananaBread demo shows just some of what is possible.

I’d like to learn more about writing OpenGL apps that can run on Android, iOS, and the web, all with a single code base in C++. I know that this is also possible with Java by using Google’s Web Toolkit and bytecode translators (after all, this is how libgdx does it), but I’d like to learn something different, outside of the Java sphere. Is this something that you guys would be interested in reading more of? This is all relatively new to me and I’m currently exploring, so as always, looking forward to your feedback. :)

Update: I am now developing an air hockey project here: Developing a Simple Game of Air Hockey Using C++ and OpenGL ES 2 for Android, iOS, and the Web

Share

Introducing GLWallpaperService

Are you looking to make a live wallpaper for Android? Wondering how to use OpenGL from a wallpaper service?

Mark Guerra and some other contributors have kindly made their work available on GitHub, at https://github.com/GLWallpaperService/GLWallpaperService. This repository includes an OpenGL wallpaper service as well as several samples that show you how to use the service.

Yours truly has submitted a couple of pull requests to add support for OpenGL ES 2.o and to provide an alternative implementation which minimally wraps GLSurfaceView. If / when these are merged in, I’ll be able to update How to Use OpenGL ES 2 in an Android Live Wallpaper, as it’ll become much easier to do so!

 

Share

Announcing the New Forums, and a Roundup!

Starting from today, Learn OpenGL ES now has a new community section of the site with a new set of forums! [Edit: Due to some technical issues and low usage, I have disabled the forums until further notice. I would still like to have a forums section in the future, so they can come back if the comments section proves to be inadequate. Thanks!] I’ve also switched themes, so please let me know if you find any issues, have feedback or miss anything from the old theme!

On to the roundup:

I’m also happy to announce that in the spirit of sharing with the community, all of the content on this site is now licensed under the Creative Commons CC-BY-SA 3.0 license. Please feel free to reuse and share in the spirit of CC-BY-SA 3.0.

Share

Introducing OpenGL ES for Android: A Quick-Start Guide, Now in Beta

OpenGL ES for Android: A Quick-Start GuideHi all,

After nearly a year of working with the great team over at The Pragmatic Bookshelf, I am happy to announce that OpenGL ES for Android: A Quick-Start Guide is now in beta!

OpenGL ES for Android: A Quick-Start Guide follows in the tradition of this website and goes into more detail, teaching you how to create your first OpenGL project from scratch. You’ll learn about shaders, the OpenGL pipeline, and discover the power of OpenGL ES 2.0.  If you want to learn more about OpenGL for Android and you have a creative vision that you’d like to share with the world, then this is the book for you.

I would like to invite you, dear reader, to come check out the book and participate in the beta. As a beta book, the book is almost finished, with just a few rough edges and a couple of chapters to go, and a few things that need to be worked on. I could benefit greatly from your suggestions and feedback!

I hope that the book proves useful to you, and thanks for your continued support. :)

Share

OpenGL Community Roundup, January 2013 Edition

Welcome to another community round-up! A lot of people have been busy, creating great games, tutorials, and live wallpapers. Check them out below (in alphabetical order):

Advancing Usability

Ino

pleyasLab

Rene van der Lende

  • Kube — a tutorial on rotating a cube using OpenGL for Android.

Teaching Machines

Team Blubee

If I forgot someone or something, just let me know! I hope you all enjoyed the holidays, and I look forward to a great 2013, with more great stuff coming from the community. :)

Share

OpenGL Community Roundup, October Edition

It’s almost Halloween, which means it’s time to showcase another great set of apps and posts from the community. :)

First up, we have…

Wubbly Bubble Live Wallpaper

This interesting and lively live wallpaper renders a deforming 3D bubble to your home screen, with five different themes, many options for customization, and it runs on a wide range of devices. Download it here: https://play.google.com/store/apps/details?id=com.Ephemeral

Next up we have…

Blu Mountain Live Wallpaper

This is a very peaceful and relaxing live wallpaper, overlooking Mt. Fuji. You can watch the waves of the rhythmic water, and see the tranquil Sakura leaves fall gracefully as you overlook one of Japan’s most beloved national treasures.

This wallpaper supports the latest tablets, and works well with any Android theme or layout. It also features an upgrade to full HD art. Download it here: https://play.google.com/store/apps/details?id=com.blubee.wp

Roundup

Android OpenGL and slow rendering

Android terrain test

Happy Halloween, everyone!

Enhanced by Zemanta
Share

Understanding OpenGL’s Matrices

I often get questions related to OpenGL’s matrices: how do they work, how do they get built, and so forth. This is a topic that I have been frequently confused by, myself, and I feel that it warrants further explanation.

To better understand OpenGL’s matrices, and how and why we use them, we first need to understand the OpenGL coordinate space.

Normalized device coordinates

At the heart of things, OpenGL 2.0 doesn’t really know anything about your coordinate space or about the matrices that you’re using. OpenGL only requires that when all of your transformations are done, things should be in normalized device coordinates.

These coordinates range from -1 to +1 on each axis, regardless of the shape or size of the actual screen. The bottom left corner will be at (-1, -1), and the top right corner will be at (1, 1). OpenGL will then map these coordinates onto the viewport that was configured with glViewport. The underlying operating system’s window manager will then map that viewport to the appropriate place on the screen.

Adjusting to the screen’s aspect ratio

While OpenGL wants things to be in normalized device coordinates, it’s hard to work with these directly. The first problem is that they always range from -1 to +1, so if you use these coordinates directly, your image might be stretched when switching from portrait mode to landscape mode.

The first thing you can do to get around this problem is to define an orthographic projection. Android has the orthoM method; other platforms will have something similar. Let’s take a closer look at Android’s method:

orthoM(float[] m, int mOffset, float left, float right, float bottom, float top, float near, float far)

To define a simple matrix that adjusts things for the screen’s aspect ratio, we might call orthoM as follows:

float aspectRatio = (float) width / (float) height;
orthoM(projectionMatrix, 0, -aspectRatio, aspectRatio, -1, 1, -1, 1);

Let’s say that the screen dimensions are 800×600. The call would proceed as follows:

orthoM(projectionMatrix, 0, -1.333, 1.333, -1, 1, -1, 1);

Although the screen is wider than it’s tall, we automatically adjust the coordinate space to match by mapping -(800/600) to the left side and (800/600) to the right side.

This also works when we switch to portrait mode:

orthoM(projectionMatrix, 0, -0.75, 0.75, -1, 1, -1, 1);

We shrink the width in order to compensate for the smaller screen.

At the heart of things, the orthographic projection matrix will still convert things to the [-1, 1] range, since that’s what OpenGL expects. It just provides a way to adjust our coordinate space, so that we can see more of our scene if the screen is wider, and less if the screen is narrower.

3D projections

What about 3D projections? For those, we can use frustumM:

frustumM(float[] m, int offset, float left, float right, float bottom, float top, float near, float far)

We could define a simple 3D projection as follows:

frustumM(projectionMatrix, 0, -aspectRatio, aspectRatio, -1, 1, 1, 100);

The near & far range are handled differently: both have to be positive, and far has to be greater than near. We also have to watch out for the Z axis: frustumM will actually invert it, so that the negative Z points into the distance!

This has to do with convention: normalized device coordinates are in a left-handed coordinate system, while by convention, when we use a projection matrix, we work in a right-handed coordinate system.

Below is a good image illustrating the situation:

Left-handed and right-handed coordinate systems. Source: http://viz.aset.psu.edu/gho/sem_notes/3d_fundamentals/html/3d_coordinates.html

Left-handed and right-handed coordinate systems. Source: http://viz.aset.psu.edu/gho/sem_notes/3d_fundamentals/html/3d_coordinates.html

The perspective divide

The perspective projection doesn’t actually create the 3D effect; for that, we need to do something called the perspective divide. Each coordinate in OpenGL actually has four components, X, Y, Z, and W. The projection matrix sets things up so that after multiplying with the projection matrix, each coordinate’s W will increase the further away the object is. OpenGL will then divide by w: X, Y, Z will be divided by W. The further away something is, the more it will be pulled towards the center of the screen.

This PDF goes into more detail: http://www.terathon.com/gdc07_lengyel.pdf

This image shows how the same coordinate gets closer to the center of the screen as the W value increases:

Perspective divide by W

Perspective divide by W

Say you have three XYZ source positions of the following:

(3, 3,    -3)
(3, 3,    -6)
(3, 3, -1000)

 
The second point is a little bit further, or more “into the screen” than the first, and the third point is much further away than the second point. An infinite projection matrix would convert the coordinates as follows:

(3, 3,   1,    3)
(3, 3,   4,    6)
(3, 3, 998, 1000)

 
That last component is W. Now, OpenGL will divide everything by W, so you get something like this:

(1,     1,     0.33...)
(0.5,   0.5,   0.66...)
(0.003, 0.003, 0.998  )

 
There are two side effects of this division by W:

  1. The depth buffer becomes non-linear. There is a lot of Z precision up close, but less further away.
  2. If you try to do translations, etc… on your vertices after the perspective projection, then you won’t get the results you expect. This is because many of these operations depend on the W being 1, while after perspective projection it can be something else.

Here is an example of the perspective divide: imagine that we have a perspective projection matrix that looks as follows:

 1.5, 0,  0,    0,
 0,   1,  0,    0,
 0,   0, -1.2, -2.2,
 0,   0, -1,    0

 
This will transform coordinates as follows:

(1, 1, -1, 1) --> (1.5, 1, -1,   1)
(1, 1, -2, 1) --> (1.5, 1,  0.2, 2)
(2, 2, -2, 1) --> (3,   2,  0.2, 2)

 
After division by W, we get this:

(1.5, 1, -1,   1) --> (1.5,  1,   -1  )
(1.5, 1,  0.2, 2) --> (0.75, 0.5,  0.1)
(3,   2,  0.2, 2) --> (1.5,  1,    0.1)

 
Notice that the projection matrix just sets up the W, and it’s the actual divide by OpenGL that does the perspective effect. To verify this, try it out with a matrix calculator:

http://www.math.ubc.ca/~israel/applet/mcalc/matcalc.html

The view and model matrices

In OpenGL, we commonly use two additional matrices: the view and model matrices:

The model matrix

This matrix is used to move a model somewhere in the world. For example, let’s say we have a car model, and it’s defined such that it is centered around (0, 0, 0). We can place one car at (5, 5, 5) by setting up a model matrix that translates everything by (5, 5, 5), and drawing the car model with this matrix. We can then easily add a second car to the scene by just adjusting the translation. The model matrix helps us to push stuff out into the world.

The view matrix

The view matrix is functionally equivalent to a camera. It does the same thing as a model matrix, but it applies the same transformations equally to every object in the scene. Moving the whole world 5 units towards us is the same as if we had walked 5 units forwards.

Order of operations

These matrices all have to be multiplied in a specific way, if we want our results to be correct. Let’s start with some basic definitions:

vertexmodel
This is an original vertex, as defined inside one of our object models.
vertexworld
This is a vertex in world coordinates. We get to here by using a model matrix to push the model out into the world.
vertexeye
This is a vertex in eye coordinates. We get here by using a view matrix to move the entire scene around.
vertexclip
This is a vertex in clip coordinates (also known as homogeneous coordinates): this is the coordinate space after projection, but before the perspective divide.
vertexndc
This is a vertex in normalized device coordinates, and this is what we end up with after the perspective divide.

As we can see, getting to vertexndc is just a matter of applying each transformation in order. Let’s try to formulate this as an expression:

vertexndc = PerspectiveDivide(ProjectionMatrix * vertexeye)
vertexndc = PerspectiveDivide(ProjectionMatrix * ViewMatrix * vertexworld)
vertexndc = PerspectiveDivide(ProjectionMatrix * ViewMatrix * ModelMatrix * vertexmodel)

OpenGL takes care of the perspective division for us, so we don’t actually need to worry about that. All we need to worry about is the order of operations; since matrix multiplication is non commutative, we’ll get a different result depending on the order.

Column-major versus row-major order

A final point of confusion is often the layout of matrices in memory. OpenGL follows column-major order, meaning that the array offsets are specified like this:

0  4   8  12
1  5   9  13
2  6  10  14
3  7  11  15

 
m[0] … m[3] refer to the first column of the matrix.

Please let me know your questions, comments, and feedback!

Enhanced by Zemanta
Share