當前位置:
首頁 > 最新 > Shader Graph著色器視圖自定義節點API:Code Function Node

Shader Graph著色器視圖自定義節點API:Code Function Node

隨著在Unity 2018.1中加入Shader Graph著色器視圖,如今在Unity中創建自定義著色器變得更為簡單。然而,儘管我們默認提供了不少各式各樣的節點Node,這些節點仍不可能滿足開發者的所有需求。因此我們開發了一個自定義節點API,提供開發者在使用C#創建新節點時使用。這個API還能幫助開發者根據需求擴展Shader Graph著色器視圖。

明天晚上8點,新一期的Unity技術直播課程將詳解使用Shader Graph著色器視圖快速創建炫酷特效。今天我們將先介紹在Unity 2018.1 beta中一個擴展Shader Graph著色器視圖的方法-使用Code Function Node,它是創建自定義節點最簡單的方法。下面將介紹如何使用該方法創建一個新節點。

使用Code Function Node創建新節點

首先新創建一個C#腳本,命名為MyCustomNode。為了使用Code Function Node API,我們需要在代碼中包含或是添加該類到命名空間UnityEditor.ShaderGraph,然後從基類CodeFunctionNode進行繼承。

usingUnityEngine;

usingUnityEditor.ShaderGraph;

publicclassMyCustomNode:CodeFunctionNode

{

}

你可能已經注意到,MyCustomNode被高亮為一個錯誤。如果我們把游標移到該錯誤信息上,會看到提示我們需要實現一個名為GetFunctionToConvert的繼承成員。基類CodeFunctionNode會告訴Shader Graph著色器視圖如何處理這個節點,但我們仍需要告訴它結果函數應該是什麼。

GetFunctionToConvert方法使用Reflection反射來將一個方法轉換為MethodInfo的實例,從而使CodeFunctionNode能在Shader Graph著色器視圖中轉換和使用。並且讓我們能更為直觀地寫出著色器函數。

如下面代碼所示,添加命名空間System.Reflection和重寫函數GetFunctionToConvert。要注意MyCustomFunction,它將作為函數名寫入著色器中。你還能根據自己正在編寫的函數為其命名,只要不以數字開頭即可。在本示例中我們將使用MyCustomFunction這個名字。

usingUnityEngine;

usingUnityEditor.ShaderGraph;

usingSystem.Reflection;

publicclassMyCustomNode:CodeFunctionNode

{

protectedoverrideMethodInfoGetFunctionToConvert()

{

returnGetType().GetMethod("MyCustomFunction",

BindingFlags.Static|BindingFlags.NonPublic);

}

}

現在我們腳本中的錯誤都已經解決,我們可以開始編寫節點的功能了!

首先我們應進行命名,在類中加入一個沒有參數的公有構造函數。在該函數中,將變數名設為包含節點標題的字元串。當該節點在圖中出現時,它將顯示在節點的標題欄上。本示例中我們將節點命名為My Custom Node。

usingUnityEngine;

usingUnityEditor.ShaderGraph;

usingSystem.Reflection;

publicclassMyCustomNode:CodeFunctionNode

{

publicMyCustomNode()

{

name="My Custom Node";

}

protectedoverrideMethodInfoGetFunctionToConvert()

{

returnGetType().GetMethod("MyCustomFunction",

BindingFlags.Static|BindingFlags.NonPublic);

}

}

接下來,我們將定義節點的函數。如果你熟悉反射,你會注意到方法GetFunctionToConvert會嘗試訪問這個類中的方法MyCustomFunction。MyCustomFunction將定義著色器函數。

現在讓我們創建一個靜態方法,返回類型為string,它的名字與方法GetFunctionToConvert中的字元串一致。本示例中,這個名字為MyCustomFunction。在該方法的參數中,我們可以定義節點將擁有哪些埠。這些參數將直接映射到最後著色器函數的參數中。我們需要添加Shader Graph著色器視圖中支持類型的參數並對其設定Slot屬性。

現在我們要加入二個類型為DynamicDimensionVector的參數,分別命名為A和B,以及一個out參數,類型為DynamicDimensionVector,命名為Out。然後我們為這些參數加入默認Slot屬性。每個Slot屬性需要一個特別的索引和綁定,我們把它們設為None。

staticstringMyCustomFunction(

[Slot(,Binding.None)]DynamicDimensionVectorA,

[Slot(1,Binding.None)]DynamicDimensionVectorB,

[Slot(2,Binding.None)]outDynamicDimensionVectorOut)

{

}

在下面方法中,我們會在返回字元串中定義著色器函數的內容。這些內容包含著色器函數和HLSL代碼。本示例中定義為Out = A + B;。我們創建好的方法如下所示:

staticstringMyCustomFunction(

[Slot(,Binding.None)]DynamicDimensionVectorA,

[Slot(1,Binding.None)]DynamicDimensionVectorB,

[Slot(2,Binding.None)]outDynamicDimensionVectorOut)

{

return

@"

{

Out = A + B;

}

";

}

}

這就是Shader Graph著色器視圖中加法節點的C#代碼。

在完成可用節點前,我們還要做一件事:指定它在Create Node Menu創建節點菜單的出現位置。這一步通過在類上添加Title屬性來完成。這會定義一個string數組,它會描述節點在菜單層級列表中出現的位置。這個數組中最後一個字元串定義了節點在Create Node Menu中的名字。

本示例中,我們會把節點稱為My Custom Node,並把它放在Custom文件夾中。

[Title("Custom","My Custom Node")]

publicclassMyCustomNode:CodeFunctionNode

{

現在我們的節點就完成了!如果我們返回Unity,編譯腳本然後打開Shader Graph著色器視圖,我們會看到在Create Node Menu中出現了新節點。

然後在Shader Graph著色器視圖中創建節點實例。你會看到它擁有和我們在MyCustomFunction類中所定義的相同名字和類型。

現在你便可以通過使用不同的介面類型和綁定來創建各種節點。這個方法返回的字元串可以包含任意在Unity常規著色器中有效的HLSL代碼。下面的節點會返回三個輸入值中的最小值。

staticstringMin3(

[Slot(,Binding.None)]DynamicDimensionVectorA,

[Slot(1,Binding.None)]DynamicDimensionVectorB,

[Slot(2,Binding.None)]DynamicDimensionVectorC,

[Slot(3,Binding.None)]outDynamicDimensionVectorOut)

{

return

@"

{

Out = min(min(A, B), C);

}

";

}

}

下面這個節點能根據輸入的布爾值反轉法線。要注意在本示例中,介面Normal是如何擁有WorldSpaceNormal的綁定的。當沒有任何邊線(Edge)連接這個介面時,它會默認使用網格的世界空間法線向量。

注意:當使用一個具體輸出類型,例如Vector 3時,我們必須在返回著色器函數前對其進行定義。

staticstringFlipNormal(

[Slot(,Binding.WorldSpaceNormal)]Vector3Normal,

[Slot(1,Binding.None)]BooleanPredicate,

[Slot(2,Binding.None)]outVector3Out)

{

Out=Vector3.zero;

return

@"

{

Out = Predicate == 1 ? -1 * Normal : Normal;;

}

";

}

}

參考文檔

Reflection

https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/reflection

CodeFunctionNode API

https://github.com/Unity-Technologies/ShaderGraph/wiki/CodeFunctionNode

Port Binding

https://github.com/Unity-Technologies/ShaderGraph/wiki/Port-Bindings

小結

現在你已經準備好在Shader Graph著色器視圖中使用Code Function Node來創建節點了嗎?當然這只是開始。要想自定義該系統,你還可以在Shader Graph著色器視圖中去做更多的事情。

明天晚上8點,Unity技術經理成亮將為開發者們帶來更多Shader Graph著色器視圖的功能講解,對著色器開發感興趣的開發或美術人員一定不能錯過,帶上你的問題和講師互動吧!


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Unity中國 的精彩文章:

技術專場部分精彩議題曝光

TAG:Unity中國 |