本文主要知识点:
- 如何设置顶点数据
- OpenGL错误检测
- OpenGL的坐标系统
添加一个顶点的数据
可能有些同学发现我在搞笑,一个点能画,两个点还不简单,你可能同我一样,直接在顶点数组里添加了一个点的三个坐标,一运行,crash
why?????
logcat里有报错,但是没有发现什么地方出错了,我们只能根据自己的改动查找相关的地方,修改了顶点数据,不可能导致加载着色器失败,相关语句排除。那就只剩下使用ByteBuffer装载数据(有错就会报出来了),glVertexAttribPointer,glDrawArrays。
OpenGL的方法在出错的时候不会报异常,而是要我们手动的调用另一个函数 GLES20.glGetError, 它会返回上一条OpenGL方法执行的错误码,通过判断错误码是否为GLES20.GL_NO_ERROR,判断是否上条语句发生错误。我们对他封装一下,在发生错误是报运行时异常:
1 | static void checkGLError(String op) { |
我们在上面,glVertexAttribPointer() 和 glDrawArrays() 后调用用checkGLError(), 发现是 glVertexAttribPointer() 出了问题。通过错误号,在网上可以查到出错信息,你可以自省搜索,这里我们通过这个错误来学习glVertexAttribPointer()方法
1 | GLES20.glVertexAttribPointer(mPositionHandle, 3, GLES20.GL_FLOAT, false, |
我们已经知道mPositionHandle相当于是一个指针,通过它,就可以为着色器中的属性设置值,而这个函数的作用正是规定怎样往着色器传递数据:
- mPositionHandle 指明数据要给谁,这里传的是顶点坐标数据,传给了shader里的vPosition
- 3 表示每个顶点传递的一组数据的元素个数,可以是1, 2, 3, 4
- GLES20.GL_FLOAT 表示传递的数据类型为float
- false 表示定点数据值不标准化(我也不知什么意思,若您知道请不吝赐教)
- 3 * 4 表示要传递的数据的大小, 我们之前传递一个点,每个点的3个float,每个float表示4byte
- mVertexBuffer 最后的一个当然是数据
问题就出第五个参数,参数 3 × 4, 3个float, 代表一个点的数据, 现在,我们在数组又添加了一个点的数据,应该是6 * 4, 再抽象一下,VERTEX.length * 4
现在运行看一下,发现只显示了一个点,为什么?
竟然也没有报错, 这个咋整,一个问题,之所以是问题,要么是我们掌握的信息不够,或者错误,要么是我们没高清信息之间的关系。好吧,我就不卖关子了,实际同上面的问题差不多。
1 | GLES20.glDrawArrays(GLES20.GL_POINTS, 0, 1); |
这个函数,原先第三个参数是1表示画一个点,现在,传了两个点的数据,要画两个点,所以为2, 如果抽象一下,VERTEX.length / 3
- GLES20.GL_POINTS 表示绘制离散的点,之后我们会了解到更多绘制模式
- 0 表示从我们之前提供的数据的第几个点的数据开始画,改成1试试吧[坏笑]
- 1 表示要绘制几次 尽管我们传了两个点的数据, 但是,如果我们从第0个开始画1个也就只显式一个,所以你懂得
下面是我们有画一个点到画两个点要改动的代码:
1 |
|
OpenGL 坐标系
看看上面两顶点的数据,它们分别是两个顶点的xyz三个坐标,我们先只考虑二维平面,你可以看到显示的效果,(0, 0, 0)的点在中间,说明原点在屏幕中间。(0.5, 0f, 0f)的点在右侧,说明从原点向有为x轴正方向。
你可以试着改变一下坐标,看一下,很容易得到OpenGL的坐标系:
- 原点在中央
- x轴的范围是-1 ~ 1
- y轴的范围是-1 ~ 1
- 右上角的坐标为(1,1,0)
剩下一个Z轴坐标系,我相信你能通过自己探索研究出它的规则的。
end