ShadeGraph節點詳解1:Artistic Nodes

ShadeGraph節點詳解1:Artistic Nodes

來自專欄 Unity探路者

本文首發於洪流學堂微信公眾號。

洪流學堂,學Unity快人幾步

注意

節點中很多輸入為In(1)的其實是動態長度的Vector,可以接收Vector1~Vector4的值哦

Artistic Nodes

Adjustment 調整

Channel Mixer

根據輸入的RGB值及各個通道的權重,輸出權重加成後的RGB值。

舉例:輸入RGB為(0.8,0.6,0.4),假設輸出R通道的比重設置為(0.1, 0.2, 0.3),則輸出R的值為0.8x0.1+0.6x0.2+0.4x0.3 = 0.32

_Node_OutRed = float3 (OutRedInRed, OutRedInGreen, OutRedInBlue);_Node_OutGreen = float3 (OutGreenInRed, OutGreenInGreen, OutGreenInBlue);_Node_OutBlue = float3 (OutBlueInRed, OutBlueInGreen, OutBlueInBlue);Out = float3(dot(In, _Node_OutRed), dot(In, _Node_OutGreen), dot(In, _Node_OutBlue));

Contrast

根據輸入In及Contrast調節對比度。Contrast為1時輸出In,Contrast為0時輸出In的中值。

float midpoint = pow(0.5, 2.2);Out = (In - midpoint) * Contrast + midpoint;

Hue

根據Offset調節色相。

可以根據Degrees調節即(-180,180)

或者根據Normalized調節即(-1,1)

Degree代碼(Normalized類似):

float4 K = float4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);float4 P = lerp(float4(In.bg, K.wz), float4(In.gb, K.xy), step(In.b, In.g));float4 Q = lerp(float4(P.xyw, In.r), float4(In.r, P.yzx), step(P.x, In.r));float D = Q.x - min(Q.w, Q.y);float E = 1e-10;float3 hsv = float3(abs(Q.z + (Q.w - Q.y)/(6.0 * D + E)), D / (Q.x + E), Q.x);float hue = hsv.x + Offset / 360;hsv.x = (hue < 0) ? hue + 1 : (hue > 1) ? hue - 1 : hue;float4 K2 = float4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);float3 P2 = abs(frac(hsv.xxx + K2.xyz) * 6.0 - K2.www);Out = hsv.z * lerp(K2.xxx, saturate(P2 - K2.xxx), hsv.y);

Invert Colors

反轉顏色,可以選擇單個或多個反轉的通道

Replace Color

替換顏色

In:輸入的顏色

From:要替換的顏色

To:替換成的顏色

Range:類似PS里的容差值

Fuzziness:軟化選區的邊緣

float Distance = distance(From, In);Out = lerp(To, In, saturate((Distance - Range) / max(Fuzziness, 1e-5f)));

Saturation

飽和度。Saturation為1時輸出原顏色,Saturation為0時為完全不飽和色。

float luma = dot(In, float3(0.2126729, 0.7151522, 0.0721750));Out = luma.xxx + Saturation.xxx * (In - luma.xxx);

White Balance

白平衡

Temperature 讓顏色變黃或者變藍

Tint 讓顏色變粉或者變綠

// Range ~[-1.67;1.67] works bestfloat t1 = Temperature * 10 / 6;float t2 = Tint * 10 / 6;// Get the CIE xy chromaticity of the reference white point.// Note: 0.31271 = x value on the D65 white pointfloat x = 0.31271 - t1 * (t1 < 0 ? 0.1 : 0.05);float standardIlluminantY = 2.87 * x - 3 * x * x - 0.27509507;float y = standardIlluminantY + t2 * 0.05;// Calculate the coefficients in the LMS space.float3 w1 = float3(0.949237, 1.03542, 1.08728); // D65 white point// CIExyToLMSfloat Y = 1;float X = Y * x / y;float Z = Y * (1 - x - y) / y;float L = 0.7328 * X + 0.4296 * Y - 0.1624 * Z;float M = -0.7036 * X + 1.6975 * Y + 0.0061 * Z;float S = 0.0030 * X + 0.0136 * Y + 0.9834 * Z;float3 w2 = float3(L, M, S);float3 balance = float3(w1.x / w2.x, w1.y / w2.y, w1.z / w2.z);float3x3 LIN_2_LMS_MAT = { 3.90405e-1, 5.49941e-1, 8.92632e-3, 7.08416e-2, 9.63172e-1, 1.35775e-3, 2.31082e-2, 1.28021e-1, 9.36245e-1};float3x3 LMS_2_LIN_MAT = { 2.85847e+0, -1.62879e+0, -2.48910e-2, -2.10182e-1, 1.15820e+0, 3.24281e-4, -4.18120e-2, -1.18169e-1, 1.06867e+0};float3 lms = mul(LIN_2_LMS_MAT, In);lms *= balance;Out = mul(LMS_2_LIN_MAT, lms);

