请,我需要教程/代码示例,如何在OpenGL ES 1.1上填充不同纹理的多维数据集的每一面
我发现很多教程,但是没有一个解释清楚如何在每个面上放置不同的纹理,没有一个给出了如何做的简单的代码示例.
我的实际代码(来自nehe的例子)在每个面上绘制一个具有相同纹理的立方体:
public class Cube {
/** The buffer holding the vertices */
private FloatBuffer vertexBuffer;
/** The buffer holding the texture coordinates */
private FloatBuffer textureBuffer;
/** The buffer holding the indices */
private ByteBuffer indexBuffer;
/** Our texture pointer */
private int[] textures = new int[1];
/**
* The initial vertex deFinition
*
* Note that each face is defined,even
* if indices are available,because
* of the texturing we want to achieve
*/
private float vertices[] = {
//Vertices according to faces
-1.0f,-1.0f,1.0f,//Vertex 0
1.0f,//v1
-1.0f,//v2
1.0f,//v3
1.0f,//...
1.0f,};
/** The initial texture coordinates (u,v) */
private float texture[] = {
//Mapping coordinates for the vertices
0.0f,0.0f,};
/** The initial indices deFinition */
private byte indices[] = {
//Faces deFinition
0,1,3,2,//Face front
4,5,7,4,6,//Face right
8,9,11,8,10,//...
12,13,15,12,14,16,17,19,18,20,21,23,22,};
/**
* The Cube constructor.
*
* Initiate the buffers.
*/
public Cube() {
//
ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
vertexBuffer = byteBuf.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
//
byteBuf = ByteBuffer.allocateDirect(texture.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
textureBuffer = byteBuf.asFloatBuffer();
textureBuffer.put(texture);
textureBuffer.position(0);
//
indexBuffer = ByteBuffer.allocateDirect(indices.length);
indexBuffer.put(indices);
indexBuffer.position(0);
}
/**
* The object own drawing function.
* Called from the renderer to redraw this instance
* with possible changes in values.
*
* @param gl - The GL Context
*/
public void draw(GL10 gl) {
//Bind our only prevIoUsly generated texture in this case
gl.glBindTexture(GL10.GL_TEXTURE_2D,textures[0]);
//Point to our buffers
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
//Set the face rotation
gl.glFrontFace(GL10.GL_ccw);
//Enable the vertex and texture state
gl.glVertexPointer(3,GL10.GL_FLOAT,vertexBuffer);
gl.glTexCoordPointer(2,textureBuffer);
//Draw the vertices as triangles,based on the Index Buffer information
gl.glDrawElements(GL10.GL_TRIANGLES,indices.length,GL10.GL_UNSIGNED_BYTE,indexBuffer);
//disable the client state before leaving
gl.gldisableClientState(GL10.GL_VERTEX_ARRAY);
gl.gldisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
}
/**
* Load the textures
*
* @param gl - The GL Context
* @param context - The Activity context
*/
public void loadGLTexture(GL10 gl,Context context) {
//Get the texture from the Android resource directory
InputStream is = context.getResources().openRawResource(R.drawable.nehe);
Bitmap bitmap = null;
try {
//BitmapFactory is an Android graphics utility for images
bitmap = BitmapFactory.decodeStream(is);
} finally {
//Always clear and close
try {
is.close();
is = null;
} catch (IOException e) {
}
}
//Generate one texture pointer...
gl.glGenTextures(1,textures,0);
//...and bind it to our array
gl.glBindTexture(GL10.GL_TEXTURE_2D,textures[0]);
//Create Nearest Filtered Texture
gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_NEAREST);
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_REPEAT);
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,bitmap,0);
//Clean up
bitmap.recycle();
}
}
解决方法
要使每个面都有不同的纹理,您需要单独渲染立方体的每个面.这意味着每个脸部需要设置纹理,然后渲染脸部(使用glDrawArrays或glDrawElements).所以它看起来像:
glEnable(GL_TEXTURE_2D);
... //maybe other state setup (like buffer bindings)
glVertexPointer(...);
glEnableClientState(GL_VERTEX_ARRAY);
...
for each(face of cube)
{
glBindTexture(GL_TEXTURE_2D,<face_texture>);
glDrawArrays(...) or glDrawElements(...); //draw only a single face
}
gldisableClientState(GL_VERTEX_ARRAY);
...
gldisable(GL_TEXTURE_2D);
... //maybe other state cleanup
如果它们需要不同的纹理,则不能在一个调用中渲染多维数据集的所有面.但是,您当然可以将它们全部保留在单个数组/ VBO中,并且只需使用glDrawArrays或glDrawElements的参数来选择相应的面,如上所述.
这是一个相当简单的伪代码示例,如果所有这些都听起来很陌生,您应该深入了解OpenGL,并在多维数据集的每个面上应用不同的纹理是您的最小问题.
编辑:好的,根据你更新的代码:首先,由于所有顶点的位置和texCoords存储在同一个数组中,我们不需要更改每个面.此外,您的索引数组似乎包含所有面部连续存储为每个面的6个索引(2个三角形).所有这一切使整个情况变得非常容易.只需将您现有的glDrawElements调用替换为所有面的循环:
for(i=0; i<6; ++i)
{
gl.glBindTexture(GL10.GL_TEXTURE_2D,texture[i]); //use texture of ith face
indexBuffer.position(6*i); //select ith face
//draw 2 triangles making up this face
gl.glDrawElements(GL10.GL_TRIANGLES,indexBuffer);
}
因此,对于每个面,我们选择其纹理,并且仅画出与该面对应的2个三角形.
一般来说,从代码示例中学习,而不是一本书或类似的东西,您至少应该确保您了解每行代码和每个函数参数的含义.只有这样,您才能够根据需要自由调整代码,并开发解决问题的解决方案.