• Aucun résultat trouvé

Adding Detail with Textures

Dans le document OpenGL ES 2 for Android (Page 128-132)

We’ve managed to get a lot done with just simple shapes and colors. There’s something missing though: what if we could paint onto our shapes and add refined detail? Like artists, we can start out with basic shapes and color and add extra detail onto our surfaces by using textures. A texture is simply an image or a picture that has been uploaded into OpenGL.

We can add an incredible amount of detail with textures. Think of a beautiful 3D game you might have played recently. At the heart of things, the game is just using points, lines, and triangles, like any other 3D program. However, with the detail of textures and the touch of a skilled artist, these triangles can be textured to build a beautiful 3D scene.

Once we start using textures, we’ll also start using more than one shader program. To make this easier to manage, we’ll learn how to adapt our code so that we can use multiple shader programs and sources of vertex data and switch between them.

Here’s our game plan for this chapter:

• We’ll start out with an introduction to textures, and then we’ll write code to load a texture into OpenGL.

• We’ll learn how to display that texture, adapting our code to support multiple shader programs.

• We’ll also cover the different texture filtering modes and what they do.

When we’re done, our air hockey table should look like the next figure. Let’s start off by copying the project from the last chapter over into a new project called ‘AirHockeyTextured’.

Figure 35—Air hockey table with a filtered texture

7.1 Understanding Textures

Textures in OpenGL can be used to represent images, pictures, and even fractal data that are generated by a mathematical algorithm. Each two-dimensional texture is composed of many small texels, which are small blocks of data analogous to the fragments and pixels that we’ve talked about previ-ously. The most common way to use a texture is to load in the data directly from an image file.

We’ll use the image in Figure 36, The Surface Image, on page 117 as our new air hockey table surface and load it in as a texture:

All of the images used in the code can be downloaded from this book’s home page. I recommend storing the texture in your project’s /res/drawable-nodpi/ folder.1

1. http://pragprog.com/book/kbogla

Chapter 7. Adding Detail with Textures

116

Figure 36—The Surface Image

Each two-dimensional texture has its own coordinate space, ranging from (0, 0) at one corner to (1, 1) at the other corner. By convention, one dimension is called S and the other is called T. When we want to apply a texture to a triangle or set of triangles, we’ll specify a set of ST texture coordinates for each vertex so that OpenGL knows which parts of the texture it needs to draw across each triangle. These texture coordinates are also sometimes referred to as UV texture coordinates, as seen in Figure 37, OpenGL 2D texture coordi-nates, on page 118.

There is no inherent orientation for an OpenGL texture, since we can use different coordinates to orient it any which way we like. However, there is a default orientation for most computer image files: they are usually specified with the y-axis pointing downward (as seen in Figure 38, Computer images:

the y-axis points downward, on page 118): the y value increases as we move toward the bottom of the image. This doesn’t cause any trouble for us so long as we remember that if we want to view our image with the right orientation, then our texture coordinates need to take this into account.

In standard OpenGL ES 2.0, textures don’t have to be square, but each dimension should be a power of two (POT). This means that each dimension should be a number like 128, 256, 512, and so on. The reason for this is that non-POT textures are very restricted in where they can be used, while POT textures are fine for all uses.

There is also a maximum texture size that varies from implementation to implementation but is usually something large, like 2048 x 2048.

Understanding Textures

117

Figure 37—OpenGL 2D texture coordinates

Figure 38—Computer images: the y-axis points downward

Chapter 7. Adding Detail with Textures

118

7.2 Loading Textures into OpenGL

Our first task will be to load data from an image file into an OpenGL texture.

To start out, let’s create a new class in the com.airhockey.android.util package called TextureHelper. We’ll begin with the following method signature:

AirHockeyTextured/src/com/airhockey/android/util/TextureHelper.java

public static int loadTexture(Context context, int resourceId) {

This method will take in an Android context and a resource ID and will return the ID of the loaded OpenGL texture. To start off, we’ll generate a new texture ID using the same type of pattern as when we’ve created other OpenGL objects:

AirHockeyTextured/src/com/airhockey/android/util/TextureHelper.java final int[] textureObjectIds = new int[1];

glGenTextures(1, textureObjectIds, 0);

if (textureObjectIds[0] == 0) { if (LoggerConfig.ON) {

Log.w(TAG, "Could not generate a new OpenGL texture object.");

}

return 0;

}

We generate one texture object by calling glGenTextures(1, textureObjectId, 0), passing in 1 as the first parameter. OpenGL will store the generated IDs in textureObjec-tIds. We also check that the call to glGenTextures() succeeded by continuing only if it’s not equal to zero; otherwise we log the error and return 0. Since TAG is not yet defined, let’s add a definition for it to the top of the class:

AirHockeyTextured/src/com/airhockey/android/util/TextureHelper.java private static final String TAG = "TextureHelper";

Dans le document OpenGL ES 2 for Android (Page 128-132)