initial commit
This commit is contained in:
parent
6715289efe
commit
788c3389af
37645 changed files with 2526849 additions and 80 deletions
|
@ -0,0 +1,193 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.ShaderGraph.Drawing.Controls;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
using UnityEngine;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("UV", "Flipbook")]
|
||||
class FlipbookNode : AbstractMaterialNode, IGeneratesBodyCode, IGeneratesFunction, IMayRequireMeshUV
|
||||
{
|
||||
public FlipbookNode()
|
||||
{
|
||||
name = "Flipbook";
|
||||
synonyms = new string[] { "atlas", "animation" };
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
const int UVSlotId = 0;
|
||||
const int WidthSlotId = 1;
|
||||
const int HeightSlotId = 2;
|
||||
const int TileSlotId = 3;
|
||||
const int OutputSlotId = 4;
|
||||
const string kUVSlotName = "UV";
|
||||
const string kWidthSlotName = "Width";
|
||||
const string kHeightSlotName = "Height";
|
||||
const string kTileSlotName = "Tile";
|
||||
const string kOutputSlotName = "Out";
|
||||
|
||||
public override bool hasPreview
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
string GetFunctionName()
|
||||
{
|
||||
string invertText = string.Empty;
|
||||
|
||||
if (m_InvertX && m_InvertY)
|
||||
invertText = "InvertXY_";
|
||||
else if (m_InvertX)
|
||||
invertText = "InvertX_";
|
||||
else if (m_InvertY)
|
||||
invertText = "InvertY_";
|
||||
|
||||
return $"Unity_Flipbook_{invertText}$precision";
|
||||
}
|
||||
|
||||
public sealed override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
AddSlot(new UVMaterialSlot(UVSlotId, kUVSlotName, kUVSlotName, UVChannel.UV0));
|
||||
AddSlot(new Vector1MaterialSlot(WidthSlotId, kWidthSlotName, kWidthSlotName, SlotType.Input, 1));
|
||||
AddSlot(new Vector1MaterialSlot(HeightSlotId, kHeightSlotName, kHeightSlotName, SlotType.Input, 1));
|
||||
AddSlot(new Vector1MaterialSlot(TileSlotId, kTileSlotName, kTileSlotName, SlotType.Input, 0));
|
||||
AddSlot(new Vector2MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, Vector2.zero));
|
||||
RemoveSlotsNameNotMatching(new[] { UVSlotId, WidthSlotId, HeightSlotId, TileSlotId, OutputSlotId });
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private bool m_InvertX = false;
|
||||
|
||||
[ToggleControl("Invert X")]
|
||||
public ToggleData invertX
|
||||
{
|
||||
get { return new ToggleData(m_InvertX); }
|
||||
set
|
||||
{
|
||||
if (m_InvertX == value.isOn)
|
||||
return;
|
||||
m_InvertX = value.isOn;
|
||||
Dirty(ModificationScope.Graph);
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private bool m_InvertY = true;
|
||||
|
||||
[ToggleControl("Invert Y")]
|
||||
public ToggleData invertY
|
||||
{
|
||||
get { return new ToggleData(m_InvertY); }
|
||||
set
|
||||
{
|
||||
if (m_InvertY == value.isOn)
|
||||
return;
|
||||
m_InvertY = value.isOn;
|
||||
Dirty(ModificationScope.Graph);
|
||||
}
|
||||
}
|
||||
|
||||
public void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
|
||||
{
|
||||
var uvValue = GetSlotValue(UVSlotId, generationMode);
|
||||
var widthValue = GetSlotValue(WidthSlotId, generationMode);
|
||||
var heightValue = GetSlotValue(HeightSlotId, generationMode);
|
||||
var tileValue = GetSlotValue(TileSlotId, generationMode);
|
||||
var outputValue = GetSlotValue(OutputSlotId, generationMode);
|
||||
|
||||
sb.AppendLine("{0} {1};", FindOutputSlot<MaterialSlot>(OutputSlotId).concreteValueType.ToShaderString(), GetVariableNameForSlot(OutputSlotId));
|
||||
if (!generationMode.IsPreview())
|
||||
{
|
||||
sb.AppendLine("$precision2 _{0}_Invert = $precision2 ({1}, {2});", GetVariableNameForNode(), invertX.isOn ? 1 : 0, invertY.isOn ? 1 : 0);
|
||||
}
|
||||
sb.AppendLine("{0}({1}, {2}, {3}, {4}, _{5}_Invert, {6});", GetFunctionName(), uvValue, widthValue, heightValue, tileValue, GetVariableNameForNode(), outputValue);
|
||||
}
|
||||
|
||||
public override void CollectPreviewMaterialProperties(List<PreviewProperty> properties)
|
||||
{
|
||||
base.CollectPreviewMaterialProperties(properties);
|
||||
|
||||
properties.Add(new PreviewProperty(PropertyType.Vector2)
|
||||
{
|
||||
name = string.Format("_{0}_Invert", GetVariableNameForNode()),
|
||||
vector4Value = new Vector2(invertX.isOn ? 1 : 0, invertY.isOn ? 1 : 0)
|
||||
});
|
||||
}
|
||||
|
||||
public override void CollectShaderProperties(PropertyCollector properties, GenerationMode generationMode)
|
||||
{
|
||||
if (!generationMode.IsPreview())
|
||||
return;
|
||||
|
||||
base.CollectShaderProperties(properties, generationMode);
|
||||
|
||||
properties.AddShaderProperty(new Vector2ShaderProperty()
|
||||
{
|
||||
overrideReferenceName = string.Format("_{0}_Invert", GetVariableNameForNode()),
|
||||
generatePropertyBlock = false
|
||||
});
|
||||
}
|
||||
|
||||
public void GenerateNodeFunction(FunctionRegistry registry, GenerationMode generationMode)
|
||||
{
|
||||
registry.ProvideFunction(GetFunctionName(), s =>
|
||||
{
|
||||
s.AppendLine("void {0} ({1} UV, {2} Width, {3} Height, {4} Tile, $precision2 Invert, out {5} Out)",
|
||||
GetFunctionName(),
|
||||
FindInputSlot<MaterialSlot>(UVSlotId).concreteValueType.ToShaderString(),
|
||||
FindInputSlot<MaterialSlot>(WidthSlotId).concreteValueType.ToShaderString(),
|
||||
FindInputSlot<MaterialSlot>(HeightSlotId).concreteValueType.ToShaderString(),
|
||||
FindInputSlot<MaterialSlot>(TileSlotId).concreteValueType.ToShaderString(),
|
||||
FindOutputSlot<MaterialSlot>(OutputSlotId).concreteValueType.ToShaderString());
|
||||
using (s.BlockScope())
|
||||
{
|
||||
s.AppendLine("Tile = floor(fmod(Tile + $precision(0.00001), Width*Height));");
|
||||
s.AppendLine("$precision2 tileCount = $precision2(1.0, 1.0) / $precision2(Width, Height);");
|
||||
|
||||
AppendInvertSpecificLines(s);
|
||||
|
||||
s.AppendLine("Out = (UV + $precision2(tileX, tileY)) * tileCount;");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void AppendInvertSpecificLines(ShaderStringBuilder stringBuilder)
|
||||
{
|
||||
if (m_InvertX)
|
||||
{
|
||||
stringBuilder.AppendLine("$precision tileX = (Invert.x * Width - ((Tile - Width * floor(Tile * tileCount.x)) + Invert.x * 1));");
|
||||
}
|
||||
else
|
||||
{
|
||||
stringBuilder.AppendLine("$precision tileX = (Tile - Width * floor(Tile * tileCount.x));");
|
||||
}
|
||||
|
||||
if (m_InvertY)
|
||||
{
|
||||
stringBuilder.AppendLine("$precision tileY = (Invert.y * Height - (floor(Tile * tileCount.x) + Invert.y * 1));");
|
||||
}
|
||||
else
|
||||
{
|
||||
stringBuilder.AppendLine("$precision tileY = (floor(Tile * tileCount.x));");
|
||||
}
|
||||
}
|
||||
|
||||
public bool RequiresMeshUV(UVChannel channel, ShaderStageCapability stageCapability)
|
||||
{
|
||||
using (var tempSlots = PooledList<MaterialSlot>.Get())
|
||||
{
|
||||
GetInputSlots(tempSlots);
|
||||
foreach (var slot in tempSlots)
|
||||
{
|
||||
if (slot.RequiresMeshUV(channel))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c31e2a2017d86b14192cc8a9fec5fffb
|
||||
timeCreated: 1495718285
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,100 @@
|
|||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("UV", "Parallax Mapping")]
|
||||
class ParallaxMappingNode : AbstractMaterialNode, IGeneratesBodyCode, IGeneratesFunction, IMayRequireViewDirection, IMayRequireMeshUV
|
||||
{
|
||||
public ParallaxMappingNode()
|
||||
{
|
||||
name = "Parallax Mapping";
|
||||
synonyms = new string[] { "offset mapping" };
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
// Input slots
|
||||
private const int kHeightmapSlotId = 1;
|
||||
private const string kHeightmapSlotName = "Heightmap";
|
||||
private const int kHeightmapSamplerSlotId = 2;
|
||||
private const string kHeightmapSamplerSlotName = "HeightmapSampler";
|
||||
private const int kAmplitudeSlotId = 3;
|
||||
private const string kAmplitudeSlotName = "Amplitude";
|
||||
private const int kUVsSlotId = 4;
|
||||
private const string kUVsSlotName = "UVs";
|
||||
|
||||
|
||||
// Output slots
|
||||
private const int kParallaxUVsOutputSlotId = 0;
|
||||
private const string kParallaxUVsOutputSlotName = "ParallaxUVs";
|
||||
|
||||
public override bool hasPreview { get { return false; } }
|
||||
|
||||
public sealed override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
AddSlot(new Texture2DInputMaterialSlot(kHeightmapSlotId, kHeightmapSlotName, kHeightmapSlotName, ShaderStageCapability.Fragment));
|
||||
AddSlot(new SamplerStateMaterialSlot(kHeightmapSamplerSlotId, kHeightmapSamplerSlotName, kHeightmapSamplerSlotName, SlotType.Input));
|
||||
AddSlot(new Vector1MaterialSlot(kAmplitudeSlotId, kAmplitudeSlotName, kAmplitudeSlotName, SlotType.Input, 1, ShaderStageCapability.Fragment));
|
||||
AddSlot(new UVMaterialSlot(kUVsSlotId, kUVsSlotName, kUVsSlotName, UVChannel.UV0, ShaderStageCapability.Fragment));
|
||||
|
||||
AddSlot(new Vector2MaterialSlot(kParallaxUVsOutputSlotId, kParallaxUVsOutputSlotName, kParallaxUVsOutputSlotName, SlotType.Output, Vector2.zero, ShaderStageCapability.Fragment));
|
||||
RemoveSlotsNameNotMatching(new[]
|
||||
{
|
||||
kParallaxUVsOutputSlotId,
|
||||
kHeightmapSlotId,
|
||||
kHeightmapSamplerSlotId,
|
||||
kAmplitudeSlotId,
|
||||
kUVsSlotId,
|
||||
});
|
||||
}
|
||||
|
||||
public override void Setup()
|
||||
{
|
||||
base.Setup();
|
||||
var textureSlot = FindInputSlot<Texture2DInputMaterialSlot>(kHeightmapSlotId);
|
||||
textureSlot.defaultType = Texture2DShaderProperty.DefaultType.Black;
|
||||
}
|
||||
|
||||
public void GenerateNodeFunction(FunctionRegistry registry, GenerationMode generationMode)
|
||||
{
|
||||
registry.RequiresIncludePath("Packages/com.unity.render-pipelines.core/ShaderLibrary/ParallaxMapping.hlsl");
|
||||
}
|
||||
|
||||
public void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
|
||||
{
|
||||
var heightmap = GetSlotValue(kHeightmapSlotId, generationMode);
|
||||
var samplerSlot = FindInputSlot<MaterialSlot>(kHeightmapSamplerSlotId);
|
||||
var edgesSampler = owner.GetEdges(samplerSlot.slotReference);
|
||||
var amplitude = GetSlotValue(kAmplitudeSlotId, generationMode);
|
||||
var uvs = GetSlotValue(kUVsSlotId, generationMode);
|
||||
|
||||
sb.AppendLines(String.Format(@"$precision2 {5} = {0}.GetTransformedUV({4}) + ParallaxMapping(TEXTURE2D_ARGS({0}.tex, {1}.samplerstate), IN.{2}, {3} * 0.01, {0}.GetTransformedUV({4}));",
|
||||
heightmap,
|
||||
edgesSampler.Any() ? GetSlotValue(kHeightmapSamplerSlotId, generationMode) : heightmap,
|
||||
CoordinateSpace.Tangent.ToVariableName(InterpolatorType.ViewDirection),
|
||||
amplitude, // cm in the interface so we multiply by 0.01 in the shader to convert in meter
|
||||
uvs,
|
||||
GetSlotValue(kParallaxUVsOutputSlotId, generationMode)
|
||||
));
|
||||
}
|
||||
|
||||
public NeededCoordinateSpace RequiresViewDirection(ShaderStageCapability stageCapability = ShaderStageCapability.All)
|
||||
{
|
||||
return NeededCoordinateSpace.Tangent;
|
||||
}
|
||||
|
||||
public bool RequiresMeshUV(UVChannel channel, ShaderStageCapability stageCapability)
|
||||
{
|
||||
if (channel != UVChannel.UV0)
|
||||
return false;
|
||||
|
||||
if (IsSlotConnected(kUVsSlotId))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 296397d582e70314a9aec3252db586ad
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,221 @@
|
|||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
using System.Linq;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("UV", "Parallax Occlusion Mapping")]
|
||||
[FormerName("UnityEditor.Experimental.Rendering.HDPipeline.ParallaxOcclusionMappingNode")]
|
||||
[FormerName("UnityEditor.Rendering.HighDefinition.ParallaxOcclusionMappingNode")]
|
||||
class ParallaxOcclusionMappingNode : AbstractMaterialNode, IGeneratesBodyCode, IGeneratesFunction, IMayRequireViewDirection, IMayRequireMeshUV
|
||||
{
|
||||
public ParallaxOcclusionMappingNode()
|
||||
{
|
||||
name = "Parallax Occlusion Mapping";
|
||||
synonyms = new string[] { "pom" };
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
// Input slots
|
||||
private const int kHeightmapSlotId = 2;
|
||||
private const string kHeightmapSlotName = "Heightmap";
|
||||
private const int kHeightmapSamplerSlotId = 3;
|
||||
private const string kHeightmapSamplerSlotName = "HeightmapSampler";
|
||||
private const int kAmplitudeSlotId = 4;
|
||||
private const string kAmplitudeSlotName = "Amplitude";
|
||||
private const int kStepsSlotId = 5;
|
||||
private const string kStepsSlotName = "Steps";
|
||||
private const int kUVsSlotId = 6;
|
||||
private const string kUVsSlotName = "UVs";
|
||||
private const int kLodSlotId = 7;
|
||||
private const string kLodSlotName = "LOD";
|
||||
private const int kLodThresholdSlotId = 8;
|
||||
private const string kLodThresholdSlotName = "LODThreshold";
|
||||
private const int kTilingSlotId = 10;
|
||||
private const string kTilingSlotName = "Tiling";
|
||||
private const int kOffsetSlotId = 11;
|
||||
private const string kOffsetSlotName = "Offset";
|
||||
private const int kPrimitiveSizeSlotId = 12;
|
||||
private const string kPrimitiveSizeSlotName = "PrimitiveSize";
|
||||
|
||||
// Output slots
|
||||
private const int kPixelDepthOffsetOutputSlotId = 0;
|
||||
private const string kPixelDepthOffsetOutputSlotName = "PixelDepthOffset";
|
||||
private const int kParallaxUVsOutputSlotId = 1;
|
||||
private const string kParallaxUVsOutputSlotName = "ParallaxUVs";
|
||||
|
||||
public override bool hasPreview { get { return false; } }
|
||||
|
||||
public sealed override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
AddSlot(new Texture2DInputMaterialSlot(kHeightmapSlotId, kHeightmapSlotName, kHeightmapSlotName, ShaderStageCapability.Fragment));
|
||||
AddSlot(new SamplerStateMaterialSlot(kHeightmapSamplerSlotId, kHeightmapSamplerSlotName, kHeightmapSamplerSlotName, SlotType.Input));
|
||||
AddSlot(new Vector1MaterialSlot(kAmplitudeSlotId, kAmplitudeSlotName, kAmplitudeSlotName, SlotType.Input, 1.0f, ShaderStageCapability.Fragment));
|
||||
AddSlot(new Vector1MaterialSlot(kStepsSlotId, kStepsSlotName, kStepsSlotName, SlotType.Input, 5.0f, ShaderStageCapability.Fragment));
|
||||
AddSlot(new UVMaterialSlot(kUVsSlotId, kUVsSlotName, kUVsSlotName, UVChannel.UV0, ShaderStageCapability.Fragment));
|
||||
AddSlot(new Vector2MaterialSlot(kTilingSlotId, kTilingSlotName, kTilingSlotName, SlotType.Input, Vector2.one, ShaderStageCapability.Fragment));
|
||||
AddSlot(new Vector2MaterialSlot(kOffsetSlotId, kOffsetSlotName, kOffsetSlotName, SlotType.Input, Vector2.zero, ShaderStageCapability.Fragment));
|
||||
AddSlot(new Vector2MaterialSlot(kPrimitiveSizeSlotId, kPrimitiveSizeSlotName, kPrimitiveSizeSlotName, SlotType.Input, Vector2.one, ShaderStageCapability.Fragment));
|
||||
AddSlot(new Vector1MaterialSlot(kLodSlotId, kLodSlotName, kLodSlotName, SlotType.Input, 0.0f, ShaderStageCapability.Fragment));
|
||||
AddSlot(new Vector1MaterialSlot(kLodThresholdSlotId, kLodThresholdSlotName, kLodThresholdSlotName, SlotType.Input, 0.0f, ShaderStageCapability.Fragment));
|
||||
|
||||
AddSlot(new Vector1MaterialSlot(kPixelDepthOffsetOutputSlotId, kPixelDepthOffsetOutputSlotName, kPixelDepthOffsetOutputSlotName, SlotType.Output, 0.0f, ShaderStageCapability.Fragment));
|
||||
AddSlot(new Vector2MaterialSlot(kParallaxUVsOutputSlotId, kParallaxUVsOutputSlotName, kParallaxUVsOutputSlotName, SlotType.Output, Vector2.zero, ShaderStageCapability.Fragment));
|
||||
RemoveSlotsNameNotMatching(new[]
|
||||
{
|
||||
kPixelDepthOffsetOutputSlotId,
|
||||
kParallaxUVsOutputSlotId,
|
||||
kHeightmapSlotId,
|
||||
kHeightmapSamplerSlotId,
|
||||
kAmplitudeSlotId,
|
||||
kStepsSlotId,
|
||||
kUVsSlotId,
|
||||
kLodSlotId,
|
||||
kLodThresholdSlotId,
|
||||
kTilingSlotId,
|
||||
kOffsetSlotId,
|
||||
kPrimitiveSizeSlotId
|
||||
});
|
||||
}
|
||||
|
||||
string GetFunctionName() => GetVariableNameForNode() + "_$precision";
|
||||
|
||||
public override void Setup()
|
||||
{
|
||||
base.Setup();
|
||||
var textureSlot = FindInputSlot<Texture2DInputMaterialSlot>(kHeightmapSlotId);
|
||||
textureSlot.defaultType = Texture2DShaderProperty.DefaultType.Black;
|
||||
}
|
||||
|
||||
public void GenerateNodeFunction(FunctionRegistry registry, GenerationMode generationMode)
|
||||
{
|
||||
// we don't declare this include via the registry include path
|
||||
// because it uses macro magic, and can be included more than once, generating different functions
|
||||
string perPixelDisplacementInclude = @"#include ""Packages/com.unity.render-pipelines.core/ShaderLibrary/PerPixelDisplacement.hlsl""";
|
||||
|
||||
// Texture sample inputs
|
||||
var samplerSlot = FindInputSlot<MaterialSlot>(kHeightmapSamplerSlotId);
|
||||
var edgesSampler = owner.GetEdges(samplerSlot.slotReference);
|
||||
var heightmap = GetSlotValue(kHeightmapSlotId, generationMode);
|
||||
|
||||
// We first generate components that can be used by multiple POM node
|
||||
registry.ProvideFunction("PerPixelHeightDisplacementParam", s =>
|
||||
{
|
||||
s.AppendLine("struct PerPixelHeightDisplacementParam");
|
||||
using (s.BlockSemicolonScope())
|
||||
{
|
||||
s.AppendLine("float2 uv;");
|
||||
}
|
||||
s.AppendNewLine();
|
||||
});
|
||||
|
||||
registry.ProvideFunction("GetDisplacementObjectScale_$precision", s =>
|
||||
{
|
||||
s.AppendLine($"$precision3 GetDisplacementObjectScale_$precision()");
|
||||
using (s.BlockScope())
|
||||
{
|
||||
s.AppendLines(@"
|
||||
float3 objectScale = float3(1.0, 1.0, 1.0);
|
||||
float4x4 worldTransform = GetWorldToObjectMatrix();
|
||||
|
||||
objectScale.x = length(float3(worldTransform._m00, worldTransform._m01, worldTransform._m02));
|
||||
objectScale.z = length(float3(worldTransform._m20, worldTransform._m21, worldTransform._m22));
|
||||
|
||||
return objectScale;");
|
||||
}
|
||||
});
|
||||
|
||||
// Then we add the functions that are specific to this node
|
||||
registry.ProvideFunction(GetFunctionName(), s =>
|
||||
{
|
||||
s.AppendLine("// Required struct and function for the ParallaxOcclusionMapping function:");
|
||||
s.AppendLine($"$precision ComputePerPixelHeightDisplacement_{GetVariableNameForNode()}($precision2 texOffsetCurrent, $precision lod, PerPixelHeightDisplacementParam param, TEXTURE2D_PARAM(heightTexture, heightSampler))");
|
||||
using (s.BlockScope())
|
||||
{
|
||||
s.AppendLine("return SAMPLE_TEXTURE2D_LOD(heightTexture, heightSampler, param.uv + texOffsetCurrent, lod).r;");
|
||||
}
|
||||
// heightmap,
|
||||
// edgesSampler.Any() ? GetSlotValue(kHeightmapSamplerSlotId, generationMode) : "sampler" + heightmap);
|
||||
|
||||
s.AppendLine($"#define ComputePerPixelHeightDisplacement ComputePerPixelHeightDisplacement_{GetVariableNameForNode()}");
|
||||
s.AppendLine($"#define POM_NAME_ID {GetFunctionName()}");
|
||||
s.AppendLine($"#define POM_USER_DATA_PARAMETERS , TEXTURE2D_PARAM(heightTexture, samplerState)");
|
||||
s.AppendLine($"#define POM_USER_DATA_ARGUMENTS , TEXTURE2D_ARGS(heightTexture, samplerState)");
|
||||
s.AppendLine(perPixelDisplacementInclude);
|
||||
s.AppendLine($"#undef ComputePerPixelHeightDisplacement");
|
||||
s.AppendLine($"#undef POM_NAME_ID");
|
||||
s.AppendLine($"#undef POM_USER_DATA_PARAMETERS");
|
||||
s.AppendLine($"#undef POM_USER_DATA_ARGUMENTS");
|
||||
});
|
||||
}
|
||||
|
||||
public void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
|
||||
{
|
||||
string amplitude = GetSlotValue(kAmplitudeSlotId, generationMode);
|
||||
string steps = GetSlotValue(kStepsSlotId, generationMode);
|
||||
string uvs = GetSlotValue(kUVsSlotId, generationMode);
|
||||
string tiling = GetSlotValue(kTilingSlotId, generationMode);
|
||||
string offset = GetSlotValue(kOffsetSlotId, generationMode);
|
||||
string primitiveSize = GetSlotValue(kPrimitiveSizeSlotId, generationMode);
|
||||
string lod = GetSlotValue(kLodSlotId, generationMode);
|
||||
string lodThreshold = GetSlotValue(kLodThresholdSlotId, generationMode);
|
||||
string heightmap = GetSlotValue(kHeightmapSlotId, generationMode);
|
||||
string sampler = GetSlotValue(kHeightmapSamplerSlotId, generationMode);
|
||||
|
||||
string tmpPOMParam = GetVariableNameForNode() + "_POM";
|
||||
string tmpViewDir = GetVariableNameForNode() + "_ViewDir";
|
||||
string tmpNdotV = GetVariableNameForNode() + "_NdotV";
|
||||
string tmpMaxHeight = GetVariableNameForNode() + "_MaxHeight";
|
||||
string tmpViewDirUV = GetVariableNameForNode() + "_ViewDirUV";
|
||||
string tmpOutHeight = GetVariableNameForNode() + "_OutHeight";
|
||||
string tmpUVs = GetVariableNameForNode() + "_UVs";
|
||||
string tmpUVSpaceScale = GetVariableNameForNode() + "_UVSpaceScale";
|
||||
|
||||
sb.AppendLines($@"
|
||||
$precision3 {tmpViewDir} = IN.{CoordinateSpace.Tangent.ToVariableName(InterpolatorType.ViewDirection)} * GetDisplacementObjectScale_$precision().xzy;
|
||||
$precision {tmpNdotV} = {tmpViewDir}.z;
|
||||
$precision {tmpMaxHeight} = {amplitude} * 0.01; // cm in the interface so we multiply by 0.01 in the shader to convert in meter
|
||||
{tmpMaxHeight} *= 2.0 / ( abs({tiling}.x) + abs({tiling}.y) ); // reduce height based on the tiling values
|
||||
|
||||
$precision2 {tmpUVSpaceScale} = {tmpMaxHeight} * {tiling} / {primitiveSize};
|
||||
|
||||
// Transform the view vector into the UV space.
|
||||
$precision3 {tmpViewDirUV} = normalize($precision3({tmpViewDir}.xy * {tmpUVSpaceScale}, {tmpViewDir}.z)); // TODO: skip normalize
|
||||
|
||||
PerPixelHeightDisplacementParam {tmpPOMParam};
|
||||
|
||||
$precision2 {tmpUVs} = {uvs} * {tiling} + {offset};
|
||||
|
||||
{tmpPOMParam}.uv = {heightmap}.GetTransformedUV({tmpUVs});");
|
||||
|
||||
// to avoid crashes when steps gets too big, and
|
||||
// to avoid divide by zero, we clamp it to the range [1, 256]
|
||||
// This should compile out when steps is a static value.
|
||||
steps = "max(min(" + steps + ", 256), 1)";
|
||||
|
||||
sb.AppendLines($@"
|
||||
$precision {tmpOutHeight};
|
||||
$precision2 {GetVariableNameForSlot(kParallaxUVsOutputSlotId)} = {heightmap}.GetTransformedUV({tmpUVs}) + ParallaxOcclusionMapping{GetFunctionName()}({lod}, {lodThreshold}, {steps}, {tmpViewDirUV}, {tmpPOMParam}, {tmpOutHeight}, TEXTURE2D_ARGS({heightmap}.tex, {sampler}.samplerstate));
|
||||
|
||||
$precision {GetVariableNameForSlot(kPixelDepthOffsetOutputSlotId)} = ({tmpMaxHeight} - {tmpOutHeight} * {tmpMaxHeight}) / max({tmpNdotV}, 0.0001);
|
||||
");
|
||||
}
|
||||
|
||||
public NeededCoordinateSpace RequiresViewDirection(ShaderStageCapability stageCapability = ShaderStageCapability.All)
|
||||
{
|
||||
return NeededCoordinateSpace.Tangent;
|
||||
}
|
||||
|
||||
public bool RequiresMeshUV(UVChannel channel, ShaderStageCapability stageCapability)
|
||||
{
|
||||
if (channel != UVChannel.UV0)
|
||||
return false;
|
||||
|
||||
if (IsSlotConnected(kUVsSlotId))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 66d33cd4e53f2a64b9d5484bc2a8e6b0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,38 @@
|
|||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("UV", "Polar Coordinates")]
|
||||
class PolarCoordinatesNode : CodeFunctionNode
|
||||
{
|
||||
public PolarCoordinatesNode()
|
||||
{
|
||||
name = "Polar Coordinates";
|
||||
}
|
||||
|
||||
protected override MethodInfo GetFunctionToConvert()
|
||||
{
|
||||
return GetType().GetMethod("Unity_PolarCoordinates", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
}
|
||||
|
||||
static string Unity_PolarCoordinates(
|
||||
[Slot(0, Binding.MeshUV0)] Vector2 UV,
|
||||
[Slot(1, Binding.None, 0.5f, 0.5f, 0.5f, 0.5f)] Vector2 Center,
|
||||
[Slot(2, Binding.None, 1.0f, 1.0f, 1.0f, 1.0f)] Vector1 RadialScale,
|
||||
[Slot(3, Binding.None, 1.0f, 1.0f, 1.0f, 1.0f)] Vector1 LengthScale,
|
||||
[Slot(4, Binding.None)] out Vector2 Out)
|
||||
{
|
||||
Out = Vector2.zero;
|
||||
return
|
||||
@"
|
||||
{
|
||||
$precision2 delta = UV - Center;
|
||||
$precision radius = length(delta) * 2 * RadialScale;
|
||||
$precision angle = atan2(delta.x, delta.y) * 1.0/6.28 * LengthScale;
|
||||
Out = $precision2(radius, angle);
|
||||
}
|
||||
";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 254f958f2febf5e42811f813c866bb2e
|
||||
timeCreated: 1495464810
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,38 @@
|
|||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("UV", "Radial Shear")]
|
||||
class RadialShearNode : CodeFunctionNode
|
||||
{
|
||||
public RadialShearNode()
|
||||
{
|
||||
name = "Radial Shear";
|
||||
}
|
||||
|
||||
protected override MethodInfo GetFunctionToConvert()
|
||||
{
|
||||
return GetType().GetMethod("Unity_RadialShear", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
}
|
||||
|
||||
static string Unity_RadialShear(
|
||||
[Slot(0, Binding.MeshUV0)] Vector2 UV,
|
||||
[Slot(1, Binding.None, 0.5f, 0.5f, 0.5f, 0.5f)] Vector2 Center,
|
||||
[Slot(2, Binding.None, 10f, 10f, 10f, 10f)] Vector2 Strength,
|
||||
[Slot(3, Binding.None)] Vector2 Offset,
|
||||
[Slot(4, Binding.None)] out Vector2 Out)
|
||||
{
|
||||
Out = Vector2.zero;
|
||||
return
|
||||
@"
|
||||
{
|
||||
$precision2 delta = UV - Center;
|
||||
$precision delta2 = dot(delta.xy, delta.xy);
|
||||
$precision2 delta_offset = delta2 * Strength;
|
||||
Out = UV + $precision2(delta.y, -delta.x) * delta_offset + Offset;
|
||||
}
|
||||
";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 568baa0401e6eee42a35609013ee8100
|
||||
timeCreated: 1495728068
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,108 @@
|
|||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using UnityEditor.ShaderGraph.Drawing.Controls;
|
||||
using UnityEditor.Graphing;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
enum RotationUnit
|
||||
{
|
||||
Radians,
|
||||
Degrees
|
||||
};
|
||||
|
||||
[Title("UV", "Rotate")]
|
||||
class RotateNode : CodeFunctionNode
|
||||
{
|
||||
[SerializeField]
|
||||
private RotationUnit m_Unit = RotationUnit.Radians;
|
||||
|
||||
[EnumControl("Unit")]
|
||||
public RotationUnit unit
|
||||
{
|
||||
get { return m_Unit; }
|
||||
set
|
||||
{
|
||||
if (m_Unit == value)
|
||||
return;
|
||||
|
||||
m_Unit = value;
|
||||
Dirty(ModificationScope.Graph);
|
||||
}
|
||||
}
|
||||
|
||||
public RotateNode()
|
||||
{
|
||||
name = "Rotate";
|
||||
}
|
||||
|
||||
protected override MethodInfo GetFunctionToConvert()
|
||||
{
|
||||
if (m_Unit == RotationUnit.Radians)
|
||||
return GetType().GetMethod("Unity_Rotate_Radians", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
else
|
||||
return GetType().GetMethod("Unity_Rotate_Degrees", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
}
|
||||
|
||||
static string Unity_Rotate_Radians(
|
||||
[Slot(0, Binding.MeshUV0)] Vector2 UV,
|
||||
[Slot(1, Binding.None, 0.5f, 0.5f, 0.5f, 0.5f)] Vector2 Center,
|
||||
[Slot(2, Binding.None)] Vector1 Rotation,
|
||||
[Slot(3, Binding.None)] out Vector2 Out)
|
||||
{
|
||||
Out = Vector2.zero;
|
||||
|
||||
|
||||
return
|
||||
@"
|
||||
{
|
||||
//rotation matrix
|
||||
UV -= Center;
|
||||
$precision s = sin(Rotation);
|
||||
$precision c = cos(Rotation);
|
||||
|
||||
//center rotation matrix
|
||||
$precision2x2 rMatrix = $precision2x2(c, -s, s, c);
|
||||
rMatrix *= 0.5;
|
||||
rMatrix += 0.5;
|
||||
rMatrix = rMatrix*2 - 1;
|
||||
|
||||
//multiply the UVs by the rotation matrix
|
||||
UV.xy = mul(UV.xy, rMatrix);
|
||||
UV += Center;
|
||||
|
||||
Out = UV;
|
||||
}";
|
||||
}
|
||||
|
||||
static string Unity_Rotate_Degrees(
|
||||
[Slot(0, Binding.MeshUV0)] Vector2 UV,
|
||||
[Slot(1, Binding.None, 0.5f, 0.5f, 0.5f, 0.5f)] Vector2 Center,
|
||||
[Slot(2, Binding.None)] Vector1 Rotation,
|
||||
[Slot(3, Binding.None)] out Vector2 Out)
|
||||
{
|
||||
Out = Vector2.zero;
|
||||
|
||||
return @"
|
||||
{
|
||||
//rotation matrix
|
||||
Rotation = Rotation * (3.1415926f/180.0f);
|
||||
UV -= Center;
|
||||
$precision s = sin(Rotation);
|
||||
$precision c = cos(Rotation);
|
||||
|
||||
//center rotation matrix
|
||||
$precision2x2 rMatrix = $precision2x2(c, -s, s, c);
|
||||
rMatrix *= 0.5;
|
||||
rMatrix += 0.5;
|
||||
rMatrix = rMatrix*2 - 1;
|
||||
|
||||
//multiply the UVs by the rotation matrix
|
||||
UV.xy = mul(UV.xy, rMatrix);
|
||||
UV += Center;
|
||||
|
||||
Out = UV;
|
||||
}";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e3897f68a598da34aa8bd55a3a3236ab
|
||||
timeCreated: 1495456132
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,38 @@
|
|||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("UV", "Spherize")]
|
||||
class SpherizeNode : CodeFunctionNode
|
||||
{
|
||||
public SpherizeNode()
|
||||
{
|
||||
name = "Spherize";
|
||||
}
|
||||
|
||||
protected override MethodInfo GetFunctionToConvert()
|
||||
{
|
||||
return GetType().GetMethod("Unity_Spherize", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
}
|
||||
|
||||
static string Unity_Spherize(
|
||||
[Slot(0, Binding.MeshUV0)] Vector2 UV,
|
||||
[Slot(1, Binding.None, 0.5f, 0.5f, 0.5f, 0.5f)] Vector2 Center,
|
||||
[Slot(2, Binding.None, 10f, 10f, 10f, 10f)] Vector2 Strength,
|
||||
[Slot(3, Binding.None)] Vector2 Offset,
|
||||
[Slot(4, Binding.None)] out Vector2 Out)
|
||||
{
|
||||
Out = Vector2.zero;
|
||||
return
|
||||
@"
|
||||
{
|
||||
$precision2 delta = UV - Center;
|
||||
$precision delta2 = dot(delta.xy, delta.xy);
|
||||
$precision delta4 = delta2 * delta2;
|
||||
$precision2 delta_offset = delta4 * Strength;
|
||||
Out = UV + delta * delta_offset + Offset;
|
||||
}";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: dfd538e33eb01974fad49a2533f8cff8
|
||||
timeCreated: 1495729511
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,35 @@
|
|||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("UV", "Tiling And Offset")]
|
||||
class TilingAndOffsetNode : CodeFunctionNode
|
||||
{
|
||||
public TilingAndOffsetNode()
|
||||
{
|
||||
name = "Tiling And Offset";
|
||||
synonyms = new string[] { "pan", "scale" };
|
||||
}
|
||||
|
||||
protected override MethodInfo GetFunctionToConvert()
|
||||
{
|
||||
return GetType().GetMethod("Unity_TilingAndOffset", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
}
|
||||
|
||||
static string Unity_TilingAndOffset(
|
||||
[Slot(0, Binding.MeshUV0)] Vector2 UV,
|
||||
[Slot(1, Binding.None, 1f, 1f, 1f, 1f)] Vector2 Tiling,
|
||||
[Slot(2, Binding.None, 0f, 0f, 0f, 0f)] Vector2 Offset,
|
||||
[Slot(3, Binding.None)] out Vector2 Out)
|
||||
{
|
||||
Out = Vector2.zero;
|
||||
return
|
||||
@"
|
||||
{
|
||||
Out = UV * Tiling + Offset;
|
||||
}
|
||||
";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 28273174b61bbd246b556e236deb7556
|
||||
timeCreated: 1495726779
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,202 @@
|
|||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Graphing;
|
||||
using UnityEditor.ShaderGraph.Drawing.Controls;
|
||||
using UnityEditor.ShaderGraph.Internal;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("UV", "Triplanar")]
|
||||
class TriplanarNode : AbstractMaterialNode, IGeneratesBodyCode, IMayRequirePosition, IMayRequireNormal, IMayRequireTangent, IMayRequireBitangent
|
||||
{
|
||||
public const int OutputSlotId = 0;
|
||||
public const int TextureInputId = 1;
|
||||
public const int SamplerInputId = 2;
|
||||
public const int PositionInputId = 3;
|
||||
public const int NormalInputId = 4;
|
||||
public const int TileInputId = 5;
|
||||
public const int BlendInputId = 6;
|
||||
const string kOutputSlotName = "Out";
|
||||
const string kTextureInputName = "Texture";
|
||||
const string kSamplerInputName = "Sampler";
|
||||
const string kPositionInputName = "Position";
|
||||
const string kNormalInputName = "Normal";
|
||||
const string kTileInputName = "Tile";
|
||||
const string kBlendInputName = "Blend";
|
||||
|
||||
public override bool hasPreview { get { return true; } }
|
||||
|
||||
public TriplanarNode()
|
||||
{
|
||||
name = "Triplanar";
|
||||
synonyms = new string[] { "project" };
|
||||
m_PreviewMode = PreviewMode.Preview3D;
|
||||
UpdateNodeAfterDeserialization();
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private TextureType m_TextureType = TextureType.Default;
|
||||
|
||||
[EnumControl("Type")]
|
||||
public TextureType textureType
|
||||
{
|
||||
get { return m_TextureType; }
|
||||
set
|
||||
{
|
||||
if (m_TextureType == value)
|
||||
return;
|
||||
|
||||
m_TextureType = value;
|
||||
Dirty(ModificationScope.Graph);
|
||||
|
||||
ValidateNode();
|
||||
}
|
||||
}
|
||||
|
||||
public sealed override void UpdateNodeAfterDeserialization()
|
||||
{
|
||||
AddSlot(new Vector4MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, Vector4.zero, ShaderStageCapability.Fragment));
|
||||
AddSlot(new Texture2DInputMaterialSlot(TextureInputId, kTextureInputName, kTextureInputName));
|
||||
AddSlot(new SamplerStateMaterialSlot(SamplerInputId, kSamplerInputName, kSamplerInputName, SlotType.Input));
|
||||
AddSlot(new PositionMaterialSlot(PositionInputId, kPositionInputName, kPositionInputName, CoordinateSpace.AbsoluteWorld));
|
||||
AddSlot(new NormalMaterialSlot(NormalInputId, kNormalInputName, kNormalInputName, CoordinateSpace.World));
|
||||
AddSlot(new Vector1MaterialSlot(TileInputId, kTileInputName, kTileInputName, SlotType.Input, 1));
|
||||
AddSlot(new Vector1MaterialSlot(BlendInputId, kBlendInputName, kBlendInputName, SlotType.Input, 1));
|
||||
RemoveSlotsNameNotMatching(new[] { OutputSlotId, TextureInputId, SamplerInputId, PositionInputId, NormalInputId, TileInputId, BlendInputId });
|
||||
}
|
||||
|
||||
public override void Setup()
|
||||
{
|
||||
base.Setup();
|
||||
var textureSlot = FindInputSlot<Texture2DInputMaterialSlot>(TextureInputId);
|
||||
textureSlot.defaultType = (textureType == TextureType.Normal ? Texture2DShaderProperty.DefaultType.NormalMap : Texture2DShaderProperty.DefaultType.White);
|
||||
}
|
||||
|
||||
// Node generations
|
||||
public virtual void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
|
||||
{
|
||||
sb.AppendLine("$precision3 {0}_UV = {1} * {2};", GetVariableNameForNode(),
|
||||
GetSlotValue(PositionInputId, generationMode), GetSlotValue(TileInputId, generationMode));
|
||||
|
||||
//Sampler input slot
|
||||
var samplerSlot = FindInputSlot<MaterialSlot>(SamplerInputId);
|
||||
var edgesSampler = owner.GetEdges(samplerSlot.slotReference);
|
||||
var id = GetSlotValue(TextureInputId, generationMode);
|
||||
|
||||
switch (textureType)
|
||||
{
|
||||
// Whiteout blend method
|
||||
// https://medium.com/@bgolus/normal-mapping-for-a-triplanar-shader-10bf39dca05a
|
||||
case TextureType.Normal:
|
||||
// See comment for default case.
|
||||
sb.AppendLine("$precision3 {0}_Blend = SafePositivePow_$precision({1}, min({2}, floor(log2(Min_$precision())/log2(1/sqrt(3)))) );"
|
||||
, GetVariableNameForNode()
|
||||
, GetSlotValue(NormalInputId, generationMode)
|
||||
, GetSlotValue(BlendInputId, generationMode));
|
||||
sb.AppendLine("{0}_Blend /= ({0}_Blend.x + {0}_Blend.y + {0}_Blend.z ).xxx;", GetVariableNameForNode());
|
||||
|
||||
sb.AppendLine("$precision3 {0}_X = UnpackNormal(SAMPLE_TEXTURE2D({1}.tex, {2}.samplerstate, {0}_UV.zy));"
|
||||
, GetVariableNameForNode()
|
||||
, id
|
||||
, edgesSampler.Any() ? GetSlotValue(SamplerInputId, generationMode) : id);
|
||||
|
||||
sb.AppendLine("$precision3 {0}_Y = UnpackNormal(SAMPLE_TEXTURE2D({1}.tex, {2}.samplerstate, {0}_UV.xz));"
|
||||
, GetVariableNameForNode()
|
||||
, id
|
||||
, edgesSampler.Any() ? GetSlotValue(SamplerInputId, generationMode) : id);
|
||||
|
||||
sb.AppendLine("$precision3 {0}_Z = UnpackNormal(SAMPLE_TEXTURE2D({1}.tex, {2}.samplerstate, {0}_UV.xy));"
|
||||
, GetVariableNameForNode()
|
||||
, id
|
||||
, edgesSampler.Any() ? GetSlotValue(SamplerInputId, generationMode) : id);
|
||||
|
||||
sb.AppendLine("{0}_X = $precision3({0}_X.xy + {1}.zy, abs({0}_X.z) * {1}.x);"
|
||||
, GetVariableNameForNode()
|
||||
, GetSlotValue(NormalInputId, generationMode));
|
||||
|
||||
sb.AppendLine("{0}_Y = $precision3({0}_Y.xy + {1}.xz, abs({0}_Y.z) * {1}.y);"
|
||||
, GetVariableNameForNode()
|
||||
, GetSlotValue(NormalInputId, generationMode));
|
||||
|
||||
sb.AppendLine("{0}_Z = $precision3({0}_Z.xy + {1}.xy, abs({0}_Z.z) * {1}.z);"
|
||||
, GetVariableNameForNode()
|
||||
, GetSlotValue(NormalInputId, generationMode));
|
||||
|
||||
sb.AppendLine("$precision4 {0} = $precision4(normalize({1}_X.zyx * {1}_Blend.x + {1}_Y.xzy * {1}_Blend.y + {1}_Z.xyz * {1}_Blend.z), 1);"
|
||||
, GetVariableNameForSlot(OutputSlotId)
|
||||
, GetVariableNameForNode());
|
||||
sb.AppendLine("$precision3x3 {0}_Transform = $precision3x3(IN.WorldSpaceTangent, IN.WorldSpaceBiTangent, IN.WorldSpaceNormal);", GetVariableNameForNode());
|
||||
sb.AppendLine("{0}.rgb = TransformWorldToTangent({0}.rgb, {1}_Transform);"
|
||||
, GetVariableNameForSlot(OutputSlotId)
|
||||
, GetVariableNameForNode());
|
||||
break;
|
||||
default:
|
||||
// We want the sum of the 3 blend weights (by which we normalize them) to be > 0.
|
||||
// Max safe exponent is log2(REAL_MIN)/log2(1/sqrt(3)):
|
||||
// Take the set of all possible normalized vectors, make a set from selecting the maximum component of each 3-vectors from the previous set,
|
||||
// the minimum (:= min_of_max) of that new set is 1/sqrt(3) (by the fact vectors are normalized).
|
||||
// We then want a maximum exponent such that
|
||||
// precision_min < min_of_max^exponent_max
|
||||
// where exponent_max is blend,
|
||||
// log(precision_min) < log(min_of_max) * exponent_max
|
||||
// log(precision_min) / log(min_of_max) > exponent_max
|
||||
sb.AppendLine("$precision3 {0}_Blend = SafePositivePow_$precision({1}, min({2}, floor(log2(Min_$precision())/log2(1/sqrt(3)))) );"
|
||||
, GetVariableNameForNode()
|
||||
, GetSlotValue(NormalInputId, generationMode)
|
||||
, GetSlotValue(BlendInputId, generationMode));
|
||||
sb.AppendLine("{0}_Blend /= dot({0}_Blend, 1.0);", GetVariableNameForNode());
|
||||
sb.AppendLine("$precision4 {0}_X = SAMPLE_TEXTURE2D({1}.tex, {2}.samplerstate, {0}_UV.zy);"
|
||||
, GetVariableNameForNode()
|
||||
, id
|
||||
, edgesSampler.Any() ? GetSlotValue(SamplerInputId, generationMode) : id);
|
||||
|
||||
sb.AppendLine("$precision4 {0}_Y = SAMPLE_TEXTURE2D({1}.tex, {2}.samplerstate, {0}_UV.xz);"
|
||||
, GetVariableNameForNode()
|
||||
, id
|
||||
, edgesSampler.Any() ? GetSlotValue(SamplerInputId, generationMode) : id);
|
||||
|
||||
sb.AppendLine("$precision4 {0}_Z = SAMPLE_TEXTURE2D({1}.tex, {2}.samplerstate, {0}_UV.xy);"
|
||||
, GetVariableNameForNode()
|
||||
, id
|
||||
, edgesSampler.Any() ? GetSlotValue(SamplerInputId, generationMode) : id);
|
||||
|
||||
sb.AppendLine("$precision4 {0} = {1}_X * {1}_Blend.x + {1}_Y * {1}_Blend.y + {1}_Z * {1}_Blend.z;"
|
||||
, GetVariableNameForSlot(OutputSlotId)
|
||||
, GetVariableNameForNode());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public NeededCoordinateSpace RequiresPosition(ShaderStageCapability stageCapability)
|
||||
{
|
||||
return CoordinateSpace.AbsoluteWorld.ToNeededCoordinateSpace() | CoordinateSpace.World.ToNeededCoordinateSpace();
|
||||
}
|
||||
|
||||
public NeededCoordinateSpace RequiresNormal(ShaderStageCapability stageCapability)
|
||||
{
|
||||
return CoordinateSpace.World.ToNeededCoordinateSpace();
|
||||
}
|
||||
|
||||
public NeededCoordinateSpace RequiresTangent(ShaderStageCapability stageCapability)
|
||||
{
|
||||
switch (m_TextureType)
|
||||
{
|
||||
case TextureType.Normal:
|
||||
return CoordinateSpace.World.ToNeededCoordinateSpace();
|
||||
default:
|
||||
return NeededCoordinateSpace.None;
|
||||
}
|
||||
}
|
||||
|
||||
public NeededCoordinateSpace RequiresBitangent(ShaderStageCapability stageCapability)
|
||||
{
|
||||
switch (m_TextureType)
|
||||
{
|
||||
case TextureType.Normal:
|
||||
return CoordinateSpace.World.ToNeededCoordinateSpace();
|
||||
default:
|
||||
return NeededCoordinateSpace.None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2210eee393fa07449a1b51817fdcb679
|
||||
timeCreated: 1495637741
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,40 @@
|
|||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.ShaderGraph
|
||||
{
|
||||
[Title("UV", "Twirl")]
|
||||
class TwirlNode : CodeFunctionNode
|
||||
{
|
||||
public TwirlNode()
|
||||
{
|
||||
name = "Twirl";
|
||||
}
|
||||
|
||||
protected override MethodInfo GetFunctionToConvert()
|
||||
{
|
||||
return GetType().GetMethod("Unity_Twirl", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
}
|
||||
|
||||
static string Unity_Twirl(
|
||||
[Slot(0, Binding.MeshUV0)] Vector2 UV,
|
||||
[Slot(1, Binding.None, 0.5f, 0.5f, 0.5f, 0.5f)] Vector2 Center,
|
||||
[Slot(2, Binding.None, 10f, 0f, 0f, 0f)] Vector1 Strength,
|
||||
[Slot(3, Binding.None)] Vector2 Offset,
|
||||
[Slot(4, Binding.None)] out Vector2 Out)
|
||||
{
|
||||
Out = Vector2.zero;
|
||||
|
||||
return
|
||||
@"
|
||||
{
|
||||
$precision2 delta = UV - Center;
|
||||
$precision angle = Strength * length(delta);
|
||||
$precision x = cos(angle) * delta.x - sin(angle) * delta.y;
|
||||
$precision y = sin(angle) * delta.x + cos(angle) * delta.y;
|
||||
Out = $precision2(x + Center.x + Offset.x, y + Center.y + Offset.y);
|
||||
}
|
||||
";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3933f2692da9060438719b86844dcc7e
|
||||
timeCreated: 1495718285
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Loading…
Add table
Add a link
Reference in a new issue