详解OpenGL Shader抗锯齿的实现

作者:JulyYu 时间:2021-09-24 21:54:07 

绘制圆形锯齿问题

普通绘制圆形形状时可以看到图形边缘会有明显锯齿现象并不像真实圆形形状一样圆润边缘平滑。在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);
}

详解OpenGL Shader抗锯齿的实现

smoothstep函数介绍

smoothstep(a, b, x)函数结果范围:

返回值条件
0x<a<b 或 x>a>b
1x<b<a 或 x>b>a
某个值根据x在[a,b]或[b,a]区间范围内,返回一个在[0,1]之间的值

内置函数smoothstep就能实现绘制圆形图形的抗锯齿效果。可能之前有使用过内置函数step同样都是步进式功能函数,不同于step函数可以理解为if-elsesmoothstep函数是平滑过渡的。

抗锯齿实现

使用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);

详解OpenGL Shader抗锯齿的实现

如果把脚本其中m-0.002,m+0.0020.002范围进行修改。例如修改成0.02,运行结果可以发现圆形变模糊了。这就是区间过大导致平滑区间渐变范围在肉眼可见范围了,因此设置一个适当过渡区间才能实现较好的抗锯齿效果。

详解OpenGL Shader抗锯齿的实现

扩展

清楚实现抗锯齿原理之后,可以根据需要自行实现一个平滑过渡函数来实现抗锯齿功能。类似像以下两个自制平滑过渡函数最终实现效果几乎看不出太大区别。

自制smoothstep函数抗锯齿

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);
}

自制linearstep函数抗锯齿

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

详解OpenGL Shader抗锯齿的实现

linearstep

详解OpenGL Shader抗锯齿的实现

来源:https://juejin.cn/post/7060050476238110750

标签:OpenGL,Shader,抗锯齿
0
投稿

猜你喜欢

  • struts2实现文件上传显示进度条效果

    2021-11-19 16:16:21
  • Java Iterator迭代器_动力节点Java学院整理

    2022-11-08 13:50:39
  • Java jar打包工具使用方法步骤解析

    2023-07-01 12:26:47
  • C#获取计算机硬件与操作系统的相关信息

    2022-12-12 07:11:36
  • c#正反序列化XML文件示例(xml序列化)

    2023-01-06 02:49:57
  • Java Date时间类型的操作实现

    2023-11-25 06:44:31
  • 如何在Java SpringBoot项目中配置动态数据源你知道吗

    2021-07-23 11:10:08
  • CentOS 7系统下配置自定义JDK的教程

    2022-02-27 13:46:26
  • Java编程实现基于用户的协同过滤推荐算法代码示例

    2022-09-06 12:44:24
  • Android开机画面的具体修改方法

    2023-05-13 20:52:22
  • C#异步执行任务的方法

    2022-02-27 15:02:41
  • C# Winform 分页功能的实现

    2023-03-29 06:07:10
  • Android中new Notification创建实例的最佳方法

    2022-03-19 15:52:25
  • 使用java + selenium + OpenCV破解腾讯防水墙滑动验证码功能

    2023-07-23 14:32:47
  • SpringBoot中实现分布式的Session共享的详细教程

    2023-08-23 18:23:43
  • 2022编程语言需求排名出炉:第一不是Python,也不是Java

    2023-10-11 19:09:17
  • java之路径分隔符介绍

    2022-12-14 22:35:23
  • Android开发实现拨打电话与发送信息的方法分析

    2023-06-19 07:09:13
  • c#同步两个子目录文件示例分享 两个文件夹同步

    2022-01-25 05:03:03
  • 如何在MyBatis中实现DataSource

    2021-11-29 13:49:48
  • asp之家 软件编程 m.aspxhome.com