Writing Effects Tutorial

This forum is currently in read-only mode.
  • I figured I'd write a quick tutorial that goes over the basics of writing a pixel shader.

    The first turial will just be a quick overview of an existing shader so you understand how it works.

    Open the directory or its equiv: C:\Program Files\Scirra\Construct\Effects\

    This is where all the effects are. Each effect is a single *.fx file which can be opened in any text-based editor. I would personally recommend notepad++ because its free, simple, has syntax colouring, and multiple undos. Anyway it doesn't really matter for this tutorial, we are simply going to be reading over the file.

    Open Multiply Plus.fx

    Lets take a look at the first few lines of the file:

    // Multiply
    // Ashley Gullen
    // PS 2.0
    // Multiplication blend with intensity.[/code:2lblvyj0]
    The first line is the name of the effect, the second is the Author, the third is the Pixel Shader version, and the fourth is its description. The // means this text is a comment, and therefore not part of the fx file...however Construct reads these specific lines and obtains information from them, so your fx files MUST contain these comments
    
    Next we have our parameter for our effect
    
    [code:2lblvyj0]//#PARAM percent intensity 1 : Intensity : Intensity of the effect.
    float intensity;[/code:2lblvyj0]
    
    The first line is a Construct definition, which goes in the form:
    #param type fxvariablename initialValue : nameInConstruct : Description
    
    For type we can either use percent or float. Currently these are all that are supported, but later we may include more (such as a texture!)
    
    Next we have any declared variables that are needed for our shader. 
    [code:2lblvyj0]
    // Foreground texture
    texture ForegroundTexture;
    
    // Background texture
    texture BackgroundTexture;
    [/code:2lblvyj0]
    
    Constructs runtime will check to see if certain variables are declared in the effect file, and will pass appropriate values to them. Here is a complete list:
    [ul]ForegroundTexture
    BackgroundTexture
    SourceTexture
    PreviousTexture
    frameCounter
    boxLeft
    boxTop
    boxRight
    boxBottom
    boxWidth
    boxHeight
    hotspotX
    hotspotY
    pixelWidth
    pixelHeight
    bgStart
    bgEnd
    [/ul]
    Other shaders such as 'wave' use most of these variables, but multiply doesn't require them so they aren't declared.
    
    Now we have our sampler definitions:
    [code:2lblvyj0]// Foreground sampler
    sampler2D foreground = sampler_state {
        Texture = (ForegroundTexture);
        MinFilter = Point;
        MagFilter = Point;
        MipFilter = Point;
    };
    
    // OriginalTexture sampler
    sampler2D background = sampler_state {
        Texture = (BackgroundTexture);
        MinFilter = Point;
        MagFilter = Point;
        MipFilter = Point;
    };[/code:2lblvyj0]
    
    In a pixel shader, samplers determine how the computer calculates the colour value of a point in the texture. If you use 'point', it will go to the nearest pixel, if you use linear, it does a linear interpolation between pixels. We tend to only use these two. Point is faster than linear, so we tend to only use linear when its possible we are looking up pixels that are between pixels. Magnify uses linear so that the magnified image looks smooth rather than 'pixelly'.
    
    Now we have our effect definition. 
    
    [code:2lblvyj0]// Effect function
    float4 EffectProcess( float2 Tex : TEXCOORD0 ) : COLOR0
    {
        float4 front = tex2D(foreground, Tex.xy);
        float4 back = tex2D(background, Tex.xy);
        front.a *= back.a;
        front.rgb *= back.rgb * intensity;
        return front;
    }[/code:2lblvyj0]
    
    This is the actual function which calculates every single pixel. It's best to write the function as simple as possible, because the fx file is converted into a machine language which is optimised and the shaders read. 
    
    [code:2lblvyj0]tex2D(foreground, Tex.xy);[/code:2lblvyj0]
    the tex2D function obtains a pixel colour from a sampler. 
    
    float4 structures are awesome. You can write stuff like: front *= 2 and the a,r,g,b values all get doubled, or front.rgb * 2 will multiply only red, green, blue, or you can refer to them individually as front.r, front.g, front.b, etc.
    
    these float values are all between 0-1, and if you want to add two colours together you simply write
    front.rgb + back.rgb.
    
    Finally we have our effect definition
    
    [code:2lblvyj0]// ConstructEffect
    technique ConstructEffect
    {
        pass p0
        {
            VertexShader = null;
            PixelShader = compile ps_2_0 EffectProcess();
        }
    }[/code:2lblvyj0]
    
    All our shaders tend to either be ps_2_0 or ps_1_4
    
    The pixel shader definition determines what functions can be used, and how many lines of instructions you can have per shader.
  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • This is awesome, thanks a lot David!

  • Nice tutorial, moving it to the effects forum .

  • Awesome... haven't got through it all yet but looks nice man!

  • Nice tut davo. Tomorrow i'll get around to experimenting with shaders.

Jump to:
Active Users
There are 1 visitors browsing this topic (0 users and 1 guests)