拜托,我需要有关如何在 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, -1.0f, 1.0f, //v1
-1.0f, 1.0f, 1.0f, //v2
1.0f, 1.0f, 1.0f, //v3
1.0f, -1.0f, 1.0f, //...
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
};
/** The initial texture coordinates (u, v) */
private float texture[] = {
//Mapping coordinates for the vertices
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
1.0f, 1.0f,
};
/** The initial indices definition */
private byte indices[] = {
//Faces definition
0,1,3, 0,3,2, //Face front
4,5,7, 4,7,6, //Face right
8,9,11, 8,11,10, //...
12,13,15, 12,15,14,
16,17,19, 16,19,18,
20,21,23, 20,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, 0, vertexBuffer);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, 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, 0, 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,并且对立方体的每个面应用不同的纹理是您最不关心的问题。
编辑: 好的,根据您更新的代码:首先,由于所有顶点的位置和纹理坐标都存储在相同的数组中,我们不需要更改每个面。此外,您的索引数组似乎包含所有面孔,每个面孔连续存储为 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, 6, GL10.GL_UNSIGNED_BYTE, indexBuffer);
}
因此,对于每张脸,我们选择它的纹理并只绘制与这张脸对应的 2 个三角形。
一般来说,在学习代码示例时,而不是书本或类似的东西,你至少应该确保你理解每一行代码和每个函数参数的含义。只有这样,您才能根据自己的需要自由调整代码并开发问题解决方案。
关于android - 如何在 OpenGL ES 1.1 上用不同的纹理填充立方体的每一面?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7767367/