using Godot; using System.Reflection; using System.Collections.Generic; namespace Rokojori { [Tool] [GlobalClass] public abstract partial class TextureModule:ShaderGenerationModule { public enum TextureChannelType { RGBA, RGB, ONE, SCALAR } public enum TextureChannelSource { R, G, B, A } public TextureChannelType _type; public TextureChannelSource _channelSource; public bool is1D => _type == TextureChannelType.ONE; public string _domainName; public string _domainValueName; public string _domainScaleName; public string _domainOffsetName; public string _domainIntensityName; public string _target; public string _scaleTarget; public string _uvChannel; public bool _srgb = false; public bool _normal = false; public bool _repeat = true; public enum DomainMode { Value, Texture, Texture_Scale, Texture_Scale_Offset, Texture_Scale_Intensity } public DomainMode _domainMode = DomainMode.Texture_Scale_Offset; public float domainOffsetDefault = 0; public float domainOffsetMin = -1; public float domainOffsetMax = 1; public float domainIntensityDefault = 1; public float domainIntensityMin = 1; public float domainIntensityMax = 20; public float domainValueDefault = 0.5f; public float domainValueMin = 0; public float domainValueMax = 1; public float domainScaleDefault = 1.0f; public float domainScaleMin = 0; public float domainScaleMax = 1; public bool _clamp = false; public enum AssignmentType { Set, Add, Subtract, Multiply, Divide } public AssignmentType _assignmentType = AssignmentType.Set; public string assignmentOperator { get { if ( AssignmentType.Add == _assignmentType ) { return " += "; } if ( AssignmentType.Subtract == _assignmentType ) { return " -= "; } if ( AssignmentType.Multiply == _assignmentType ) { return " *= "; } if ( AssignmentType.Divide == _assignmentType ) { return " /= "; } return " = "; } } public TextureChannelType scaleType = TextureChannelType.SCALAR; public Color scaleColor = Colors.White; public enum TextureDefault { White, Black } public TextureDefault _textureDefault = TextureDefault.White; public TextureFilter _textureFilter = TextureFilter.Linear_MipMap_Anisotropic; public enum TextureFilter { Nearest, Nearest_MipMap, Nearest_MipMap_Anisotropic, Linear, Linear_MipMap, Linear_MipMap_Anisotropic } public virtual void GrabValues() { } public virtual string AddVariables() { return ""; } public string GetSampledName() { return "sampled".ExtendVariableName( _domainName ); } public override List GetVariants( ShaderGenerationContext context ) { GrabValues(); if ( _clamp && ShaderPhase.Includes == context.phase ) { return ToVariants( IncludeMathLibrary() ); } if ( ShaderPhase.Variables == context.phase ) { var textureName = _domainName; var valuesDefinition = ""; var samplerDefinition = ""; if ( DomainMode.Value != _domainMode ) { var hints = new List(); if ( _srgb ) { hints.Add( "source_color" ); } if ( _normal ) { hints.Add( "hint_normal" ); } else { hints.Add( TextureDefault.Black == _textureDefault ? "hint_default_black" : "hint_default_white" ); } hints.Add( _repeat ? "repeat_enable" : "repeat_disable" ); hints.Add( "filter_" + ( _textureFilter + "" ).ToLower() ); var textureSamplerName = _domainName + "Texture"; samplerDefinition = UniformSampler( textureSamplerName, hints.Join() ); if ( _domainMode != DomainMode.Texture ) { if ( is1D ) { valuesDefinition += Uniform( _domainScaleName, domainScaleDefault, domainScaleMin, domainScaleMax ); } else { if ( TextureChannelType.SCALAR == scaleType ) { valuesDefinition += Uniform( _domainScaleName, domainScaleDefault, domainScaleMin, domainScaleMax ); } else { valuesDefinition += Uniform( _domainScaleName, scaleColor ); } } valuesDefinition +="\n"; } } if ( DomainMode.Value == _domainMode ) { valuesDefinition += Uniform( _domainValueName, domainValueDefault, domainValueMin, domainValueMax ); } else if ( DomainMode.Texture_Scale_Offset == _domainMode ) { valuesDefinition += "\n"; valuesDefinition += Uniform( _domainOffsetName, domainOffsetDefault, domainOffsetMin, domainOffsetMax ); valuesDefinition += "\n"; } else if ( DomainMode.Texture_Scale_Intensity == _domainMode ) { valuesDefinition += "\n"; valuesDefinition += Uniform( _domainIntensityName, domainIntensityDefault, domainIntensityMin, domainIntensityMax ); valuesDefinition += "\n"; } var code = valuesDefinition + samplerDefinition; code += AddVariables(); return ToVariants( AsUniformGroup( textureName, code ) ); } if ( ShaderPhase.Fragment == context.phase ) { if ( DomainMode.Texture == _domainMode || DomainMode.Texture_Scale == _domainMode || DomainMode.Texture_Scale_Offset == _domainMode || DomainMode.Texture_Scale_Intensity == _domainMode ) { var textureSamplerName = _domainName + "Texture"; var code = new List(); var sampledName = GetSampledName(); var sampled = "vec4 " + sampledName + " = texture( " + textureSamplerName + ", " + _uvChannel + " );"; code.Add( sampled ); var member = ""; if ( TextureChannelType.RGB == _type ) { member = ".rgb"; } else if ( TextureChannelType.ONE== _type ) { member = TextureChannelSource.R == _channelSource ? ".r" : TextureChannelSource.G == _channelSource ? ".g" : TextureChannelSource.B == _channelSource ? ".b" : ".a"; } var scaleOffset = ""; var scaleMember = ""; if ( TextureChannelType.RGB == scaleType ) { scaleMember = ".rgb"; } else if ( TextureChannelType.ONE == scaleType ) { scaleMember = TextureChannelSource.R == _channelSource ? ".r" : TextureChannelSource.G == _channelSource ? ".g" : TextureChannelSource.B == _channelSource ? ".b" : ".a"; } // RJLog.Log( GetType().Name, "SCALE MEMBER", scaleMember, scaleType ); if ( DomainMode.Texture_Scale == _domainMode || DomainMode.Texture_Scale_Offset == _domainMode || DomainMode.Texture_Scale_Intensity == _domainMode ) { scaleOffset += " * " + _domainScaleName + scaleMember; if ( DomainMode.Texture_Scale_Offset == _domainMode ) { scaleOffset += " + " + _domainOffsetName + scaleMember; } else if ( DomainMode.Texture_Scale_Intensity == _domainMode ) { scaleOffset += " * " + _domainIntensityName; } } if ( DomainMode.Texture_Scale == _domainMode && _scaleTarget != "" && _scaleTarget != null ) { code.Add( _target + assignmentOperator + sampledName + member + ";" ); code.Add( _scaleTarget + assignmentOperator + _domainScaleName + ";" ); } else { code.Add( _target + assignmentOperator + sampledName + member + scaleOffset + ";" ); } if ( _clamp ) { code.Add( $"{_target} = clamp01( {_target} ); "); } return ToVariants( ToCode( code.Join( "\n" ).Indent( " " ).LineBreaks() ) ); } else { } } return null; } } }