<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>

          OpenGL ES Shader 怎樣繪制一顆“心”

          共 4597字,需瀏覽 10分鐘

           ·

          2023-08-28 09:49

          今天講一下繪制心形的兩種方式,主要是為了擴(kuò)展一下繪制復(fù)雜形狀的思路,為后面講特效做一些簡單的鋪墊。

          心形繪制可以參考 ShaderToy 上的代碼:
          https://www.shadertoy.com/view/XsfGRn

          上述代碼繪制心形,首先將原點(diǎn)從左下角移至坐標(biāo)系中央,這樣所有片元的向量均以屏幕中心為起點(diǎn),則向量 uv 就是畫布中心與像素點(diǎn)坐標(biāo)之間的方向向量。

            vec2 uv = (2.0 * fragCoord - iResolution.xy) / min(iResolution.y,iResolution.x); //坐標(biāo)原點(diǎn)設(shè)置到中心位置

          然后利用反正切函數(shù)值和當(dāng)前片元(像素)與屏幕中心點(diǎn)的距離相比較,來確定心形狀的邊界。

          GL ES 中的反正切函數(shù) atan(p.x,p.y) 取值范圍是[-π, π],然后除以 PI 后,取值范圍變成了 [-1, 1] 。

          void mainImage(out vec4 fragColor, in vec2 fragCoord)
          {
            vec2 uv = (2.0 * fragCoord - iResolution.xy) / min(iResolution.y,iResolution.x); //坐標(biāo)原點(diǎn)設(shè)置到中心位置

            float r = length(uv);  
            float d = atan(uv.x,uv.y)/PI; //[-1.0,1.0] 
            float s = abs(d);

            vec3 color = vec3(s) * vec3(1.00.00.0);

            fragColor = vec4(color,1.0);

          }

          我們把反正切的結(jié)果取絕對值,渲染出來:

          可以看到,從中心向外輻射,每條直線上的值都是一樣的,即每條直線上像素點(diǎn)得到的 s 值都是相同的。

          我們用黃點(diǎn)表示距離屏幕中心的遠(yuǎn)近 length(uv),然后通過 s-r 的值來確定心形的邊界,得到一個最簡單的心形。

          再貼一下代碼:

          void mainImage(out vec4 fragColor, in vec2 fragCoord)
          {
            vec2 uv = (2.0 * fragCoord - iResolution.xy) / min(iResolution.y,iResolution.x);

            uv.y -= 0.3;// 向上移動一些
            float r = length(uv);  
            float d = atan(uv.x,uv.y)/PI; //[-1.0,1.0] 
            float s = abs(d);
            float col = smoothstep(-0.010.01, s-r);//邊緣過渡
            vec3 color = vec3(col) * vec3(1.00.00.0);

            fragColor = vec4(color,1.0);

          }

          增加一個函數(shù)使心的形狀更加扁平化 float e = (13.0*s - 22.0*s*s + 10.0*s*s*s)/(6.0-5.0*s);

          void mainImage(out vec4 fragColor, in vec2 fragCoord)
          {
            vec2 uv = (2.0 * fragCoord - iResolution.xy) / min(iResolution.y,iResolution.x);

            uv.y -= 0.3;  
            float r = length(uv);  
            float d = atan(uv.x,uv.y)/PI; //[-1.0,1.0] 
            float s = abs(d);
            float e = (13.0*s - 22.0*s*s + 10.0*s*s*s)/(6.0-5.0*s);
            float col = smoothstep(-0.010.01, e-r);
            vec3 color = vec3(col) * vec3(1.00.00.0);

            fragColor = vec4(color,1.0);
          }

          增加扁平化函數(shù)之后的心形:

          上述反正切和距離判斷繪制心形,實(shí)際上是有向距離場(SDF)算法思路,除此之外還有一種直接通過函數(shù)曲線繪制的思路。

          float heart(vec2 p) {
              p.y += 0.3;
              float offset = 0.3;
              // (x^2+(1.2*y-sqrt(abs(x)))^2?1)
              float k = 1.2 * p.y - sqrt(abs(p.x)*1.2 + offset);
              return 1.0 - p.x * p.x - k * k;
          }

          void mainImage(out vec4 fragColor, in vec2 fragCoord)
          {
            vec2 uv = (2.0 * fragCoord - iResolution.xy) / min(iResolution.y,iResolution.x);

            uv.y += 0.3;   
            float d = heart(uv);
            float col = smoothstep(-0.010.01, d);
            vec3 color = vec3(col) * vec3(1.00.00.0);

            fragColor = vec4(color,1.0);
          }

          函數(shù)曲線實(shí)際上是把整個畫布當(dāng)做一個原點(diǎn)位于中心坐標(biāo)系,利用函數(shù)特效構(gòu)建一個閉合的圖形。你要問這個函數(shù)怎么得出來的,這個當(dāng)然是圖形大佬調(diào)出來的。

          效果如下:



          -- END --

          AI 問答助手




          進(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 給小姐姐做了幾個抖音濾鏡

          Shader 編程:只用一個函數(shù)就能生成三角形、矩形等所有的正多邊形

          別人用 Shader 畫了個圓,你卻只能畫橢圓?

          瀏覽 656
          點(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>
                  看操逼网站 | 日日夜夜一区 | 一级a性色生活久久无 | 麻豆国产91 在线播放 | www.人人色 |