首页 > 代码库 > 【ShaderToy】抗锯齿相关函数

【ShaderToy】抗锯齿相关函数

*示例代码可以直接在ShaderToy中运行。

 

先上未抗锯齿的两个圆形图案,可以清楚看清图案边缘像素块,即“锯齿”。


技术分享

附代码:

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 r =  2.0*vec2(fragCoord.xy - 0.5*iResolution.xy)/iResolution.y;
      vec2 center1 = vec2(-0.75,0);
    vec2 center2 = vec2(0.75,0);
    
    vec3 bgcol = vec3(1.0,0.5,0.5);//bg color
    vec3 col1 = vec3(0.4,0.6,0.6);//circle1
    vec3 col2 = vec3(0.4,0.2,0.5);//circle2
    vec3 pixel;
    
    pixel = bgcol;
    
    if(length(r-center1)<0.4)
        pixel = col1;
    
    if(length(r-center2)<0.4)
        pixel = col2;
    
    fragColor = vec4(pixel,1.0);
}

要消除锯齿,这里借助几个GLSL内置函数,下面一个一个做笔记QAQ:

①mix()函数

原型:

//x为下限,y为上限,a为权重
//mix函数返回以a为权重,(x,y)为范围的线性插值
//返回值计算公式:x ×(1?a)+y×a

float mix(float x, float y, float a) 
vec2 mix(vec2 x, vec2 y, vec2 a) 
vec3 mix(vec3 x, vec3 y, vec3 a) 
vec4 mix(vec4 x, vec4 y, vec4 a)

 

②clamp函数:

原型:

//返回值计算公式:
//      min(max(x, minVal), maxVal)
//超出下界即等于下界
//超出上界即等于上界
float clamp(float x, float minVal, float maxVal) vec2 clamp(vec2 x, vec2 minVal, vec2 maxVal) vec3 clamp(vec3 x, vec3 minVal, vec3 maxVal) vec4 clamp(vec4 x, vec4 minVal, vec4 maxVal)

 

③smoothstep函数:

原型:

//在x、y间进行Hermite插值
//等价代码:
//  genType t;  
//  t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0); 
//  return t * t * (3.0 - 2.0 * t);

float smoothstep(float edge0, float edge1, float x) vec2 smoothstep(vec2 edge0, vec2 edge1, vec2 x) vec3 smoothstep(vec3 edge0, vec3 edge1, vec3 x) vec4 smoothstep(vec4 edge0, vec4 edge1, vec4 x)

 

④step函数:

原型:

//step函数返回小于edge的值,否则返回1

float step(float edge, float x) 
vec2 step(vec2 edge, vec2 x) 
vec3 step(vec3 edge, vec3 x) 
vec4 step(vec4 edge, vec4 x)

 

下面用一个简单明了的小例子来体现mix等函数的功能:

 技术分享

 

代码如下:

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 p = fragCoord.xy / iResolution.xy;
    vec3 col1 = vec3(1.0,0.2,0.4);
    vec3 col2 = vec3(0.4,0.6,1.0);
    vec3 pixel;
    float m;
    
    //area 1
    //展示用作示例的两种颜色
    if(p.x<0.2){
        if(p.y<0.5)
            pixel = col1;
        else
            pixel = col2;
    }
//area 2 //step函数效果 else if(p.x<0.4){ m = step(0.5,p.y); pixel = mix(col1,col2,m); }
//area 3 //根据纵坐标数值线性变化效果 else if(p.x<0.6){ m = p.y; pixel = mix(col1,col2,m); } //area 4 //clamp函数效果 else if(p.x<0.8){ m = clamp(p.y,0.4,0.8);//即将线性变化区间从完整的[0,1]变成[0.4,0.8] pixel = mix(col1,col2,m); }
//area 5 //smoothstep函数效果 else{ m = smoothstep(0.45, 0.55, p.y); pixel = mix(col1,col2,m); }
//区域分界线 for(float i=0.2;i<1.0;i += 0.2){ if(p.x<i&&p.x>i-0.005) pixel = vec3(1.0); } 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);
}

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 mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 r =  2.0*vec2(fragCoord.xy - 0.5*iResolution.xy)/iResolution.y;
    vec3 bgcol = vec3(1.0,0.3,0.5);//bg color
    vec3 col1 = vec3(0.4,0.2,0.5);//circle
    vec2 center1 = vec2(-1.35,0);
    vec2 center2 = vec2(-0.45,0);
    vec2 center3 = vec2(0.45,0);
    vec2 center4 = vec2(1.35,0);
    vec3 pixel = bgcol;
    float m=0.4;
    
    pixel = bgcol; 
    
    //circle 0
    //未经任何处理
    /*
    if(r.x<-0.9){
        if(length(r-center1)<m){
            pixel = col1;
        }
    }
    */
    
    //circle 1
    //step处理,等同于未经任何处理的circle 0 
    if(r.x<-0.9){
        m =  step(m,length(r-center1));
        pixel = mix(col1,bgcol,m);
    } 
    
    //circle 2
    //linearstep处理
    else if(r.x<-0.0){
        m =  linearstep(m-0.005,m+0.005,length(r-center2));
        pixel = mix(col1,bgcol,m);
    }
    
    //circle 3
    //smoothstep处理
    else if(r.x<0.9){
           m =  smoothstep(m-0.005,m+0.005,length(r-center3));
        pixel = mix(col1,bgcol,m);
    }
    
    //circle 4
    //自定义smootherstep处理
    else if(r.x<1.8){
           m =  smootherstep(m-0.005,m+0.005,length(r-center4));
        pixel = mix(col1,bgcol,m);
    }
 
    //区域分解线
    for(float i=-0.9;i<2.0;i += 0.9){
        if(r.x<i&&r.x>i-0.005)
            pixel = vec3(1.0);
    }
    
    fragColor = vec4(pixel,1.0);
}

上图可能不太明显,在shadertoy网站运行代码全屏会更清楚点。事实是从左到右四个图的圆形锯齿越来越不明显。

这里有段代码蛮有意思的:

float t = (x - edge0)/(edge1 - edge0);
return clamp(t, 0.0, 1.0);

第一行代码的作用是判断x和edge1之间的关系,结合第二行clamp函数,如果>1说明x>edge1;如果<1则反之。

 

【over.】

【ShaderToy】抗锯齿相关函数