You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用glOrthof在Android OpenGL ES 2中居中矩形崩溃求助

问题分析与解决方案

崩溃核心原因

  • 着色器变量类型错误:将投影矩阵u_Projection定义为attribute,但它属于全局统一的uniform变量,attribute是每个顶点独有的属性,类型不匹配会导致OpenGL内部状态异常,引发崩溃。
  • 错误使用固定管线函数:glOrthof是OpenGL 1.x固定管线的函数,OpenGL ES 2.0为可编程管线,无法通过该函数直接生成矩阵到你定义的projectionMatrix数组中,导致数组始终为初始全0值,传递给着色器后触发内存访问错误。
  • Uniform设置时机与矩阵未初始化:projectionMatrix数组未被填充有效矩阵数据,且glUniformMatrix4fv在onSurfaceChanged中调用时,可能程序尚未完成链接,后续绘制也未重新设置矩阵。

修复步骤

1. 修正顶点着色器变量类型

将attribute mat4 u_Projection改为uniform mat4 u_Projection,投影矩阵是所有顶点共用的全局参数:

attribute vec4 a_Position;

uniform mat4 u_Projection; // 修正为uniform类型

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

2. 使用Android矩阵工具生成正交投影矩阵

替换glOrthof为Android提供的Matrix.orthoM方法,正确填充projectionMatrix数组,同时调整矩阵范围让矩形居中显示:

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

    float rectWidth = 9f;
    float rectHeight = 14f;
    float aspectRatio = (float) width / height;

    // 以矩形中心为原点,计算初始边界
    float left = -rectWidth / 2f;
    float right = rectWidth / 2f;
    float bottom = -rectHeight / 2f;
    float top = rectHeight / 2f;

    // 适配屏幕宽高比,保持矩形比例不变且居中
    if (aspectRatio > rectWidth / rectHeight) {
        float scale = aspectRatio / (rectWidth / rectHeight);
        left *= scale;
        right *= scale;
    } else {
        float scale = (rectWidth / rectHeight) / aspectRatio;
        bottom *= scale;
        top *= scale;
    }

    // 生成正交投影矩阵到数组中
    Matrix.orthoM(projectionMatrix, 0, left, right, bottom, top, -1f, 1f);

    // 获取uniform变量位置(确保program已链接完成)
    projectionMatrixLocation = glGetUniformLocation(program, U_PROJECTION);
}

3. 在绘制流程中设置Uniform矩阵

将glUniformMatrix4fv移到onDrawFrame中,确保每次绘制前参数正确:

@Override
public void onDrawFrame(GL10 gl10) {
    glClear(GL_COLOR_BUFFER_BIT);

    // 设置投影矩阵uniform
    glUniformMatrix4fv(projectionMatrixLocation, 1, false, projectionMatrix, 0);

    // 执行原有矩形绘制逻辑...
}

4. 可选:调整顶点坐标到中心原点

如果不想修改投影矩阵范围,可直接将顶点坐标改为以矩形中心为原点,简化后续矩阵计算:

private float[] tableVerticesWithTriangles = {
        // Triangle 1
        -4.5f, -7f,
        4.5f, 7f,
        -4.5f, 7f,
        // Triangle 2
        -4.5f, -7f,
        4.5f, -7f,
        4.5f, 7f
};

对应的正交矩阵可简化为适配屏幕的标准范围:

Matrix.orthoM(projectionMatrix, 0, -aspectRatio, aspectRatio, -1f, 1f, -1f, 1f);

关键说明

  • OpenGL ES 2.0中,uniform用于传递全局不变参数(如矩阵、颜色),attribute用于传递每个顶点独有数据(如位置、纹理坐标),类型不可混用。
  • 可编程管线中,所有矩阵需手动计算或通过工具类生成,无法依赖固定管线函数。
  • Uniform变量需在绘制前设置,确保每次绘制时参数有效。

内容的提问来源于stack exchange,提问作者Quim PerVal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 06:46:03