CocosCreator-Shader-Effect-.../assets/effects/sprite-round-corner-crop-v1.effect

146 lines
4.2 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
//
// 圆角裁剪(仅支持正方形纹理)
//
// 原理https://www.cnblogs.com/jqm304775992/p/4987793.html
// 代码:复制 yanjifa/shaderDemor 的 https://github.com/yanjifa/shaderDemo/blob/master/assets/Effect/CircleAvatar.effect
CCEffect %{
techniques:
- passes:
- vert: vs
frag: fs
blendState:
targets:
- blend: true
rasterizerState:
cullMode: none
properties:
texture: { value: white }
alphaThreshold: { value: 0.5 }
# 圆角半径
radius: {
value: 0.4,
editor: {
tooltip: "圆角半径"
}
}
}%
CCProgram vs %{
precision highp float;
#include <cc-global>
#include <cc-local>
in vec3 a_position;
in vec4 a_color;
out vec4 v_color;
#if USE_TEXTURE
in vec2 a_uv0;
out vec2 v_uv0;
#endif
void main () {
vec4 pos = vec4(a_position, 1);
#if CC_USE_MODEL
pos = cc_matViewProj * cc_matWorld * pos;
#else
pos = cc_matViewProj * pos;
#endif
#if USE_TEXTURE
v_uv0 = a_uv0;
#endif
v_color = a_color;
gl_Position = pos;
}
}%
CCProgram fs %{
precision highp float;
#include <alpha-test>
in vec4 v_color;
#if USE_TEXTURE
in vec2 v_uv0;
uniform sampler2D texture;
#endif
#if ENABLE_ROUNDCORNER
uniform RoundCorner {
// 圆角半径
float radius;
};
#endif
void main () {
vec4 o = vec4(1, 1, 1, 1);
#if USE_TEXTURE
o *= texture(texture, v_uv0);
#if CC_USE_ALPHA_ATLAS_TEXTURE
o.a *= texture2D(texture, v_uv0 + vec2(0, 0.5)).r;
#endif
#endif
o *= v_color;
ALPHA_TEST(o);
#if ENABLE_ROUNDCORNER
// 约束圆角半径范围在 [0.0, 0.5]
float circleRadius = clamp(0.0, 0.5, radius);
// 将纹理uv往左上偏移实现偏移后的坐标系原点在纹理中心
vec2 uv = v_uv0.xy - vec2(0.5, 0.5);
// uv.x , uv.y : 为偏移后的的uv
// abs(uv.x) , abs(uv.y) : 将第二、三、四象限的点都投影到第一象限上,这样子只需要处理第一象限的情况就可以,简化判断
// 0.5 - radius : 计算出第一象限的圆角所在圆的圆心坐标
// (rx, ry) : 偏移映射后的 新的uv 坐标,相对于 第一象限圆角坐在圆心坐标 的相对坐标
float rx = abs(uv.x) - (0.5 - circleRadius);
float ry = abs(uv.y) - (0.5 - circleRadius);
// 区分 以第一象限圆角所在圆心坐标为原点的坐标的四个象限
//
// 第一象限 mx = 1, my = 1
// 第二象限 mx = 0, my = 1
// 第三象限 mx = 0, my = 0
// 第四象限 mx = 1, my = 0
//
// 当 mx * my 时只要等于1那就是标识第一象限实际对应圆角区域所在矩形否则就是第二、三、四象限
float mx = step(0.5 - circleRadius, abs(uv.x));
float my = step(0.5 - circleRadius, abs(uv.y));
// 计算相对uv坐标到圆心的距离
float len = length(vec2(rx, ry));
// mx * my = 0 时代表非圆角区域a 值为1代表完全采用原始纹理的透明度
// mx * my = 1 时,代表园所所在矩形区域
// step(circleRadius, len) 可以区分出圆角所在矩形区域的 圆角区域 和 非圆角区域
// 其中圆角区域值为0非圆角区域值为1
// 当为圆角区域时a 值为1代表完全采用原始纹理透明度
// 当为非圆角区域时a 值为0代表完全透明
// 至此已经实现圆角裁剪
//
// smoothstep(0., circleRadius * 0.01, len - circleRadius) 是用于抗锯齿优化
// 原理:针对点在非圆角区域的情况,针对点在大于「圆半径一点点」地方的区域,进行平滑过渡,以实现抗锯齿
// 其中,
// 「圆半径一点点」用 circleRadius * 0.01 表示0.01 可自行改变)
// 点在大于圆半径的区域用 len - circleRadius ,此值会在 [0.0, circleRadius * 0.01] 之间时会平滑过渡
float a = 1.0 - mx * my * step(circleRadius, len) * smoothstep(0., circleRadius * 0.01, len - circleRadius);
o = vec4(o.rgb, o.a * a);
#endif
gl_FragColor = o;
}
}%