Welcome, Guest
Username Password: Remember me

TOPIC: Documentation for developing Lightworks effects

Re: Any new variables available to pixel shaders? 12 months ago #162085

  • jwrl
  • Moderator
    Pro User
  • OFFLINE
  • Moderator
  • Posts: 9775
  • 12 months ago
schrauber wrote:
I think that some of my future effects will use the new variables to make the user's effects settings easier. ... Such effects will probably continue to be compatible with old Lightworks versions. The user would, of course, only from LW14.1 get the benefit of the new comfort.

That's obviously the ideal way to handle this issue, but that may not always be possible. If not, some form of error handling will be necessary. My suggestion is one method, rhinox202's is another. Each has their own merits, and hopefully others will post with their ideas too. Possibly there should be some attempt at standardising error handling, but at the moment it's too early to do that - if it ever can be at all.

But at least we have a reliable method for determining whether we are running in a version of Lightworks that supports these variables!
Last Edit: 12 months ago by jwrl.

Re: Any new variables available to pixel shaders? 12 months ago #162094

  • hugly
  • OFFLINE
  • Platinum Boarder
  • Posts: 16068
  • 12 months ago
jwrl wrote:
we have a reliable method for determining whether we are running in a version of Lightworks that supports these variables!

Yes, and that's great!
It's better to travel well than to arrive...

Re: Any new variables available to pixel shaders? 11 months, 3 weeks ago #162469

  • schrauber
  • OFFLINE
  • Platinum Boarder
  • Posts: 2231
  • 11 months, 3 weeks ago
gr00by wrote:
BTW: is possible to read nearby pixels (from same frame)?

Yes, by you change the position of the sampling.
In the first example, nothing is changed.
float4 ps_main(float2 uv : TEXCOORD1) : COLOR
{
   return  = tex2D (FgSampler,uv);
}

The two-dimensional variable "uv" (also called "xy" in other effects) is assigned to the original positions of the pixels of the first input.
float2 uv : TEXCOORD1
(TEXCOORD2 would be the second input, etc.)
Of course, the value of the variable "uv" changes with each pixel, which happens automatically.
tex2D (FgSampler,uv) takes the sample at the original position "uv".
Because in this example the original RGB + alpha values are returned, the result will be the same as if no effect were used.

This changes when the sampling position is changed:
float4 ps_main(float2 uv : TEXCOORD1) : COLOR
{
   float2 position = float2 (uv.x , uv.y + 0.01);
   return = tex2D (FgSampler, position);
}

In this example, the position of the sampling is shifted by 0.01 (1% of the texture height) in the y-direction. It should be noted that a video frame is traditionally built from top to bottom. If I increase the Y-value, then the sample is taken below the original position. This is different than in mathematics.

It only changes the position of the sampling, not the output position.

You can also use tex2D ... several times for different positions.

It should be noted that the variable "position" will also take values outside the texture (> 1). In the sampler settings you determine whether the sampler should automatically use an alternative position within the texture in such cases, or returns black-transparent.(see first post on page 1)
Mainly automatically translated
--------------------------------------------
Windows 10, 64 Bit
Intel i5-4440 (3,1 GHz) ; Intel HD Graphics 4600
Last Edit: 11 months, 3 weeks ago by schrauber.

Re: Any new variables available to pixel shaders? 11 months, 2 weeks ago #163221

  • schrauber
  • OFFLINE
  • Platinum Boarder
  • Posts: 2231
  • 11 months, 2 weeks ago
News from the Beta Forum.

ClampToEdge , Clamp , Cross platform compatibility:

Great White wrote:
... the root problem is in the use of "Clamp" for the sampler states AddressU/AddressV in dve1.fx. It appears that "Clamp" means distinctly different things in Microsoft/HLSL and Cg (Mac/Linux).

To get the right/expected answer with Cg, we need to use ClampToEdge (not Clamp). I've modded all our affected shaders accordingly (and added a #define for ClampToEdge=Clamp when running on Windows).

The changes won't be in the imminent beta build, but the one after.



Interesting new feature in the test,
Pixel-shader image support:
Great White wrote:
I've added some experimental support in the latest beta which allows you to refer to image files directly from within Lightworks pixels-shader effect files. For example, you can now write something like :

texture _Grain = < string Resource = "FilmGrain.png"; >;


Which will cause the '_Grain' texture to be initialised with image-data in FilmGrain.png.

The texture variable name should start with a leading underscore to prevent it from being identified as an effect input, and the specified image should be located in the same folder as the .fx file.

