using Godot; using System.Reflection; using System.Collections.Generic; using System.Linq; namespace Rokojori { [Tool] [GlobalClass] public partial class LineFading:FadingModifier { public enum Mode { World, WorldPoint_To_Camera, Screen } [Export] public Mode mode; public override bool IsSameType( FadingModifier modifier ) { if ( modifier is LineFading lf ) { return lf.mode == mode; } return false; } public override List GetFadingCode( ShaderGenerationContext context, int offsetIndex, AlphaFadeMode parentFadeMode ) { var alphaFadeMode = GetFadeMode( parentFadeMode ); var suffix = GetSuffix( offsetIndex ); if ( context.isIncludesPhase ) { return IncludeTransformLibrary().Concat( IncludeFromLibrary( "Line3" ) ).Concat( IncludeSDFLibrary() ); } if ( context.isVariablesPhase ) { if ( Mode.Screen == mode ) { List variables = [ Uniform( "screenLineDistanceFadeWorldPositionA" + suffix, Vector3.Zero ), Uniform( "screenLineDistanceFadeWorldPositionB" + suffix, Vector3.One ), VaryingVec3( "screenLineDistanceFadeScreenPositionA" + suffix ), VaryingVec3( "screenLineDistanceFadeScreenPositionB" + suffix ), Uniform( "screenLineDistanceFadeInnerRadius" + suffix, 0.1f ), Uniform( "screenLineDistanceFadeOuterRadius" + suffix, 0.15f ), VaryingVec2( "screenLineDistanceViewportRatio" + suffix ) ]; variables = variables.Map( v => v.LineBreak() ); return ToCode( variables ); } else if ( Mode.World == mode ) { List variables = [ Uniform( "worldLineDistanceFadeWorldPositionA" + suffix, Vector3.Zero ), Uniform( "worldLineDistanceFadeWorldPositionB" + suffix, Vector3.One ), VaryingVec3( "worldLineDistanceFadeViewPositionA" + suffix ), VaryingVec3( "worldLineDistanceFadeViewPositionB" + suffix ), Uniform( "worldLineDistanceFadeInnerRadius" + suffix, 0.1f ), Uniform( "worldLineDistanceFadeOuterRadius" + suffix, 0.15f ) ]; variables = variables.Map( v => v.LineBreak() ); return ToCode( variables ); } else if ( Mode.WorldPoint_To_Camera == mode ) { List variables = [ Uniform( "worldCameraLineDistanceFadeWorldPosition" + suffix, Vector3.Zero ), VaryingVec3( "worldCameraLineDistanceFadeViewPosition" + suffix ), Uniform( "worldCameraLineDistanceFadeInnerRadius" + suffix, 0.1f ), Uniform( "worldCameraLineDistanceFadeOuterRadius" + suffix, 0.15f ) ]; variables = variables.Map( v => v.LineBreak() ); return ToCode( variables ); } } if ( context.isVertexPhase ) { if ( Mode.Screen == mode ) { var code = $@" screenLineDistanceFadeScreenPositionA{suffix} = vec3( worldToScreen( screenLineDistanceFadeWorldPositionA{suffix}, VIEW_MATRIX, PROJECTION_MATRIX ), 0.0 ); screenLineDistanceFadeScreenPositionB{suffix} = vec3( worldToScreen( screenLineDistanceFadeWorldPositionB{suffix}, VIEW_MATRIX, PROJECTION_MATRIX ), 0.0 ); "; return ToCode( code.Indent( " ") ); } else if ( Mode.World == mode ) { var code = $@" worldLineDistanceFadeViewPositionA{suffix} = worldToView( worldLineDistanceFadeWorldPositionA{suffix}, VIEW_MATRIX ); worldLineDistanceFadeViewPositionB{suffix} = worldToView( worldLineDistanceFadeWorldPositionB{suffix}, VIEW_MATRIX ); "; return ToCode( code.Indent( " ") ); } else if ( Mode.WorldPoint_To_Camera == mode ) { var code = $@" worldCameraLineDistanceFadeViewPosition{suffix} = worldToView( worldCameraLineDistanceFadeWorldPosition{suffix}, VIEW_MATRIX ); "; return ToCode( code.Indent( " ") ); } } if ( context.isFragmentPhase ) { if ( Mode.Screen == mode ) { var fadeVariable = "screenLineDistanceFadeAmount" + suffix; var fade = AlphaFade.Fragment( fadeVariable, alphaFadeMode ); var code = $@" {{ vec2 screenRatioMultiply = VIEWPORT_SIZE; if ( screenRatioMultiply.x > screenRatioMultiply.y ) {{ screenRatioMultiply /= VIEWPORT_SIZE.x; }} else {{ screenRatioMultiply /= VIEWPORT_SIZE.y; }} vec2 screenVertex = viewToScreen( VERTEX, PROJECTION_MATRIX ) * screenRatioMultiply; Line3 screenLineDistanceFadeLine3; screenLineDistanceFadeLine3.start = screenLineDistanceFadeScreenPositionA{suffix} * vec3( screenRatioMultiply, 1.0 ); screenLineDistanceFadeLine3.end = screenLineDistanceFadeScreenPositionB{suffix} * vec3( screenRatioMultiply, 1.0 ); float screenLineDistanceFadeDistance = Line3_getDistance( screenLineDistanceFadeLine3, vec3( screenVertex, 0.0 ) ); float {fadeVariable} = clamp( smoothstep( screenLineDistanceFadeInnerRadius{suffix}, screenLineDistanceFadeOuterRadius{suffix}, screenLineDistanceFadeDistance ), 0.0, 1.0 ); {fade} }} "; return ToCode( code.Indent( " ") ); } else if ( Mode.World == mode ) { var fadeVariable = "worldLineDistanceFadeAmount" + suffix; var fade = AlphaFade.Fragment( fadeVariable, alphaFadeMode ); var code = $@" {{ Line3 worldLineDistanceFadeLine3; worldLineDistanceFadeLine3.start = worldLineDistanceFadeViewPositionA{suffix}; worldLineDistanceFadeLine3.end = worldLineDistanceFadeViewPositionB{suffix}; float worldLineDistanceFadeDistance = Line3_getDistance( worldLineDistanceFadeLine3, VERTEX ); float {fadeVariable} = clamp( smoothstep( worldLineDistanceFadeInnerRadius{suffix}, worldLineDistanceFadeOuterRadius{suffix}, worldLineDistanceFadeDistance ), 0.0, 1.0 ); {fade} }} "; return ToCode( code.Indent( " ") ); } else if ( Mode.WorldPoint_To_Camera == mode ) { var fadeVariable = "worldLineDistanceFadeAmount" + suffix; var fade = AlphaFade.Fragment( fadeVariable, alphaFadeMode ); var code = $@" {{ float worldLineDistanceFadeDistance = sdRoundCone( VERTEX, vec3( 0.0, 0.0, 0.0), worldCameraLineDistanceFadeViewPosition{suffix}, 0, worldCameraLineDistanceFadeInnerRadius ); float {fadeVariable} = clamp( smoothstep( 0, ( worldCameraLineDistanceFadeOuterRadius{suffix} - worldCameraLineDistanceFadeInnerRadius{suffix} ), worldLineDistanceFadeDistance ), 0.0, 1.0 ); {fade} }} "; return ToCode( code.Indent( " ") ); } } return []; } } }