Http://www.educity.cn/wenda/92368.html
OpenGL ES tutorial VI texture map (source control)
OpenGL ES Tutorial for Android–part vi–textures
December 30th, by Per-erik Bergman-android, Embedded, Java
Last tutorial we worked a bit more on meshes and we had also talked about adding colors to our mesh. The most common-on-the-adding colors to your mesh are to add a texture. There is a couple of different steps involved with adding a texture to the mesh I'll try to go through them all and expl Ain the basics about them.
The previous tutorial we generated some models, and we already know how to color the model. However, the most common coloring method is to add textures. There are several different procedures for adding textures to a model. I'll start with the following.
Loading bitmaps
First step would is to get a bitmap to generate a texture from. You can get hold of a bitmap in many different ways from downloading, generating or simply just load one from the resource S. I ' m going with the simplest one for this example witch are loading from the resources.
In the first step, we need to get a picture of the map, which has many ways. You can download, build, or simply load from a resource, and I use the last one: Load from a resource file.
Bitmap Bitmap = Bitmapfactory.decoderesource (Contect.getresources (),
R.drawable.icon);
One other thing about textures was that some hardware requires the height and width being in the power of 2 (1, 2, 4, 8, 16, 32, 64 ...). If you run a texture with a size of 30x30pixels in a hardware that don t support it you'll just get a white square (Unle SS you change the default color).
It should be noted that on some hardware, the image size required for the map must be 2 of the n-th square (1,2,4,8,16,32 ... )。 If your picture is 30x30, and the hardware is not supported, then you can only see a white box (unless you change the default color)
Generating a texture
After we had loaded the bitmap we need to tell OpenGL to actually create the texture.
Once the picture is loaded, you can tell OpenGL to produce the texture.
First thing we need to do are to let OpenGL generate some texture ID ' s so we'll use as handles to the textures later on . In this example we'll only has one texture.
The first thing to do is to have OpenGL produce the texture ID, which will be used later. In the example we have only one texture.
Create an int array with the number of textures we want,
In the case 1.
int[] Textures = new int[1];
Tell OpenGL to generate textures.
Gl.glgentextures (1, textures, 0);
With the same parameters you can delete the textures:
Delete a texture.
Gl.gldeletetextures (1, textures, 0)
Now when the texture ID ' s is generated we need to just like everything else-tell OpenGL-what-to-work with. With textures we use the command glbindtexture:
After the ID is generated, we need to bind these IDs using the Glbindtexture method
Gl.glbindtexture (gl10.gl_texture_2d, textures[0]);
From this-point-all commands we-call on regarding textures would be a applied on-your texture with the generated ID.
After that, we'll use the resulting ID to call the texture later.
Gltexparameter
There is a couple of parameters we need to set on the texture, the first one are to tell OpenGL, and do if the texture n Eed to is shrunk or magnified to match the rendered image.
In texture mapping, we need to set several parameters, the first one is to tell OpenGL how to zoom in or zoom out to fit the size when rendering the picture.
If the texture is smaller it needs to being magnified that's done with the magnification function:
If the map is small, then we need to zoom in using the amplification function.
Scale up if the texture if smaller.
Gl.gltexparameterf (gl10.gl_texture_2d,
Gl10.gl_texture_mag_filter,
Gl10.gl_linear);
If the texture needs to is scaled down using the minification function.
Similarly, use the compression function to zoom out when there is too much mapping.
scale linearly when image smalled than texture
Gl.gltexparameterf (gl10.gl_texture_2d,
Gl10.gl_texture_min_filter,
Gl10.gl_linear);
You need to pass a argument to these functions. I ' M only going to show you from them the rest you can investigate your self
Take a look at the above function, you can study it yourself, what parameters should be passed to it.
If you are want a crisp and clean rendering like this image you need to use the Gl10.gl_nearest parameter.
If you want a clear rendering effect, you can use Gl10.gl_nearest.
If you rather want a blurred image you should use the Gl10.gl_linear parameter.
If you like to blur a little, you should use Gl10.gl_linear
UV Mapping
We'll also need to-tell OpenGL how to map this image onto the mesh this was done in both steps, fist we need to assign UV Coordinates
Below we need to tell OpenGL how to map the image to the model, there are two steps. First we specify a UV coordinate
UV mapping is the the-the-pixels-on-the-bitmap-to-the-vertices in our mesh. The UV coordinates is 0,0 in the upper left and the "the bottom right" like the left image below. The right image below illustrates how we plane is built. To get the texture mapped correctly we need to map the lower left part of the texture (0,1) to the lower left vertex (0) I n Our plane and we need to map the the The bottom right (at the texture to the bottom right (1) to the bottom right in OU R plane and ... Get the idea.
We use UV mapping to map each pixel of a picture to the vertices of the model. In UV coordinates, the upper-left corner is 0, 0, and the lower-right corner is 1, 1, see the left half. The right half is the plane we want to create. To ensure the mapping is correct, we map the lower left corner of the texture to the lower left corner of vertex 0, the lower right corner to the vertex 1 ... And so on
Note: In the OpenGL tutorial, the lower left corner of the image is 0, 0 coordinates. But here we are Android's OpenGL ES. Perhaps Android in the interface package, some changes it.
We put this mapping to a float array like this:
The texture coordinate array is defined as follows:
Float texturecoordinates[] = {0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f};
If we instead used 0.5 instead of 1.0 like this:
Float texturecoordinates[] = {0.0f, 0.5f,
0.5f, 0.5f,
0.0f, 0.0f,
0.5f, 0.0f};
The texture is mapped so the plane would have the same upper left part of it.
Then map the upper-left corner of the picture to the plane
Back to the Gltexparameterf, if we go the other-and uses values higher then 1.0 like this:
Please recall the Gltexparameterf function. If we zoom in 1.0 to 2.0,
Float texturecoordinates[] = {0.0f, 2.0f,
2.0f, 2.0f,
0.0f, 0.0f,
2.0f, 0.0f};
We actually tell OpenGL-to-use part of the texture this does not exist so we need to-tell OpenGL what does with the part That's does not exist.
So what does OpenGL do with the location of the image? That's what we're talking about here.
We Use the Gltexparameterf function-to-tell OpenGL-what-does with the texture. By default OpenGL uses something called Gl_repeat.
We use the Gltexparameterf function to tell OpenGL how to do the mapping, with the default parameter entry being Gl_repeat
gl_repeat means that OpenGL should REPEAT the texture beyond 1.0.
gl_repeat that means OpenGL. The texture should be repeated more than 1.0 part of
Gl_clamp_to_edge means that OpenGL only would draw the image once and after that just repeat the last pixel line t He rest of the image.
Gl_clamp_to_edge indicates that OpenGL only draws pictures once, and the remainder is repeated using the last line of the picture
Since We is working with a 2D texture so we need-to-tell OpenGL-what-do-in-both directions:gl_texture_wrap_s and Gl_te xture_wrap_t.
For a 2D texture, we also need to tell them the direction.
Below a chart with the 4 combinations of gl_repeat and Gl_clamp_to_edge.
See below for their four combinations (the third combination corresponds to a picture that is wrong.) )
|
|
Wrap_s:gl_repeat Wrap_t:gl_repeat |
Wrap_s:gl_repeat Wrap_t:gl_clamp_to_edge |
|
|
Wrap_s:gl_repeat Wrap_t:gl_clamp_to_edge |
Wrap_s:gl_clamp_to_edge Wrap_t:gl_clamp_to_edge |
The Gltexparameterf function:
Gl.gltexparameterf (gl10.gl_texture_2d,
gl10.gl_texture_wrap_s,
Gl10.gl_repeat);
Gl.gltexparameterf (gl10.gl_texture_2d,
gl10.gl_texture_wrap_t,
Gl10.gl_repeat);
The last thing we need to the bind the bitmap we loaded to the texture ID we created.
Glutils.teximage2d (gl10.gl_texture_2d, 0, bitmap, 0);
Using the texture
To is able to use the texture we need just like with everything else create a byte buffer with the UV coordinates:
For UV coordinates, we also use byte buffers
Floatbuffer bytebuf = Bytebuffer.allocatedirect (Texture.length * 4);
Bytebuf.order (Byteorder.nativeorder ());
Texturebuffer = Bytebuf.asfloatbuffer ();
Texturebuffer.put (texturecoordinates);
Texturebuffer.position (0);
Rendering
Telling OpenGL to enable textures.
Gl.glenable (gl10.gl_texture_2d);
Tell OpenGL where we texture is located.
Gl.glbindtexture (gl10.gl_texture_2d, textures[0]);
Tell OpenGL to enable the use of the UV coordinates.
Gl.glenableclientstate (Gl10.gl_texture_coord_array);
Telling OpenGL where our UV coordinates is.
Gl.gltexcoordpointer (2, gl10.gl_float, 0, Texturebuffer);
... here goes the rendering of the mesh ...
Disable the use of UV coordinates.
Gl.gldisableclientstate (Gl10.gl_texture_coord_array);
Disable the use of textures.
Gl.gldisable (gl10.gl_texture_2d);
Putting it all together
I ' m using a modified version of the code from the previous tutorial. The different is mostly, that I renamed some variables and functions, and added more comments and all code are now under Apac He License. The code easier to understand I removed the previous plane and added a new easier one called Simpleplane.
Updating the Mesh class
The first thing we need to update the Mesh class (Se.jaywash.Mesh). We need to add the functionality to load and render a texture.
We need to is able to set and store the UV coordinates.
Our UV texture buffer.
Private Floatbuffer Mtexturebuffer;
/**
* Set the texture coordinates.
*
* @param texturecoords
*/
protected void Settexturecoordinates (float[] texturecoords) {
Float is 4 bytes, therefore we multiply the number if
Vertices with 4.
Bytebuffer bytebuf = Bytebuffer.allocatedirect (
Texturecoords.length * 4);
Bytebuf.order (Byteorder.nativeorder ());
Mtexturebuffer = Bytebuf.asfloatbuffer ();
Mtexturebuffer.put (texturecoords);
Mtexturebuffer.position (0);
}
We also need to add functions to set the bitmap and create the texture.
Our texture ID.
private int mtextureid =-1;
The bitmap we want to load as a texture.
Private Bitmap Mbitmap;
/**
* Set the bitmap to load into a texture.
*
* @param bitmap
*/
public void LoadBitmap (Bitmap Bitmap) {
this. mbitmap = bitmap;
Mshouldloadtexture = true;
}
/**
* Loads the texture.
*
* @param GL
*/
private void Loadgltexture (GL10 gl) {
Generate One texture pointer ...
int[] Textures = new int[1];
Gl.glgentextures (1, textures, 0);
Mtextureid = Textures[0];
... and bind it to our array
Gl.glbindtexture (gl10.gl_texture_2d, Mtextureid);
Create Nearest Filtered Texture
Gl.gltexparameterf (gl10.gl_texture_2d, Gl10.gl_texture_min_filter,
Gl10.gl_linear);
Gl.gltexparameterf (gl10.gl_texture_2d, Gl10.gl_texture_mag_filter,
Gl10.gl_linear);
Different possible texture parameters, e.g. Gl10.gl_clamp_to_edge
Gl.gltexparameterf (gl10.gl_texture_2d, gl10.gl_texture_wrap_s,
Gl10.gl_clamp_to_edge);
Gl.gltexparameterf (gl10.gl_texture_2d, gl10.gl_texture_wrap_t,
Gl10.gl_repeat);
Use the Android glutils to specify a two-dimensional texture image
From our bitmap
Glutils.teximage2d (gl10.gl_texture_2d, 0, Mbitmap, 0);
}
And finally we need to add the call to the texture loading and to actually tell OpenGL-to-render with this texture. I removed some code so the page would isn't being so long but you'll find the code complete in the attached zip file.
Indicates if we need to load the texture.
Private Boolean mshouldloadtexture = false;
/**
* Render the mesh.
*
* @param GL
* The OpenGL context to render to.
*/
public void Draw (GL10 gl) {
...
Smooth Color
if (mcolorbuffer! = null) {
Enable the color array buffer to be used during rendering.
Gl.glenableclientstate (Gl10.gl_color_array);
Gl.glcolorpointer (4, gl10.gl_float, 0, Mcolorbuffer);
}
if (mshouldloadtexture) {
Loadgltexture (GL);
Mshouldloadtexture = false;
}
if (Mtextureid! =-1 && mtexturebuffer! = null) {
Gl.glenable (gl10.gl_texture_2d);
Enable the texture state
Gl.glenableclientstate (Gl10.gl_texture_coord_array);
Point to our buffers
Gl.gltexcoordpointer (2, gl10.gl_float, 0, Mtexturebuffer);
Gl.glbindtexture (gl10.gl_texture_2d, Mtextureid);
}
Gl.gltranslatef (x, y, z);
...
Point out the where the-the color buffer is.
Gl.gldrawelements (Gl10.gl_triangles, Mnumofindices,
Gl10.gl_unsigned_short, Mindicesbuffer);
...
if (Mtextureid! =-1 && mtexturebuffer! = null) {
Gl.gldisableclientstate (Gl10.gl_texture_coord_array);
}
...
}
Creating the Simpleplane class
We also need to create the Simpleplane.java. The code is pretty simple and self-explaining if you have read my previous tutorials. The new element is the texturecoordinates variable.
Package Se.jaywash;
/**
* Simpleplane is a setup class for Mesh that creates a plane mesh.
*
* @author Per-erik Bergman (Per-erik.)
*
*/
Public class Simpleplane extends Mesh {
/**
* Create a plane with a default with and height of 1 unit.
*/
Public Simpleplane () {
This (1, 1);
}
/**
* Create a plane.
*
* @param width
* The width of the plane.
* @param height
* The height of the plane.
*/
Public Simpleplane (float width, float height) {
Mapping coordinates for the vertices
Float texturecoordinates[] = {0.0f, 2.0f,//
2.0f, 2.0f,//
0.0f, 0.0f,//
2.0f, 0.0f,//
};
short[] Indices = new short[] {0, 1, 2, 1, 3, 2};
float[] vertices = new float[] { -0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
-0.5f, 0.5f, 0.0f,
0.5f, 0.5f, 0.0f};
SetIndices (indices);
Setvertices (vertices);
Settexturecoordinates (texturecoordinates);
}
}
References
The info used in this tutorial are collected from:
Android Developers
OpenGL ES 1.1 Reference Pages
You can download the source for this tutorial Here:tutorial_part_vi
You can also checkout the code FROM:COD
Previous Tutorial:opengl ES Tutorial for Android–part v–more on Meshes
Per-erik Bergman
Consultant at Jayway
OpenGL ES course VI Texture map (source control)