【OpenGL】Shader執行個體分析(二)- Heart

來源:互聯網
上載者:User

轉寄請保持地址:http://blog.csdn.net/stalendp/article/details/22221597

這片文章將介紹怎麼用Shader來繪製一個跳動的心臟。這裡會涉及到一些數學知識。先看:


原始碼如下:

// Created by inigo quilez - iq/2013// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.// changed by stalendp@gmail.comShader "shadertoy/Heart" {  // see https://www.shadertoy.com/view/XsfGRnCGINCLUDE              #include "UnityCG.cginc"                        #pragma target 3.0            struct vertOut {                float4 pos:SV_POSITION;                float4 srcPos;           };            vertOut vert(appdata_base v) {              vertOut o;              o.pos = mul (UNITY_MATRIX_MVP, v.vertex);              return o;          }            fixed4 frag(float4 sp:WPOS) : COLOR0 {  float2 p = (2.0*sp.xy - _ScreenParams.xy) / min(_ScreenParams.y, _ScreenParams.x);p.y -= 0.25;//background colorfloat3 bcol = float3(1.0,0.8,0.7-0.07*p.y) * (1.0 - 0.25*length(p));// animatefloat tt = fmod(_Time.y, 1.5)/1.5;float ss = pow(tt,.2) * 0.5 + 0.5;ss -= ss*0.2*sin(tt*6.2831*3.0)*exp(-tt*4.0);p *= float2(0.5, 1.5) + ss * float2(0.5, -0.5);    // shape    float a = atan2(p.x,p.y)/3.141593;    float r = length(p);    float h = abs(a);    float d = (13.0*h - 22.0*h*h + 10.0*h*h*h)/(6.0-5.0*h);// colorfloat s = 1.0-0.5*clamp(r/d,0.0,1.0);s = 0.75 + 0.75*p.x;s *= 1.0-0.25*r;s = 0.5 + 0.6*s;s *= 0.5+0.5*pow( 1.0-clamp(r/d, 0.0, 1.0 ), 0.1 );float3 hcol = float3(1.0,0.5*r,0.3)*s;    float3 col = lerp( bcol, hcol, smoothstep( -0.01, 0.01, d-r) );    return float4(col,1.0);        }        ENDCG          SubShader {            Pass {                CGPROGRAM                  #pragma vertex vert                #pragma fragment frag                #pragma fragmentoption ARB_precision_hint_fastest                   ENDCG            }          }         FallBack Off  }

網上有很多關於心形的繪製方法,這裡介紹一種。

1. 心形畫法的原理

float a = atan2(p.y,p.x)/3.1415;

atan2(p.y,p.x)求的是向量(x,y)所對應的角度。求得的是弧度制的值,除以pi後得到的範圍是[0,1];

所以上面的函數就是求得平面上的座標點所對應向量的角度(被映射到[0,1]之間);

如,點p1和p2是螢幕上的不同的兩點,但是他們對應的角度是(4/8)*pi(經過上面公式的映射,值為4/8);

是個單位圓,p1和p2中間標註的點4/8就是(atan2(p.y,p.x)/3.1415)的值。這個整個標註出來的點(除了p1和p2外)呈現一個心形。所以只要為心形內部和外部染成不同的顏色即可(如中,p1染成紅色,p2染成背景色)。

方法是用step方法,這裡用smoothstep,使得邊緣不那麼硬, 然後結合lerp方法,如下:

 float a = atan2(p.y,p.x)/3.141593; 
 float r = length(p);

 float3 col = lerp( bcol, hcol, smoothstep( -0.01, 0.01, a-r) ); // 當p1時,smoothstep返回1;p2時,smoothstep返回0;


這樣就可以畫半個倒著的心:


翻轉xy軸,並取絕對值,

float a = atan2(p.x,p.y)/3.141593;
float r = length(p);
float h = abs(a);
float3 col = lerp( bcol, hcol, smoothstep( -0.01, 0.01, h-r) );

得到:


心太肥了,用下面的函數來調節心形:

,對應的曲線如下:


這樣就得到比較ok的心形了,如下:


2. 心形跳動的演算法

接下來,結合時間和函數來擷取一個跳動的心臟:


對應的映像:


正真的效果函數,如下:



對應的代碼為:

// animate
float tt = fmod(_Time.y, 1.5)/1.5; // 周期為1.5秒
float ss = pow(tt,.2) * 0.5 + 0.5;
ss -= ss*0.2*sin(tt*6.2831*3.0)*exp(-tt*4.0);
p *= float2(0.5, 1.5) + ss * float2(0.5, -0.5); // 不同的軸影響不同,使得心在跳動時,縱向變矮,橫向變寬

3. 顏色(待續)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.