rj-action-library/Runtime/Shading/Generators/Spatial/Overlays/SpatialOverlayLayer.cs

157 lines
3.3 KiB
C#

using Godot;
using System.Reflection;
using System.Collections.Generic;
using System.Linq;
namespace Rokojori
{
[Tool]
[GlobalClass]
public abstract partial class SpatialOverlayLayer:ShaderGenerationModule
{
[Export]
public SpatialMask[] masks;
[Export]
public SpatialMaskFormulaType maskFormulaType = SpatialMaskFormulaType.Multiply;
[Export]
public string customMaskFormula;
public enum OverlayMode
{
Mix,
Blend_Alpha
}
[Export]
public OverlayMode overlayMode;
public enum ChannelType
{
RGBA,
RGB,
RG,
R,
G,
B,
A,
Float
}
public ChannelType channelType = ChannelType.RGB;
public string GetDataType()
{
if ( ChannelType.RGBA == channelType )
{
return "vec4";
}
if ( ChannelType.RGB == channelType )
{
return "vec3";
}
if ( ChannelType.RG == channelType )
{
return "vec2";
}
return "float";
}
public bool IsColorBlendMode()
{
List<OverlayMode> modes =
[
OverlayMode.Blend_Alpha
];
return modes.IndexOf( overlayMode ) != -1;
}
public List<ShaderCode> GetOverlayCode( ShaderGenerationContext context, string name, string oldValue, string targetValue )
{
var list = new List<ShaderCode>();
var currentValueName = $"{name}Value";
if ( context.isFragmentPhase )
{
var dataType = GetDataType();
var initData = $"{dataType} {currentValueName};\n";
list.Add( ToCode( initData.Indent( " " ) ) );
var valueCode = GetLayerCode( context, name, currentValueName );
list.Add( valueCode );
var maskName = $"{name}CombinedMask";
var maskCode = SpatialMaskFormulaTypeUtility.GetFragmentMaskCode(
context, maskFormulaType, customMaskFormula, masks, name, maskName );
list.Add( maskCode );
if ( OverlayMode.Mix == overlayMode )
{
var blendCode =
@$"
{targetValue} = mix( {oldValue}, {currentValueName}, {maskName} );
";
list.Add( ToCode( blendCode.Indent( " " ) ) );
}
else if ( IsColorBlendMode() )
{
var blendModeFunction = ( overlayMode + "" ).Replace( "Blend_", "" ).ToLower();
var blendCode =
@$"
{targetValue} = blend_{blendModeFunction}( {oldValue}, fade( {currentValueName} * {maskName} ) );
";
list.Add( ToCode( blendCode.Indent( " " ) ) );
}
}
else
{
var maskIndex = 0;
masks.ForEach(
( m )=>
{
var maskName = $"{name}Mask{maskIndex}";
var maskCode = m.GetMaskCode( context, name, maskName );
if ( maskCode != null )
{
list.Add( maskCode );
}
maskIndex++;
}
);
var layerCode = GetLayerCode( context, name, currentValueName );
if ( layerCode != null )
{
list.Add( layerCode );
}
}
return list;
}
public abstract List<ShaderCode> GetLayerCode( ShaderGenerationContext context, string name, string currentValueName );
}
}