Let me know if you have any questions
Mainly automatically translated
--------------------------------------------
Windows 10, 64 Bit
Intel i5-4440 (3,1 GHz) ; Intel HD Graphics 4600
Last Edit: 11 months, 2 weeks ago by schrauber.

Re: Any new variables available to pixel shaders? 11 months, 2 weeks ago #163232

  • jwrl
  • Moderator
    Pro User
  • OFFLINE
  • Moderator
  • Posts: 9775
  • 11 months, 2 weeks ago
Unfortunately the ClampToEdge problem is a very serious one. A high proportion of the user effects suffer from this bug, so in the short term what I propose doing is locking the user effects library where it is, and that will become the pre-14.1 Windows version and be labelled archive.zip. It will never be updated, so any newer effects posted will be unavailable to Windows users of earlier versions of Lightworks.

A second updated zip library will also be posted and all individual zip files will be updated too. This means that the only place that pre-14.1 effects will be available to Windows user will be archive.zip. If an individual Lightworks user requires a feature in a new effect it will be up to them to negotiate with the effect's author for a version that meets their needs.

So what are the thoughts on this? Personally, I don't want to have to maintain separate libraries of the 230+ user effects that we currently have. It's enough of a job with the single version that we have.

Re: Any new variables available to pixel shaders? 11 months, 2 weeks ago #163233

  • jwrl
  • Moderator
    Pro User
  • OFFLINE
  • Moderator
  • Posts: 9775
  • 11 months, 2 weeks ago
Also, just an advisory note: I am at the moment working through the library off-line adding the following code to all of the effects that suffer from this bug.

#ifdef WINDOWS
#define ClampToEdge Clamp
#endif

The body code is being changed to the following where necessary.

   ...
   AddressU = ClampToEdge;
   AddressV = ClampToEdge;
   ...

That should meet the immediate problem. I have not at this stage included any version number checking. A Windows user will be unable to compile this if they are using a version prior to 14.1 build 102161. They should get a compiler error, but I will verify that later today. There may course be a grey area with build 101919, but I don't think so. I'll certainly test that too though.
Last Edit: 11 months, 2 weeks ago by jwrl.

Re: Any new variables available to pixel shaders? 11 months, 2 weeks ago #163242

  • jwrl
  • Moderator
    Pro User
  • OFFLINE
  • Moderator
  • Posts: 9775
  • 11 months, 2 weeks ago
OK, I've been through all 240 effects except for the remote control effects and where necessary edited them to support the changes. I think that I'll leave the remote control effects up to you, schrauber. Now I need to go through and test the changed effects on build 101919 and 102161 on Windows and any build on Linux. It could take a while.

I've also compiled a zip file reflecting the current state of the library, including versions of some effects that I was about to post but haven't yet. That includes the following warning at the head of the readme (if anyone chooses to actually read it).

WARNING: Most Lightworks users should download the current library zip file or the individual effects zips from either of the two user effects threads (use the links below to get to them). This archive version of the library is solely for Windows users of version 14.0 and earlier. It is locked off at the state that the library was in on December 5 2017, and is highly unlikely to be updated.

If you are a Windows user of one of those earlier versions of Lightworks and need any effect that isn't here try it from the standard library first. If it doesn't compile you should directly contact the author of that effect. You could alternatively edit the effect code in a text editor (not a word processor) and search for “ClampToEdge” and replace it with “Clamp” anywhere it appears. It should then work, but if it doesn't you could be on your own I'm afraid.

I can think of nothing else to do to sort this out at the moment. If anyone else has any ideas I would really welcome them.
Last Edit: 11 months, 2 weeks ago by jwrl.

Re: Any new variables available to pixel shaders? 11 months, 2 weeks ago #163258

  • jwrl
  • Moderator
    Pro User
  • OFFLINE
  • Moderator
  • Posts: 9775
  • 11 months, 2 weeks ago
Follow on from the above: feedback from Great White makes clear that the ClampToEdge issue will only apply to DVEs and similar scaling effects.

Great White wrote:
the problem only really surfaces when you read at the very edge of a source texture (ie. x < 0.5/sourceWidth, y < 0.5/sourceHeight, etc) which won't happen unless the effect does scaling in some way.

That's a lot better than 200+ effects!
Last Edit: 11 months, 2 weeks ago by jwrl.

Re: Any new variables available to pixel shaders? 11 months, 2 weeks ago #163263

  • schrauber
  • OFFLINE
  • Platinum Boarder
  • Posts: 2231
  • 11 months, 2 weeks ago
