Skip to content

Instantly share code, notes, and snippets.

@s-leroux
Last active July 12, 2016 00:09
Show Gist options
  • Save s-leroux/97a222330216bb732e6c34521aade2f7 to your computer and use it in GitHub Desktop.
Save s-leroux/97a222330216bb732e6c34521aade2f7 to your computer and use it in GitHub Desktop.
Pologon mask effect for LightWorks
//--------------------------------------------------------------//
// Header
//
// Lightworks effects have to have a _LwksEffectInfo block
// which defines basic information about the effect (ie. name
// and category). EffectGroup must be "GenericPixelShader".
//--------------------------------------------------------------//
int _LwksEffectInfo
<
string EffectGroup = "GenericPixelShader";
string Description = "PolyMask"; // The title
string Category = "Masks"; // Governs the category that the effect appears in in Lightworks
> = 0;
//--------------------------------------------------------------//
// Inputs
//--------------------------------------------------------------//
// For each 'texture' declared here, Lightworks adds a matching
// input to your effect (so for a four input effect, you'd need
// to delcare four textures and samplers)
float _OutputWidth, _OutputHeight, _OutputAspectRatio;
texture fg;
texture bg;
sampler FGround = sampler_state {
Texture = <fg>;
AddressU = Clamp;
AddressV = Clamp;
MinFilter = Linear;
MagFilter = Linear;
MipFilter = Linear;
};
sampler BGround = sampler_state {
Texture = <bg>;
AddressU = Clamp;
AddressV = Clamp;
MinFilter = Linear;
MagFilter = Linear;
MipFilter = Linear;
};
texture MaskTexture : RenderColorTarget;
sampler Mask = sampler_state {
Texture = <MaskTexture>;
AddressU = Clamp;
AddressV = Clamp;
MinFilter = Linear;
MagFilter = Linear;
MipFilter = Linear;
};
//--------------------------------------------------------------//
// Define parameters here.
//
// The Lightworks application will automatically generate
// sliders/controls for all parameters which do not start
// with a a leading '_' character
//--------------------------------------------------------------//
bool show
<
string Description = "Show mask";
> = false;
bool P1
<
string Description = "Enable";
string Group = "P1";
> = true;
float P1X
<
string Description = "P1";
string Group = "P1";
string Flags = "SpecifiesPointX";
float MinVal = -1.00;
float MaxVal = 2.00;
> = 0.25;
float P1Y
<
string Description = "P1";
string Group = "P1";
string Flags = "SpecifiesPointY";
float MinVal = -1.00;
float MaxVal = 2.00;
> = 0.25;
bool P2
<
string Description = "Enable";
string Group = "P2";
> = true;
float P2X
<
string Description = "P2";
string Group = "P2";
string Flags = "SpecifiesPointX";
float MinVal = -1.00;
float MaxVal = 2.00;
> = 0.25;
float P2Y
<
string Description = "P2";
string Group = "P2";
string Flags = "SpecifiesPointY";
float MinVal = -1.00;
float MaxVal = 2.00;
> = 0.75;
bool P3
<
string Description = "Enable";
string Group = "P3";
> = true;
float P3X
<
string Description = "P3";
string Group = "P3";
string Flags = "SpecifiesPointX";
float MinVal = -1.00;
float MaxVal = 2.00;
> = 0.75;
float P3Y
<
string Description = "P3";
string Group = "P3";
string Flags = "SpecifiesPointY";
float MinVal = -1.00;
float MaxVal = 2.00;
> = 0.75;
bool P4
<
string Description = "Enable";
string Group = "P4";
> = true;
float P4X
<
string Description = "P4";
string Group = "P4";
string Flags = "SpecifiesPointX";
float MinVal = -1.00;
float MaxVal = 2.00;
> = 0.75;
float P4Y
<
string Description = "P4";
string Group = "P4";
string Flags = "SpecifiesPointY";
float MinVal = -1.00;
float MaxVal = 2.00;
> = 0.25;
// ???
//#pragma warning ( disable : 3571 )
//--------------------------------------------------------------
// Pixel Shader
//
// This section defines the code which the GPU will
// execute for every pixel in an output image.
//
// Note that pixels are processed out of order, in parallel.
// Using shader model 2.0, so there's a 64 instruction limit -
// use multple passes if you need more.
//--------------------------------------------------------------
float4 mask( float2 xy : TEXCOORD1 ) : COLOR
{
// Build the sequence of vertex indexes
int idx[4+1];
int count = 0;
if (P1) idx[count++] = 0;
if (P2) idx[count++] = 1;
if (P3) idx[count++] = 2;
if (P4) idx[count++] = 3;
idx[count] = idx[0];
if (count < 3) return float4(0,0,0,0);
bool oddPixel = false;
float2 vertex[4];
vertex[0] = float2(P1X, 1.0f - P1Y);
vertex[1] = float2(P2X, 1.0f - P2Y);
vertex[2] = float2(P3X, 1.0f - P3Y);
vertex[3] = float2(P4X, 1.0f - P4Y);
float2 pixel = xy;
int x = 0;
for(x=0; x < count; ++x) {
int i = idx[x];
int j = idx[x+1];
// (vertex[i] - vertex[j]) is an oriented edge.
if (vertex[i].y != vertex[j].y) {
// Not an horizontal edge
float s = (pixel.y - vertex[i].y)/(vertex[j].y - vertex[i].y);
if (s >= 0.0f && s <= 1.0f) {
// on the scan line
if (lerp(vertex[i].x, vertex[j].x, s) < pixel.x) {
oddPixel = !oddPixel;
}
}
}
}
return (oddPixel) ? float4(1,1,1,1) : float4(0,0,0,0);
}
/*
float4 GrowablePoissonDisc13FilterRGBA (sampler tSource, float2 texCoord, float2 pixelSize, float discRadius, float run)
{
float4 cOut;
float2 poisson[12] = {float2(-0.326212f, -0.40581f),
float2(-0.840144f, -0.07358f),
float2(-0.695914f, 0.457137f),
float2(-0.203345f, 0.620716f),
float2(0.96234f, -0.194983f),
float2(0.473434f, -0.480026f),
float2(0.519456f, 0.767022f),
float2(0.185461f, -0.893124f),
float2(0.507431f, 0.064425f),
float2(0.89642f, 0.412458f),
float2(-0.32194f, -0.932615f),
float2(-0.791559f, -0.59771f)};
// center tap
cOut = tex2D (tSource, texCoord);
for (int tap = 0; tap < 12; tap++)
{
float2 coord = texCoord.xy + (pixelSize * (poisson[tap]/run) * discRadius);
cOut += tex2D (tSource, coord);
}
return (cOut / 13.0f);
}
float4 PSBlur( float2 Tex : TEXCOORD0, uniform float run ) : COLOR0
{
float2 pixsize = float2(1.0f / _OutputWidth, 1.0f / _OutputHeight);
float4 orig;
if (run == 1.0f) orig = GrowablePoissonDisc13FilterRGBA(Samp2, Tex + (pixsize / 2.0f), pixsize, feather, run);
else orig = GrowablePoissonDisc13FilterRGBA(Samp1, Tex + (pixsize / 2.0f), pixsize, feather, run);
return orig;
}
*/
float4 combine( float2 uv : TEXCOORD0 ) : COLOR0
{
float4 mk = tex2D( Mask, uv);
if (show)
return mk;
float4 fg = tex2D( FGround, uv);
float4 bg = tex2D( BGround, uv);
float4 color = lerp(fg,bg,mk.a);
return color;
}
//--------------------------------------------------------------
// Technique
//
// Specifies the order of passes
//--------------------------------------------------------------
technique SampleFxTechnique
{
pass Pass1
<
string Script = "RenderColorTarget0 = MaskTexture;";
>
{
PixelShader = compile PROFILE mask();
}
pass Pass2
{
PixelShader = compile PROFILE combine();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment