// #include "res://addons/rokojori_action_library/Runtime/Shading/Library/Billboard.gdshaderinc"

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

void applyBillboardBending( 
  inout vec3 _VERTEX, 
  vec3 _CAMERA_DIRECTION_WORLD, 
  vec3 _CAMERA_POSITION_WORLD,
  mat4 _MODEL_MATRIX,
  mat4 _VIEW_MATRIX,
  mat4 _PROJECTION_MATRIX,
  mat4 _INV_VIEW_MATRIX,
  float _bendingAmount,
  float _maxBendingAmount,
  float _edgeScale,
  float _minY,
  float _maxY
)
{
  float camDot = max( 0, dot( vec3( 0, 1, 0 ), _CAMERA_DIRECTION_WORLD ) );
  
  camDot = camDot * camDot * camDot;

  vec3 worldPosition = localToView( _VERTEX, _MODEL_MATRIX ); 
  vec3 directionToCam = worldPosition - _CAMERA_POSITION_WORLD;
  float d = length( directionToCam );
  directionToCam.y = 0.0;
  float dScale = min( _bendingAmount / d, _maxBendingAmount );
  vec3 view = worldToView( worldPosition, _VIEW_MATRIX );
  vec2 clip = viewToClip( view, _PROJECTION_MATRIX ).xy;
  float sd = 1.0 / ( 1.0 + length( clip ) );
  sd = mix( 1, sd, _edgeScale );
  //directionToCam = normalize( directionToCam );

  directionToCam = applyMatrixWithoutTranslation( vec3(0,-1,0), _INV_VIEW_MATRIX );

  float am = camDot * mapClamped( _VERTEX.y, _minY, _maxY, 1, -1 );
  am = am * am * am;
  _VERTEX += am * worldToLocalDirection(  directionToCam, _MODEL_MATRIX ) * dScale * sd;
}

void applyBillboardBendingWithDirection( 
  inout vec3 _VERTEX, 
  vec3 _CAMERA_DIRECTION_WORLD, 
  vec3 _CAMERA_POSITION_WORLD,
  mat4 _MODEL_MATRIX,
  mat4 _VIEW_MATRIX,
  mat4 _PROJECTION_MATRIX,
  mat4 _INV_VIEW_MATRIX,
  float _bendingAmount,
  float _maxBendingAmount,
  float _edgeScale,
  float _minY,
  float _maxY,
  vec3 _bendingDirection
)
{
  float camDot = max( 0, dot( vec3( 0, 1, 0 ), _CAMERA_DIRECTION_WORLD ) );
  
  camDot = camDot * camDot * camDot;

  vec3 worldPosition = localToView( _VERTEX, _MODEL_MATRIX ); 
  vec3 directionToCam = worldPosition - _CAMERA_POSITION_WORLD;
  float d = length( directionToCam );
  directionToCam.y = 0.0;
  float dScale = min( _bendingAmount / d, _maxBendingAmount );
  vec3 view = worldToView( worldPosition, _VIEW_MATRIX );
  vec2 clip = viewToClip( view, _PROJECTION_MATRIX ).xy;
  float sd = 1.0 / ( 1.0 + length( clip ) );
  sd = mix( 1, sd, _edgeScale );
  //directionToCam = normalize( directionToCam );

  directionToCam = worldToViewDirection( _bendingDirection, _VIEW_MATRIX );
  directionToCam.y = 0.0;
  directionToCam = viewToWorldDirection( _bendingDirection, _INV_VIEW_MATRIX );

  float am = camDot * mapClamped( _VERTEX.y, _minY, _maxY, 1, -1 );
  am = am * am * am;
  _VERTEX += am * worldToLocalDirection(  directionToCam, _MODEL_MATRIX ) * dScale * sd;
}