詳解OpenGL Shader抗鋸齒的實現(xiàn)
繪制圓形鋸齒問題
普通繪制圓形形狀時可以看到圖形邊緣會有明顯鋸齒現(xiàn)象并不像真實圓形形狀一樣圓潤邊緣平滑。在glsl中這種情況是常見情況,這里是可以借助glsl內(nèi)置函數(shù)來消除鋸齒現(xiàn)象。
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在畫圓范圍內(nèi)
}
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函數(shù)介紹
smoothstep(a, b, x)函數(shù)結(jié)果范圍:
| 返回值 | 條件 |
|---|---|
| 0 | x<a<b 或 x>a>b |
| 1 | x<b<a 或 x>b>a |
| 某個值 | 根據(jù)x在[a,b]或[b,a]區(qū)間范圍內(nèi),返回一個在[0,1]之間的值 |
內(nèi)置函數(shù)smoothstep就能實現(xiàn)繪制圓形圖形的抗鋸齒效果??赡苤坝惺褂眠^內(nèi)置函數(shù)step同樣都是步進式功能函數(shù),不同于step函數(shù)可以理解為if-else而smoothstep函數(shù)是平滑過渡的。
抗鋸齒實現(xiàn)
使用smoothstep實現(xiàn)抗鋸齒功能需要修改一下原先的畫圓公式。原來只需要使用到length(uv) - r來判斷是否選擇繪制圓的顏色,而現(xiàn)在需要修改成通過smoothstep(m-0.002,m+0.002,length(uv) - 0.2)計算值作為mix函數(shù)混合系數(shù)值來實現(xiàn)平滑過渡到畫圓色值,這樣就能實現(xiàn)抗鋸齒了。
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,運行結(jié)果可以發(fā)現(xiàn)圓形變模糊了。這就是區(qū)間過大導致平滑區(qū)間漸變范圍在肉眼可見范圍了,因此設(shè)置一個適當過渡區(qū)間才能實現(xiàn)較好的抗鋸齒效果。

擴展
清楚實現(xiàn)抗鋸齒原理之后,可以根據(jù)需要自行實現(xiàn)一個平滑過渡函數(shù)來實現(xiàn)抗鋸齒功能。類似像以下兩個自制平滑過渡函數(shù)最終實現(xiàn)效果幾乎看不出太大區(qū)別。
自制smoothstep函數(shù)抗鋸齒
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函數(shù)抗鋸齒
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

以上就是詳解OpenGL Shader抗鋸齒的實現(xiàn)的詳細內(nèi)容,更多關(guān)于OpenGL Shader抗鋸齒的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android DataBinding單向數(shù)據(jù)綁定深入探究
看了谷歌官方文章確實寫的太簡略了,甚至看完之后有很多地方還不知道怎么回事兒或者怎么用,那么接下來我將通過文章全面介紹一下DataBinding單向數(shù)據(jù)綁定2022-11-11
Android實現(xiàn)讀取SD卡下所有TXT文件名并用listView顯示出來的方法
這篇文章主要介紹了Android實現(xiàn)讀取SD卡下所有TXT文件名并用listView顯示出來的方法,涉及Android針對SD卡的讀取及文件遍歷等相關(guān)操作技巧,需要的朋友可以參考下2017-06-06
android使用surfaceview+MediaPlayer播放視頻
這篇文章主要為大家詳細介紹了android使用surfaceview+MediaPlayer播放視頻,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-11-11

