Shader 函式視覺化

Hahnn發表於2018-09-06

一、正弦餘弦

正弦運動y = sin(x)

Shader 函式視覺化

餘弦運動y = cos(x)

Shader 函式視覺化

動畫演示:

Shader 函式視覺化

通過給sin()cos()新增一些處理,可以製作出更多有趣的效果:

Shader 函式視覺化

Shader 函式視覺化

Shader 函式視覺化

二、smoothstep

在兩個值之間取埃爾米特插值(Hermite interpolation)link,它的值永遠是 0~1。

描述:在edge0edge1之間取一個平緩的差值,在我們需要一個平滑的漸變的時候特別有用。當前值小於edge0,取值為0。當前值大於edge1,取值1。在這個區間內,取edge0edge1的差值。

適用場景1:由於它的值永遠介於 0~1,edge0 和 edge1 的差值只會決定曲線的陡或平緩,所以我們可以控制他們的差值來做一些動畫速度的變化。比如:

zoom(uv, smoothstep(0.0, nQuick, progress));
複製程式碼

上面通過控制 nQuick 的值來決定 zoom 縮放速度了。

適用場景2smoothstepedge0,edge10的時候,相當於step

smoothstep(0.0, 0.0, x);
複製程式碼

Shader 函式視覺化

那我們怎麼實現類似 step(edge, x) 的 edge 移動的效果呢,只需要這麼做就一樣了:

smoothstep(0.0, 0.0, x-edge);
複製程式碼

Shader 函式視覺化

Shader 函式視覺化

smoothstep() 的運算同樣可以製作出一些不同的變體曲線:

y = smoothstep(0.0,1.0,x) - smoothstep(1.0,  2.0, x); 
複製程式碼

Shader 函式視覺化

使用

float smoothstep(float edge0, float edge1, float x)  
vec2 smoothstep(vec2 edge0, vec2 edge1, vec2 x)  
vec3 smoothstep(vec3 edge0, vec3 edge1, vec3 x)  
vec4 smoothstep(vec4 edge0, vec4 edge1, vec4 x)

vec2 smoothstep(float edge0, float edge1, vec2 x)  
vec3 smoothstep(float edge0, float edge1, vec3 x)  
vec4 smoothstep(float edge0, float edge1, vec4 x)
複製程式碼

它等同於:

genType t;  /* Or genDType t; */
t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
return t * t * (3.0 - 2.0 * t);
複製程式碼

視覺化呈現:y = smoothstep(0.0,1.0,x);

Shader 函式視覺化

三、clamp

將值限制在兩個其他值之間。link

說明clamp()返回minValmaxVal範圍內的值。返回值計算:min(max(x, minVal), maxVal)。

使用

float clamp(float x, float minVal, float maxVal)  
vec2 clamp(vec2 x, vec2 minVal, vec2 maxVal)  
vec3 clamp(vec3 x, vec3 minVal, vec3 maxVal)  
vec4 clamp(vec4 x, vec4 minVal, vec4 maxVal)

vec2 clamp(vec2 x, float minVal, float maxVal)  
vec3 clamp(vec3 x, float minVal, float maxVal)  
vec4 clamp(vec4 x, float minVal, float maxVal)
複製程式碼

視覺化呈現:y = clamp(x,0.,1.);

Shader 函式視覺化

四、step

通過比較兩個值生成步進函式。link

說明step()通過將xedge進行比較來生成步進函式。對於返回值i,如果x[i] < edge[i]則返回0.0,否則返回1.0

適用場景step()有著一個最大的特徵,那就是非黑即白。edge 表示非黑即白的邊界,小於edge就是黑(0),大於edge就是白(1)。當我們這麼使用時,可以判斷畫素點是否存在歸一化座標系裡:

step(0.0, p.y) * step(p.y, 1.0) * step(0.0, p.x) * step(p.x, 1.0)
複製程式碼

當它為 0 時,表示畫素點在水平或垂直方向超出了邊界;當它為 1 時,表示在座標系內。當我我們把它和mix(texture2D_1, texture2D_2, step())函式一起用時,就可以得到非黑即白的兩張相連的紋理圖(紋理圖超過邊界的部分會用紋理圖2取代)。

使用

