rj-action-library/Runtime/Shading/Generators/Generic/ShaderGenerationModule.cs

297 lines
7.8 KiB
C#

using Godot;
using System.Reflection;
using System.Collections.Generic;
using Microsoft.VisualBasic;
using System.Linq;
namespace Rokojori
{
[Tool]
[GlobalClass]
public abstract partial class ShaderGenerationModule:Resource
{
public bool sortableCode = true;
public virtual bool CodeIsSortable( ShaderPhase phase )
{
return sortableCode;
}
public virtual List<string> GetVariantNames()
{
return new List<string>(){ "" };
}
public virtual List<ShaderVariant> GetVariants( ShaderGenerationContext context )
{
return new List<ShaderVariant>(){};
}
public static ShaderVariant ToVariant( params ShaderCode[] code )
{
var variant = new ShaderVariant();
variant.shaderCode = code.ToList();
return variant;
}
public static List<ShaderVariant> ToVariants( params ShaderCode[] code )
{
return [ ToVariant( code ) ];
}
public string GetShaderCacheData()
{
var shaderHash = "";
var name = "[ " + GetType().FullName + " ]";
var exportedTuples = ReflectionHelper.GetExportedMembersAsJSON( this );
exportedTuples.Sort();
shaderHash = name + " { " + ( exportedTuples.Map( t => $"\"{t.Item1}\":{t.Item2}" ).Join( ", " ) ) + " } ";
return shaderHash.Replace( "\n", "" );
}
public string GetShaderCacheHash()
{
var name = GetType().Name.Substring( 0, 3 ).ToLower();
var exportedTuples = ReflectionHelper.GetExportedMembersAsJSON( this );
exportedTuples.Sort();
var allAtts = " { " + ( exportedTuples.Map( t => $"\"{t.Item1}\":{t.Item2}" ).Join( ", " ) ) + " } ";
return name + "." + allAtts.Length;
}
public static List<ShaderCode> IncludeFromLibrary( string path )
{
return ToCode( "#include \"res://addons/rokojori_action_library/Runtime/Shading/Library/" + path + ".gdshaderinc\"\n" );
}
public static List<ShaderCode> IncludeTransformLibrary(){ return IncludeFromLibrary( "Transform" ); }
public static List<ShaderCode> IncludeDepthLibrary(){ return IncludeFromLibrary( "Depth" ); }
public static List<ShaderCode> IncludeCamerasLibrary(){ return IncludeFromLibrary( "Cameras" ); }
public static List<ShaderCode> IncludeNoiseLibrary(){ return IncludeFromLibrary( "Noise" ); }
public static List<ShaderCode> IncludeDitheringLibrary(){ return IncludeFromLibrary( "Dithering" ); }
public static List<ShaderCode> IncludeSDFLibrary(){ return IncludeFromLibrary( "SDF" ); }
public static List<ShaderCode> IncludeMathLibrary(){ return IncludeFromLibrary( "Math" ); }
public static List<ShaderCode> IncludeLightLibrary(){ return IncludeFromLibrary( "Light" ); }
public static ShaderVariant ToVariant( List<ShaderCode> code )
{
var variant = new ShaderVariant();
variant.shaderCode = code;
return variant;
}
public static List<ShaderVariant> ToVariants( List<ShaderCode> code )
{
return [ ToVariant( code ) ];
}
public static List<ShaderVariant> ToVariants( params string[] values )
{
return ToVariants( ToCode( values ) );
}
public static List<ShaderCode> ToCode( params string[] values )
{
return Lists.From( (ShaderCode)new StringShaderCode( Lists.From( values ).Join( "" ) ) );
}
public static List<ShaderCode> ToCode( string value )
{
return Lists.From( (ShaderCode)new StringShaderCode( value ) );
}
public List<ShaderCode> AsUniformGroup( string name, string value )
{
var wideName = RegexUtility.UpperCaseAndWide( name );
var blockCode = value.Indent( " ", false );
var code =
@$"
// [ {wideName} ]
group_uniforms {name};
{blockCode}
group_uniforms;
";
return ToCode( code.Indent( "" ) );
}
public List<ShaderCode> AsUniformGroup( string name, List<ShaderCode> code )
{
var wideName = RegexUtility.UpperCaseAndWide( name );
var codeBefore =
@$"
// [ {wideName} ]
group_uniforms {name};
";
var codeAfter =
@$"
group_uniforms;
";
return Lists.From( ToCode( codeBefore.Indent("") ), code, ToCode( codeAfter.Indent("") ) );
}
public List<ShaderCode> StartUniformGroup( string name )
{
var wideName = RegexUtility.UpperCaseAndWide( name );
var codeBefore =
@$"
// [ {wideName} ]
group_uniforms {name};
";
return ToCode( codeBefore.Indent("") );
}
public List<ShaderCode> EndUniformGroup()
{
var codeAfter =
@$"
group_uniforms;
";
return ToCode( codeAfter.Indent("") );
}
public static List<ShaderCode> ToInnerBlock( string name, string block )
{
var wideName = RegexUtility.UpperCaseAndWide( name );
var blockCode = block.Indent( " ", false );
var code =
@$"
// [ {wideName} ]
{blockCode}
";
return ToCode( code.Indent( " " ) );
}
public static List<ShaderCode> ToCode( List<string> values )
{
return Lists.From( (ShaderCode)new StringShaderCode( Lists.From( values ).Join( "" ) ) );
}
public static string Uniform( Vector2Property property )
{
var name = property.propertyName.propertyName;
var x = property.value.X._G();
var y = property.value.Y._G();
return @$"uniform vec2 {name} = vec2( {x}, {y});";
}
public static string Uniform( string name, float value )
{
return @$"uniform float {name} = {value._G()};";
}
public static string Uniform01( string name, float value )
{
return Uniform( name, value, 0, 1 );
}
public static string Uniform( string name, float value, float min, float max )
{
var mi = min._G();
var ma = max._G();
var v = value._G();
return @$"uniform float {name}:hint_range( {mi}, {ma}) = {v};";
}
public static string UniformSampler( string name, string hints )
{
return @$"uniform sampler2D {name}:{hints};";
}
public static string Uniform( string name, Color color )
{
var r = color.R._G();
var g = color.G._G();
var b = color.B._G();
var a = color.A._G();
return @$"uniform vec4 {name}:source_color = vec4( {r}, {g}, {b}, {a});";
}
public static string Uniform( string name, Vector3 vec )
{
var x = vec.X._G();
var y = vec.Y._G();
var z = vec.Z._G();
return @$"uniform vec3 {name} = vec3( {x}, {y}, {z});";
}
public static string Varying( string type, string name )
{
return @$"varying {type} {name};";
}
public static string VaryingFloat( string name ){ return Varying( "float", name ); }
public static string VaryingVec2( string name ){ return Varying( "vec2", name ); }
public static string VaryingVec3( string name ){ return Varying( "vec3", name ); }
public static string VaryingVec4( string name ){ return Varying( "vec4", name ); }
public static string Uniform( string name, Vector4 vec )
{
var x = vec.X._G();
var y = vec.Y._G();
var z = vec.Z._G();
var w = vec.W._G();
return @$"uniform vec4 {name} = vec4( {x}, {y}, {z}, {w});";
}
public static string DepthTextureUniform()
{
return UniformSampler( "depthTexture", "hint_depth_texture, repeat_disable, filter_nearest" );
}
public static string ScreenTextureUniform()
{
return UniformSampler( "screenTexture", "hint_screen_texture, repeat_disable, filter_linear" );
}
public static string NormalRoughnessTextureUniform()
{
return UniformSampler( "normalRoughness", "hint_normal_roughness_texture, repeat_disable, filter_linear" );
}
}
}