OpenGL ES之一——概念扫盲
OpenGL ES之二——Android中的OpenGL ES概述
OpenGL ES之三——绘制纯色背景
OpenGL ES之四——绘制点,线,三角形
OpenGL ES之五——相机和投影,绘制等腰三角形
OpenGL ES之六——绘制矩形和圆形
OpenGL ES之七——着色器语言GLSL
OpenGL ES之八——GLES20类和Matrix类
OpenGL ES之九——相机和投影
OpenGL ES之十——纹理贴图(展示一张图片)
OpenGL ES之十一——绘制3D图形
OpenGL ES之十二——地球仪和VR图
上面对于GLSL也有了一定的了解,并且通过之前编程过程,我们基本了解了GLSL语言的特色和通过调用Java语言编写的SDK来完成一些基本操作。下面总结一下GLES20和Matrix(GLES30或者更高这里就不一一列举了,由于是继承自GLES20所以好多直接使用的其中的)
重点:
GLES20作为我们和着色器连接的工具类提供了丰富的api。
同时由我们从前面的编程过程中也发现要想实现各种效果Matrix工具类是必不可少的
GLES20.glGetAttribLocation方法:获取着色器程序中,指定为attribute类型变量的id。
GLES20.glGetUniformLocation方法:获取着色器程序中,指定为uniform类型变量的id。
如:
// 获取指向着色器中aPosition的index
maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
// 获取指向着色器中uMVPMatrix的index
muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
使用上一节获取的指向着色器相应数据成员的各个id,就能将我们自己定义的顶点数据、颜色数据等等各种数据传递到着色器当中了。
// 使用shader程序
GLES20.glUseProgram(mProgram);
// 将最终变换矩阵传入shader程序
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, MatrixState.getFinalMatrix(), 0);
// 设置缓冲区起始位置
mRectBuffer.position(0);
// 顶点位置数据传入着色器
GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false, 20, mRectBuffer);
// 顶点颜色数据传入着色器中
GLES20.glVertexAttribPointer(maColorHandle, 4, GLES20.GL_FLOAT, false, 4*4, mColorBuffer);
// 顶点坐标传递到顶点着色器
GLES20.glVertexAttribPointer(maTextureHandle, 2, GLES20.GL_FLOAT, false, 20, mRectBuffer);
// 允许使用顶点坐标数组
GLES20.glEnableVertexAttribArray(maPositionHandle);
// 允许使用顶点颜色数组
GLES20.glDisableVertexAttribArray(maColorHandle);
// 允许使用定点纹理数组
GLES20.glEnableVertexAttribArray(maTextureHandle);
// 绑定纹理
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture);
// 图形绘制
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, 4);
void glVertexAttribPointer (int index, int size, int type, boolean normalized, int stride, Buffer ptr )
参数含义:
index 指定要修改的顶点着色器中顶点变量id;
size 指定每个顶点属性的组件数量。必须为1、2、3或者4。如position是由3个(x,y,z)组成,而颜色是4个(r,g,b,a));
type 指定数组中每个组件的数据类型。可用的符号常量有GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT,GL_UNSIGNED_SHORT, GL_FIXED, 和 GL_FLOAT,初始值为GL_FLOAT;
normalized 指定当被访问时,固定点数据值是否应该被归一化(GL_TRUE)或者直接转换为固定点值(GL_FALSE);
stride 指定连续顶点属性之间的偏移量。如果为0,那么顶点属性会被理解为:它们是紧密排列在一起的。初始值为0。如果normalized被设置为GL_TRUE,意味着整数型的值会被映射至区间-1,1,或者区间[0,1](无符号整数),反之,这些值会被直接转换为浮点值而不进行归一化处理;
ptr 顶点的缓冲数据。
调用GLES20.glEnableVertexAttribArray和GLES20.glDisableVertexAttribArray传入参数index。
GLES20.glEnableVertexAttribArray(glHPosition);
GLES20.glEnableVertexAttribArray(glHCoordinate);
如果启用,那么当GLES20.glDrawArrays或者GLES20.glDrawElements被调用时,顶点属性数组会被使用。
void glActiveTexture (int texture)
texture指定哪一个纹理单元被置为活动状态。texture必须是GL_TEXTUREi之一,其中0 <= i < GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,初始值为GL_TEXTURE0。
GLES20.glActiveTexture()确定了后续的纹理状态改变影响哪个纹理,纹理单元的数量是依据该纹理单元所被支持的具体实现。
我们知道OpenGl中实现图形的操作大量使用了矩阵,在OpenGL中使用的向量为列向量
,我们通过利用矩阵与列向量(颜色、坐标都可看做列向量)相乘,得到一个新的列向量。利用这点,我们构建一个的矩阵,与图形所有的顶点坐标坐标相乘,得到新的顶点坐标集合,当这个矩阵构造恰当的话,新得到的顶点坐标集合形成的图形相对原图形就会出现平移、旋转、缩放或拉伸、抑或扭曲的效果。
Matrix:专门为处理4*4矩阵和4元素向量设计的,其中的方法都是static的,不需要初始化Matrix实例
。其实其中的方法也是比较少的共有18个(其中部分是native的调用本地代码),这里不一一详细介绍,重点是让大家了解各个方法的功能。
而Matrix就是专门设计出来帮助我们简化矩阵和向量运算操作的,里面所有的实现原理都是线性代数中的运算
。
下面矩阵的处理方法中参数不少是相同的并且含义也是相同的,所以只是将少数一些参数含义做了解释说明,未说明的参照已有说明都可以理解。
下面是Matrix中的15种类型的方法:
计算两个矩阵乘法
public static native void multiplyMM(float[] result, int resultOffset,
float[] lhs, int lhsOffset, float[] rhs, int rhsOffset);
将两个4x4矩阵相乘,并将结果存储在第三个4x4矩阵中。以矩阵表示法表示:结果=lhs x rhs。
参数含义:
参数 | 含义 |
---|---|
result | The float array that holds the result. 保存结果的浮点数数组。 |
resultOffset | The offset into the result array where the result is stored。结果数组中存储结果的偏移量。 |
lhs | The float array that holds the left-hand-side matrix. 保存左侧矩阵的浮点数数组。 |
lhsOffset | The offset into the lhs array where the lhs is stored 左侧数组中存储结果的偏移量。 |
rhs | The float array that holds the right-hand-side matrix. 保存右侧矩阵的浮点数数组 |
rhsOffset | The offset into the rhs array where the rhs is stored.右侧数组中存储结果的偏移量。 |
我们并不陌生了在使用投影矩阵和相机视图矩阵获取变换矩阵的时候使用过。
//计算变换矩阵
Matrix.multiplyMM(mMVPMatrix,0,mProjectMatrix,0,mViewMatrix,0);
关于数组,多维数组和偏移量的问题不在这里展开说明,他是一个数学问题,请自行搜索。
利用一个变换矩阵和向量相乘获取新向量
将一个4*4矩阵和一个四元素向量相乘获取一个新的四元素向量。
public static native void multiplyMV(float[] resultVec,int resultVecOffset,
float[] lhsMat, int lhsMatOffset,
float[] rhsVec, int rhsVecOffset);
获取转置矩阵
矩阵的转置处理:
public static void transposeM(float[] mTrans, int mTransOffset, float[] m, int mOffset)
获取逆矩阵
获取逆矩阵
public static boolean invertM(float[] mInv, int mInvOffset, float[] m, int mOffset)
正交投影和透视投影
计算正交投影矩阵
public static void orthoM(float[] m, int mOffset,
float left, float right,
float bottom, float top,
float near, float far)
计算透视投影矩阵:以六个裁剪平面定义投影矩阵。
public static void frustumM(float[] m, int offset,
float left, float right,
float bottom, float top,
float near, float far)
根据视场角度、纵横比和Z裁剪平面定义投影矩阵。
public static void perspectiveM(float[] m, int offset,
float fovy, float aspect,
float zNear, float zFar)
向量长度
计算向量长度
public static float length(float x, float y, float z)
定义单位矩阵
创建单位矩阵
public static void setIdentityM(float[] sm, int smOffset)
缩放矩阵
按x、y和z缩放矩阵m,将结果放入sm。
public static void scaleM(float[] sm, int smOffset,
float[] m, int mOffset,
float x, float y, float z)
将m矩阵自身按照x,y,z进行缩放。
public static void scaleM(float[] m, int mOffset,
float x, float y, float z)
平移矩阵
将m矩阵按照x,y,z平移得到tm矩阵
public static void translateM(float[] tm, int tmOffset,
float[] m, int mOffset,
float x, float y, float z)
将m矩阵自身按照x,y,z进行平移。
public static void translateM(
float[] m, int mOffset,
float x, float y, float z)
旋转矩阵
将矩阵m经过a,x,y,z参数处理形成一个新的rm矩阵。(a单位采用普通角度)
public static void rotateM(float[] rm, int rmOffset,
float[] m, int mOffset,
float a, float x, float y, float z)
矩阵m根据a,x,y,z参数处理变成新的矩阵。(a单位采用普通角度)
public static void rotateM(float[] m, int mOffset,
float a, float x, float y, float z)
创造一个新的矩阵rm,根据a,x,y,z参数。(a单位采用普通角度)
public static void setRotateM(float[] rm, int rmOffset,
float a, float x, float y, float z)
根据欧拉角度变换rm矩阵为新矩阵。
public static void setRotateEulerM(float[] rm, int rmOffset,
float x, float y, float z)
获取相机视图矩阵
定义相机视图
public static void setLookAtM(float[] rm, int rmOffset,
float eyeX, float eyeY, float eyeZ,
float centerX, float centerY, float centerZ,
float upX, float upY, float upZ)
我们平时的开发中都可能用到上面的方法,但是比较常用的是获取相机矩阵和投影矩阵
;同时在操作图像使其动起来时,旋转,平移
等亦经常用到,在下面文章中都会详细介绍。