在OpenGL ES中绘制一张图片需要使用到纹理(texture),绘制纹理步骤如下:


编写shader


绘制纹理的shader需要顶点数据、纹理顶点数据和纹理。Vertex Shader代码如下:

  • a_Position:顶点数据。

  • a_TexCoordinate:纹理顶点数据。

  • v_TexCoord:varying类型,v_TexCoord是a_TexCoordinate的值,传递给Fragment Shader使用。


Fragment Shader代码如下:

  • u_Texture:纹理,其类型是sampler2D。

  • v_TexCoord:Vertex Shader传递过来的纹理顶点数据,texture2D是OpenGL ES内置函数,称之为采样器,获取纹理上指定位置的颜色值。


创建program并获取参数句柄


创建program的过程在《OpenGL ES for Android 环境搭建》中详细介绍,这里不在介绍,直接使用封装好的工具类,代码如下:

bitmap_vs.glsl和bitmap_fs.glsl是assets/glsl目录下文件,分别代表顶点shader和纹理shader。


AssetsUtils.readAssetsTxt为工具类,读取asset文件下的文件返回String类型,代码如下:


program的创建要在GLThread线程(所有的OpenGL ES的相关操作都要在GLThread线程中运行),在Renderer的onSurfaceCreated回调中创建,代码如下:


program创建完成后获取顶点数据(a_Position)、纹理顶点数据(a_TexCoordinate)、纹理(u_Texture)的句柄,代码如下:

a_Poition、a_TexCoordinate、u_Texture对应Shader中的名称,mProgramHandle为program的句柄。


定义顶点数据


创建全屏的顶点数据代码如下:


这里有4个点,每个点包含3个float数据,代表x,y,z。4个顶点的位置如下图:

OpenGL ES 绘制纹理-LMLPHP

OpenGL ES中绘制任何形状都是通过绘制多个三角形而组成,所以我们将这4个点分为2个三角形,分布为(V1,V2,V3)和(V1,V3,V4),因此定义三角形索引数组代码如下:

将索引数组转为buffer,我们也将此方法封装在工具类里面,代码如下:

调用方式代码如下:


定义纹理顶点


纹理坐标系统如下图:

OpenGL ES 绘制纹理-LMLPHP

纹理坐标的原点是左上角,右下角是(1,1),将整张图片绘制的纹理顶点数据代码如下:

纹理坐标的顶点顺序不是随便定义的,要与定义的顶点数据一一对应,否则可能出现纹理错乱,对应顺序如下图:

OpenGL ES 绘制纹理-LMLPHP

如果将纹理顶点设置如下:


纹理将逆时针旋转90度,通过此方法可以旋转、镜像纹理,但我们一般不会使用此方法旋转、镜像纹理,可以通过OpenGL ES中著名的MVP矩阵进行此操作。


加载纹理


纹理的的来源是一张图片,将图片转为Bitmap,代码如下:


创建2D纹理id,代码如下(此方法将封装在工具类中):

  • GLES20.glGenTextures(count,array,offset):生成纹理,参数说明如下:

  • GLES20.glGenTextures():生成1个纹理,textures[0]存放纹理id。


  • GLES20.glTexParameteri:纹理映射方式。


纹理创建成功后返回纹理id,将Bitmap传递给此纹理,代码如下:

GLUtils是系统工具类,并不是我们自己写的工具类。


制纹理


  • GLES20.glUseProgram():启用当前program,mProgramHandle是启用program的句柄。


  • 设置纹理,代码如下:

  • GLES20.glActiveTexture:激活纹理,GLES20.GL_TEXTURE0表示激活0号纹理,也可以是GLES20.GL_TEXTURE1、GLES20.GL_TEXTURE2等。

  • GLES20.glBindTexture:将纹理绑定到GL_TEXTURE_2D类型。

  • GLES20.glUniform1i(textureLoc, 0):设置纹理,textureLoc是Fragment Shader中纹理句柄,后面的参数0和GLES20.GL_TEXTURE0是对应的,如果启用GLES20.GL_TEXTURE1,那么使用GLES20.glUniform1i(textureLoc, 1)。


  • GLES20.glDrawElements是真正的绘制,函数结构如下:

参数说明如下:

  • mode:绘制方式,GLES20.GL_TRIANGLES表示绘制三角形。

  • count:顶点的个数

  • type:索引(indices)数组中的元素类型,注意不是顶点的类型,值必须是GL_UNSIGNED_BYTE或者GL_UNSIGNED_SHORT。

  • indices:索引数组


到此绘制纹理就完成了。



更多相关阅读:



本文分享自微信公众号 - 老孟Flutter(lao_meng_qd)。
如有侵权,请联系 [email protected] 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

09-04 03:55