UnityGame/Library/PackageCache/com.unity.shadergraph/Editor/Generation/Targets/Fullscreen/FullscreenSubTarget.cs

905 lines
42 KiB
C#
Raw Normal View History

2024-10-27 10:53:47 +03:00
using UnityEditor.ShaderGraph;
using UnityEngine;
using System;
using UnityEditor.ShaderGraph.Internal;
using System.Linq;
using BlendMode = UnityEngine.Rendering.BlendMode;
using BlendOp = UnityEditor.ShaderGraph.BlendOp;
using UnityEngine.UIElements;
using UnityEditor.UIElements;
using UnityEngine.Rendering;
namespace UnityEditor.Rendering.Fullscreen.ShaderGraph
{
[GenerateBlocks("Fullscreen")]
internal struct FullscreenBlocks
{
public static BlockFieldDescriptor color = new BlockFieldDescriptor(BlockFields.SurfaceDescription.name, "FullscreenColor", "Color",
"SURFACEDESCRIPTION_COLOR", new ColorControl(UnityEngine.Color.grey, true), ShaderStage.Fragment);
public static BlockFieldDescriptor eyeDepth = new BlockFieldDescriptor(BlockFields.SurfaceDescription.name, "FullscreenEyeDepth", "Eye Depth",
"SURFACEDESCRIPTION_EYE_DEPTH", new FloatControl(0), ShaderStage.Fragment);
public static BlockFieldDescriptor linear01Depth = new BlockFieldDescriptor(BlockFields.SurfaceDescription.name, "FullscreenLinear01Depth", "Linear01 Depth",
"SURFACEDESCRIPTION_LINEAR01_DEPTH", new FloatControl(0), ShaderStage.Fragment);
public static BlockFieldDescriptor rawDepth = new BlockFieldDescriptor(BlockFields.SurfaceDescription.name, "FullscreenRawDepth", "Raw Depth",
"SURFACEDESCRIPTION_RAW_DEPTH", new FloatControl(0), ShaderStage.Fragment);
}
[GenerationAPI]
internal struct FullscreenFields
{
public static FieldDescriptor depth = new FieldDescriptor("OUTPUT", "depth", "OUTPUT_DEPTH");
}
internal enum FullscreenMode
{
FullScreen,
CustomRenderTexture,
}
internal enum FullscreenCompatibility
{
Blit,
DrawProcedural,
}
internal enum FullscreenBlendMode
{
Disabled,
Alpha,
Premultiply,
Additive,
Multiply,
Custom,
}
internal enum FullscreenDepthWriteMode
{
LinearEye,
Linear01,
Raw,
}
internal static class FullscreenUniforms
{
public static readonly string blendModeProperty = "_Fullscreen_BlendMode";
public static readonly string srcColorBlendProperty = "_Fullscreen_SrcColorBlend";
public static readonly string dstColorBlendProperty = "_Fullscreen_DstColorBlend";
public static readonly string srcAlphaBlendProperty = "_Fullscreen_SrcAlphaBlend";
public static readonly string dstAlphaBlendProperty = "_Fullscreen_DstAlphaBlend";
public static readonly string colorBlendOperationProperty = "_Fullscreen_ColorBlendOperation";
public static readonly string alphaBlendOperationProperty = "_Fullscreen_AlphaBlendOperation";
public static readonly string depthWriteProperty = "_Fullscreen_DepthWrite";
public static readonly string depthTestProperty = "_Fullscreen_DepthTest";
public static readonly string stencilEnableProperty = "_Fullscreen_Stencil";
public static readonly string stencilReferenceProperty = "_Fullscreen_StencilReference";
public static readonly string stencilReadMaskProperty = "_Fullscreen_StencilReadMask";
public static readonly string stencilWriteMaskProperty = "_Fullscreen_StencilWriteMask";
public static readonly string stencilComparisonProperty = "_Fullscreen_StencilComparison";
public static readonly string stencilPassProperty = "_Fullscreen_StencilPass";
public static readonly string stencilFailProperty = "_Fullscreen_StencilFail";
public static readonly string stencilDepthFailProperty = "_Fullscreen_StencilDepthFail";
public static readonly string srcColorBlend = "[" + srcColorBlendProperty + "]";
public static readonly string dstColorBlend = "[" + dstColorBlendProperty + "]";
public static readonly string srcAlphaBlend = "[" + srcAlphaBlendProperty + "]";
public static readonly string dstAlphaBlend = "[" + dstAlphaBlendProperty + "]";
public static readonly string colorBlendOperation = "[" + colorBlendOperationProperty + "]";
public static readonly string alphaBlendOperation = "[" + alphaBlendOperationProperty + "]";
public static readonly string depthWrite = "[" + depthWriteProperty + "]";
public static readonly string depthTest = "[" + depthTestProperty + "]";
public static readonly string stencilReference = "[" + stencilReferenceProperty + "]";
public static readonly string stencilReadMask = "[" + stencilReadMaskProperty + "]";
public static readonly string stencilWriteMask = "[" + stencilWriteMaskProperty + "]";
public static readonly string stencilComparison = "[" + stencilComparisonProperty + "]";
public static readonly string stencilPass = "[" + stencilPassProperty + "]";
public static readonly string stencilFail = "[" + stencilFailProperty + "]";
public static readonly string stencilDepthFail = "[" + stencilDepthFailProperty + "]";
}
internal abstract class FullscreenSubTarget<T> : SubTarget<T>, IRequiresData<FullscreenData>, IHasMetadata where T : Target
{
static readonly GUID kSourceCodeGuid = new GUID("1cfc804c75474e144be5d4158b9522ed"); // FullscreenSubTarget.cs // TODO
static readonly string[] kSharedTemplateDirectories = GenerationUtils.GetDefaultSharedTemplateDirectories().Union(new string[] { "Packages/com.unity.shadergraph/Editor/Generation/Targets/Fullscreen/Templates" }).ToArray();
// HLSL includes
protected static readonly string kFullscreenCommon = "Packages/com.unity.shadergraph/Editor/Generation/Targets/Fullscreen/Includes/FullscreenCommon.hlsl";
protected static readonly string kTemplatePath = "Packages/com.unity.shadergraph/Editor/Generation/Targets/Fullscreen/Templates/ShaderPass.template";
protected static readonly string kCommon = "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl";
protected static readonly string kColor = "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl";
protected static readonly string kTexture = "Packages/com.unity.render-pipelines.core/ShaderLibrary/Texture.hlsl";
protected static readonly string kInstancing = "Packages/com.unity.render-pipelines.core/ShaderLibrary/UnityInstancing.hlsl";
protected static readonly string kFullscreenShaderPass = "Packages/com.unity.shadergraph/Editor/Generation/Targets/Fullscreen/Includes/FullscreenShaderPass.cs.hlsl";
protected static readonly string kSpaceTransforms = "Packages/com.unity.render-pipelines.core/ShaderLibrary/SpaceTransforms.hlsl";
protected static readonly string kFunctions = "Packages/com.unity.shadergraph/ShaderGraphLibrary/Functions.hlsl";
protected static readonly string kTextureStack = "Packages/com.unity.render-pipelines.core/ShaderLibrary/TextureStack.hlsl";
protected virtual string fullscreenDrawProceduralInclude => "Packages/com.unity.shadergraph/Editor/Generation/Targets/Fullscreen/Includes/FullscreenDrawProcedural.hlsl";
protected virtual string fullscreenBlitInclude => "Packages/com.unity.shadergraph/Editor/Generation/Targets/Fullscreen/Includes/FullscreenBlit.hlsl";
FullscreenData m_FullscreenData;
FullscreenData IRequiresData<FullscreenData>.data
{
get => m_FullscreenData;
set => m_FullscreenData = value;
}
public FullscreenData fullscreenData
{
get => m_FullscreenData;
set => m_FullscreenData = value;
}
public override void Setup(ref TargetSetupContext context)
{
context.AddAssetDependency(kSourceCodeGuid, AssetCollection.Flags.SourceDependency);
context.SetDefaultShaderGUI(GetDefaultShaderGUI().FullName);
context.AddSubShader(GenerateSubShader());
}
protected virtual IncludeCollection pregraphIncludes => new IncludeCollection();
protected abstract string pipelineTag { get; }
protected virtual Type GetDefaultShaderGUI() => typeof(FullscreenShaderGUI);
public virtual string identifier => GetType().Name;
public virtual ScriptableObject GetMetadataObject(GraphDataReadOnly graph)
{
var bultInMetadata = ScriptableObject.CreateInstance<FullscreenMetaData>();
bultInMetadata.fullscreenMode = fullscreenData.fullscreenMode;
return bultInMetadata;
}
public RenderStateCollection GetRenderState()
{
var result = new RenderStateCollection();
if (fullscreenData.allowMaterialOverride)
{
if (fullscreenData.depthTestMode != CompareFunction.Disabled)
result.Add(RenderState.ZTest(FullscreenUniforms.depthTest));
else
result.Add(RenderState.ZTest("Off"));
result.Add(RenderState.ZWrite(FullscreenUniforms.depthWrite));
if (fullscreenData.blendMode != FullscreenBlendMode.Disabled)
{
result.Add(RenderState.Blend(FullscreenUniforms.srcColorBlend, FullscreenUniforms.dstColorBlend, FullscreenUniforms.srcAlphaBlend, FullscreenUniforms.dstAlphaBlend));
result.Add(RenderState.BlendOp(FullscreenUniforms.colorBlendOperation, FullscreenUniforms.alphaBlendOperation));
}
else
{
result.Add(RenderState.Blend("Blend Off"));
}
if (fullscreenData.enableStencil)
{
result.Add(RenderState.Stencil(new StencilDescriptor { Ref = FullscreenUniforms.stencilReference, ReadMask = FullscreenUniforms.stencilReadMask, WriteMask = FullscreenUniforms.stencilWriteMask, Comp = FullscreenUniforms.stencilComparison, ZFail = FullscreenUniforms.stencilDepthFail, Fail = FullscreenUniforms.stencilFail, Pass = FullscreenUniforms.stencilPass }));
}
}
else
{
if (fullscreenData.depthTestMode == CompareFunction.Disabled)
result.Add(RenderState.ZTest("Off"));
else
result.Add(RenderState.ZTest(CompareFunctionToZTest(fullscreenData.depthTestMode).ToString()));
result.Add(RenderState.ZWrite(fullscreenData.depthWrite ? ZWrite.On.ToString() : ZWrite.Off.ToString()));
// Blend mode
if (fullscreenData.blendMode == FullscreenBlendMode.Alpha)
result.Add(RenderState.Blend(Blend.SrcAlpha, Blend.OneMinusSrcAlpha, Blend.One, Blend.OneMinusSrcAlpha));
else if (fullscreenData.blendMode == FullscreenBlendMode.Premultiply)
result.Add(RenderState.Blend(Blend.One, Blend.OneMinusSrcAlpha, Blend.One, Blend.OneMinusSrcAlpha));
else if (fullscreenData.blendMode == FullscreenBlendMode.Additive)
result.Add(RenderState.Blend(Blend.SrcAlpha, Blend.One, Blend.One, Blend.One));
else if (fullscreenData.blendMode == FullscreenBlendMode.Multiply)
result.Add(RenderState.Blend(Blend.DstColor, Blend.Zero));
else if (fullscreenData.blendMode == FullscreenBlendMode.Disabled)
result.Add(RenderState.Blend("Blend Off"));
else
{
result.Add(RenderState.Blend(BlendModeToBlend(fullscreenData.srcColorBlendMode), BlendModeToBlend(fullscreenData.dstColorBlendMode), BlendModeToBlend(fullscreenData.srcAlphaBlendMode), BlendModeToBlend(fullscreenData.dstAlphaBlendMode)));
result.Add(RenderState.BlendOp(fullscreenData.colorBlendOperation, fullscreenData.alphaBlendOperation));
}
if (fullscreenData.enableStencil)
{
result.Add(RenderState.Stencil(new StencilDescriptor
{
Ref = fullscreenData.stencilReference.ToString(),
ReadMask = fullscreenData.stencilReadMask.ToString(),
WriteMask = fullscreenData.stencilWriteMask.ToString(),
Comp = CompareFunctionToStencilString(fullscreenData.stencilCompareFunction),
ZFail = StencilOpToStencilString(fullscreenData.stencilDepthTestFailOperation),
Fail = StencilOpToStencilString(fullscreenData.stencilFailOperation),
Pass = StencilOpToStencilString(fullscreenData.stencilPassOperation),
}));
}
}
result.Add(RenderState.Cull(UnityEditor.ShaderGraph.Cull.Off));
return result;
}
public static Blend BlendModeToBlend(BlendMode mode)
{
switch (mode)
{
case BlendMode.Zero: return Blend.Zero;
case BlendMode.One: return Blend.One;
case BlendMode.DstColor: return Blend.DstColor;
case BlendMode.SrcColor: return Blend.SrcColor;
case BlendMode.OneMinusDstColor: return Blend.OneMinusDstColor;
case BlendMode.SrcAlpha: return Blend.SrcAlpha;
case BlendMode.OneMinusSrcColor: return Blend.OneMinusSrcColor;
case BlendMode.DstAlpha: return Blend.DstAlpha;
case BlendMode.OneMinusDstAlpha: return Blend.OneMinusDstAlpha;
case BlendMode.SrcAlphaSaturate: return Blend.SrcAlpha;
case BlendMode.OneMinusSrcAlpha: return Blend.OneMinusSrcAlpha;
default: return Blend.Zero;
}
;
}
public static ZTest CompareFunctionToZTest(CompareFunction mode)
{
switch (mode)
{
case CompareFunction.Equal: return ZTest.Equal;
case CompareFunction.NotEqual: return ZTest.NotEqual;
case CompareFunction.Greater: return ZTest.Greater;
case CompareFunction.Less: return ZTest.Less;
case CompareFunction.GreaterEqual: return ZTest.GEqual;
case CompareFunction.LessEqual: return ZTest.LEqual;
case CompareFunction.Always: return ZTest.Always;
case CompareFunction.Disabled: return ZTest.Always;
default: return ZTest.Always;
}
;
}
public static string CompareFunctionToStencilString(CompareFunction compare)
{
switch (compare)
{
case CompareFunction.Never: return "Never";
case CompareFunction.Equal: return "Equal";
case CompareFunction.NotEqual: return "NotEqual";
case CompareFunction.Greater: return "Greater";
case CompareFunction.Less: return "Less";
case CompareFunction.GreaterEqual: return "GEqual";
case CompareFunction.LessEqual: return "LEqual";
case CompareFunction.Always: return "Always";
default: return "Always";
}
;
}
public static string StencilOpToStencilString(StencilOp op)
{
switch (op)
{
case StencilOp.Keep: return "Keep";
case StencilOp.Zero: return "Zero";
case StencilOp.Replace: return "Replace";
case StencilOp.IncrementSaturate: return "IncrSat";
case StencilOp.DecrementSaturate: return "DecrSat";
case StencilOp.Invert: return "Invert";
case StencilOp.IncrementWrap: return "IncrWrap";
case StencilOp.DecrementWrap: return "DecrWrap";
default: return "Keep";
}
;
}
public virtual SubShaderDescriptor GenerateSubShader()
{
var result = new SubShaderDescriptor()
{
generatesPreview = true,
passes = new PassCollection(),
pipelineTag = pipelineTag,
};
result.passes.Add(GenerateFullscreenPass(FullscreenCompatibility.DrawProcedural));
result.passes.Add(GenerateFullscreenPass(FullscreenCompatibility.Blit));
return result;
}
public virtual IncludeCollection GetPreGraphIncludes()
{
return new IncludeCollection
{
{ kCommon, IncludeLocation.Pregraph },
{ kColor, IncludeLocation.Pregraph },
{ kTexture, IncludeLocation.Pregraph },
{ kTextureStack, IncludeLocation.Pregraph },
{ kFullscreenShaderPass, IncludeLocation.Pregraph }, // For VR
{ pregraphIncludes },
{ kSpaceTransforms, IncludeLocation.Pregraph },
{ kFunctions, IncludeLocation.Pregraph },
};
}
public virtual IncludeCollection GetPostGraphIncludes()
{
return new IncludeCollection { { kFullscreenCommon, IncludeLocation.Postgraph } };
}
static readonly KeywordDescriptor depthWriteKeyword = new KeywordDescriptor
{
displayName = "Depth Write",
referenceName = "DEPTH_WRITE",
type = KeywordType.Boolean,
definition = KeywordDefinition.ShaderFeature,
stages = KeywordShaderStage.Fragment,
};
static readonly KeywordDescriptor depthWriteModeKeyword = new KeywordDescriptor
{
displayName = "Depth Write Mode",
referenceName = "DEPTH_WRITE_MODE",
type = KeywordType.Enum,
definition = KeywordDefinition.Predefined,
entries = new KeywordEntry[]
{
new KeywordEntry("Eye Depth", "EYE"),
new KeywordEntry("Eye Linear 01", "LINEAR01"),
new KeywordEntry("Eye Raw", "RAW"),
},
stages = KeywordShaderStage.Fragment,
};
public static StructDescriptor Varyings = new StructDescriptor()
{
name = "Varyings",
packFields = true,
populateWithCustomInterpolators = false,
fields = new FieldDescriptor[]
{
StructFields.Varyings.positionCS,
StructFields.Varyings.texCoord0,
StructFields.Varyings.texCoord1,
StructFields.Varyings.instanceID,
StructFields.Varyings.stereoTargetEyeIndexAsBlendIdx0,
StructFields.Varyings.stereoTargetEyeIndexAsRTArrayIdx,
}
};
protected virtual DefineCollection GetPassDefines(FullscreenCompatibility compatibility)
=> new DefineCollection();
protected virtual KeywordCollection GetPassKeywords(FullscreenCompatibility compatibility)
=> new KeywordCollection();
static StructDescriptor GetFullscreenAttributes(FullscreenCompatibility compatibility)
{
var desc = new StructDescriptor()
{
name = "Attributes",
packFields = false,
};
if (compatibility == FullscreenCompatibility.Blit)
{
desc.fields = new FieldDescriptor[]
{
StructFields.Attributes.instanceID,
StructFields.Attributes.vertexID,
StructFields.Attributes.positionOS,
};
}
else
{
desc.fields = new FieldDescriptor[]
{
StructFields.Attributes.instanceID,
StructFields.Attributes.vertexID,
};
}
return desc;
}
public virtual PassDescriptor GenerateFullscreenPass(FullscreenCompatibility compatibility)
{
var fullscreenPass = new PassDescriptor
{
// Definition
displayName = compatibility.ToString(),
referenceName = "SHADERPASS_" + compatibility.ToString().ToUpper(),
useInPreview = true,
// Template
passTemplatePath = kTemplatePath,
sharedTemplateDirectories = kSharedTemplateDirectories,
// Port Mask
validVertexBlocks = null,
validPixelBlocks = new BlockFieldDescriptor[]
{
BlockFields.SurfaceDescription.BaseColor,
BlockFields.SurfaceDescription.Alpha,
FullscreenBlocks.eyeDepth,
FullscreenBlocks.linear01Depth,
FullscreenBlocks.rawDepth,
},
// Fields
structs = new StructCollection
{
{ GetFullscreenAttributes(compatibility) },
{ Structs.SurfaceDescriptionInputs },
{ Varyings },
{ Structs.VertexDescriptionInputs },
},
fieldDependencies = FieldDependencies.Default,
requiredFields = new FieldCollection
{
StructFields.Varyings.texCoord0, // Always need texCoord0 to calculate the other properties in fullscreen node code
StructFields.Varyings.texCoord1, // We store the view direction computed in the vertex in the texCoord1
StructFields.Attributes.vertexID, // Need the vertex Id for the DrawProcedural case
},
// Conditional State
renderStates = GetRenderState(),
pragmas = new PragmaCollection
{
{ Pragma.Target(ShaderModel.Target30) },
{ Pragma.Vertex("vert") },
{ Pragma.Fragment("frag") },
},
defines = new DefineCollection
{
{depthWriteKeyword, 1, new FieldCondition(FullscreenFields.depth, true)},
{depthWriteModeKeyword, (int)fullscreenData.depthWriteMode, new FieldCondition(FullscreenFields.depth, true)},
GetPassDefines(compatibility),
},
keywords = GetPassKeywords(compatibility),
includes = new IncludeCollection
{
// Pre-graph
GetPreGraphIncludes(),
// Post-graph
GetPostGraphIncludes(),
},
};
switch (compatibility)
{
default:
case FullscreenCompatibility.Blit:
fullscreenPass.includes.Add(fullscreenBlitInclude, IncludeLocation.Postgraph);
break;
case FullscreenCompatibility.DrawProcedural:
fullscreenPass.includes.Add(fullscreenDrawProceduralInclude, IncludeLocation.Postgraph);
break;
}
return fullscreenPass;
}
// We don't need the save context / update materials for now
public override object saveContext => null;
public FullscreenSubTarget()
{
displayName = "Fullscreen";
}
public override bool IsNodeAllowedBySubTarget(Type nodeType)
{
var interfaces = nodeType.GetInterfaces();
bool allowed = true;
// Subgraph nodes inherits all the interfaces including vertex ones.
if (nodeType == typeof(SubGraphNode))
return true;
// There is no input in the vertex block for now
if (interfaces.Contains(typeof(IMayRequireVertexID))
|| interfaces.Contains(typeof(IMayRequireVertexSkinning))
|| interfaces.Contains(typeof(IMayRequireInstanceID)))
allowed = false;
return allowed;
}
public override bool IsActive() => true;
public override void GetFields(ref TargetFieldContext context)
{
context.AddField(UnityEditor.ShaderGraph.Fields.GraphPixel);
context.AddField(FullscreenFields.depth, fullscreenData.depthWrite || fullscreenData.depthTestMode != CompareFunction.Disabled);
}
public override void GetActiveBlocks(ref TargetActiveBlockContext context)
{
context.AddBlock(BlockFields.SurfaceDescription.BaseColor);
context.AddBlock(BlockFields.SurfaceDescription.Alpha);
var depthBlock = FullscreenBlocks.eyeDepth;
if (fullscreenData.depthWriteMode == FullscreenDepthWriteMode.Linear01)
depthBlock = FullscreenBlocks.linear01Depth;
if (fullscreenData.depthWriteMode == FullscreenDepthWriteMode.Raw)
depthBlock = FullscreenBlocks.rawDepth;
context.AddBlock(depthBlock, fullscreenData.depthWrite || fullscreenData.depthTestMode != CompareFunction.Disabled);
}
public override void CollectShaderProperties(PropertyCollector collector, GenerationMode generationMode)
{
if (fullscreenData.allowMaterialOverride)
{
base.CollectShaderProperties(collector, generationMode);
CollectRenderStateShaderProperties(collector, generationMode);
}
collector.AddFloatProperty("_FlipY", 0, HLSLDeclaration.Global, false);
}
public void CollectRenderStateShaderProperties(PropertyCollector collector, GenerationMode generationMode)
{
if (generationMode != GenerationMode.Preview && fullscreenData.allowMaterialOverride)
{
// When blend mode is disabled, we can't override
if (fullscreenData.blendMode != FullscreenBlendMode.Disabled)
{
BlendMode srcColorBlend = fullscreenData.srcColorBlendMode;
BlendMode srcAlphaBlend = fullscreenData.srcAlphaBlendMode;
BlendMode dstColorBlend = fullscreenData.dstColorBlendMode;
BlendMode dstAlphaBlend = fullscreenData.dstAlphaBlendMode;
BlendOp colorBlendOp = fullscreenData.colorBlendOperation;
BlendOp alphaBlendOp = fullscreenData.alphaBlendOperation;
// Patch the default blend values depending on the Blend Mode:
if (fullscreenData.blendMode != FullscreenBlendMode.Custom)
{
colorBlendOp = BlendOp.Add;
alphaBlendOp = BlendOp.Add;
}
if (fullscreenData.blendMode == FullscreenBlendMode.Alpha)
{
srcColorBlend = BlendMode.SrcAlpha;
dstColorBlend = BlendMode.OneMinusSrcAlpha;
srcAlphaBlend = BlendMode.One;
dstAlphaBlend = BlendMode.OneMinusSrcAlpha;
}
else if (fullscreenData.blendMode == FullscreenBlendMode.Premultiply)
{
srcColorBlend = BlendMode.One;
dstColorBlend = BlendMode.OneMinusSrcAlpha;
srcAlphaBlend = BlendMode.One;
dstAlphaBlend = BlendMode.OneMinusSrcAlpha;
}
else if (fullscreenData.blendMode == FullscreenBlendMode.Additive)
{
srcColorBlend = BlendMode.SrcAlpha;
dstColorBlend = BlendMode.One;
srcAlphaBlend = BlendMode.One;
dstAlphaBlend = BlendMode.One;
}
else if (fullscreenData.blendMode == FullscreenBlendMode.Multiply)
{
srcColorBlend = BlendMode.DstColor;
dstColorBlend = BlendMode.Zero;
srcAlphaBlend = BlendMode.One;
dstAlphaBlend = BlendMode.OneMinusSrcAlpha;
}
collector.AddEnumProperty(FullscreenUniforms.blendModeProperty, fullscreenData.blendMode);
collector.AddEnumProperty(FullscreenUniforms.srcColorBlendProperty, srcColorBlend);
collector.AddEnumProperty(FullscreenUniforms.dstColorBlendProperty, dstColorBlend);
collector.AddEnumProperty(FullscreenUniforms.srcAlphaBlendProperty, srcAlphaBlend);
collector.AddEnumProperty(FullscreenUniforms.dstAlphaBlendProperty, dstAlphaBlend);
collector.AddEnumProperty(FullscreenUniforms.colorBlendOperationProperty, colorBlendOp);
collector.AddEnumProperty(FullscreenUniforms.alphaBlendOperationProperty, alphaBlendOp);
}
collector.AddBoolProperty(FullscreenUniforms.depthWriteProperty, fullscreenData.depthWrite);
if (fullscreenData.depthTestMode != CompareFunction.Disabled)
collector.AddEnumProperty(FullscreenUniforms.depthTestProperty, fullscreenData.depthTestMode);
// When stencil is disabled, we can't override
if (fullscreenData.enableStencil)
{
collector.AddBoolProperty(FullscreenUniforms.stencilEnableProperty, fullscreenData.enableStencil);
collector.AddIntProperty(FullscreenUniforms.stencilReferenceProperty, fullscreenData.stencilReference);
collector.AddIntProperty(FullscreenUniforms.stencilReadMaskProperty, fullscreenData.stencilReadMask);
collector.AddIntProperty(FullscreenUniforms.stencilWriteMaskProperty, fullscreenData.stencilWriteMask);
collector.AddEnumProperty(FullscreenUniforms.stencilComparisonProperty, fullscreenData.stencilCompareFunction);
collector.AddEnumProperty(FullscreenUniforms.stencilPassProperty, fullscreenData.stencilPassOperation);
collector.AddEnumProperty(FullscreenUniforms.stencilFailProperty, fullscreenData.stencilFailOperation);
collector.AddEnumProperty(FullscreenUniforms.stencilDepthFailProperty, fullscreenData.stencilDepthTestFailOperation);
}
}
}
public override void GetPropertiesGUI(ref TargetPropertyGUIContext context, Action onChange, Action<String> registerUndo)
{
context.AddProperty("Allow Material Override", new Toggle() { value = fullscreenData.allowMaterialOverride }, (evt) =>
{
if (Equals(fullscreenData.allowMaterialOverride, evt.newValue))
return;
registerUndo("Change Allow Material Override");
fullscreenData.allowMaterialOverride = evt.newValue;
onChange();
});
GetRenderStatePropertiesGUI(ref context, onChange, registerUndo);
}
protected virtual void GetRenderStatePropertiesGUI(ref TargetPropertyGUIContext context, Action onChange, Action<String> registerUndo)
{
GetBlendingPropertiesGUI(ref context, onChange, registerUndo);
context.AddProperty("Depth Test", new EnumField(fullscreenData.depthTestMode) { value = fullscreenData.depthTestMode }, (evt) =>
{
if (Equals(fullscreenData.depthTestMode, evt.newValue))
return;
registerUndo("Change Depth Test");
fullscreenData.depthTestMode = (CompareFunction)evt.newValue;
onChange();
});
context.AddProperty("Depth Write", new Toggle { value = fullscreenData.depthWrite }, (evt) =>
{
if (Equals(fullscreenData.depthWrite, evt.newValue))
return;
registerUndo("Change Depth Write");
fullscreenData.depthWrite = evt.newValue;
onChange();
});
if (fullscreenData.depthWrite || fullscreenData.depthTestMode != CompareFunction.Disabled)
{
context.AddProperty("Depth Write Mode", new EnumField(fullscreenData.depthWriteMode) { value = fullscreenData.depthWriteMode }, (evt) =>
{
if (Equals(fullscreenData.depthWriteMode, evt.newValue))
return;
registerUndo("Change Depth Write Mode");
fullscreenData.depthWriteMode = (FullscreenDepthWriteMode)evt.newValue;
onChange();
});
}
GetStencilPropertiesGUI(ref context, onChange, registerUndo);
}
protected virtual void GetBlendingPropertiesGUI(ref TargetPropertyGUIContext context, Action onChange, Action<String> registerUndo)
{
context.AddProperty("Blend Mode", new EnumField(fullscreenData.blendMode) { value = fullscreenData.blendMode }, (evt) =>
{
if (Equals(fullscreenData.blendMode, evt.newValue))
return;
registerUndo("Change Blend Mode");
fullscreenData.blendMode = (FullscreenBlendMode)evt.newValue;
onChange();
});
if (fullscreenData.blendMode == FullscreenBlendMode.Custom)
{
context.globalIndentLevel++;
context.AddLabel("Color Blend Mode", 0);
context.AddProperty("Src Color", new EnumField(fullscreenData.srcColorBlendMode) { value = fullscreenData.srcColorBlendMode }, (evt) =>
{
if (Equals(fullscreenData.srcColorBlendMode, evt.newValue))
return;
registerUndo("Change Blend Mode");
fullscreenData.srcColorBlendMode = (BlendMode)evt.newValue;
onChange();
});
context.AddProperty("Dst Color", new EnumField(fullscreenData.dstColorBlendMode) { value = fullscreenData.dstColorBlendMode }, (evt) =>
{
if (Equals(fullscreenData.dstColorBlendMode, evt.newValue))
return;
registerUndo("Change Blend Mode");
fullscreenData.dstColorBlendMode = (BlendMode)evt.newValue;
onChange();
});
context.AddProperty("Color Operation", new EnumField(fullscreenData.colorBlendOperation) { value = fullscreenData.colorBlendOperation }, (evt) =>
{
if (Equals(fullscreenData.colorBlendOperation, evt.newValue))
return;
registerUndo("Change Blend Mode");
fullscreenData.colorBlendOperation = (BlendOp)evt.newValue;
onChange();
});
context.AddLabel("Alpha Blend Mode", 0);
context.AddProperty("Src", new EnumField(fullscreenData.srcAlphaBlendMode) { value = fullscreenData.srcAlphaBlendMode }, (evt) =>
{
if (Equals(fullscreenData.srcAlphaBlendMode, evt.newValue))
return;
registerUndo("Change Blend Mode");
fullscreenData.srcAlphaBlendMode = (BlendMode)evt.newValue;
onChange();
});
context.AddProperty("Dst", new EnumField(fullscreenData.dstAlphaBlendMode) { value = fullscreenData.dstAlphaBlendMode }, (evt) =>
{
if (Equals(fullscreenData.dstAlphaBlendMode, evt.newValue))
return;
registerUndo("Change Blend Mode");
fullscreenData.dstAlphaBlendMode = (BlendMode)evt.newValue;
onChange();
});
context.AddProperty("Blend Operation Alpha", new EnumField(fullscreenData.alphaBlendOperation) { value = fullscreenData.alphaBlendOperation }, (evt) =>
{
if (Equals(fullscreenData.alphaBlendOperation, evt.newValue))
return;
registerUndo("Change Blend Mode");
fullscreenData.alphaBlendOperation = (BlendOp)evt.newValue;
onChange();
});
context.globalIndentLevel--;
}
}
protected virtual void GetStencilPropertiesGUI(ref TargetPropertyGUIContext context, Action onChange, Action<String> registerUndo)
{
context.AddProperty("Enable Stencil", new Toggle { value = fullscreenData.enableStencil }, (evt) =>
{
if (Equals(fullscreenData.enableStencil, evt.newValue))
return;
registerUndo("Change Enable Stencil");
fullscreenData.enableStencil = evt.newValue;
onChange();
});
if (fullscreenData.enableStencil)
{
context.globalIndentLevel++;
context.AddProperty("Reference", new IntegerField { value = fullscreenData.stencilReference, isDelayed = true }, (evt) =>
{
if (Equals(fullscreenData.stencilReference, evt.newValue))
return;
registerUndo("Change Stencil Reference");
fullscreenData.stencilReference = evt.newValue;
onChange();
});
context.AddProperty("Read Mask", new IntegerField { value = fullscreenData.stencilReadMask, isDelayed = true }, (evt) =>
{
if (Equals(fullscreenData.stencilReadMask, evt.newValue))
return;
registerUndo("Change Stencil Read Mask");
fullscreenData.stencilReadMask = evt.newValue;
onChange();
});
context.AddProperty("Write Mask", new IntegerField { value = fullscreenData.stencilWriteMask, isDelayed = true }, (evt) =>
{
if (Equals(fullscreenData.stencilWriteMask, evt.newValue))
return;
registerUndo("Change Stencil Write Mask");
fullscreenData.stencilWriteMask = evt.newValue;
onChange();
});
context.AddProperty("Comparison", new EnumField(fullscreenData.stencilCompareFunction) { value = fullscreenData.stencilCompareFunction }, (evt) =>
{
if (Equals(fullscreenData.stencilCompareFunction, evt.newValue))
return;
registerUndo("Change Stencil Comparison");
fullscreenData.stencilCompareFunction = (CompareFunction)evt.newValue;
onChange();
});
context.AddProperty("Pass", new EnumField(fullscreenData.stencilPassOperation) { value = fullscreenData.stencilPassOperation }, (evt) =>
{
if (Equals(fullscreenData.stencilPassOperation, evt.newValue))
return;
registerUndo("Change Stencil Pass Operation");
fullscreenData.stencilPassOperation = (StencilOp)evt.newValue;
onChange();
});
context.AddProperty("Fail", new EnumField(fullscreenData.stencilFailOperation) { value = fullscreenData.stencilFailOperation }, (evt) =>
{
if (Equals(fullscreenData.stencilFailOperation, evt.newValue))
return;
registerUndo("Change Stencil Fail Operation");
fullscreenData.stencilFailOperation = (StencilOp)evt.newValue;
onChange();
});
context.AddProperty("Depth Fail", new EnumField(fullscreenData.stencilDepthTestFailOperation) { value = fullscreenData.stencilDepthTestFailOperation }, (evt) =>
{
if (Equals(fullscreenData.stencilDepthTestFailOperation, evt.newValue))
return;
registerUndo("Change Stencil Depth Fail Operation");
fullscreenData.stencilDepthTestFailOperation = (StencilOp)evt.newValue;
onChange();
});
context.globalIndentLevel--;
}
}
}
internal static class FullscreenPropertyCollectorExtension
{
public static void AddEnumProperty<T>(this PropertyCollector collector, string prop, T value, HLSLDeclaration hlslDeclaration = HLSLDeclaration.DoNotDeclare) where T : Enum
{
collector.AddShaderProperty(new Vector1ShaderProperty
{
floatType = FloatType.Enum,
enumType = EnumType.CSharpEnum,
cSharpEnumType = typeof(T),
hidden = true,
overrideHLSLDeclaration = true,
hlslDeclarationOverride = hlslDeclaration,
value = Convert.ToInt32(value),
overrideReferenceName = prop,
});
}
public static void AddIntProperty(this PropertyCollector collector, string prop, int value, HLSLDeclaration hlslDeclaration = HLSLDeclaration.DoNotDeclare)
{
collector.AddShaderProperty(new Vector1ShaderProperty
{
floatType = FloatType.Integer,
hidden = true,
overrideHLSLDeclaration = true,
hlslDeclarationOverride = hlslDeclaration,
value = value,
overrideReferenceName = prop,
});
}
public static void AddBoolProperty(this PropertyCollector collector, string prop, bool value, HLSLDeclaration hlslDeclaration = HLSLDeclaration.DoNotDeclare)
{
collector.AddShaderProperty(new BooleanShaderProperty
{
hidden = true,
overrideHLSLDeclaration = true,
hlslDeclarationOverride = hlslDeclaration,
value = value,
overrideReferenceName = prop,
});
}
public static void AddFloatProperty(this PropertyCollector collector, string referenceName, float defaultValue, HLSLDeclaration declarationType = HLSLDeclaration.DoNotDeclare, bool generatePropertyBlock = true)
{
collector.AddShaderProperty(new Vector1ShaderProperty
{
floatType = FloatType.Default,
hidden = true,
overrideHLSLDeclaration = true,
hlslDeclarationOverride = declarationType,
value = defaultValue,
generatePropertyBlock = generatePropertyBlock,
overrideReferenceName = referenceName,
});
}
}
}