将纹理映射到方形,就像图片本身一样

时间:2016-02-06 15:22:30

标签: android opengl-es

我用两个星期的时间开玩笑,试着在一个正方形上画一个图像。 正方形由两个三角形组成。当我绘制原始图像(http://satgeo.zum.de/satgeo/methoden/DHM_Web/Bilder/Grundidee/Raster.gif)时,它会以这种方式结束https://pl.vc/tfuc

这是我的代码:

public class Square {
    public static final String TAG = "Screen";
    private static final int POSITION_COMPONENT_COUNT = 3;
    private static final int TEXTURE_COORDINATES_COMPONENT_COUNT = 2;
    private static final int STRIDE =
            (POSITION_COMPONENT_COUNT + TEXTURE_COORDINATES_COMPONENT_COUNT) * Constants.BYTES_PER_FLOAT;

    private static final float[] VERTEX_DATA = {
            -1.0f,  1.0f, 0.0f, 1.0f, 0.0f,
            -1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
             1.0f,  1.0f, 0.0f, 0.0f, 1.0f,

             1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
            -1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
             1.0f,  1.0f, 0.0f, 0.0f, 1.0f
    };

    private final VertexArray vertexArray;

    public Square(){
        vertexArray = new VertexArray(VERTEX_DATA);
    }

    public void bindData(TextureShaderProgram textureShader){
        vertexArray.setVertexAttribPointer(0, textureShader.getPositionAttributeLocation(),
                POSITION_COMPONENT_COUNT, STRIDE);

        vertexArray.setVertexAttribPointer(POSITION_COMPONENT_COUNT, textureShader.getTextureCoordinatesAttributeLocation(),
                TEXTURE_COORDINATES_COMPONENT_COUNT, STRIDE);
    }

    public void draw(){
        int anzVertices = VERTEX_DATA.length / (POSITION_COMPONENT_COUNT + TEXTURE_COORDINATES_COMPONENT_COUNT);
        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, anzVertices);
    }
}

public class Square { public static final String TAG = "Screen"; private static final int POSITION_COMPONENT_COUNT = 3; private static final int TEXTURE_COORDINATES_COMPONENT_COUNT = 2; private static final int STRIDE = (POSITION_COMPONENT_COUNT + TEXTURE_COORDINATES_COMPONENT_COUNT) * Constants.BYTES_PER_FLOAT; private static final float[] VERTEX_DATA = { -1.0f, 1.0f, 0.0f, 1.0f, 0.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f }; private final VertexArray vertexArray; public Square(){ vertexArray = new VertexArray(VERTEX_DATA); } public void bindData(TextureShaderProgram textureShader){ vertexArray.setVertexAttribPointer(0, textureShader.getPositionAttributeLocation(), POSITION_COMPONENT_COUNT, STRIDE); vertexArray.setVertexAttribPointer(POSITION_COMPONENT_COUNT, textureShader.getTextureCoordinatesAttributeLocation(), TEXTURE_COORDINATES_COMPONENT_COUNT, STRIDE); } public void draw(){ int anzVertices = VERTEX_DATA.length / (POSITION_COMPONENT_COUNT + TEXTURE_COORDINATES_COMPONENT_COUNT); GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, anzVertices); } }

如何在不进行转换的情况下绘制纹理,它看起来像原始纹理?

2 个答案:

答案 0 :(得分:0)

您的纹理坐标是错误的:例如,顶点[-1,-1,0]和[1,1,0]通过正方形的对角线连接,因此它们也应该具有位于对角线。在您的数据中,它们有[0,0]和[1,0]。此外,具有相同纹理坐标(均为[1,0])的不同顶点位置([-1,1,0]和[1,-1,0])也无法解决。

更正后的版本可能如下所示:

-1.0f,  1.0f, 0.0f, 0.0f, 1.0f,
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
 1.0f,  1.0f, 0.0f, 1.0f, 1.0f,

 1.0f, -1.0f, 0.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

仅为了完整性:两个三角形具有不同的缠绕顺序,这将在启用背面剔除时引起问题。

答案 1 :(得分:0)

对于这种情况,您实际上不需要纹理坐标的顶点属性。由于它们是位置的直接映射,因此您可以根据位置属性的值计算顶点着色器中的纹理坐标。

您当然必须调整您的命名,但顶点着色器中的GLSL代码可能如下所示:

attribute vec3 Position;
varying vec2 TexCoord;
...
    gl_Position = vec4(Position, 1.0);
    TexCoord = 0.5 * Position.xy + 0.5;

将[-1.0,1.0]范围内的坐标映射到[0.0,1.0]范围内的纹理坐标。

这将节省代码,提高效率,减少错误。

如果您使用纹理坐标,那么您尝试的那些显然是错误的。您可以通过两个三角形使用相同的纹理坐标来判断它们可能是正确的。因此,图像的相同三角形部分将映射到用于渲染四边形的两个三角形。

不是功能问题,但我还建议使用GL_TRIANGLE_STRIP代替GL_TRIANGLES。这样,您只需要4个顶点而不是6个。顶点数据(包括纹理坐标,只要您使用它们)将如下所示:

private static final float[] VERTEX_DATA = {
        -1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
         1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
        -1.0f,  1.0f, 0.0f, 0.0f, 1.0f,
         1.0f,  1.0f, 0.0f, 1.0f, 1.0f
};

和平局电话:

GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, anzVertices);

同样,这将使您的代码更简单,更高效,并且冗余更少,您可以减少错误来源。