Blend 混合

Blend節點

根據輸入的Base、Blend兩個值進行混合

Opacity可以設置混合的強度,0=不增強

Mode可以設置混合的模式

不同Mode的Shader代碼

Burn

Out = 1.0 - (1.0 - Blend)/Base;Out = lerp(Base, Out, Opacity);

Darken

Out = min(Blend, Base);Out = lerp(Base, Out, Opacity);

Difference

Out = abs(Blend - Base);Out = lerp(Base, Out, Opacity);

Dodge

Out = Base / (1.0 - Blend);Out = lerp(Base, Out, Opacity);

Divide

Out = Base / (Blend + 0.000000000001);Out = lerp(Base, Out, Opacity);

Exclusion

Out = Blend + Base - (2.0 * Blend * Base);Out = lerp(Base, Out, Opacity);

HardLight

float# result1 = 1.0 - 2.0 * (1.0 - Base) * (1.0 - Blend);float# result2 = 2.0 * Base * Blend;float# zeroOrOne = step(Blend, 0.5);Out = result2 * zeroOrOne + (1 - zeroOrOne) * result1;Out = lerp(Base, Out, Opacity);

HardMix

Out = step(1 - Base, Blend);Out = lerp(Base, Out, Opacity);

Lighten

Out = max(Blend, Base);Out = lerp(Base, Out, Opacity);

LinearBurn

Out = Base + Blend - 1.0;Out = lerp(Base, Out, Opacity);

LinearDodge

Out = Base + Blend;Out = lerp(Base, Out, Opacity);

LinearLight

Out = Blend < 0.5 ? max(Base + (2 * Blend) - 1, 0) : min(Base + 2 * (Blend - 0.5), 1);Out = lerp(Base, Out, Opacity);

LinearLightAddSub

Out = Blend + 2.0 * Base - 1.0;Out = lerp(Base, Out, Opacity);

Multiply

Out = Base * Blend;Out = lerp(Base, Out, Opacity);

Negation

Out = 1.0 - abs(1.0 - Blend - Base);Out = lerp(Base, Out, Opacity);

Screen

Out = 1.0 - (1.0 - Blend) * (1.0 - Base);Out = lerp(Base, Out, Opacity);

Overlay

float# result1 = 1.0 - 2.0 * (1.0 - Base) * (1.0 - Blend);float# result2 = 2.0 * Base * Blend;float# zeroOrOne = step(Base, 0.5);Out = result2 * zeroOrOne + (1 - zeroOrOne) * result1;Out = lerp(Base, Out, Opacity);

PinLight

float# check = step (0.5, Blend);float# result1 = check * max(2.0 * (Base - 0.5), Blend);Out = result1 + (1.0 - check) * min(2.0 * Base, Blend);Out = lerp(Base, Out, Opacity);

SoftLight

float# result1 = 2.0 * Base * Blend + Base * Base * (1.0 - 2.0 * Blend);float# result2 = sqrt(Base) * (2.0 * Blend - 1.0) + 2.0 * Base * (1.0 - Blend);float# zeroOrOne = step(0.5, Blend);Out = result2 * zeroOrOne + (1 - zeroOrOne) * result1;Out = lerp(Base, Out, Opacity);

VividLight

float# result1 = 1.0 - (1.0 - Blend) / (2.0 * Base);float# result2 = Blend / (2.0 * (1.0 - Base));float# zeroOrOne = step(0.5, Base);Out = result2 * zeroOrOne + (1 - zeroOrOne) * result1;Out = lerp(Base, Out, Opacity);

