
#include "res://addons/rokojori_action_library/Runtime/Shading/Library/Colors.gdshaderinc"
#include "res://addons/rokojori_action_library/Runtime/Shading/Library/Math.gdshaderinc"
#include "res://addons/rokojori_action_library/Runtime/Shading/Library/Transform.gdshaderinc"
#include "res://addons/rokojori_action_library/Runtime/Shading/Library/Depth.gdshaderinc"

uniform sampler2D depthTexture:hint_depth_texture;
uniform vec4 color : source_color = vec4( 0.887, 0.434, 0.233, 1.0 );
uniform float alphaScale = 1;
uniform float circleAmount = 1;
uniform float circleDistortion = 1;
uniform float ellipseAmount = 1;
uniform float ellipseDistortion = 1;
uniform vec2 ellipseScale = vec2( 1, 0.5 ); 
uniform float add_vs_max:hint_range(0,1) = 0.5; 

uniform vec4 centerHSL = vec4( 0.08, 0.0, 0.18, 1.0 );
varying vec4 centerColor;

uniform vec4 outsideHSL = vec4( -0.05, 1.65, 0.02, 0.0 );
varying vec4 outsideColor;

uniform float sizeX:hint_range(1,100) = 10;
uniform float sizeY:hint_range(1,100) = 1;
uniform float scaleAll = 1;
uniform float worldSize_vs_screenSize:hint_range(0,1) = 1;
varying vec2 stretch; 

uniform bool usSpectralsNoise = false;
uniform vec3 spectralsAmount = vec3( 0.1, 0.05, 0.02 );
uniform float nonSpectralAmount = 0.95;
uniform vec3 spectralsSize = vec3( 1,0.8, 0.5 );
uniform vec3 spectralsSharpness = vec3( 0, 0, 0 );
uniform vec3 spectralsFrequency = vec3( 50.0, 200.0, 500.0 );
uniform vec3 spectralsSpeed = vec3( 5.0, -3.0, -2.0 );

uniform sampler2D fading;
uniform sampler2D sizeXfading;
uniform sampler2D sizeYfading;


uniform bool useQuickOcclusionTest = false;
uniform float occlusionZOffset:hint_range(-30,30) = 0;
uniform int occlusionTestMaxSteps = 10;
uniform float occlusionTestStepStride = 1;
uniform float occlusionTest_ViewDependingScaleAmount:hint_range(0,1) = 0.5;
uniform float occlusionTest_ViewDependingDistance = 100; 



varying float occlusionAlpha;

void vertex() 
{  
  vec3 viewOffset = viewToWorldDirection( vec3( 0, 0, occlusionZOffset ), INV_VIEW_MATRIX );
  vec3 nodePositionView = worldToView( NODE_POSITION_WORLD + viewOffset, VIEW_MATRIX );
  vec2 screenPosition = viewToScreen( nodePositionView, PROJECTION_MATRIX );

  float fadeValue = textureLod( fading, screenPosition, 0.0 ).r;
  float sizeXFade = textureLod( sizeXfading, screenPosition, 0.0 ).r; 
  float sizeYFade = textureLod( sizeYfading, screenPosition, 0.0 ).r; 
  
  float nodeScale = length( extractScale( MODEL_MATRIX ) );
  
  float sX = sizeX * sizeXFade;
  float sY = sizeY * sizeYFade;

  
  vec2 uvPixelSize = vec2( 1.0, 1.0 ) / VIEWPORT_SIZE ;

  vec2 scaledUVPixelSize = uvPixelSize * max( 1.0, nodePositionView.z / occlusionTest_ViewDependingDistance );
  uvPixelSize = mix( uvPixelSize, scaledUVPixelSize, occlusionTest_ViewDependingScaleAmount );

  float occlusionValue = useQuickOcclusionTest ?
                        
                         getQuickOcclusionAt( depthTexture, nodePositionView, uvPixelSize,
                                              occlusionTestMaxSteps, occlusionTestStepStride,
                                              PROJECTION_MATRIX, INV_PROJECTION_MATRIX ) :

                         getOcclusionAt( depthTexture, nodePositionView, uvPixelSize,
                                         occlusionTestMaxSteps, occlusionTestStepStride,
                                         PROJECTION_MATRIX, INV_PROJECTION_MATRIX );

  occlusionAlpha =  occlusionValue * fadeValue;
  
  float camDist = length( NODE_POSITION_WORLD - CAMERA_POSITION_WORLD );
  vec2 sizeScaled = vec2( sX, sY ) * scaleAll * occlusionAlpha * nodeScale;
  vec2 size = mix( sizeScaled, sizeScaled * camDist * 0.1, worldSize_vs_screenSize );  
  stretch = vec2( sX, sY );
  vec3 worldOffset = billboardWorldOffsetWithSize( size, UV, INV_VIEW_MATRIX, MODEL_MATRIX );
  VERTEX += worldOffset;
  vec3 hsl = RGBtoHSL( color.rgb );
  vec3 shiftedHSL = shiftHSL( hsl, centerHSL.rgb, 60.0 ); 
  vec3 shiftedRGB = HSLtoRGB( shiftedHSL ); 
  
  centerColor  = vec4( shiftRGBwithHSL( color.rgb, centerHSL.rgb, 60.0 ), centerHSL.a * color.a);
  outsideColor = vec4( shiftRGBwithHSL( color.rgb, outsideHSL.rgb, 60.0 ), outsideHSL.a * color.a );
}

