Xamarin Android C# OpenGL ES 2.0 GlUniform4fv着色三角形抛异常问题
OpenGL ES 2.0 三角形绘制异常排查与修复
报错含义解释
你碰到的
Java.Lang.IllegalArgumentException: length - offset < count*4 < needed是OpenGL驱动的缓冲区边界校验逻辑抛出的,核心逻辑是:你传给GL方法的浮点数组,从指定偏移位置开始计算的可读取元素长度,完全达不到调用方要求的填充长度。
直接触发崩溃的错误点
draw()方法内的着色调用参数完全错误:
你编写的触发异常的代码为GLES20.GlUniform4fv(colorHandle, 1, color, 3);
该方法的官方参数顺序为:- uniform变量的位置句柄
- 要更新的向量数量
- 存储数据的浮点数组
- 从数组的哪个下标位置开始取数
你传入的偏移位置为3,但你的color数组仅包含3个元素(下标范围0~2),从下标3开始取数本身就已经越界;同时你的片段着色器中vColor是vec4类型,需要RGBA共4个浮点值,你的color数组仅包含3个元素,就算偏移位置写0,也满足不了取4个值的长度要求。
- 对应修复方式:
- 把color数组补全为4个元素,补上Alpha通道值:
private float[] color = new float[] { 0.63671875f, 0.76953125f, 0.22265625f, 1.0f }; - 把
GlUniform4fv的偏移参数从3改成0,从数组开头取数:GLES20.GlUniform4fv(colorHandle, 1, color, 0);
- 把color数组补全为4个元素,补上Alpha通道值:
其他会导致绘制失败/性能问题的代码错误
OnSurfaceCreated里的错误GL调用:你在设置完清屏颜色后写了GLES20.GlDrawArrays(GLES20.GlColorBufferBit, 2, 10);,这行属于参数混淆错误:GlDrawArrays第一个参数需要传入绘制图元模式(比如GLES20.GlTriangles),你传的GLES20.GlColorBufferBit是清缓冲的标记位,属于非法参数,且这行代码本就不该出现在表面创建的回调里,直接删除即可。- 每帧实例化Triangle对象的问题:你在
OnDrawFrame里每帧执行Triangle triangle = new Triangle();,Triangle构造函数包含着色器编译、GL程序链接这类重量级操作,每帧重复执行不仅会造成严重的性能损耗,还会因为反复创建GL资源导致内存泄漏。正确做法是把Triangle实例作为Renderer的成员变量,仅在OnSurfaceCreated回调里初始化一次,每帧直接调用draw方法即可:// 作为Renderer的字段 private Triangle _triangle; // OnSurfaceCreated方法末尾初始化 public void OnSurfaceCreated(IGL10 gl, EGLConfig config) { GLES20.GlClearColor(0.0f, 0.0f, 1.0f, 0.0f); _triangle = new Triangle(); // 仅初始化一次 } // OnDrawFrame里直接调用 public void OnDrawFrame(IGL10 gl) { GLES20.GlClear(GLES20.GlColorBufferBit); _triangle.draw(); } - 着色器链接状态无校验:你在执行
GLES20.GlLinkProgram(mProgram)后没有校验链接结果,一旦着色器编译失败、程序链接出错,后续获取属性位置、uniform位置的方法会返回-1,用无效句柄调用GL方法还会继续抛出异常。 - 冗余无效代码:Triangle构造函数里创建了
myfloat变量但完全没有使用,属于无用代码,可以直接删除不影响功能。
内容的提问来源于stack exchange,提问作者user10913773
相关产品推荐
相关产品推荐