I think "Clamp" could be replaced by "Border" in some of my effects.

I also tested the Clamp-functionality to generate in shader code:
return tex2D (LinearSampler, saturate(uv) );
Unfortunately, the saturated position values 0 and 1 are on the edge or just outside the texture, so the sample setting "Border" can not be used. A correction of 0.5 Texel would probably be too complex for this purpose.
Under Windos, however, it works with the sample setting "Mirror", because the pixels / texels on both sides of the texture edges have identical values:
sampler LinearSampler = sampler_state
{ 
   Texture = <In1>;
   AddressU = Mirror;
   AddressV = Mirror;
   MinFilter = Linear;
   MagFilter = Linear;
   MipFilter = Linear;
};

// [ various code in between ]

return tex2D (LinearSampler, saturate(uv) );[/



This only makes sense if "Mirror" does not have the same problem as "Clamp" on Linux / Mac.
It should also be remembered that Mirror produces more GPU load, depending on the scaling.
Mainly automatically translated
--------------------------------------------
Windows 10, 64 Bit
Intel i5-4440 (3,1 GHz) ; Intel HD Graphics 4600
Last Edit: 11 months, 2 weeks ago by schrauber.

Re: Any new variables available to pixel shaders? 11 months, 2 weeks ago #163302

  • schrauber
  • OFFLINE
  • Platinum Boarder
  • Posts: 2231
  • 11 months, 2 weeks ago
jwrl wrote:
I think that I'll leave the remote control effects up to you, schrauber...


Ok, with the new shader variables and >= 16-bit GPU precision, there are new ways to simplify things.
Mainly automatically translated
--------------------------------------------
Windows 10, 64 Bit
Intel i5-4440 (3,1 GHz) ; Intel HD Graphics 4600

Re: Any new variables available to pixel shaders? 11 months ago #164367

  • jwrl
  • Moderator
    Pro User
  • OFFLINE
  • Moderator
  • Posts: 9775
  • 11 months ago
With the kind permission of khaver, I'm going to work through an exercise in conversion of an earlier effect to take advantage of one of the new variables. The effect that I have chosen to use is his strobe.fx, because it's comparatively simple to work with. We'll only need to modify a few small sections of the code to get where we want, but at the end we will have an effect that compiles and runs in both version 14.0 and earlier and version 14.1 and later but behaves differently in each case.

So without further ado, here's khaver's original for reference.

//--------------------------------------------------------------//
// 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 = "Strobe";        // The title
   string Category    = "Stylize";            // Governs the category that the effect appears in in Lightworks
   string SubCategory = "User Effects";
> = 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)

texture fg;
texture bg;

sampler FGround = sampler_state { Texture = <fg>; };
sampler BGround = sampler_state { Texture = <bg>; };

//--------------------------------------------------------------//
// Define parameters here.
//
// The Lightworks application will automatically generate
// sliders/controls for all parameters which do not start
// with a a leading '_' character
//--------------------------------------------------------------//

float _Progress;

bool swap
<
	string Description = "Swap";
> = false;

float strobe
<
	string Description = "Strobe Spacing";
	float MinVal = 0.0f;
	float MaxVal = 1.0f;
> = 1.0f;

#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 Combine( float2 uv : TEXCOORD1 ) : COLOR
{
  float theprogress = 20000.0 * _Progress;
  float mini = 20000 * strobe;
  float4 FG, BG;
  if (swap) {
	BG = tex2D( BGround, uv);
	FG = tex2D( FGround, uv);
  }
  else {
	BG = tex2D( FGround, uv);
	FG = tex2D( BGround, uv);
  }
  float rem = frac(ceil(theprogress/mini) / 2.0);
  if (rem == 0.0) return FG;
  else return BG;
}


//--------------------------------------------------------------
// Technique
//
// Specifies the order of passes (we only have a single pass, so
// there's not much to do)
//--------------------------------------------------------------
technique SampleFxTechnique
{

   pass Pass1
   {
      PixelShader = compile PROFILE Combine();
   }
}

What we want to do is to arrange for the effect to accurately use frame counts where Lightworks will let it. At the moment it uses a value derived from the percentage progress of the effect.

The first thing that we will do is add a declaration of the variable that we're going to use. We can do that without taking any precautions because if the variable isn't already available in Lightworks it will be treated as an uninitialised variable, and ignored.

//--------------------------------------------------------------//

float _Progress;
float _LengthFrames;                   // New code for version 14.1

bool swap
...