float psin( float x, float power )
{
  float v = sin( x ) * 0.5 + 0.5;
  return mix( v, v * v * v, power );
}

void fragment() 
{
  vec2 circleUV = ( UV - vec2( 0.5 ) ) * stretch + vec2( 0.5 );
  vec2 centerUV = UV - vec2( 0.5 );

  float angle = atan( centerUV.y, centerUV.x );
  vec3 sizes = vec3( 1.0 ) * length( circleUV ) / 0.701;

  float distanceToCircle = 1.0 - min( 1, length( circleUV - vec2( 0.5, 0.5 ) ) / 0.5 );

  float noise = 1.0;
  
  if ( usSpectralsNoise )
  {
    noise = nonSpectralAmount;
    
    float spX = max( 0, mix( psin( TIME * spectralsSpeed.x + angle * spectralsFrequency.x, spectralsSharpness.x ) * spectralsAmount.x, 0.0, -spectralsSize.x - distanceToCircle ) );
    float spY = max( 0, mix( psin( TIME * spectralsSpeed.y + angle * spectralsFrequency.y, spectralsSharpness.y ) * spectralsAmount.y, 0.0, -spectralsSize.y - distanceToCircle ) ); 
    float spZ = max( 0, mix( psin( TIME * spectralsSpeed.z + angle * spectralsFrequency.z, spectralsSharpness.z ) * spectralsAmount.z, 0.0, -spectralsSize.z - distanceToCircle ) ); 

    float oa = occlusionAlpha * occlusionAlpha;
    noise += spX * oa; 
    noise += spY * oa;  
    noise += spZ * oa; 

    noise = mix( noise, 1.0, 1.0 - oa );
  }
  

  vec2 ellipseUV = ( UV - vec2( 0.5 ) ) / ellipseScale + vec2( 0.5 ); 
  float distanceToEllipse = 1.0 - min( 1, length( ellipseUV - vec2( 0.5, 0.5 ) ) / 0.5 );
    
  distanceToCircle = clamp01( distanceToCircle * noise );
  distanceToEllipse = clamp01( distanceToEllipse );
  
  distanceToCircle = pow( distanceToCircle, circleDistortion ); 
  distanceToEllipse = pow( distanceToEllipse, ellipseDistortion ); 
  
  distanceToCircle *= circleAmount;
  distanceToEllipse *= ellipseAmount;
  
  float addResult = min( 1, distanceToEllipse + distanceToCircle );
  float maxResult = min( 1, max( distanceToEllipse, distanceToCircle ) );
  float t = mix( addResult, maxResult, add_vs_max );
  vec4 mixedColor = mixThreeColors( outsideColor, color, centerColor, t );
  
	ALBEDO = mixedColor.rgb;
  ALPHA  = mixedColor.a * occlusionAlpha * alphaScale;

}
