Android OpenGL ES 纹理映射/绘图问题 - 倾斜图像
Posted
技术标签:
【中文标题】Android OpenGL ES 纹理映射/绘图问题 - 倾斜图像【英文标题】:Android OpenGL ES texture mapping/drawing problem - skewed images 【发布时间】:2011-05-04 14:41:47 【问题描述】:我在 android 中使用 OpenGL 的纹理映射有问题。基本上问题是,大多数正方形(我用来绘制 2 个三角形的类)都被正确绘制,也就是说它们上的纹理完全符合它们应该的样子,一切都很甜蜜。 但是有些 Square 画得有点奇怪。基本上,从顶部开始的每条下一条水平线都会向左移动大约 1 个像素。 这是一个示例图像: http://postimage.org/image/1la0mr99g/ 这就是它的绘制方式(上面的按钮是完全相同的,但纹理不同): http://postimage.org/image/1lafildpg/
这是负责将图像绘制到屏幕上的类。我还必须补充一点,一旦创建了 Square,我就会继续使用,并且以后可能会重新映射一些纹理,但是对于绘制错误的图像而言并非如此(实际上,我已经重新映射了一些其他图像的纹理以便绘制得很好)。所以基本上,通过查看代码,我不知道可能出了什么问题,因为大多数正方形都被正确绘制,并且我看不到任何错误。 此外,我实际上有 2 个按钮,它们的大小完全相同,它们的图像也大小相同 - 但其中一个被绘制得很好,而另一个被“歪斜”。创建这些按钮的代码实际上是相同的,所以我完全不知道出了什么问题。
public class GLSquare
private float width, height;
private FloatBuffer vertexBuffer; // buffer holding the vertices
private float vertices[]; /* =
-1.0f, 1.0f, 0.0f, // V1 - bottom left
-1.0f, -1.0f, 0.0f, // V2 - top left
1.0f, 1.0f, 0.0f, // V3 - bottom right
1.0f, -1.0f, 0.0f // V4 - top right
;
*/
private FloatBuffer textureBuffer; // buffer holding the texture coordinates
private float texture[] =
// Mapping coordinates for the vertices
0.0f, 1.0f, // top left (V2)
0.0f, 0.0f, // bottom left (V1)
1.0f, 1.0f, // top right (V4)
1.0f, 0.0f // bottom right (V3)
;
/** The texture pointer */
private int[] textures = new int[1];
public GLSquare(float width, float height)
this.width = width;
this.height = height;
vertices = new float[12];
vertices[0] = -(width/2); vertices[1] = (height/2); vertices[2] = 0.0f;// V1 - bottom left
vertices[3] = -(width/2); vertices[4] = -(height/2); vertices[5] = 0.0f;// V2 - top left
vertices[6] = width/2; vertices[7] = (height/2); vertices[8] = 0.0f;// V3 - bottom right
vertices[9] = width/2; vertices[10] = -(height/2); vertices[11] = 0.0f;// V4 - top right
// a float has 4 bytes so we allocate for each coordinate 4 bytes
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(vertices.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());
// allocates the memory from the byte buffer
vertexBuffer = byteBuffer.asFloatBuffer();
// fill the vertexBuffer with the vertices
vertexBuffer.put(vertices);
// set the cursor position to the beginning of the buffer
vertexBuffer.position(0);
byteBuffer = ByteBuffer.allocateDirect(texture.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());
textureBuffer = byteBuffer.asFloatBuffer();
textureBuffer.put(texture);
textureBuffer.position(0);
public float getWidth()
return width;
public float getHeight()
return height;
public void loadGLTexture(GL10 gl, Bitmap bitmap)
// Generate a texture pointer
gl.glGenTextures(1, textures, 0);
// Bind texture to 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);
// Use 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();
public void draw(GL10 gl, float x, float y, float scaleX, float scaleY, float angle)
gl.glPushMatrix();
// bind the previously generated texture
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_CW);
// Point to our vertex buffer
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
//translate to the wanted x,y coord
gl.glTranslatef(x, y, 0.0f);
if(angle != 0.0f)
gl.glRotatef(angle, 0.0f, 0.0f, 1.0f);
if(scaleX != 1.0f && scaleY != 1.0f)
gl.glScalef(scaleX, scaleY, 0.0f);
// Draw the vertices as triangle strip
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);
//Disable the client state before leaving
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glPopMatrix();
【问题讨论】:
【参考方案1】:看起来像是对齐问题。这有点令人惊讶,因为我预计 GLUtils.texImage2D
会正确设置所有参数。
在 C 中你会添加
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // correction, should be 1
但是,如果您真的遇到对齐问题,这很容易测试:使您的图像宽度为 8 的倍数:无论对齐设置如何,您的图像都应该始终正确显示。
也可能是 ROW_LENGTH 设置错误。您可以尝试添加我上图中的两个调用(当然添加正确的命名空间,即 gl. 和 GL10。)
【讨论】:
嘿 datenwolf,是的,我在 OpenGL irc 频道上得到了答案。需要调用 glPixelStorei 方法才能使其工作。它必须是 gl.glPixelStorei(GL10.GL_UNPACK_ALIGNMENT, 1);让它工作。此外,第一种方法不起作用 - 因为没有值 GL_UNPACK_ROW_LENGTH。无论如何感谢您的帮助,希望如果有人遇到同样的问题,他们会看到这个。现在我需要弄清楚,为什么应用程序在模拟器上运行而不是在我的 2 部手机上运行......天哪! 我有一个无关紧要的问题。但是,这个解释对我帮助很大。 “使您的图像宽度为 8 的倍数”。为此 +1。 这个答案涵盖了缺少的 GL_UNPACK_ROW_LENGTH 选项:***.com/a/205569以上是关于Android OpenGL ES 纹理映射/绘图问题 - 倾斜图像的主要内容,如果未能解决你的问题,请参考以下文章
Android NDK SDL2 OpenGL ES 2 阴影映射(定向)- 可能吗?