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 GetVariantNames() { return new List(){ "" }; } public virtual List GetVariants( ShaderGenerationContext context ) { return new List(){}; } public static ShaderVariant ToVariant( params ShaderCode[] code ) { var variant = new ShaderVariant(); variant.shaderCode = code.ToList(); return variant; } public static List 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 IncludeFromLibrary( string path ) { return ToCode( "#include \"res://addons/rokojori_action_library/Runtime/Shading/Library/" + path + ".gdshaderinc\"\n" ); } public static List IncludeTransformLibrary(){ return IncludeFromLibrary( "Transform" ); } public static List IncludeDepthLibrary(){ return IncludeFromLibrary( "Depth" ); } public static List IncludeCamerasLibrary(){ return IncludeFromLibrary( "Cameras" ); } public static List IncludeNoiseLibrary(){ return IncludeFromLibrary( "Noise" ); } public static List IncludeDitheringLibrary(){ return IncludeFromLibrary( "Dithering" ); } public static List IncludeSDFLibrary(){ return IncludeFromLibrary( "SDF" ); } public static List IncludeMathLibrary(){ return IncludeFromLibrary( "Math" ); } public static List IncludeLightLibrary(){ return IncludeFromLibrary( "Light" ); } public static ShaderVariant ToVariant( List code ) { var variant = new ShaderVariant(); variant.shaderCode = code; return variant; } public static List ToVariants( List code ) { return [ ToVariant( code ) ]; } public static List ToVariants( params string[] values ) { return ToVariants( ToCode( values ) ); } public static List ToCode( params string[] values ) { return Lists.From( (ShaderCode)new StringShaderCode( Lists.From( values ).Join( "" ) ) ); } public static List ToCode( string value ) { return Lists.From( (ShaderCode)new StringShaderCode( value ) ); } public List 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 AsUniformGroup( string name, List 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 StartUniformGroup( string name ) { var wideName = RegexUtility.UpperCaseAndWide( name ); var codeBefore = @$" // [ {wideName} ] group_uniforms {name}; "; return ToCode( codeBefore.Indent("") ); } public List EndUniformGroup() { var codeAfter = @$" group_uniforms; "; return ToCode( codeAfter.Indent("") ); } public static List 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 ToCode( List 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" ); } } }