时间:2023-03-14 14:14:02 | 栏目:Android代码 | 点击:次
普通绘制圆形形状时可以看到图形边缘会有明显锯齿现象并不像真实圆形形状一样圆润边缘平滑。在glsl
中这种情况是常见情况,这里是可以借助glsl
内置函数来消除锯齿现象。
vec3 sdfCircle(vec2 uv,float r,vec3 value){ float d = length(uv) - r; return d > 0. ? vec3(0.3294, 0.3294, 0.9333) : value; // 大于0超出画圆范围,小于0在画圆范围内 } void main() { vec2 uv = gl_FragCoord.xy / iResolution.xy; uv -= 0.5; // x: <-0.5, 0.5>, y: <-0.5, 0.5> uv.x *= iResolution.x/iResolution.y; // x: <-0.5, 0.5> * aspect ratio, y: <-0.5, 0.5> vec3 circle = sdfCircle(uv,0.4,vec3(1.)); circle = mix(circle,sdfCircle(uv,0.3,vec3(1.)),0.5); circle = mix(circle,sdfCircle(uv,0.2,vec3(1.)),0.7); gl_FragColor = vec4(circle,.9); }
smoothstep(a, b, x)
函数结果范围:
返回值 | 条件 |
---|---|
0 | x<a<b 或 x>a>b |
1 | x<b<a 或 x>b>a |
某个值 | 根据x在[a,b]或[b,a]区间范围内,返回一个在[0,1]之间的值 |
内置函数smoothstep
就能实现绘制圆形图形的抗锯齿效果。可能之前有使用过内置函数step
同样都是步进式
功能函数,不同于step
函数可以理解为if-else
而smoothstep
函数是平滑过渡的。
使用smoothstep
实现抗锯齿功能需要修改一下原先的画圆公式。原来只需要使用到length(uv) - r
来判断是否选择绘制圆的颜色,而现在需要修改成通过smoothstep(m-0.002,m+0.002,length(uv) - 0.2)
计算值作为mix
函数混合系数值来实现平滑过渡到画圆色值,这样就能实现抗锯齿了。
vec2 uv = gl_FragCoord.xy / iResolution.xy; uv -= 0.5; // x: <-0.5, 0.5>, y: <-0.5, 0.5> uv.x *= iResolution.x/iResolution.y; // x: <-0.5, 0.5> * aspect ratio, y: <-0.5, 0.5> float m = 0.2; m = smoothstep(m-0.002,m+0.002,length(uv) - 0.2); vec3 pixel = mix(vec3(1.),vec3(0.3294, 0.3294, 0.9333),m); gl_FragColor = vec4(pixel,1.0);
如果把脚本其中m-0.002,m+0.002
把0.002
范围进行修改。例如修改成0.02
,运行结果可以发现圆形变模糊了。这就是区间过大导致平滑区间渐变范围在肉眼可见范围了,因此设置一个适当过渡区间才能实现较好的抗锯齿效果。
清楚实现抗锯齿原理之后,可以根据需要自行实现一个平滑过渡函数来实现抗锯齿功能。类似像以下两个自制平滑过渡函数最终实现效果几乎看不出太大区别。
float smootherstep(float edge0, float edge1, float x) { float t = (x - edge0)/(edge1 - edge0); float t1 = t*t*t*(t*(t*6. - 15.) + 10.); return clamp(t1, 0.0, 1.0); } void main() { vec2 uv = gl_FragCoord.xy / iResolution.xy; uv -= 0.5; // x: <-0.5, 0.5>, y: <-0.5, 0.5> uv.x *= iResolution.x/iResolution.y; // x: <-0.5, 0.5> * aspect ratio, y: <-0.5, 0.5> float m = 0.2; m = smootherstep(m-0.002,m+0.002,length(uv) - 0.2); vec3 pixel = mix(vec3(1.),vec3(0.3294, 0.3294, 0.9333),m); gl_FragColor = vec4(pixel,1.0); }
float linearstep(float edge0, float edge1, float x) { float t = (x - edge0)/(edge1 - edge0); return clamp(t, 0.0, 1.0); } void main(){ vec2 uv = gl_FragCoord.xy / iResolution.xy; uv -= 0.5; // x: <-0.5, 0.5>, y: <-0.5, 0.5> uv.x *= iResolution.x/iResolution.y; // x: <-0.5, 0.5> * aspect ratio, y: <-0.5, 0.5> float m = 0.2; m = linearstep(m-0.002,m+0.002,length(uv) - 0.2); vec3 pixel = mix(vec3(1.),vec3(0.3294, 0.3294, 0.9333),m); gl_FragColor = vec4(pixel,1.0); }
smoothstep
linearstep