float step(float edge, float x)  
vec2 step(vec2 edge, vec2 x)  
vec3 step(vec3 edge, vec3 x)  
vec4 step(vec4 edge, vec4 x)

vec2 step(float edge, vec2 x)  
vec3 step(float edge, vec3 x)  
vec4 step(float edge, vec4 x)
複製程式碼

視覺化呈現:y = step(0.5,x);

Shader 函式視覺化

五、mod

以第二個模數計算第一個引數的值。

說明x指定要求模的值,y指定要獲取模數的值。計算公式為:x - y * floor(x / y)

使用

float mod(float x, float y)  
vec2 mod(vec2 x, vec2 y)  
vec3 mod(vec3 x, vec3 y)  
vec4 mod(vec4 x, vec4 y)

vec2 mod(vec2 x, float y)  
vec3 mod(vec3 x, float y)  
vec4 mod(vec4 x, float y)
複製程式碼

視覺化呈現:y = mod(x,1.)

Shader 函式視覺化

六、fract

計算引數的小數部分。

說明fract()返回x的小數部分。計算公式為x - floor(x)

適用場景:假如我們在一個歸一化的座標系裡,fract(uv) 能夠讓畫素點永遠都在座標系裡不會超出邊界。以從上往下平移作為例子,fract()可以讓從上往下的平移無限迴圈,且首尾相連。

使用

float fract(float x)  
vec2 fract(vec2 x)  
vec3 fract(vec3 x)  
vec4 fract(vec4 x)
複製程式碼

視覺化呈現:y = fract(x)

Shader 函式視覺化

七、floor

找到小於或等於引數的最接近的整數

說明floor()返回一個等於最小整數的值,該整數小於或等於x

使用

float floor(float x)  
vec2 floor(vec2 x)  
vec3 floor(vec3 x)  
vec4 floor(vec4 x)

複製程式碼

視覺化呈現:y = floor(x)

Shader 函式視覺化

八、ceil

找到大於或等於引數的最近整數

說明ceil()返回一個等於最接近的整數的值,該整數大於或等於x

使用

float ceil(float x)  
vec2 ceil(vec2 x)  
vec3 ceil(vec3 x)  
vec4 ceil(vec4 x)
複製程式碼

視覺化呈現:y = ceil(x);

Shader 函式視覺化

九、sign

提取引數的符號。

說明:如果x小於0.0,則sign()返回-1.0,如果x等於0.0,則返回0.0,如果x大於0.0,則返回+1.0

適用場景sign()用來判斷運動方向非常高效,因為它的值只有 -1,0,1,所以我們可以通過

vec2 direction = vec2(0.0, 1.0);   // x, y 代表方向
sign(direction)
複製程式碼

來判斷水平和垂直的方向,正數為正方向,負數為反方向,也不用擔心使用者傳了超出長度為1的值。

使用

float sign(float x)  
vec2 sign(vec2 x)  
vec3 sign(vec3 x)  
vec4 sign(vec4 x)
複製程式碼

視覺化呈現:y = sign(x);

Shader 函式視覺化

十、mix

將值限制在兩個其他值之間並做融合,常用於顏色混合:

Shader 函式視覺化

說明mix()xy之間執行線性插值,使用它們之間的權重。返回值計算為x*(1-a)+y*a。可以這麼理解,a決定了x,y所佔的比重,比如a < 0.5,那麼x的比重更大,a > 0.5y的比重更大。當 a = 0.5時,xy的比重各一半。

使用場景:我們經常會有一些動畫,需要在單位時間內往返一次,比如先放大後縮小。通過以下公式可以輕鬆做到(scale 表示放大的倍數):

mix(scale, 1.0, 2.0 * abs(progress - 0.5))
複製程式碼

上面的公式即可做到先放大到scale(當進度為0.5時達到最大),然後再縮小到1

使用

float mix(float x, float y, float a)  
vec2 mix(vec2 x, vec2 y, vec2 a)  
vec3 mix(vec3 x, vec3 y, vec3 a)  
vec4 mix(vec4 x, vec4 y, vec4 a)

vec2 mix(vec2 x, vec2 y, float a)  
vec3 mix(vec3 x, vec3 y, float a)  
vec4 mix(vec4 x, vec4 y, float a)
複製程式碼

視覺化呈現:y = mix(0.,1.,x);

Shader 函式視覺化

相關文章