一、添加目标颜色
上文主要使用GLSL在一个图元上进行了纹理的填充,这里进一步为图元添加一个纹理混合。
纹理混合有一个必要的条件,也就是源颜色必须透明的,否则就会直接将目标颜色给覆盖掉。所以我们先为图元本身添加一个颜色,再将纹理色的透明度进行调节后进行混合。
首先先为顶点数据中添加顶点颜色:
//顶点数据
GLfloat attrArr[] =
{
//顶点 顶点颜色 纹理坐标
-0.5f, 0.5f, 0.0f, 1,0,0, 0.0f, 1.0f,//左上0
0.5f, 0.5f, 0.0f, 0,1,0, 1.0f, 1.0f,//右上1
-0.5f, -0.5f, 0.0f, 0,0,1, 0.0f, 0.0f,//左下2
0.5f, -0.5f, 0.0f, 1,0,1, 1.0f, 1.0f,//右下3
0.0f, 0.0f, 1.0f, 0,1,1, 1.0f, 0.0f//顶点4
};
再在顶点着色器中需要额外添加一个attribute进行接收顶点颜色,并添加一个varying将顶点颜色传递给片元着色器:
attribute vec4 position;//顶点坐标
attribute vec4 positionColor;//顶点颜色
attribute vec2 textCoordinate;//纹理坐标
varying lowp vec2 varyTextCoord;//纹理坐标传递给片元
varying lowp vec4 varyColor;//顶点颜色传递给片元
uniform mat4 projectionMatrix;//投影矩阵
uniform mat4 modelViewMatrix;//视图模型矩阵
void main()
{
varyTextCoord = textCoordinate;
varyColor = positionColor;
gl_Position = projectionMatrix * modelViewMatrix * position;//m v p
}
接下来就需要在绘制中打开顶点颜色通道:
- (void)renderLayer {
//...省略
//顶点颜色通道
GLuint pisitionColor = glGetAttribLocation(self.myPrograme, "positionColor");
glEnableVertexAttribArray(pisitionColor);
glVertexAttribPointer(pisitionColor, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 8, (GLfloat *)NULL+3);
//...省略
}
注意由于顶点数据中新增了顶点颜色,所以此处的步长应调整为8不再是6, 并且顶点数据通道以及纹理数据通道的步长都需要调整为8.
二、开始颜色混合
接下里就需要对源颜色也就是纹理颜色进行一个透明处理:
precision highp float;
varying lowp vec2 varyTextCoord;//传递过来的纹理坐标
varying lowp vec4 varyColor;//传递过来的顶点颜色
uniform sampler2D colorMap;//纹理数据
void main()
{
vec4 weakMask = texture2D(colorMap, varyTextCoord);//纹理坐标对应纹理数据(纹素)
vec4 mask = varyColor;//顶点颜色
float alpha = 0.3;//透明度
vec4 tempColor = mask * (1.0 - alpha) + weakMask * alpha;//根据公式:Cf = (Cs * S) + (Cd * D) 进行性颜色混合计算
gl_FragColor = tempColor; //混合后的颜色提交给顶点着色器
}
最终效果如下: