OpenGL二维图像绘制流程说明
Vertex Shader
Shader Program
必须包含Vertex Shader
和Fragment Shader
, 其中Vertex Shader
负责告诉GPU图像顶点的位置,Fragment Shader
负责告诉GPU某个位置的颜色值Vertex Shader
// attribute 仅能在Vertex Shader中使用变量, 在Shader Program运行期间不断变化, 一般用于定点坐标、纹理坐标、顶点颜色
attribute vec4 position;
attribute vec4 inputTextureCoordinate;
// uniform声明Vertex Shader和Fragment Shader中使用的常量, 在Shader 中不能修改, 但外部可通过`glUniformXX`函数给`uniform`的常量赋值.
uniform mat4 mvpMatrix;
// varying 用于修饰Vertex Shader传递数据到Fragment Shader的变量的关键字, 一旦有(Vertex/Fragment)Shader使用了varying变量, 另一方(Vertex/Fragment)Shader也必须声明同样类型和命名的变量。在Shader外不能直接修改varying变量
varying vec2 textureCoordinate;
void main() {
// `gl_Position`是Vertex Shader的内置输出变量, 表示当前Vertex Shader处理的顶点坐标最终映射的位置, 并赋给`gl_Position`
gl_Position = mvpMatrix * position;
// 将外部输入的纹理坐标`inputTextureCoordinate.xy`赋值给`textureCoordinate`, 即传递给Fragment Shader
textureCoordinate = inputTextureCoordinate.xy;
}
// 变量类型
`vecN`表示N(2<=N<=4)个浮点数类型分量的向量(vector), `vecN`的读取和构造方式灵活, 可按需通过`x`, `y`, `x`, `w`; `r`、`g`、`b`、`a`或者`s`、`t`、`p`、`q`来读取
vec3 v3 = vec3(1.0, 2.0, 3.0);
// 读取第二分量值
float y = v3.y; // 2.0
float g = v3.g; // 2.0
// 将xyz值赋给vec3变量
vec4 v4 = vec4(v3.xyz, 4.0);
float q = v4.q;// 4.0
Fragment Shader
// 定义Fragment Shader使用的浮点数的精度为中等精度, 可以使用低精度`lowp`和高精度`highp`。高精度不是所有设备支持。Fragment Shader必须声明浮点数精度, 否则在mali GPU上运行失败(如美图手机)
precision mediump float;
varying highp vec2 textureCoordinate;
// `sample2D`表示2D的texture类型
uniform sample2D inputTextureCoordinate;
void main() {
// 表示从纹理`inputTextureCoordinate`中获取坐标为`textureCoordinate`的像素值
vec4 color = texture2D(inputTextureCoordinate, textureCoordinate);
// `gl_FragColor`是Fragment Shader的内置输出变量, 表示Vertex Shader处理的顶点坐标的位置对应的色值
// 注意这里丢失了`inputImageTexture`的alpha通道, 原因是如果纹理的RGB和alpha混合后, 离屏渲染再混合可能出现泛白问题
gl_FragColor = vec4(color.rgb, 1.0);
}
Shader Program
// 1. 定义句柄
// Shader Program句柄
private int mProgramHandle;
// 水印纹理ID
private int mTextureId;
// 顶点坐标数组
private FloatBuffer mVertexBuffer;
...
// 2. 定义好句柄, 给句柄赋值
public GLProgram(String vertexShader, String fragmentShader) {
mProgramHandle = OpenGLUtils.loadProgram(vertexShader, fragmentShader);
...
}
// 3. bitmap转纹理
public void loadTexture(Bitmap bitmap) {
mTextureId = OpenGLUtils.loadTexture(bitmap, mTextureId, true);
}
// 4. 定点坐标
// 5. gl准备工作
// 6. 绘制