<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 繪制一只可愛的 “小撓斧” 【GLSL】

          共 13900字,需瀏覽 28分鐘

           ·

          2023-10-12 12:44

          完整效果圖

           

          設(shè)計(jì)思路

          我設(shè)計(jì)的這只 “小撓斧” 的造型十分簡單,只用到了三種基本圖形

          • 圓形

          • (圓頭)弧線

          • (圓頭)直線

          那么在 shader 當(dāng)中我們?cè)撊绾卫L制這三種基本圖形呢?答案是通過 SDF !【想進(jìn)一步了解的同學(xué)可以搜索我的相關(guān)專欄文章 ShaderJoy

          限于篇幅,我這里就直接列出了本文所用到的三種 SDF 的函數(shù)

          • sdCircle

          • udSegment

          • sdArc

          sdCircle 的使用

          sdCircle 具體代碼分別如下所示

          /// @note 圓形
          float sdCircle( in vec2 p, in float r )
          {
              return length(p) - r;
          }

          通過圓形我們可以首先繪制出兩只耳朵(外耳郭)的基本造型

           

          然后同樣,繪制出內(nèi)耳的造型

           

          進(jìn)而繪制出 大臉盤子

           

          以及眼睛

           

          udSegment 的使用

          udSegment 具體代碼分別如下所示

          /// @note (圓頭)直線形
          /// @param a 起點(diǎn)
          /// @param b 終點(diǎn)
          float udSegment( in vec2 p, in vec2 a, in vec2 b )
          {
              vec2 ba = b - a;
              vec2 pa = p - a;
              float h = clamp( dot(pa, ba) / dot(ba, ba), 0.01.0 );
              return length(pa - h * ba);
          }

          通過它,我們可以給 “小撓斧” 繪制一個(gè)鼻子

           

          是不是已經(jīng)有點(diǎn)可可愛愛了~ 但是這樣還是不行的,因?yàn)榭雌饋碛悬c(diǎn)像小熊。。。畢竟是 “小撓斧” ,應(yīng)該給它添加一個(gè) 的印記!那就要配合使用我們下一個(gè) SDF 函數(shù)了。

          sdArc 的使用

          sdArc 具體代碼分別如下所示

          /// @note (圓頭)弧形
          /// @param sc 角度、弧長
          /// @param ra 弧長
          /// @param rb 粗細(xì)
          float sdArc( in vec2 p, in vec2 sc, in float ra, float rb )
          {
              // sc is the sin/cos of the arc's aperture
              p.x = abs(p.x);
              return ((sc.y * p.x > sc.x * p.y) ? length(p - sc * ra) :
                      abs(length(p) - ra)) - rb;
          }

          因?yàn)?“王” 的結(jié)構(gòu)是 三橫一豎,(三橫其實(shí)是略帶彎曲的),所以我決定用 sdArc 來繪制那 “三橫”,udSegment 來繪制那 “一豎” 。

           

          感覺還差點(diǎn)意思,豐富一下它的條紋

           

          以及再給它添加一對(duì)靈性的小胡紙

           

          大功就完成了 !

          總結(jié)

          有了這三種基本圖形的繪制之后,其實(shí)就只需把它們合理地拼接在一起的工作了,但其實(shí)也是最需要耐心的工作,因?yàn)橛性S多細(xì)節(jié)參數(shù)需要調(diào)教。。。啊呸!是調(diào)校!

          最后,完整代碼如下所示

          完整代碼

          // 版權(quán)聲明:轉(zhuǎn)載請(qǐng)附上原文出處及鏈接。

          #define YELLOW vec3(255., 214., 34.)/255.
          #define ORANGE vec3(255., 80., 2.)/255.
          #define BLACK vec3(29., 21., 22.)/255.
          #define WHITE vec3(1.)
          #define Pi 3.14159
          const float AA = 0.007;
          /// ---------------- SDF ----------------

          /// @note 圓形
          float sdCircle( in vec2 p, in float r )
          {
              return length(p) - r;
          }

          /// @note (圓頭)弧形
          /// @param sc 角度、弧長
          /// @param ra 弧長
          /// @param rb 粗細(xì)
          float sdArc( in vec2 p, in vec2 sc, in float ra, float rb )
          {
              // sc is the sin/cos of the arc's aperture
              p.x = abs(p.x);
              return ((sc.y * p.x > sc.x * p.y) ? length(p - sc * ra) :
                      abs(length(p) - ra)) - rb;
          }

          /// @note (圓頭)直線形
          /// @param a 起點(diǎn)
          /// @param b 終點(diǎn)
          float udSegment( in vec2 p, in vec2 a, in vec2 b )
          {
              vec2 ba = b - a;
              vec2 pa = p - a;
              float h = clamp( dot(pa, ba) / dot(ba, ba), 0.01.0 );
              return length(pa - h * ba);
          }

          /// ---------------- SDF ----------------

          /// @note 關(guān)于 (0, 0) 點(diǎn)的旋轉(zhuǎn)
          vec2 rot(vec2 uv, float a)
          {
              // [uv.x uv.y] * [cos(a),  sin(a),
              //                -sin(a), cos(a)]
              return vec2(uv.x * cos(a) - uv.y * sin(a), uv.y * cos(a) + uv.x * sin(a));
          }

          vec2 rotCenter(vec2 uv, float a, vec2 center)
          {
              return rot(uv - center, a) + center;
          }

          /// @note 融合
          float sminfloat d1, float d2, float k )
          {
              float h = clamp( 0.5 + 0.5 * (d2 - d1) / k, 0.01.0 );
              return mix( d2, d1, h ) - k * h * (1.0 - h);
          }

          void drawStripe(vec2 uv, vec2 offset, float tb, float ra, float rb, inout vec3 col)
          {
              float arc_t = sdArc(uv - offset,                 vec2(sin(tb), cos(tb)), ra, rb);
              float arc_m = sdArc(uv - offset + vec2(.0.13), vec2(sin(tb), cos(tb)), ra, rb);
              float arc_b = sdArc(uv - offset + vec2(.0.25), vec2(sin(tb), cos(tb)), ra, rb);

              float arc_3 = min(1., min(sign(arc_t), min(sign(arc_m), sign(arc_b))));
              col = mix(BLACK, col, arc_3);
              col = mix( col, BLACK, 1.0 - smoothstep(0.0, AA, abs(arc_t)) ); ///< 邊緣平滑 抗鋸齒
              col = mix( col, BLACK, 1.0 - smoothstep(0.0, AA, abs(arc_m)) );
              col = mix( col, BLACK, 1.0 - smoothstep(0.0, AA, abs(arc_b)) );
          }

          void mainImage( out vec4 fragColor, in vec2 fragCoord )
          {
              /// @note 將屏幕坐標(biāo)轉(zhuǎn)為 [-1., 1.]
              /// 以屏幕中心為原點(diǎn)
              vec2 uv = (2.0 * fragCoord - iResolution.xy) / iResolution.y;

              /// @note 構(gòu)建各個(gè)組件的 SDF
              /// @note 臉
              float faceSDF = sdCircle(uv - vec2(0.-.83), 1.02);

              /// @note 耳朵
              float leftOutterEarSDF = sdCircle(uv - vec2(-.61-.02), .31);
              float rightOutterEarSDF = sdCircle(uv - vec2(+.61-.02), .31);
              float leftInnerEarSDF = sdCircle(uv - vec2(-.61-.02), .15);
              float rightInnerEarSDF = sdCircle(uv - vec2(+.61-.02), .15);

              /// @note 眼睛
              float leftEyeSDF = sdCircle(uv - vec2(-.33-.61), .06);
              float rightEyeSDF = sdCircle(uv - vec2(+.33-.61), .06);

              /// @note 嘴
              float leftMouthSDF = sdCircle(uv - vec2(-.21-1.), .291);
              float rightMouthSDF = sdCircle(uv - vec2(+.21-1.), .291);

              // 繪制
              vec3 col = WHITE; ///< 背景

              /// @note 耳朵
              col = mix(YELLOW, col, smoothstep(0..01, leftOutterEarSDF));
              col = mix(YELLOW, col, smoothstep(0..01, rightOutterEarSDF));
              col = mix(ORANGE, col, smoothstep(0..01, leftInnerEarSDF));
              col = mix(ORANGE, col, smoothstep(0..01, rightInnerEarSDF));

              /// @note 臉
              col = mix(YELLOW, col, smoothstep(0..01, faceSDF));

              /// @note 眼睛
              col = mix(BLACK, col, smoothstep(0..01, leftEyeSDF));
              col = mix(BLACK, col, smoothstep(0..01, rightEyeSDF));

              /// @note 嘴
              float mouth = smin(leftMouthSDF, rightMouthSDF, 0.05);
              col = mix(WHITE, col, smoothstep(0..01, mouth));

              /// @note 鼻子
              float nose = udSegment( uv, vec2(-.038-0.73), vec2(.038-.73) ) - .085;
              col = mix(BLACK, col, smoothstep(0..01, nose));

              /// @note 王
              float d = udSegment( uv, vec2(0.-0.25), vec2(.0-.06) ) - .03///< |
              col = mix( col, BLACK, 1.0 - smoothstep(0.0, AA, abs(d)) );

              float tb = Pi / 12.;
              float arc_t = sdArc(uv - vec2(0.-0.9), vec2(sin(tb), cos(tb)), .840.03); ///< 三
              float arc_m = sdArc(uv - vec2(0.-1.0), vec2(sin(tb), cos(tb)), .840.03);
              float arc_b = sdArc(uv - vec2(0.-1.1), vec2(sin(tb), cos(tb)), .840.03);

              float wang = min(1., min(sign(d), min(sign(arc_t), min(sign(arc_m), sign(arc_b)))));
              col = mix(BLACK, col, wang);

              col = mix( col, BLACK, 1.0 - smoothstep(0.0, AA, abs(arc_t)) ); ///< 邊緣平滑 抗鋸齒
              col = mix( col, BLACK, 1.0 - smoothstep(0.0, AA, abs(arc_m)) );
              col = mix( col, BLACK, 1.0 - smoothstep(0.0, AA, abs(arc_b)) );

              /// @note 花紋
              float ttb = Pi / 20.;
              drawStripe(uv, vec2(-.82-1.52), ttb, .840.035, col);
              drawStripe(uv, vec2(.82-1.52), ttb, .840.035, col);

              /// @note 胡子
              float angle = Pi / 6.*(.5 * sin(iTime * 3.) + .5);

              /// 靜態(tài)版                           
              float leftBeard = udSegment( uv, vec2(-.4-0.77), vec2(-.618-.618)) - .008;
              col = mix(BLACK, col, smoothstep(0..01, leftBeard));

              /// 靜態(tài)版  
              float rightBeard = udSegment( uv, vec2(.4-0.77), vec2(.618-.618) ) - .008;
              col = mix(BLACK, col, smoothstep(0..01, rightBeard));

              fragColor = vec4(col, 1.0);
          }

          原文鏈接: https://juejin.cn/post/7056666793003188261



          -- END --


          進(jìn)技術(shù)交流群,掃碼添加我的微信:Byte-Flow



          獲取相關(guān)資料和源碼


          推薦:

          Android FFmpeg 實(shí)現(xiàn)帶濾鏡的微信小視頻錄制功能

          全網(wǎng)最全的 Android 音視頻和 OpenGL ES 干貨,都在這了

          一文掌握 YUV 圖像的基本處理

          抖音傳送帶特效是怎么實(shí)現(xiàn)的?

          所有你想要的圖片轉(zhuǎn)場效果,都在這了

          面試官:如何利用 Shader 實(shí)現(xiàn) RGBA 到 NV21 圖像格式轉(zhuǎn)換?

          我用 OpenGL ES 給小姐姐做了幾個(gè)抖音濾鏡


          項(xiàng)目疑難問題解答、大廠內(nèi)部推薦、面試指導(dǎo)、簡歷指導(dǎo)、代碼指導(dǎo)、offer 選擇建議、學(xué)習(xí)路線規(guī)劃,可以點(diǎn)擊找我一對(duì)一解答。


          瀏覽 917
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

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

          手機(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>
                  五月天av在线 | 无码精品人妻一区二区欧美 | 东北熟女宾馆3p露脸 | 日本黄色A片 | 久久女人高朝视频免费看 |