Subtract

Out = Base - Blend;Out = lerp(Base, Out, Opacity);

Filter 濾鏡

Dither

Dither是一種特定格式的噪波,用於隨機量化誤差。它用於防止大幅拉伸圖片時出現的異常情況,如圖像中的色帶。Dither節點在屏幕空間抖動來確保圖案的均勻分布。可以通過連接另一個節點來輸入屏幕位置。此節點通常作為主節點上Alpha Clip Threshold的輸入,為不透明對象提供透明的外觀。這對於創建透明的對象很有用,而且仍然可以寫入深度緩衝區。

float2 uv = ScreenPosition.xy * _ScreenParams.xy;float DITHER_THRESHOLDS[16] ={ 1.0 / 17.0, 9.0 / 17.0, 3.0 / 17.0, 11.0 / 17.0, 13.0 / 17.0, 5.0 / 17.0, 15.0 / 17.0, 7.0 / 17.0, 4.0 / 17.0, 12.0 / 17.0, 2.0 / 17.0, 10.0 / 17.0, 16.0 / 17.0, 8.0 / 17.0, 14.0 / 17.0, 6.0 / 17.0};uint index = (uint(uv.x) % 4) * 4 + uint(uv.y) % 4;Out = In - DITHER_THRESHOLDS[index];

Mask 遮罩

Channel Mask

可以從下拉框中選擇輸出的通道。可以用來過濾或使用某個或某幾個通道。

Color Mask

從輸入顏色與Mask Color相等的顏色的位置創建一個遮罩。

Range:類似PS里的容差值

Fuzziness:軟化選區的邊緣

float Distance = distance(MaskColor, In);Out = saturate(1 - (Distance - Range) / max(Fuzziness, 1e-5));

Normal 法線

Normal Blend 法線混合

混合兩個法線

Out = normalize(float3(A.rg + B.rg, A.b * B.b));

Normal Create 創建法線

從一張高度圖Texture創建法線貼圖。UV和Sampler可以從對應的UV和Sampler State節點連接,如果沒有設置將使用默認值。

創建的法線貼圖的強度可以用Offset和Strength屬性修改。Offset定義了法線細節的最大距離,Strength是結果的係數。

Offset = pow(Offset, 3) * 0.1;float2 offsetU = float2(UV.x + Offset, UV.y);float2 offsetV = float2(UV.x, UV.y + Offset);float normalSample = Texture.Sample(Sampler, UV);float uSample = Texture.Sample(Sampler, offsetU);float vSample = Texture.Sample(Sampler, offsetV);float3 va = float3(1, 0, (uSample - normalSample) * Strength);float3 vb = float3(0, 1, (vSample - normalSample) * Strength);Out = normalize(cross(va, vb));

Normal Strength

修改法線貼圖的Strength。Strength為1時返回原圖,為0時返回純黑的法線貼圖。

Out = {precision}3(In.rg * Strength, In.b);

Normal Unpack

解包一個法線貼圖。

注意

通常這是多餘的,因為在Sample的時候法線貼圖的Type一般會設置為Normal,如下圖所示,已經自動解包成法線貼圖。可以看下面Normal Unpack節點是多餘的,下面預覽是相同的。

Out = UnpackNormalmapRGorAG(In);

Utility 工具

Colorspace Conversion

顏色空間轉換。從一種顏色空間轉換到另一種顏色空間。

小結

本文講解了ShaderGraph眾多Node中的Artistic Nodes。你可以收藏本文作為一個工具庫。

其他Node的詳解,關注洪流學堂公眾號第一時間獲取。

你有沒有飽受shader折磨的同學?你可以把今天的內容分享給他,或許你能幫到他。


Unity:世界領先的遊戲,VR/AR引擎

《鄭洪智的Unity2018課》,傾盡我8年的開發經驗,結合最新的Unity2018,帶你從入門到精通。

推薦閱讀:

[shader]漸變過度
Shader(四)邊緣發光和卡通光照
Unity手游開發札記——使用Shader進行UGUI的優化
Unity Compute Shader 硬體粒子效果
衝擊波製作方法探討

TAG:Unity遊戲引擎 | shader | 著色器 |