Android OpenGL ES 纹理映射/绘图问题 - 图像倾斜

发布于 2024-11-04 21:15:39 字数 4511 浏览 2 评论 0原文

我在 Android 中使用 OpenGL 进行纹理映射时遇到问题。基本上问题是,大多数正方形(我用来绘制 2 个三角形的类)都正确绘制,即它们上的纹理完全符合其应有的样子,而且一切都很甜蜜。 但有些方块画得有点奇怪。基本上,从顶部开始的每一条水平线都会向左移动约 1 个像素。 这是一个示例图像: http://postimage.org/image/1la0mr99g/ 这就是它的绘制方式(上面的按钮是完全相同的,但纹理不同): http://postimage.org/image/1lafildpg/

这是负责绘制图像的类屏幕。我还必须补充一点,一旦创建了一个正方形,我就会继续使用,并且可能会在以后重新映射一些纹理,但对于绘制错误的图像而言,情况并非如此(事实上,我已经重新映射了一些其他图像以便绘制得很好) )。所以基本上,通过查看代码,我不知道可能出了什么问题,因为大多数方块都正确绘制,并且我没有看到任何错误。 另外,我实际上有 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();
}

}

I have a problem with texture mapping in Android using OpenGL . Basically the problem is, that most of the Squares (my class I use for drawing 2 triangles) are drawn properly, that is the textures on them are exactly as they should be and everything is sweet.
But some Squares are drawn a bit weirdly. Basically every next horizontal line starting from the top gets drawn about 1 pixel shifted to the left.
This is an example image:
http://postimage.org/image/1la0mr99g/
and this is how it gets drawn (the button above is the one that is exactly the same, but different texture):
http://postimage.org/image/1lafildpg/

This is the class that is responsible for drawing images to screen. I must also add, that once a Square gets created I keep using and would potentially remap some textures later, but this is not the case for the images that get drawn wrong (in fact some other images I've remapped textures for get drawn fine). So basically, by looking at the code I've no idea what could be going wrong, as most of the Squares get drawn properly, and there is no bug visible to me.
Also, I actually have 2 buttons, and they are exactly the same sizes and their images are also the same size - but one of the gets drawn just fine, whereas the other gets 'skewed'. The code for creating those buttons is literally the same, so I'm totally at a loss at what is going wrong.

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();
}

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

夜声 2024-11-11 21:15:39

看起来像是对齐问题。这有点令人惊讶,因为我预计 GLUtils.texImage2D 会适当地设置所有参数。

在 C 中,您可以添加

glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // correction, should be 1 

然而,如果您真的遇到对齐问题,测试起来很容易:将图像宽度设置为 8 的倍数:使用该大小,无论对齐设置是什么,您的图像都应该始终正确显示。

也可能是 ROW_LENGTH 设置错误。您可以尝试添加我上图所示的两个调用(当然添加正确的命名空间,即 gl. 和 GL10。)

It looks like an alignment problem. This is a bit surprising as I expected GLUtils.texImage2D was setting all parameters apropriately.

In C you would add

glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // correction, should be 1 

However it's quite easy to test if you're really running into an alignment problem: Make your image width a multiple of 8: With that size no matter what the alignment setting is, your image should always show correctly.

It could also be a wrong setting of ROW_LENGTH. You could try adding the two calls I pictured above (of course adding the proper namespaces, i.e. gl. and GL10.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文