通过在Android中使用glOrthof与opengles 2和java将矩形对象居中显示在屏幕上

izkcnapc  于 2023-01-03  发布在  Android
关注(0)|答案(2)|浏览(107)

我正在写OpenGles 2 for Android这本书的例子,我做了第一个例子,画一个底9高14的矩形,用下面的数组定义坐标

private float[] tableVerticesWithTriangles = {
        //Triangle
        0f, 0f,
        9f, 14f,
        0f, 14f,
        //Triangle 2
        0f, 0f,
        9f, 0f,
        9f, 14f
};

矩形的外观如示例所示,白色矩形位于右上角:

我正在处理的代码位于存储库https://github.com/quimperval/opengles-android-rectangle
现在在书中作者通过修改矩形的坐标来使矩形居中,然而据我所知,openGl可以通过使用投影矩阵来处理这个问题,所以,我修改了顶点着色器来使用投影矩阵

attribute vec4 a_Position;

attribute mat4 u_Projection;

void main(){
    gl_Position =  u_Projection * a_Position;
}

在CRenderer类中,我添加了以下变量

private static final String U_PROJECTION = "u_Projection";
int projectionMatrixLocation;

float[] projectionMatrix = new float[16];

在onSurfaceChanged方法中,我添加了考虑aspectRatio的逻辑

@Override
public void onSurfaceChanged(GL10 gl10, int width, int height) {
    glViewport(0, 0, width, height);

    // Calculate the projection matrix
    float aspectRatio = width > height ?
            (float) width / (float) height :
            (float) height / (float) width;
    if (width > height) {
        // Landscape
        glOrthof(-aspectRatio, aspectRatio, -1f, 1f, -1f, 1f);
    } else {
        // Portrait or square
        glOrthof(-1f, 1f, -aspectRatio, aspectRatio, -1f, 1f);
    }

    projectionMatrixLocation = glGetUniformLocation(program, "u_Projection");
    glUniformMatrix4fv(projectionMatrixLocation, 1, false, projectionMatrix, 0);
}

在onDrawFrame中,我没有做任何更改。
当我在模拟器中编译和安装应用程序时,它崩溃了,并显示错误:
2022年12月31日14:45:23.971 10499-10521/com我的申请表A/libc:致命信号11(SIGSEGV),代码1,tid 10521(GLThread 411)中的故障地址0x 0
我是不是错过了什么手术?
我期望将矩形(任何维度)居中显示在设备屏幕上。

wkyowqbh

wkyowqbh1#

我相信答案是你是:

  • 未将矩阵声明为统一矩阵
  • 不检查您来自glGetUniformLocation()的响应

使用glGetUniformLocation访问制服时,应在着色器中声明制服,如下所示:

uniform mat4 u_Projection;
daupos2t

daupos2t2#

我设法找到了另一种方法来获得所需的结果,方法是在onSurfaceChangedMethod中使用以下代码

@Override
    public void onSurfaceChanged(GL10 gl10, int width, int height) {
        glViewport(0,0, width, height);

        /*orthoM
         *projectionMarix - float[] m - the destination array
         * mOffset - the offset in to m which the result is written
         * float left - the minimum range of the x-axis
         * float right - the maximum range of the x-axis
         * float bottom - the minimum range of the y-axis
         * float top - the maximum range ot the y-axis
         * float near - the minimum range of the z-axis
         * float far - the maximum range of the z-axis
         *
         */

        float boundingBoxWidth = 300;
        float boundingBoxHeight = 300;

        float aspectRatio;

        if(width>height){
            //Landscape
            aspectRatio = (float) width / (float) height;
            orthoM(projectionMatrix, 0, -aspectRatio*boundingBoxHeight, aspectRatio*boundingBoxHeight, -boundingBoxHeight, boundingBoxHeight, -1f, 1f);
        } else {
            //Portrait or square
            aspectRatio = (float) height / (float) width;
            orthoM(projectionMatrix, 0, -boundingBoxWidth, boundingBoxWidth, -boundingBoxWidth*aspectRatio, boundingBoxWidth*aspectRatio, -1f, 1f);
        }
    }

通过这种方式,我得到了我想要的行为,将一个对象放置在屏幕的中心,该对象的顶点坐标在表面范围(-1,-1)到(1,1)之外。

关键是要知道我想要绘制的对象的碰撞框的宽度和高度,然后只需根据屏幕的方向,使用aspectRatio变量缩放left、right或bottom/top变量即可。
https://github.com/quimperval/opengl-es-android-draw-object

相关问题