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.
 
 
 
 

235 lines
10 KiB

using System.Collections.Generic;
using System;
using UnityEngine;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph;
using UnityEditor.ShaderGraph.Drawing.Controls;
using UnityEditor.ShaderGraph.Internal;
using UnityEngine.Rendering.HighDefinition;
namespace UnityEditor.Rendering.HighDefinition
{
enum FresnelEquationMode
{
Schlick,
Dielectric,
DielectricGeneric
};
[SRPFilter(typeof(HDRenderPipeline))]
[Title("Math", "Advanced", "High Definition Render Pipeline", "Fresnel Equation")]
class HDFresnelEquationNode : AbstractMaterialNode
, IGeneratesBodyCode
, IGeneratesFunction
{
[SerializeField]
private FresnelEquationMode m_FresnelEquationMode = FresnelEquationMode.Schlick;
const string kDotVectorsInputSlotName = "Dot Vector";
const string kF0InputSlotName = "F0";
const string kIORSourceInputSlotName = "IOR Source";
const string kIORMediumInputSlotName = "IOR Medium";
const string kIORMediumImInputSlotName = "IOR Medium K";
const string kFresnelOutputSlotName = "Fresnel";
public override string documentationURL => Documentation.GetPageLink("Fresnel-Equation-Node");
private enum FresnelSlots
{
kDotVectorsInputSlotId,
kF0InputSlotId,
kIORSourceInputSlotId,
kIORMediumInputSlotId,
kIORMediumKInputSlotId,
kFresnelOutputSlotId
}
Vector1MaterialSlot dotInputSlot;
Vector1MaterialSlot f0InputSlot;
Vector1MaterialSlot iorSourceInputSlot;
Vector1MaterialSlot iorMediumInputSlot;
Vector1MaterialSlot iorMediumKInputSlot;
Vector1MaterialSlot fresnelOutputSlot;
[EnumControl("Mode")]
public FresnelEquationMode fresnelEquationMode
{
get { return m_FresnelEquationMode; }
set
{
if (m_FresnelEquationMode == value)
return;
m_FresnelEquationMode = value;
UpdateNodeAfterDeserialization();
Dirty(ModificationScope.Graph);
}
}
public HDFresnelEquationNode()
{
name = "Fresnel Equation";
synonyms = new string[] { "fresnel", "schlick", "metal", "dielectric", "tir", "reflection", "critical" };
UpdateNodeAfterDeserialization();
}
public override bool hasPreview { get { return true; } }
public sealed override void UpdateNodeAfterDeserialization()
{
var addedSlots = new List<int>();
dotInputSlot = null;
f0InputSlot = null;
iorSourceInputSlot = null;
iorMediumInputSlot = null;
iorMediumKInputSlot = null;
fresnelOutputSlot = null;
dotInputSlot = new Vector1MaterialSlot((int)FresnelSlots.kDotVectorsInputSlotId, kDotVectorsInputSlotName, kDotVectorsInputSlotName, SlotType.Input, 0.0f);
AddSlot(dotInputSlot);
addedSlots.Add(dotInputSlot.id);
if (m_FresnelEquationMode == FresnelEquationMode.Schlick)
{
f0InputSlot = new Vector1MaterialSlot((int)FresnelSlots.kF0InputSlotId, kF0InputSlotName, kF0InputSlotName, SlotType.Input, 0.04f);
AddSlot(f0InputSlot);
addedSlots.Add(f0InputSlot.id);
}
else if (m_FresnelEquationMode == FresnelEquationMode.Dielectric)
{
iorSourceInputSlot = new Vector1MaterialSlot((int)FresnelSlots.kIORSourceInputSlotId, kIORSourceInputSlotName, kIORSourceInputSlotName, SlotType.Input, 1.0f);
iorMediumInputSlot = new Vector1MaterialSlot((int)FresnelSlots.kIORMediumInputSlotId, kIORMediumInputSlotName, kIORMediumInputSlotName, SlotType.Input, 1.5f);
AddSlot(iorSourceInputSlot);
addedSlots.Add(iorSourceInputSlot.id);
AddSlot(iorMediumInputSlot);
addedSlots.Add(iorMediumInputSlot.id);
}
else if (m_FresnelEquationMode == FresnelEquationMode.DielectricGeneric)
{
iorSourceInputSlot = new Vector1MaterialSlot((int)FresnelSlots.kIORSourceInputSlotId, kIORSourceInputSlotName, kIORSourceInputSlotName, SlotType.Input, 1.0f);
iorMediumInputSlot = new Vector1MaterialSlot((int)FresnelSlots.kIORMediumInputSlotId, kIORMediumInputSlotName, kIORMediumInputSlotName, SlotType.Input, 1.5f);
iorMediumKInputSlot = new Vector1MaterialSlot((int)FresnelSlots.kIORMediumKInputSlotId, kIORMediumImInputSlotName, kIORMediumImInputSlotName, SlotType.Input, 2.0f);
AddSlot(iorSourceInputSlot);
addedSlots.Add(iorSourceInputSlot.id);
AddSlot(iorMediumInputSlot);
addedSlots.Add(iorMediumInputSlot.id);
AddSlot(iorMediumKInputSlot);
addedSlots.Add(iorMediumKInputSlot.id);
}
fresnelOutputSlot = new Vector1MaterialSlot((int)FresnelSlots.kFresnelOutputSlotId, kFresnelOutputSlotName, kFresnelOutputSlotName, SlotType.Output, 0.5f);
AddSlot(fresnelOutputSlot);
addedSlots.Add(fresnelOutputSlot.id);
RemoveSlotsNameNotMatching(addedSlots, supressWarnings: true);
}
string GetFunctionName()
{
return string.Format("Unity_FresnelEquation_{0}_$precision", m_FresnelEquationMode.ToString());
}
string GetResultType()
{
string resultType;
if (m_FresnelEquationMode == FresnelEquationMode.Schlick)
{
resultType = f0InputSlot.concreteValueType.ToShaderString();
}
else if (m_FresnelEquationMode == FresnelEquationMode.Dielectric)
{
resultType = ((ConcreteSlotValueType)System.Math.Min((int)iorSourceInputSlot.concreteValueType, (int)iorMediumInputSlot.concreteValueType)).ToShaderString();
}
else //if (m_FresnelEquationMode == FresnelEquationMode.DielectricGeneric)
{
resultType = ((ConcreteSlotValueType)System.Math.Min(System.Math.Min((int)iorSourceInputSlot.concreteValueType, (int)iorMediumInputSlot.concreteValueType), (int)iorMediumKInputSlot.concreteValueType)).ToShaderString();
}
return resultType;
}
public void GenerateNodeFunction(FunctionRegistry registry, GenerationMode generationMode)
{
registry.RequiresIncludePath("Packages/com.unity.render-pipelines.core/ShaderLibrary/BSDF.hlsl");
string resultType = GetResultType();
registry.ProvideFunction(GetFunctionName(), s =>
{
if (m_FresnelEquationMode == FresnelEquationMode.Schlick)
{
s.AppendLine("void {0}(out {1} FresnelValue, $precision cos0, {1} f0)", GetFunctionName(), resultType, resultType);
}
else if (m_FresnelEquationMode == FresnelEquationMode.Dielectric)
{
s.AppendLine("void {0}(out {1} FresnelValue, $precision cos0, {2} iorSource, {3} iorMedium)",
GetFunctionName(),
resultType,
iorSourceInputSlot.concreteValueType.ToShaderString(),
iorMediumInputSlot.concreteValueType.ToShaderString());
}
else //if (m_FresnelEquationMode == FresnelEquationMode.DielectricGeneric)
{
s.AppendLine("void {0}(out {1} FresnelValue, $precision cos0, {2} iorSource, {3} iorMedium, {4} iorMediumK)",
GetFunctionName(),
resultType,
iorSourceInputSlot.concreteValueType.ToShaderString(),
iorMediumInputSlot.concreteValueType.ToShaderString(),
iorMediumKInputSlot.concreteValueType.ToShaderString());
}
using (s.BlockScope())
{
if (m_FresnelEquationMode == FresnelEquationMode.Schlick)
{
s.AppendLine("FresnelValue = F_Schlick(f0, cos0);");
}
else if (m_FresnelEquationMode == FresnelEquationMode.Dielectric)
{
s.AppendLine("FresnelValue = F_FresnelDielectric(iorMedium/iorSource, cos0);");
}
else //if (m_FresnelEquationMode == FresnelEquationMode.DielectricGeneric)
{
s.AppendLine("FresnelValue = F_FresnelConductor(iorMedium/iorSource, iorMediumK/iorSource, cos0);");
}
}
});
}
public void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
{
sb.AppendLine("{0} {1};", GetResultType(), GetVariableNameForSlot((int)FresnelSlots.kFresnelOutputSlotId));
if (m_FresnelEquationMode == FresnelEquationMode.Schlick)
{
sb.AppendLine("{0}({1}, {2}, {3});",
GetFunctionName(),
GetVariableNameForSlot(fresnelOutputSlot.id),
GetSlotValue(dotInputSlot.id, generationMode),
GetSlotValue(f0InputSlot.id, generationMode)
);
}
else if (m_FresnelEquationMode == FresnelEquationMode.Dielectric)
{
sb.AppendLine("{0}({1}, {2}, {3}, {4});",
GetFunctionName(),
GetVariableNameForSlot(fresnelOutputSlot.id),
GetSlotValue(dotInputSlot.id, generationMode),
GetSlotValue(iorSourceInputSlot.id, generationMode),
GetSlotValue(iorMediumInputSlot.id, generationMode)
);
}
else //if (m_FresnelEquationMode == FresnelEquationMode.DielectricGeneric)
{
sb.AppendLine("{0}({1}, {2}, {3}, {4}, {5});",
GetFunctionName(),
GetVariableNameForSlot(fresnelOutputSlot.id),
GetSlotValue(dotInputSlot.id, generationMode),
GetSlotValue(iorSourceInputSlot.id, generationMode),
GetSlotValue(iorMediumInputSlot.id, generationMode),
GetSlotValue(iorMediumKInputSlot.id, generationMode)
);
}
}
}
}