<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Shader基礎(chǔ)技巧整理

          共 3686字,需瀏覽 8分鐘

           ·

          2021-10-28 11:47

          自從接觸了shader之后我便深深得愛上了它,因?yàn)樗?dú)特的編程思考方式?jīng)_擊著我這十幾年的慣性認(rèn)知。
          在向各位大佬學(xué)習(xí)的過程中,每學(xué)到一個(gè)新的技巧,我都不禁感嘆:“實(shí)在是妙!”

          本文將整理一些個(gè)人常用的shader技巧/方法,只包含片元著色器相關(guān)內(nèi)容。
          由于本人尚屬初學(xué),所以內(nèi)容會比較基礎(chǔ)。

          簡單幾何圖形

          區(qū)間(帶通)


          兩個(gè)階梯函數(shù)疊加構(gòu)成的帶通函數(shù),用數(shù)字信號處理的角度去思考貌似是個(gè)不錯(cuò)的選擇

          float Band(float v, float start, float end) {    float up = step(start, v);    float down = 1.0 - step(end, v);    return up * down;}

          矩形


          x, y兩個(gè)方向的帶通函數(shù)疊加

          float Rect(vec2 uv, float l, float b, float r, float t) {    float x = Band(uv.x, l, r);    float y = Band(uv.y, b, t);    return x * y;}

          圓形


          圓形比較容易出現(xiàn)鋸齒,所以用?smoothstep?做平滑處理。
          由于?distance()?依賴?sqrt()?開根號,在一些老硬件上會比較耗時(shí),實(shí)際使用時(shí)可以考慮轉(zhuǎn)換為和r平方進(jìn)行比較的公式。

          float Circle(vec2 uv, vec2 o, float r, float blur) {    return smoothstep(r, r-blur, distance(uv, o));}

          混合疊加

          上述幾何圖形函數(shù)的輸出值是0或1的float(經(jīng)過?smoothstep()?可能會出現(xiàn)中間值,不過此處可以不考慮)。
          0或1的float值可以利用加、減、乘來模擬位運(yùn)算。比如上述區(qū)間、矩形幾何圖形都是通過乘法疊加。

          加減法例子:ET臉


          畫一個(gè)大圓當(dāng)臉,減去兩個(gè)小圓當(dāng)眼睛

          float ETFace(vec2 uv, vec2 o) {    float c = Circle(uv, vec2(.0, .0), 0.5, 0.01);    c -= Circle(uv, vec2(-.2, -.2), 0.2, 0.01);    c -= Circle(uv, vec2(.2, -.2), 0.2, 0.01);    return c;}

          坐標(biāo)空間處理

          Cocos Creator以?左上角?為坐標(biāo)原點(diǎn),范圍(0, 1)。
          shadertoy, GlslEditor中均以?左下角?為坐標(biāo)原點(diǎn),范圍(0, 1),接下來所有代碼將使用這個(gè)坐標(biāo)系。

          在繪制某些對稱圖形時(shí)可能需要將原點(diǎn)調(diào)整到屏幕中心,即將(0, 1)區(qū)間映射到(-0.5, 0.5)。
          根據(jù)不同場景也可以將(0, 1)區(qū)間映射到(-1, 1),哪個(gè)處理起來方便用哪個(gè)。

          // (0, 1)區(qū)間映射到(-1, 1)uv = uv * 2.0 - 1.0;

          也可以用下面的方法從任意區(qū)間映射到任意區(qū)間

          float Remap01(float a, float b, float t) {    return (t-a) / (b-a);}
          float Remap(float a, float b, float c, float d, float t) { return Remap01(a, b, t) * (d-c) + c;}

          長寬適配

          不知道這個(gè)功能的簡稱是什么,暫且這么稱呼吧。
          其作用是在分辨率長寬不等的情況下將坐標(biāo)空間映射為等邊,映射后原先較長的一邊其自變量區(qū)間會被放大

          void main() {    vec2 uv = gl_FragCoord.xy/u_resolution.xy;    uv = uv * 2.0 - 1.0;            // 位移到以中間為原點(diǎn)    uv.x *= u_resolution.x/u_resolution.y;    // 將x的自變量區(qū)間拉長        float mask = Rect(uv, -0.5, -0.5, 0.5, 0.5);    vec3 color = vec3(mask);    gl_FragColor = vec4(color,1.0);}

          計(jì)算角度


          atan()?計(jì)算角度,圖中將(-PI, PI)區(qū)間映射到(0, 1)區(qū)間,并且將值對應(yīng)的灰度輸出。
          atan()?計(jì)算比較耗時(shí),實(shí)際項(xiàng)目中慎用。

          #define PI 3.141592653589793
          void main() { vec2 uv = gl_FragCoord.xy/u_resolution.xy; uv = uv * 2.0 - 1.0; uv.x *= u_resolution.x/u_resolution.y; float angle = atan(uv.y, uv.x); angle = Remap(-PI, PI, 0., 1.0, angle); vec3 color = vec3(angle); gl_FragColor = vec4(color,1.0);}

          旋轉(zhuǎn)


          uv乘以旋轉(zhuǎn)矩陣

          #define PI 3.141592653589793
          mat2 Rotate2d(float angle){ return mat2(cos(angle), -sin(angle), sin(angle), cos(angle));}
          void main() { vec2 uv = gl_FragCoord.xy/u_resolution.xy; uv = uv * 2.0 - 1.0; uv.x *= u_resolution.x/u_resolution.y; uv = Rotate2d(PI / 6.) * uv; float mask = Rect(uv, -0.5, -0.5, 0.5, 0.5); vec3 color = vec3(mask); gl_FragColor = vec4(color,1.0);}

          網(wǎng)格化


          將屏幕分割成5x5個(gè)網(wǎng)格,每個(gè)格子里畫一個(gè)圓。
          原理是將uv拉伸5倍后取小數(shù)部分,這樣處理后uv會變成每個(gè)網(wǎng)格內(nèi)的局部坐標(biāo),這個(gè)技巧被廣泛使用。

          void main() {    // ...    uv = fract(uv * 5.);    float mask = Circle(uv, vec2(0.5), 0.5, 0.01);    // ...}

          噪音(隨機(jī)化hash)


          獲取噪音的方法很多很靈活,輸入一般是和uv相關(guān)的變量,輸出(0, 1)范圍的1維或2維值。
          只要讓人肉眼難分辨出模式,就是一個(gè)好用的噪音函數(shù)。
          噪音的用途非常廣泛,可以利用噪音降低圖片的人工痕跡,后面會單獨(dú)整理一篇文章。

          float Noise1(vec2 p) {    return fract(sin(        dot(p, vec2(12.9898,78.233))    ) * 43758.5453123);}
          float Noise2(vec2 p) { p = frac(p * vec2(123.34, 345.45)); p += dot(p, p + 34.345); return frac(p.x * p.y);}


          常用鏈接

          • shadertoy
            可以找到很多大神級shader作品
            http://shadertoy.com/

          • The Art Of Code頻道
            邊做邊講解,帶你領(lǐng)略01之間的藝術(shù)
            https://www.youtube.com/c/TheArtofCodeIsCool/videos


          • 《The Book Of Shaders》
            很棒的入門書籍,可惜還沒更新完
            https://thebookofshaders.com/


          • 我的博客
            將《The Book Of Shaders》里的GlslEditor嵌入博客用于平時(shí)練習(xí)
            https://caogtaa.github.io/shader/2020/07/16/shader-playground/



          技術(shù)交流,歡迎加我微信:ezglumes ,拉你入技術(shù)交流群。

          推薦閱讀:

          音視頻開發(fā)工作經(jīng)驗(yàn)分享 || 視頻版

          OpenGL ES 學(xué)習(xí)資源分享

          開通專輯 | 細(xì)數(shù)那些年寫過的技術(shù)文章專輯

          NDK 學(xué)習(xí)進(jìn)階免費(fèi)視頻來了

          你想要的音視頻開發(fā)資料庫來了

          推薦幾個(gè)堪稱教科書級別的 Android 音視頻入門項(xiàng)目

          覺得不錯(cuò),點(diǎn)個(gè)在看唄~


          瀏覽 38
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日韩三级片在线视频 | 欧美操女人| www夜插内射视频网站 | 爱啪啪网 | 天堂在线视频精品 |