The next thing to do is set up the shader code to support that variable, but only if we're running version 14.1 or better. First, here's the section of code that we need to adjust. Note that I have moved the declaration and calculation of rem up from further down the shader code. The reason for the change will become obvious from the section that follows this.

{
  float theprogress = 20000.0 * _Progress;
  float mini = 20000 * strobe;
  float rem = frac(ceil(theprogress/mini) / 2.0);
...

We need first to add a test for the variable _LengthFrames. We can do that by checking if _LENGTHFRAMES has been defined. That test reliably checks whether this is 14.1 or better. What we will then do is add some code to allow accurate calculation of frame intervals between the strobes when using version 14.1.

#ifdef _LENGTHFRAMES
   float frame = round (_LengthFrames * _Progress);   // This finds the current frame
   float rate  = max (round (strobe), 1.0);           // Limit rate to an integer value
   float rem   = frac (floor (frame / rate) / 2.0);   // Turn upper layer on or off
#else
  float theprogress = 20000.0 * _Progress;
  float mini = 20000 * strobe;
  float rem = frac(ceil(theprogress/mini) / 2.0);
#endif
...

Having done that, we now have a serious problem with the strobe setting. It can only ever be set to 1 frame flashes unless you want to type in the actual value that you need each time. To get around that we need to conditionally compile the settings section of the code. Note that I have changed the label from "Strobe Spacing" to "Strobe rate". That probably wasn't really necessary but to me it felt clearer when dealing with frames.

float strobe
<
   string Description = "Strobe rate";
#ifdef _LENGTHFRAMES
   float MinVal = 1;
   float MaxVal = 60;
#else
   float MinVal = 0.0;
   float MaxVal = 1.0;
#endif
> = 1.0;

So what we now have is an effect that will compile under version 14.0 and earlier and give a percentage setting of the strobe rate but under version 14.1 and higher allow setting the strobe rate in frames.


This image is hidden for guests. Please log in or register to see it.


However there's a little more finessing that can be done. By changing the parameter declaration section even more we can make everything much clearer to the user.

bool swap
<
   string Description = "Swap start frame";
> = false;

float strobe
<
#ifdef _LENGTHFRAMES
   string Description = "Strobe frame rate";
   float MinVal = 1;
   float MaxVal = 60;
#else
   string Description = "Strobe Spacing";
   float MinVal = 0.0;
   float MaxVal = 1.0;
#endif
> = 1.0;

We now finally have an effect that that not only compiles under version 14.0 and earlier with a percentage setting and under version 14.1 and higher with a strobe rate set in frames, but which also tells you what it does. As you can see, the changes required were minor. They will in no way damage its use in earlier LW versions.


This image is hidden for guests. Please log in or register to see it.


There is one caveat to be borne in mind: if we compile this effect in 14.1 then open it in 14.0 or earlier the result will at best be undefined. You should never do this. If you need to roll back to an earlier version of Lightworks you will need to remove the effect completely then re-install it.

This has been tested in LW 14.1 beta build 102397 and functions as described. It will not work correctly on earlier beta versions of 14.1.
Last Edit: 7 months, 2 weeks ago by jwrl.

Re: Any new variables available to pixel shaders? 10 months, 4 weeks ago #164855

  • jwrl
  • Moderator
    Pro User
  • OFFLINE
  • Moderator
  • Posts: 9775
  • 10 months, 4 weeks ago
I have been experimenting with various follow-ups to the "Clamp" / "ClampToEdge" cross-platform problem identified by Great White. Here's a reminder of the problem.

Great White wrote:
... the root problem is in the use of "Clamp" for the sampler states AddressU/AddressV in dve1.fx. It appears that "Clamp" means distinctly different things in Microsoft/HLSL and Cg (Mac/Linux).

To get the right/expected answer with Cg, we need to use ClampToEdge (not Clamp). I've modded all our affected shaders accordingly (and added a #define for ClampToEdge=Clamp when running on Windows).

The changes won't be in the imminent beta build, but the one after.

I have come up with a technique which addresses the problem by achieving the same effect as a Clamp/ClampToEdge while avoiding using either. There may be other ways of doing this, but this one works as expected, and has the advantage of being completely back-compatible. Here are some code fragments that explain what I do.

sampler Fg_S = sampler_state
{
   Texture  = <Fg>;
   AddressU = Wrap;   // Note use of "Wrap" addressing here.  Any
   AddressV = Wrap;   // other mode should work too, even "Clamp".

...

   float4 Fgd = (any(xy<0.0) || any(xy>1.0)) ? 0.0.xxxx : tex2D (Fg_S, xy);

...

Because "Border" appears to behave ambiguously in Linux I don't believe that it can be used on its own to give the same result. If it could the conditional setting of Fgd could be avoided. Because I no longer have a working Linux install because of recent hardware upgrades I can't test other alternatives, but hopefully that situation will be remedied soon.
Last Edit: 10 months, 4 weeks ago by jwrl.

Re: Any new variables available to pixel shaders? 10 months, 4 weeks ago #164858

  • schrauber
  • OFFLINE
  • Platinum Boarder
  • Posts: 2231
  • 10 months, 4 weeks ago
This unfortunately has a small edge problem with certain scalings (tested under Windows). 1 pixel from the top edge, for example, is visible at the bottom:
This image is hidden for guests. Please log in or register to see it.

This image is hidden for guests. Please log in or register to see it.

The reason for this seems to be that 0.0 and 1.0 are a half texel off the texture. (compare my former experiments mirror)

In the case of Border seems to work:

float _OutputWidth; 
float _OutputHeight; 

//.....

   #define TEXEL05   (float2 (1 / _OutputWidth, 1 / _OutputHeight  ) / 2.0)      //  Half texel dimensions.
   float4 Fgd = (any (xy < TEXEL05) || any (xy > 1.0 -TEXEL05)) ? 0.0.xxxx : tex2D (CropSampler, xy);


According to internet this also seems to be the problem with Clamp-Sampler-setting under Linux, that Clamp works on Linux without this texel-correction.


Edit: Although I suspect your shader code would be sufficient if the Clamp sampler setting were also used under Linux. With "Wrap" a 1 pixel error is more visible.

Edit 2:
My code is not working properly
Mainly automatically translated
--------------------------------------------
Windows 10, 64 Bit
Intel i5-4440 (3,1 GHz) ; Intel HD Graphics 4600
Last Edit: 10 months, 4 weeks ago by schrauber.

Re: Any new variables available to pixel shaders? 10 months, 4 weeks ago #164862

  • schrauber
  • OFFLINE
  • Platinum Boarder
  • Posts: 2231
  • 10 months, 4 weeks ago
Ok, the problem in my formula was that I had positioned the border on the texel center, which caused problems with original scaling.
Just outside the center it seems to work under Windows (Linkux not tested):
float _OutputWidth; 
float _OutputHeight; 

//.....

   #define TEXEL05   (float2 (1 / _OutputWidth, 1 / _OutputHeight  ) / 2.0)      //  Half texel dimensions.
   float4 Fgd = (any (xy < TEXEL05 - 1E-6) || any (xy > 1.0 - TEXEL05 + 1E-6)) ? 0.0.xxxx : tex2D (CropSampler, xy);
Mainly automatically translated
--------------------------------------------
Windows 10, 64 Bit
Intel i5-4440 (3,1 GHz) ; Intel HD Graphics 4600
Last Edit: 10 months, 4 weeks ago by schrauber.

Re: Any new variables available to pixel shaders? 10 months, 4 weeks ago #164885

  • jwrl
  • Moderator
    Pro User
  • OFFLINE
  • Moderator
  • Posts: 9775
  • 10 months, 4 weeks ago
OK, it's possible to avoid the half texel adjustment (which I consider a good thing to avoid, especially if using _OutputHeight as part of the calculation). Until I get time to set up my Linux system again I can't check Clamp, but using Mirror effectively hides the problem. Border most certainly doesn't work. In tests here I was getting a spurious black pixel on the left edge of the frame, thus trading a horizontal error for a vertical one.

So the code then becomes as shown.

sampler Fg_S = sampler_state
{
   Texture  = <Fg>;
   AddressU = Mirror;   // Unfortunately this at the moment is
   AddressV = Mirror;   // the only address mode tested to work

...

   float4 Fgd = (any(xy<0.0) || any(xy>1.0)) ? 0.0.xxxx : tex2D (Fg_S, xy);

...

If Clamp does work it would be a better solution than Mirror. Hopefully some time over the Christmas break I'll get a chance to check that cross-platform.

[EDIT] The reason for taking this approach rather than the ClampToEdge / Clamp approach outlined earlier is backwards compatibility. An effect written with this code will be fully backwards compatible at the expense of a simple conditional statement. This may of course become a consideration when using it with complex multi-pass effects.
Last Edit: 10 months, 3 weeks ago by jwrl.
Time to create page: 0.49 seconds
Scroll To Top