【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.】


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM