您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
186 行
7.9 KiB
186 行
7.9 KiB
using UnityEngine;
|
|
using UnityEditor.Graphing;
|
|
|
|
namespace UnityEditor.ShaderGraph
|
|
{
|
|
[Title("UV/MultiLayerParallax")]
|
|
public class MultiLayerParallaxNode : AbstractMaterialNode, IGeneratesBodyCode, IGeneratesFunction, IMayRequireMeshUV, IMayRequireViewDirection
|
|
{
|
|
protected const string kInputDepthShaderName = "Depth";
|
|
protected const string kInputFadeRateShaderName = "FadeRate";
|
|
protected const string kInputLayerCountShaderName = "LayerCount";
|
|
protected const string kTextureSlotShaderName = "Texture";
|
|
protected const string kOutputSlotShaderName = "Result";
|
|
|
|
public const int InputDepthSlotId = 0; // 'depth'
|
|
public const int InputFadeRateSlotId = 1; // 'fade_rate'
|
|
public const int InputLayerCountSlotId = 2; // 'layer_count'
|
|
public const int TextureSlotId = 3; // 'tex'
|
|
public const int OutputSlotId = 4; // 'result'
|
|
|
|
public override bool hasPreview
|
|
{
|
|
get { return true; }
|
|
}
|
|
|
|
public override PreviewMode previewMode
|
|
{
|
|
get
|
|
{
|
|
return PreviewMode.Preview3D;
|
|
}
|
|
}
|
|
|
|
public MultiLayerParallaxNode()
|
|
{
|
|
name = "MultiLayerParallax";
|
|
UpdateNodeAfterDeserialization();
|
|
}
|
|
|
|
public string GetFunctionName()
|
|
{
|
|
return "unity_multilayer_parallax_" + precision;
|
|
}
|
|
|
|
public sealed override void UpdateNodeAfterDeserialization()
|
|
{
|
|
AddSlot(GetInputDepthSlot());
|
|
AddSlot(GetInputFadeRateSlot());
|
|
AddSlot(GetInputLayerCountSlot());
|
|
AddSlot(GetTextureSlot());
|
|
AddSlot(GetOutputSlot());
|
|
RemoveSlotsNameNotMatching(validSlots);
|
|
}
|
|
|
|
protected int[] validSlots
|
|
{
|
|
get { return new[] { InputDepthSlotId, InputFadeRateSlotId, InputLayerCountSlotId, TextureSlotId, OutputSlotId }; }
|
|
}
|
|
|
|
protected virtual MaterialSlot GetInputDepthSlot()
|
|
{
|
|
return new Vector1MaterialSlot(InputDepthSlotId, GetInputSlot1Name(), kInputDepthShaderName, SlotType.Input,0);
|
|
}
|
|
|
|
protected virtual MaterialSlot GetInputFadeRateSlot()
|
|
{
|
|
return new DynamicVectorMaterialSlot(InputFadeRateSlotId, GetInputSlot2Name(), kInputFadeRateShaderName, SlotType.Input, Vector4.zero);
|
|
}
|
|
|
|
protected virtual MaterialSlot GetInputLayerCountSlot()
|
|
{
|
|
return new DynamicVectorMaterialSlot(InputLayerCountSlotId, GetInputSlot3Name(), kInputLayerCountShaderName, SlotType.Input, Vector4.zero);
|
|
}
|
|
|
|
protected virtual MaterialSlot GetTextureSlot()
|
|
{
|
|
return new Texture2DMaterialSlot(TextureSlotId, GetTextureSlotName(), kTextureSlotShaderName, SlotType.Input);
|
|
}
|
|
|
|
protected virtual MaterialSlot GetOutputSlot()
|
|
{
|
|
return new DynamicVectorMaterialSlot(OutputSlotId, GetOutputSlotName(), kOutputSlotShaderName, SlotType.Output, Vector4.zero);
|
|
}
|
|
|
|
protected virtual string GetInputSlot1Name()
|
|
{
|
|
return kInputDepthShaderName;
|
|
}
|
|
|
|
protected virtual string GetInputSlot2Name()
|
|
{
|
|
return kInputFadeRateShaderName;
|
|
}
|
|
|
|
protected virtual string GetInputSlot3Name()
|
|
{
|
|
return kInputLayerCountShaderName;
|
|
}
|
|
|
|
protected virtual string GetTextureSlotName()
|
|
{
|
|
return kTextureSlotShaderName;
|
|
}
|
|
|
|
protected virtual string GetOutputSlotName()
|
|
{
|
|
return kOutputSlotShaderName;
|
|
}
|
|
|
|
protected virtual string GetFunctionPrototype(string depth, string fadeRate, string layerCount, string tex, string UVs, string viewTangentSpace)
|
|
{
|
|
var input1 = ConvertConcreteSlotValueTypeToString(precision, FindInputSlot<MaterialSlot>(InputDepthSlotId).concreteValueType);
|
|
var input2 = ConvertConcreteSlotValueTypeToString(precision, FindInputSlot<MaterialSlot>(InputFadeRateSlotId).concreteValueType);
|
|
var input3 = ConvertConcreteSlotValueTypeToString(precision, FindInputSlot<MaterialSlot>(InputLayerCountSlotId).concreteValueType);
|
|
var output = ConvertConcreteSlotValueTypeToString(precision, FindOutputSlot<MaterialSlot>(OutputSlotId).concreteValueType);
|
|
|
|
return string.Format("inline {0} {1} ({2} {3}, {4} {5}, {6} {7}, " + "sampler2D {8}, {9}2 {10}, {9}3 {11})", output, GetFunctionName(), input1, depth, input2, fadeRate, input3, layerCount, tex, precision, UVs, viewTangentSpace);
|
|
}
|
|
|
|
public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode)
|
|
{
|
|
NodeUtils.SlotConfigurationExceptionIfBadConfiguration(this, new[] { InputDepthSlotId, InputFadeRateSlotId, InputLayerCountSlotId, TextureSlotId }, new[] { OutputSlotId });
|
|
string depthValue = GetSlotValue(InputDepthSlotId, generationMode);
|
|
string fadeRateValue = GetSlotValue(InputFadeRateSlotId, generationMode);
|
|
string layerCountValue = GetSlotValue(InputLayerCountSlotId, generationMode);
|
|
string textureValue = GetSlotValue(TextureSlotId, generationMode);
|
|
|
|
var output = ConvertConcreteSlotValueTypeToString(precision, FindOutputSlot<MaterialSlot>(OutputSlotId).concreteValueType);
|
|
visitor.AddShaderChunk(string.Format("{0} {1} = {2};", output, GetVariableNameForSlot(OutputSlotId), GetFunctionCallBody(depthValue, fadeRateValue, layerCountValue, textureValue)), true);
|
|
}
|
|
|
|
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
|
|
{
|
|
var outputString = new ShaderGenerator();
|
|
outputString.AddShaderChunk(GetFunctionPrototype("depth", "fadeRate", "layerCount", "tex", "UVs", "viewTangentSpace"), false);
|
|
outputString.AddShaderChunk("{", false);
|
|
outputString.Indent();
|
|
|
|
outputString.AddShaderChunk(precision + "2 texcoord = UVs;", false);
|
|
outputString.AddShaderChunk(precision + "2 offset = -viewTangentSpace.xy * depth / layerCount;", false);
|
|
|
|
var output = ConvertConcreteSlotValueTypeToString(precision, FindOutputSlot<MaterialSlot>(OutputSlotId).concreteValueType);
|
|
outputString.AddShaderChunk(output + " result = 0.0f;", false);
|
|
outputString.AddShaderChunk(output + " fade = 1.0f;", false);
|
|
outputString.AddShaderChunk(precision + " alpha = 0.0f;", false);
|
|
|
|
outputString.AddShaderChunk("for (int i = 0; i < 10; i++) {", false);
|
|
outputString.Indent();
|
|
|
|
outputString.AddShaderChunk("result += fade * tex2D(tex, texcoord);", false);
|
|
outputString.AddShaderChunk("texcoord += offset;", false);
|
|
outputString.AddShaderChunk("fade *= fadeRate;", false);
|
|
|
|
outputString.Deindent();
|
|
outputString.AddShaderChunk("}", false);
|
|
|
|
outputString.AddShaderChunk("return result / layerCount;", false);
|
|
|
|
outputString.Deindent();
|
|
outputString.AddShaderChunk("}", false);
|
|
|
|
visitor.AddShaderChunk(outputString.GetShaderString(0), true);
|
|
}
|
|
|
|
protected virtual string GetFunctionCallBody(string depthValue, string fadeRateValue, string layerCountValue, string texValue)
|
|
{
|
|
return GetFunctionName() + " (" +
|
|
depthValue + ", " +
|
|
fadeRateValue + ", " +
|
|
layerCountValue + ", " +
|
|
texValue + ", " +
|
|
UVChannel.uv0.GetUVName() + ", " +
|
|
CoordinateSpace.View.ToVariableName(InterpolatorType.Tangent) + ")";
|
|
}
|
|
|
|
public bool RequiresMeshUV(UVChannel channel)
|
|
{
|
|
return channel == UVChannel.uv0;
|
|
}
|
|
|
|
public NeededCoordinateSpace RequiresViewDirection()
|
|
{
|
|
return NeededCoordinateSpace.Tangent;
|
|
}
|
|
}
|
|
}
|