Scrolling Effect - My first attempt at a shader

Welcome to our brand new Clickteam Community Hub! We hope you will enjoy using the new features, which we will be further expanding in the coming months.

A few features including Passport are unavailable initially whilst we monitor stability of the new platform, we hope to bring these online very soon. Small issues will crop up following the import from our old system, including some message formatting, translation accuracy and other things.

Thank you for your patience whilst we've worked on this and we look forward to more exciting community developments soon!

Clickteam.
  • I am trying to teach myself some pixel shader coding in order to spice up my games a bit while not having to rely on other people's work too much.

    After a lot of headaches I managed to get something simple going by modifying the default "Flip Horizontal" code into a shader that scrolls whatever that is behind it.

    Please login to see this picture.
    In the above example the Cloud Backdrop is behind the Shader while the Active Object is on top of it it.

    It would be mainly useful for games where you'd like the background to scroll without having to put in extra layers or move big images around. This way you're also not limited to scrolling entire objects but the targeted areas that the shader is covering.

    The shader comes with an example file and the it's relatively easy to use as far as pixel shaders for Fusion games goes.

    If there are any shader gurus out there, please let me know how I can improve in general. I don't even know what half of the code in the shader does. :)

  • Hey that good, very good

    very useful, thanks for sharing ;)

    ----------------------------------------

    could it do in diagonal also?

    I imagine that you can do by changing "fScrollY" and "fScrollx" at the same time

    Edited once, last by Zonacas (June 21, 2016 at 8:43 AM).

  • Glad you guys like it!

    Zonacas: Yup! I just tried it out and it works. You can also map out the fScroll parameters to two different alterable values and have them scroll individually on two axis.

    Please login to see this link. Please login to see this link.
    Freelance Dev | Currently Working on Jarvis | Please login to see this link.

  • That's a good start! :)
    Not sure if I qualify as a "shader guru", but I'll try and explain a few things:

    Code
    struct PS_INPUT
    {
        float4 Position   : POSITION;
        float2 Texture    : TEXCOORD0;
    };


    This defines the structure of the information which the shader receives as an input. The input structure ("PS_INPUT") contains two other properties:
    "Position" is a float4 containing vertex coordinates (as CF2.5 doesn't play well with vertex shaders, you can safely ignore this part).
    "Texture" is a float2 containing texture coordinates (x and y).
    "POSITION", "TEXCOORD" and "PS_INPUT" (and anything else in all uppercase) are things called "semantics", which tell the compiler what kind of data is represented by the variables (necessary because "Position" and "Texture" are nothing more than variable names, and you could, if you were so inclined, change them to anything you liked).

    Code
    struct PS_OUTPUT
    {
        float4 Color   : COLOR0;
    };


    This is very similar to the above, except that this time it is defining the structure of the information which the shader outputs - which must always be a float4 containing red, green, blue and alpha color components.

    Code
    sampler2D Tex0;
    sampler2D bkd : register(s1);


    This is where the required samplers are listed (samplers being the functions which retrieve color information from a point within a texture).
    However, as the shader only actually samples the background, the first of these two lines isn't actually doing anything, and can be safely deleted.

    Code
    float fScrollX = 1.0;
    float fScrollY = 1.0;


    This is where parameters that stay the same for every pixel are declared. Rather than setting them to actual values here, the default values should be set from within the .xml file, using "<value>1.0</value>". It's also worth noting that more than one variable may be declared in the same statement. eg. "float fScrollX, fScrollY;"

    Code
    PS_OUTPUT ps_main( in PS_INPUT In )
    {


    This is the start of the main shader function, where all the magic happens. The important thing here, is that it is giving you access to the input structure "PS_INPUT" (described previously), under the name "In". In other words, it creates a variable called "In", which contains a float4 called "Position" and a float2 called "Texture". As access to "Position" is never needed, you could have "In" represent just the "Texture" variable, rather than the whole of the "PS_INPUT" structure - so you could later say "In.x" instead of "In.Texture.x".

    Code
    PS_OUTPUT Out;
    Out.Color = tex2D(bkd, float2(In.Texture.x+fScrollX,In.Texture.y+fScrollY));
    return Out;


    This is the actual meat of the shader.
    "tex2D()" is the sampler function that retrieves a float4 color from a specified point within a texture - the first argument is the texture; the second is a float2 containing the x and y coordinates of the point to be sampled. The infinite scrolling effect happens because x and y coordinates "wrap" when less than 0 or greater than 1.
    It's not strictly necessary to create and then return an "Out" variable - you could just say: "return tex2D(bkd, float2(In.Texture.x+fScrollX,In.Texture.y+fScrollY));"

    Code
    technique tech_main
    {
        pass P0
        {
            // shaders
            VertexShader = NULL;
            PixelShader  = compile ps_1_4 ps_main();
        }  
    }


    Finally, this tells the compiler which shader model to use (in this case ps1.4). The rest can be ignored, as you won't be including a vertex shader, and CF2.5 doesn't allow for multi-pass shaders.


    Now, as it happens, I didn't really need to explain a lot of that, because it turns out that much of the code above isn't actually even required. Personally, I use my own stripped-out template, which would let you rewrite the entire shader in this much more compact form:


    (try it - it works!)

    Now, if you'd like a challenge to hone your skills...
    - try making it so that fScrollX and fScrollY are specified in pixels (rather than in the range 0-1), so if fScrollX = -8, then scroll 8 pixels to the left. Hint: This will require the height and width of the object to be passed as parameters.
    - try replacing fScrollX and fScrollY with fScrollAngle (0-360) and fScrollDistance (pixels) parameters. Hint: This will require some trigonometry - some of these functions may help you: Please login to see this link. (careful with degrees and radians!)
    - try adding a "motion blur" in the direction of scrolling. Hint: This will require sampling at more than one position, as well as blending colors.
    - try adding an option that lets the user disable or enable the motion blur effect by (un)ticking a checkbox in the properties panel.

    Anyway, I hope that helps, and good luck! :)

    Edited 6 times, last by MuddyMole (June 22, 2016 at 3:55 PM).

  • Quote

    - try making it so that fScrollX and fScrollY are specified in pixels (rather than in the range 0-1), so if fScrollX = -8, then scroll 8 pixels to the left. Hint: This will require the height and width of the object to be passed as parameters.
    - try replacing fScrollX and fScrollY with fScrollAngle (0-360) and fScrollDistance (pixels) parameters.
    Hint: This will require some trigonometry - some of these functions may help you: Please login to see this link. (careful with degrees and radians!)
    - try adding a "motion blur" in the direction of scrolling.
    Hint: This will require sampling at more than one position, as well as blending colors.
    - try adding an option that lets the user disable or enable the motion blur effect by (un)ticking a checkbox in the properties panel.


    MuddyMole It would be great if you add all those options. :)

  • Thanks for the detailed explanation MuddyMole! It really cleared up a lot of questions that I had.

    It's also impressive how short the shader became once you remade it. Btw - Does the removal of "PS_Input" and "PS_Output" parts while keeping "ps_main()" work any differently or is it just a cleaner way of doing the same thing? It looks much easier to work with in your version. Is it based on what pixel shader version that is used? I noticed my shader was 1.4 and yours is 2.0.

    I'll see if I can figure out your challenges :)

    Please login to see this link. Please login to see this link.
    Freelance Dev | Currently Working on Jarvis | Please login to see this link.

  • Removing the PS_INPUT and PS_OUTPUT structure definitions has no effect at all - they're simply not needed when making a shader for CF2.5.
    My version uses ps2.0a, just because I forgot to change it - it would still work fine using ps1.4.

    The potentially confusing bit is this line here: "float4 ps_main(in float2 In : TEXCOORD0) : COLOR0 {"
    The important thing here is that the variable "In" represents TEXCOORD0, which you will remember is a float2 within PS_INPUT, which contains the x and y coordinates of the point being sampled - unlike in your original version, where "In" was the structure PS_INPUT itself, which contained TEXCOORD0 as well as POSITION. This just means you can reference x and y by saying "In.x", instead of having to say "In.Texture.x".
    Also, the last part specifies that the function outputs COLOR0, which you will remember is the float4 color contained within PS_OUTPUT.

    Good luck with the challenges - don't expect to manage a very good motion blur effect, as I'm not sure it's possible to make one that's very impressive.

    Zonacas: I don't think my challenges would actually improve the shader (the second one would be very inconvenient!) - they're just simple exercises that focus on different common tasks, such as dealing with actual pixels, using maths functions, manipulating colors, using comparisons, adjusting the CF2.5 shader interface, etc.

  • Nice work :) It's nice to see more people experimenting with shaders. It's very rewarding, but can also be confusing/frustrating.

    Quote

    - try making it so that fScrollX and fScrollY are specified in pixels (rather than in the range 0-1), so if fScrollX = -8, then scroll 8 pixels to the left. Hint: This will require the height and width of the object to be passed as parameters.


    That's not quite correct, as it doesn't actually require you to add a parameter in the XML. Instead, you need two special variables that MMF passes automatically.

    Please login to see this link.

  • Hey, I know this thread isn't exactly new at this point, so sorry about the bump, but if I were to use your shader in one of my games, then would you like me to credit you for using the shader? And if so, should I just use your forum user-name?

    My Please login to see this link. (which I actually use), my Please login to see this link. (which I mostly don't use), and my Please login to see this link. (which I don't use anymore pretty much at all really). If there are awards for "'highest number of long forum posts", then I'd have probably won at least 1 by now. XD

  • Sure, go ahead!

    Forum nickname works just fine. There's no requirement to credit me but I certainly don't mind. :)

    Please login to see this link. Please login to see this link.
    Freelance Dev | Currently Working on Jarvis | Please login to see this link.

Participate now!

Don’t have an account yet? Register yourself now and be a part of our community!