OpenGL ES 2.0 square看起来像矩形

时间:2013-12-26 14:39:08

标签: android opengl-es-2.0

我终于在Android上使用OpenGL ES 2.0绘制了一些几何图形,当我绘制一个正方形时,它最终看起来像一个矩形。

在3D中,您可以计算投影矩阵的纵横比,但我只是在进行2D绘图,所以我需要设置一些不具有“拉伸”几何体的东西吗?

由于

矩形:

public Rectangle(float width, float height) {

    _width = width;
    _height = height;

    float halfWidth = _width * 0.5f;
    float halfHeight = _height * 0.5f;

    float[] vertices = new float[] {
        -halfWidth, halfHeight, 0.0f,      0.0f, 0.0f,
        -halfWidth, -halfHeight, 0.0f,     0.0f, 1.0f,
        halfWidth, -halfHeight, 0.0f,      1.0f, 1.0f,
        halfWidth, halfHeight, 0.0f,       1.0f, 0.0f
    };

    _vertexBuffer = ByteBuffer.allocateDirect(vertices.length * 4)
            .order(ByteOrder.nativeOrder())
            .asFloatBuffer();
    _vertexBuffer.put(vertices).position(0);

    short[] indices = new short[] {
        0, 1, 2, 0, 2, 3
    };

    _indexBuffer = ByteBuffer.allocateDirect(indices.length * 2)
            .order(ByteOrder.nativeOrder())
            .asShortBuffer();
    _indexBuffer.put(indices).position(0);
}

public void draw(Shader shader, Vector2 pos, Texture2D texture)
{
    int shaderId = shader.getProgramId();

    int vertexPosId = GLES20.glGetAttribLocation(shaderId, "vPosition");
    int texCoordId = GLES20.glGetAttribLocation(shaderId, "vTexCoord");
    int textureLoc = GLES20.glGetUniformLocation(shaderId, "texture");
    int positionId = GLES20.glGetUniformLocation(shaderId, "mPosition");

    _vertexBuffer.position(0);
    GLES20.glVertexAttribPointer(vertexPosId, 3, GLES20.GL_FLOAT, false, 5 * 4, _vertexBuffer);

    _vertexBuffer.position(3);
    GLES20.glVertexAttribPointer(texCoordId, 2, GLES20.GL_FLOAT, false, 5 * 4, _vertexBuffer);

    GLES20.glEnableVertexAttribArray(vertexPosId);
    GLES20.glEnableVertexAttribArray(texCoordId);

    GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
    texture.bind();

    GLES20.glUniform1i(textureLoc, 0);
    GLES20.glUniform2fv(positionId, 1, pos.getArray(), 0);

    GLES20.glDrawElements(GLES20.GL_TRIANGLES, 6, GLES20.GL_UNSIGNED_SHORT, _indexBuffer);

    GLES20.glDisableVertexAttribArray(vertexPosId);
    GLES20.glDisableVertexAttribArray(texCoordId);
}

GLRenderer:

public void onSurfaceCreated(GL10 unused, EGLConfig config) {

    _shader = Shader.createShaderProgram(Shader.VERT_2D_TEX, Shader.FRAG_TEX);

    _rect = new Rectangle(1.0f, 1.0f);

    GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
}

public void onDrawFrame(GL10 unused) {

    GLES20.glViewport(0, 0, _width, _height);
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);

    GLES20.glEnable(GLES20.GL_BLEND);
    GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA);

    _rect.draw(_shader, _pos, _texture);
}

public void onSurfaceChanged(GL10 unused, int width, int height) {
    GLES20.glViewport(0, 0, width, height);
    _width = width;
    _height = height;
}

顶点着色器:

public static final String VERT_2D_TEX =
                "uniform vec3 mPosition;" +
                "attribute vec3 vPosition;" +
                "attribute vec2 vTexCoord;" +
                "varying vec2 uv;" +
                "void main()" +
                "{" +
                "  uv = vTexCoord;" +
                "  gl_Position = vec4(mPosition + vPosition, 1.0);" +
                "}";

2 个答案:

答案 0 :(得分:4)

该方面与3D与2D无关。目前,您不使用任何trasnformation矩阵,而只是通过添加一些位置向量来转换顶点。由于您使用1作为w组件,因此剪辑空间与规范化设备空间不同。因此,square [-1,1] x [-1,1]将映射到您的窗口。如果窗口不是方形,则输入坐标中的方形将最终为矩形。您应该更正顶点转换阶段中的方面。通常,人们使用某种正交投影矩阵来校正该方面。但这里不需要完整的矩阵。您需要做的就是将方面作为一个均匀的方向转发到顶点着色器,并使用它沿x(或y)缩放。

答案 1 :(得分:0)

Here是一个关于OpenGL ES 2.0和Android入门的精彩教程。阅读关于矩阵的说明,并记下如何在顶点着色器中使用模型,视图和投影矩阵。