//--------------------------------------------------------------//
// Lightworks user effect
//
// Created [June 2019]
/** --- Prototype ---
Known issues and limitations:
Only for Windows
Maybe the effect doesn't work with all GPUs?
Cause of incompatibility: The used random number generator
More limitations: Lightworks 14.5 or better
Effect description see: https://fxschrauber.github.io/lwks-fx/Windows_only/Camera_shake_crop/
*/
//--------------------------------------------------------------//
int _LwksEffectInfo
<
string EffectGroup = "GenericPixelShader";
string Description = "Camera shake & crop & reflections";
string Category = "Stylize";
string SubCategory = "Video artefacts";
string Notes = "Prototype, Windows only, >= Lightworks 14.5 , see: https://fxschrauber.github.io/lwks-fx/ ";
> = 0;
//--------------------------------------------------------------//
// Inputs und Samplers
//--------------------------------------------------------------//
texture Input;
sampler s_input = sampler_state
{
Texture = ;
AddressU = Mirror;
AddressV = Mirror;
MinFilter = Linear;
MagFilter = Linear;
MipFilter = Linear;
};
texture RenderPass1 : RenderColorTarget;
sampler s_render = sampler_state
{
Texture = ;
};
//--------------------------------------------------------------//
// Parameters
//--------------------------------------------------------------//
float Move
<
string Group = "Strength";
string Description = "Move";
float MinVal = 0.0;
float MaxVal = 1.0;
> = 0.1;
int AutoZoom
<
string Group = "Strength";
string Description = "Automatic";
string Enum = "Mirrored edges (no zoom),"
"Zoom; mirrored edges visible,"
"Zoom; mirrored edges maybe visible,"
"Secure zoom; edges never visible";
> = 2;
float XYratio
<
string Group = "Strength";
string Description = "XY Shake ratio";
float MinVal = -1.0;
float MaxVal = 1.0;
> = 0.0;
float Speed
<
string Description = "Speed";
float MinVal = 0.0;
float MaxVal = 1.0;
> = 0.2;
int MirrorMode
<
string Group = "Crop & mirror edges (Adaptation to original at Move = 0)";
string Description = " ";
string Enum = "Reflection on set edges acting on incoming frames,"
"Reflection on the edges of the incoming frame,"
"NO cropping ; Reflection on the set edges";
> = 0;
float CropY
<
string Group = "Crop & mirror edges (Adaptation to original at Move = 0)";
string Description = "Top & Bottom";
float MinVal = 0.0;
float MaxVal = 0.5;
> = 0.0;
float CropX
<
string Group = "Crop & mirror edges (Adaptation to original at Move = 0)";
string Description = "Left & Right";
float MinVal = 0.0;
float MaxVal = 0.5;
> = 0.0;
float4 CropColor
<
string Group = "Crop & mirror edges (Adaptation to original at Move = 0)";
string Description = "Crop color ";
bool SupportsAlpha = true;
> = { 0.0, 0.0, 0.0, 1.0};
float Progress
<
string Description = "Random values";
float MinVal = 0.0;
float MaxVal = 1.0;
float KF0 = 0.0;
float KF1 = 1.0;
> = 0.0;
//-----------------------------------------------------------------------------------------//
// Definitions and declarations
//-----------------------------------------------------------------------------------------//
float _OutputAspectRatio;
float _Length;
#define FRAMECENTER 0.5
#define OFFSETnoise 2.2
#define PROGRESS ((Progress * 20.0) * _Length)
#define EDGEleft CropX
#define EDGEright (1.0 - CropX)
#define EDGEtop CropY
#define EDGEbottom (1.0 - CropY)
//--------------------------------------------------------------//
// Shader
//--------------------------------------------------------------//
float4 ps_main (float2 uv : TEXCOORD1) : COLOR
{
float2 multiplier1 = saturate (float2 (1.0 - XYratio,
1.0 - (XYratio * -1.0))); // Two multipliers of X and Y motion strength (range from 0 to 1)
float2 move = float2 (Move * multiplier1); // Motion strength, Without correction based on media aspect ratio
float2 multiplier = float2 (multiplier1.x / _OutputAspectRatio, multiplier1.y);
if (AutoZoom == 1) multiplier *= _OutputAspectRatio * 2.0;
if (AutoZoom == 2) multiplier *= _OutputAspectRatio;
float deltaX = multiplier.x * (noise(PROGRESS * Speed + OFFSETnoise)); // !! Windows only !! X Sampler-position shift of the semi-randomly determined effect center
float deltaY = multiplier.y * (noise(PROGRESS * Speed)); // !! Windows only !! Y Sampler-position shift of the semi-randomly determined effect center
float2 delta = float2 (deltaX, deltaY) / 2.0; // Sampler-position shift
float2 delta2 = move * delta; // Sampler-position shift without zoom
// ...... Zoom at the semi-randomly changing effect center ....
float zoom = max(move.x , move.y);
if (AutoZoom == 1) zoom /= _OutputAspectRatio * 2.0;
if (AutoZoom == 2) zoom /= _OutputAspectRatio;
delta = delta + FRAMECENTER - uv;
delta = zoom * delta;
delta = (AutoZoom == 0) ? delta2 : delta;
// ... Reflection at the set edges (Corrected sample position)
float2 xy2 = delta + uv;
if (xy2.x < EDGEleft) xy2.x = xy2.x + 2.0 * (EDGEleft - xy2.x);
if (xy2.x > EDGEright ) xy2.x = xy2.x + 2.0 * (EDGEright - xy2.x);
if (xy2.y < EDGEtop) xy2.y = xy2.y + 2.0 * (EDGEtop - xy2.y);
if (xy2.y > EDGEbottom ) xy2.y = xy2.y + 2.0 * (EDGEbottom - xy2.y);
// ... Reflection at the edges of the incoming frame (sampler settings)
xy2 = (MirrorMode == 1) ? delta + uv : xy2;
float4 retval = tex2D (s_input, xy2);
// ... Crop
float y = 1.0 - uv.y;
if ( ( MirrorMode == 2)
||
(
(uv.x > EDGEleft)
&& (uv.x < EDGEright)
&& (y > EDGEtop)
&& (y < EDGEbottom)
)
)
return retval;
return CropColor;
}
//--------------------------------------------------------------//
// Techniques
//--------------------------------------------------------------//
technique tech_main
{
pass P_1 { PixelShader = compile PROFILE ps_main(); }
}