You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

141 lines
6.0 KiB

using System.Collections.Generic;
using System;
using UnityEngine;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph;
using UnityEditor.ShaderGraph.Drawing.Controls;
using UnityEditor.ShaderGraph.Internal;
namespace UnityEditor.ShaderGraph
{
enum RefractMode
{
CriticalAngle,
Safe
};
[FormerName("UnityEditor.Rendering.HighDefinition.HDRefractNode")]
[Title("Math", "Vector", "Refract")]
class RefractNode : AbstractMaterialNode
, IGeneratesBodyCode
, IGeneratesFunction
{
[SerializeField]
private RefractMode m_RefractMode = RefractMode.Safe;
const int kIncidentInputSlotId = 0;
const string kIncidentInputSlotName = "Incident";
const int kNormalInputSlotId = 1;
const string kNormalInputSlotName = "Normal";
const int kIORSourceInputSlotId = 2;
const string kIORSourceInputSlotName = "IORSource";
const int kIORMediumInputSlotId = 3;
const string kIORMediumInputSlotName = "IORMedium";
const int kRefractedOutputSlotId = 4;
const string kRefractedOutputSlotName = "Refracted";
const int kIntensityOutputSlotId = 5;
const string kIntensityOutputSlotName = "Intensity";
[EnumControl("Mode")]
public RefractMode refractMode
{
get { return m_RefractMode; }
set
{
if (m_RefractMode == value)
return;
m_RefractMode = value;
Dirty(ModificationScope.Graph);
}
}
public RefractNode()
{
name = "Refract";
synonyms = new string[] { "refract", "warp", "bend", "distort" };
UpdateNodeAfterDeserialization();
}
public override bool hasPreview { get { return true; } }
public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new Vector3MaterialSlot(kIncidentInputSlotId, kIncidentInputSlotName, kIncidentInputSlotName, SlotType.Input, Vector3.forward));
AddSlot(new Vector3MaterialSlot(kNormalInputSlotId, kNormalInputSlotName, kNormalInputSlotName, SlotType.Input, -Vector3.forward));
AddSlot(new Vector1MaterialSlot(kIORSourceInputSlotId, kIORSourceInputSlotName, kIORSourceInputSlotName, SlotType.Input, 1.0f));
AddSlot(new Vector1MaterialSlot(kIORMediumInputSlotId, kIORMediumInputSlotName, kIORMediumInputSlotName, SlotType.Input, 1.5f));
AddSlot(new Vector3MaterialSlot(kRefractedOutputSlotId, kRefractedOutputSlotName, kRefractedOutputSlotName, SlotType.Output, Vector3.forward));
AddSlot(new Vector1MaterialSlot(kIntensityOutputSlotId, kIntensityOutputSlotName, kIntensityOutputSlotName, SlotType.Output, 1.0f));
RemoveSlotsNameNotMatching(new[]
{
kIncidentInputSlotId,
kNormalInputSlotId,
kIORSourceInputSlotId,
kIORMediumInputSlotId,
kRefractedOutputSlotId,
kIntensityOutputSlotId
});
}
string GetFunctionName()
{
return string.Format("Unity_Refract_{0}_$precision", m_RefractMode.ToString());
}
public void GenerateNodeFunction(FunctionRegistry registry, GenerationMode generationMode)
{
registry.RequiresIncludePath("Packages/com.unity.render-pipelines.core/ShaderLibrary/BSDF.hlsl");
registry.ProvideFunction(GetFunctionName(), s =>
{
s.AppendLine("void {0}(out $precision3 Refracted, out $precision3 Intensity, $precision3 Incident, $precision3 Normal, $precision IORSource, $precision IORMedium)", GetFunctionName());
using (s.BlockScope())
{
s.AppendLine("$precision internalIORSource = max(IORSource, 1.0);");
s.AppendLine("$precision internalIORMedium = max(IORMedium, 1.0);");
s.AppendLine("$precision eta = internalIORSource/internalIORMedium;");
s.AppendLine("$precision cos0 = dot(Incident, Normal);");
s.AppendLine("$precision k = 1.0 - eta*eta*(1.0 - cos0*cos0);");
if (m_RefractMode == RefractMode.Safe)
{
s.AppendLine("Refracted = eta*Incident - (eta*cos0 + sqrt(max(k, 0.0)))*Normal;");
}
else
{
s.AppendLine("Refracted = k >= 0.0 ? eta*Incident - (eta*cos0 + sqrt(k))*Normal : reflect(Incident, Normal);");
}
s.AppendLine("Intensity = internalIORSource <= internalIORMedium ?");
s.AppendLine(" saturate(F_Transm_Schlick(IorToFresnel0(internalIORMedium, internalIORSource), -cos0)) :");
s.AppendLine(" (k >= 0.0 ? F_FresnelDielectric(internalIORMedium/internalIORSource, -cos0) : ");
if (m_RefractMode == RefractMode.Safe)
{
s.Append("0.0);");
}
else
{
s.Append("1.0);");
}
}
});
}
public void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
{
sb.AppendLine("$precision3 {0};", GetVariableNameForSlot(kRefractedOutputSlotId));
sb.AppendLine("$precision3 {0};", GetVariableNameForSlot(kIntensityOutputSlotId));
sb.AppendLine("{0}({1}, {2}, {3}, {4}, {5}, {6});",
GetFunctionName(),
GetVariableNameForSlot(kRefractedOutputSlotId),
GetVariableNameForSlot(kIntensityOutputSlotId),
GetSlotValue(kIncidentInputSlotId, generationMode),
GetSlotValue(kNormalInputSlotId, generationMode),
GetSlotValue(kIORSourceInputSlotId, generationMode),
GetSlotValue(kIORMediumInputSlotId, generationMode)
);
}
}
}