iOS视觉(十三) -- 初用GLSL(三):图元颜色混合

417 阅读2分钟

一、添加目标颜色

上文主要使用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; //混合后的颜色提交给顶点着色器
}

最终效果如下: