首先需要两个自定义节点
1.三角形平铺定制节点
如果是老版本shader graph 直接创建脚本继承 CodeFunctionNode
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor.ShaderGraph;
using System.Reflection;
[Title("Distance", "Triangle")]
public class TriangleNode : CodeFunctionNode
{
public TriangleNode()
{
name = "Triangle";
}
protected override MethodInfo GetFunctionToConvert()
{
return GetType().GetMethod("TriangleNode_Function",
BindingFlags.Static | BindingFlags.NonPublic);
}
public override void GenerateNodeFunction(FunctionRegistry registry, GraphContext graphContext, GenerationMode generationMode)
{
registry.ProvideFunction("fmod", s => s.Append(@"
float fmod(float a, float b)
{
return a - floor(a / b) * b;
}
"));
base.GenerateNodeFunction(registry, graphContext, generationMode);
}
static string TriangleNode_Function(
[Slot(0, Binding.MeshUV0)] Vector2 UV,
[Slot(1, Binding.None, 4f, 0f, 0f, 0f)] Vector1 Scale,
[Slot(10, Binding.None)] out Vector1 Triangle, // 三角形
[Slot(11, Binding.None)] out Vector2 TrianglePosition // 三角形
)
{
TrianglePosition = Vector2.zero;
return @"{
#define N Scale
float2 p = UV;
p.x *= 0.86602; // sqrt(3)/2倍
float isTwo = fmod(floor(p.y * N), 2.0); // 偶数列
float isOne = 1.0 - isTwo; // 奇数列
// 将xy坐标0~1的正方形以瓷砖形式排列多个
p = p * N;
p.x += isTwo * 0.5; // 偶数列数乘以0.5
float2 p_index = floor(p); // 正方形编号
float2 p_rect = frac(p);
p = p_rect; // 正方形内部的坐标
float xSign = sign(p.x - 0.5); // 瓷砖的右侧为+1.0,左侧为-1.0
p.x = abs(0.5 - p.x); // 以x=0.5为轴左右对称
float isInTriangle = step(p.x * 2.0 + p.y, 1.0); // 三角形の内部にある場合は1.0
float isOutTriangle = 1.0 - isInTriangle; //在三角形内部时为1.0
// 中央三角形
float w1 = max( p.x * 2.0 + p.y, 1.0 - p.y * 1.5 );
// 右上角(左上角)的三角形
p = float2(0.5, 1.0) - p;
float w2 = max(p.x * 2.0 + p.y, 1.0 - p.y * 1.5 );
// 三角形渐变
Triangle = lerp(1.0 - w2, 1.0 - w1, isInTriangle) / 0.6;
// 三角形位置
float2 triangleIndex = p_index + float2(
isOutTriangle * xSign / 2.0 // 左上部分是-0.5,右上部分是+0.5
+ isOne / 2.0, // 基数列的三角形水平偏移0.5,+0.5
);
// 三角形坐标
TrianglePosition = triangleIndex / N;
}";
}
}
新版本无法继承CodeFunctionNode ,需要在shader里创建一个Custom Function Node
上面代码改成hlsl就行了,或者简单的直接用string body
2.范围扭曲节点
using UnityEngine;
using UnityEditor.ShaderGraph;
using System.Reflection;
[Title("Custom", "Domain Warping")]
public class DomainWarpingNode : CodeFunctionNode
{
public DomainWarpingNode()
{
name = "Domain Warping";
}
protected override MethodInfo GetFunctionToConvert()
{
return GetType().GetMethod("DomainWarpingNode_Function",
BindingFlags.Static | BindingFlags.NonPublic);
}
public override void GenerateNodeFunction(FunctionRegistry registry, GraphContext graphContext, GenerationMode generationMode)
{
registry.ProvideFunction("random", s => s.Append(@"
float random(float2 st) {
return frac(sin(dot(st.xy,
float2(12.9898,78.233)))*
43758.5453123);
}
"));
registry.ProvideFunction("noise", s => s.Append(@"
float noise (float2 st) {
float2 i = floor(st);
float2 f = frac(st);
// Four corners in 2D of a tile
float a = random(i);
float b = random(i + float2(1.0, 0.0));
float c = random(i + float2(0.0, 1.0));
float d = random(i + float2(1.0, 1.0));
float2 u = f * f * (3.0 - 2.0 * f);
return lerp(a, b, u.x) +
(c - a)* u.y * (1.0 - u.x) +
(d - b) * u.x * u.y;
}
"));
registry.ProvideFunction("fbm", s => s.Append(@"
#define OCTAVES 6
float fbm (float2 st) {
// Initial values
float value = 0.0;
float amplitude = .5;
float frequency = 0.;
// Loop of octaves
for (int i = 0; i < OCTAVES; i++) {
value += amplitude * noise(st);
st *= 2.;
amplitude *= .5;
}
return value;
}
"));
registry.ProvideFunction("pattern_1", s => s.Append(@"
float pattern_1 (float2 p) {
return fbm(p);
}
"));
registry.ProvideFunction("pattern_2", s => s.Append(@"
float pattern_2 (float2 p) {
float2 q = float2(
fbm( p + float2(0.0,0.0) ),
fbm( p + float2(5.2,1.3) )
);
return fbm( p + 4.0*q );
}
"));
registry.ProvideFunction("pattern_3", s => s.Append(@"
float pattern_3 (float2 p) {
// first domain warping
float2 q = float2(
fbm( p + float2(0.0,0.0) ),
fbm( p + float2(5.2,1.3) )
);
// second domain warping
float2 r = float2(
fbm( p + 4.0*q + float2(1.7,9.2) ),
fbm( p + 4.0*q + float2(8.3,2.8) )
);
return fbm( p + 4.0*r );
}
"));
registry.ProvideFunction("pattern", s => s.Append(@"
float pattern (float2 p, float4 scale_1, float scale_2, float4 add_1, float4 add_2) {
// first domain warping
float2 q = float2(
fbm( p + scale_1.x * add_1.xy ),
fbm( p + scale_1.y * add_1.zw )
);
// second domain warping
float2 r = float2(
fbm( p + scale_1.z * q + add_2.xy ),
fbm( p + scale_1.w * q + add_2.zw )
);
return fbm( p + scale_2 * r );
}
"));
base.GenerateNodeFunction(registry, graphContext, generationMode);
}
static string DomainWarpingNode_Function(
[Slot(0, Binding.MeshUV0)] Vector2 UV,
[Slot(1, Binding.None, 0f, 0f, 5.2f, 1.3f)] Vector4 Fbm_AddFactor_1,
[Slot(2, Binding.None, 1.7f, 9.2f, 8.3f, 2.8f)] Vector4 Fbm_AddFactor_2,
[Slot(3, Binding.None, 1f, 1f, 4f, 4f)] Vector4 Fbm_ScaleFactor_1,
[Slot(4, Binding.None, 4f, 0f, 0f, 0f)] Vector1 Fbm_ScaleFactor_2,
[Slot(5, Binding.None)] out Vector1 Pattern
)
{
return @"{
Pattern = pattern(UV, Fbm_ScaleFactor_1, Fbm_ScaleFactor_2, Fbm_AddFactor_1, Fbm_AddFactor_2);
}";
}
}
新版本同样,改成hlsl