圆形头像(shader)

效果演示

圆形头像在creator中没有提供,但是这个又是个比较高频的使用功能。

实现思路

可以使用一张圆的图片,然后配合mask的反向遮罩来实现,但是这种实现的效果会有锯齿,所以一般会写一个shader。异名上篇文章中追光效果中那个shader刚好直接就可以使用了,这系列的定位是常用功能集锦,圆形头像又是高频应用,因此异名就再单独拿出来再水一篇,方面后面查看使用。

光圈是一个圆,假设圆心在纹理的中间,它的坐标是vec2(0.5,0.5),我们只需让到圆心的距离大于半径的像素丢弃或者透明度为0,代码如下:

void main () {
  vec4 color = vec4(1, 1, 1, 1);
  color *= texture(texture, v_uv0);
  color *= v_color;

  color.a = step(length(v_uv0 - vec2(0.5,0.5)), 0.1);
  gl_FragColor = color;
}

其中step 是内置的规整函数 step(a, x) = x >= a? 1 : 0length是取模。上面的代码段应用在可以在正方形的纹理中可以得出一个正圆,但是如果纹理不是正方形,上面出来的效果会是一个椭圆,因为在shader无论纹理的真实宽高是多少,它的x,y变化范围都是0~1,是比例的变化。如果需要产生一个正圆,还是得通过获取纹理的真实宽高,来计算真实的宽高比例,异名选择的方式是在在组件初始化的时候,输入一个wh_ratio比例来获取,圆的真实半径通过勾股定理来计算,异名这里就没有开方了,直接通过半径平方的比较来舍去圆外的点。

void main () {
  vec4 o = vec4(1, 1, 1, 1);
  o *= texture(texture, v_uv0);
  o *= v_color;

  float circle = radius * radius;
  float rx = center.x * wh_ratio;
  float ry = center.y;
  float dis = (v_uv0.x * wh_ratio - rx) * (v_uv0.x * wh_ratio - rx) + (v_uv0.y  - ry) * (v_uv0.y - ry);

  o.a = step(dis, 0.1);
  gl_FragColor = o;
}

这样子就能在一个不同宽高比的纹理中都能够画出一个正圆。

但是这样的圆的边缘是有锯齿的,所以我们需要借助另外一个内置插值函数smoothstep(min, max, x),它能够返回一个在输入值之间平稳变化的插值,以此来达到边缘羽化的效果。

void main () {
  vec4 o = vec4(1, 1, 1, 1);
  o *= texture(texture, v_uv0);
  o *= v_color;

  float circle = radius * radius;
  float rx = center.x * wh_ratio;
  float ry = center.y;
  float dis = (v_uv0.x * wh_ratio - rx) * (v_uv0.x * wh_ratio - rx) + (v_uv0.y  - ry) * (v_uv0.y - ry);

  o.a = smoothstep(circle, circle - blur, dis);
  gl_FragColor = o;
}

效果预览

源码获取请点击查看原文,长按二维码查看效果:point_down:

ewm

我是异名,你的阅读是我的动力,其他文章链接:

源码地址https://github.com/ifengzp/cocos-awesome/

3赞

请问 为何当shader的图片资源比较小的时候,运行的就是 就不会显示?

编辑器正常? 预览效果就不正常的话,是自动合图后,改变了图片的UV坐标,可以把图片的自动合批去掉
如果不是这样的话,检查下 shader里的方法吧

编辑器上显示是正常的,运行的时候就无法看见,大图是可以正常显示的(编辑器和运行),小图(100x100)运行的时候啥也看不见。

那就是自动合批了~
可以把这个去掉

或者自己在代码里做uv坐标的转换

确实是这个问题 谢谢!

很不错 mark

请问大佬,如果自己在代码里面做uv坐标的转换,具体是怎么做呢?

#mark

把合批后的uv传到shader中计算就好,spriteframe.uv[0~7]

前几天论坛里有人问了,我回复了下,你搜下,那个帖子还在呢

战略性mark

为什么远程加载图片后会错误呢?

我也是用本地图就没问题,加载网络图就显示异常,救命 :sob:

是这个问题 看了好久