Shader question

0 favourites
  • Just a quick question about shaders in C2. I don't know much about the workings of shaders in general, and C2 even less. The way they're programmed... it's all a bit frightening So I'll probably try to hire someone to write what I need, but first I need to know if what I'm thinking of is possible with C2's render pipeline.

    So here goes: I want to take what's rendered on screen, modify it with an interpolation filter, and then render the result to a texture/sprite/somesuch while leaving the original screen render unmodified. Then I want to overlay the result onto the screen so I can adjust how much it blends with opacity. Is that something that can be accomplished in C2 with a shader?

  • Might require a tick or two, but yes it's doable.

    Canvas, or Paster plug would help.

  • Cool, thanks I'll check those out.

  • Try Construct 3

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

    Try Now Construct 3 users don't see these ads
  • If all you want is to blend the original screen with a processed version of itself, all you need is a single shader applied to a layer. Using a canvas or paster will just impact performance by adding another unnecessary texture.

  • Yeah, Canvas or Paster lets you paste objects into them, where the system grab takes the whole screen.

  • Okay I see. Thanks for the pointers

    I have been sniffing around the various shaders that come with C2 and an FXAA shader I found on the net, and I'm starting to get an idea of what's what. I tried converting an FXAA shader I found on the net but get greeted with this error straight off the bat:

    Error reading XML file

    Unknown effect parameter type

    Line 36, column 9

    Element c2effect \ parameters \ param

    ... which is very strange since the XML is basically a straight copy/paste job from an existing effect. Man this isn't very confidence-building :/

    XML:

    <?xml version="1.0" encoding="UTF-8" ?>
    <c2effect>
    	<!-- About -->
    	<id>fxaa</id>			<!-- Never change the ID.  Change the name instead -->
    	<name>FXAA</name>
    	<category>Blend</category>
    	<description>Apply FX antialiasing.</description>
    	<author>ErekT</author>
    	
    	<!-- Settings -->
    	
    	<!-- Extend the bounding box for effect processing by a number of pixels to show the edges
    		 of effects which go beyond the object edges, e.g. blur and warp. -->
    	<extend-box-horizontal>0</extend-box-horizontal>
    	<extend-box-vertical>0</extend-box-vertical>
    	
    	<!-- Set to true if the background is sampled (samplerBack is referenced at all in the shader) -->
    	<blends-background>true</blends-background>
    	
    	<!-- Set to true if the background is not sampled at 1:1 with the foreground (e.g. the
    		 background texture co-ordinates are modified in some way by the shader, as done
    		 by Glass and Lens) -->
    	<cross-sampling>false</cross-sampling>
    	
    	<!-- Set to true if the shader does not modify the opaque areas of the foreground. In other words
    		 any opaque pixels in the original image are output in the same position and still fully opaque.
    		 This is used to optimise the front-to-back renderer's depth pass, since it can still write depth
    		 and skip overdraw for any objects using only shaders which preserve opaqueness. -->
    	<preserves-opaqueness>false</preserves-opaqueness>
    	
    	<!-- Set to true if the effect changes over time, e.g. Noise or Warp effects. -->
    	<animated>false</animated>
    	
    	<!-- Parameters -->
    	<parameters>
    		<param>
    			<name>Width</name>
    			<description>Game resolution X</description>
    			<type>int</type>
    			<initial>0</initial>
    			<uniform>WindowWidth</uniform>
    		</param>
    		<param>
    			<name>Height</name>
    			<description>Game resolution Y</description>
    			<type>int</type>
    			<initial>0</initial>
    			<uniform>WindowHeight</uniform>
    		</param>
    	</parameters>
    </c2effect>
    
    [/code:rmnp6ym2]
    
    The shader itself:
    [code:rmnp6ym2]
    /////////////////////////////////////////////////////////
    // FXAA effect
    
    varying mediump vec2 vTex;
    uniform lowp sampler2D samplerFront;
    uniform lowp sampler2D samplerBack;
    uniform mediump vec2 destStart;
    uniform mediump vec2 destEnd;
    
    //uniform lowp sampler2D tex;
    //uniform mediump vec2 fragCoord;
    uniform highp int WindowWidth;
    uniform highp int WindowHeight;
    
    void main(void)
    {
    	lowp vec4 front = texture2D(samplerFront, vTex);
    	lowp vec4 back = texture2D(samplerBack, mix(destStart, destEnd, vTex));
    
                vec2 v_rgbNW, vec2 v_rgbNE, 
                vec2 v_rgbSW, vec2 v_rgbSE, 
                vec2 v_rgbM) {
        vec4 color;
        mediump vec2 inverseVP = vec2(1.0 / WindowWidth, 1.0 / WindowHeight);
        vec3 rgbNW = texture2D(samplerFront, v_rgbNW).xyz;
        vec3 rgbNE = texture2D(samplerFront, v_rgbNE).xyz;
        vec3 rgbSW = texture2D(samplerFront, v_rgbSW).xyz;
        vec3 rgbSE = texture2D(samplerFront, v_rgbSE).xyz;
        vec4 texColor = texture2D(samplerFront, v_rgbM);
        vec3 rgbM  = texColor.xyz;
        vec3 luma = vec3(0.299, 0.587, 0.114);
        float lumaNW = dot(rgbNW, luma);
        float lumaNE = dot(rgbNE, luma);
        float lumaSW = dot(rgbSW, luma);
        float lumaSE = dot(rgbSE, luma);
        float lumaM  = dot(rgbM,  luma);
        float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
        float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
        
        mediump vec2 dir;
        dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));
        dir.y =  ((lumaNW + lumaSW) - (lumaNE + lumaSE));
        
        float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) *
                              (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN);
        
        float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce);
        dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX),
                  max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),
                  dir * rcpDirMin)) * inverseVP;
        
        vec3 rgbA = 0.5 * ( 
    	texture2D(samplerFront, vTex * inverseVP + dir * (1.0 / 3.0 - 0.5)).xyz +
            texture2D(samplerFront, vTex * inverseVP + dir * (2.0 / 3.0 - 0.5)).xyz);
        vec3 rgbB = rgbA * 0.5 + 0.25 * (
            texture2D(samplerFront, vTex * inverseVP + dir * -0.5).xyz +
            texture2D(samplerFront, vTex * inverseVP + dir * 0.5).xyz);
    
        float lumaB = dot(rgbB, luma);
        if ((lumaB < lumaMin) || (lumaB > lumaMax))
            color = vec4(rgbA, texColor.a);
        else
            color = vec4(rgbB, texColor.a);
    
        gl_FragColor = mix(gl_FragColor, color);
    }
    [/code:rmnp6ym2]
    
    EDIT:
    Seems 'int' isn't acceptable syntax so I replaced it with a float for now.
  • Hmm. I get this error from the line "gl_FragColor = mix(gl_FragColor, color);":

    'mix': no matching overloaded function found.

    'assign': cannot convert from 'const float' to 'Fragcolor mediump 4-component vector of float'

    Any shader-experts out there who knows what's going on?

    Here's the full shader code:

    /////////////////////////////////////////////////////////
    // FXAA effect
    
    #ifndef FXAA_REDUCE_MIN
        #define FXAA_REDUCE_MIN   (1.0/ 128.0)
    #endif
    #ifndef FXAA_REDUCE_MUL
        #define FXAA_REDUCE_MUL   (1.0 / 8.0)
    #endif
    #ifndef FXAA_SPAN_MAX
        #define FXAA_SPAN_MAX     8.0
    #endif
    
    precision mediump float;
    
    varying mediump vec2 vTex;
    uniform lowp sampler2D samplerFront;
    uniform lowp sampler2D samplerBack;
    uniform mediump vec2 destStart;
    uniform mediump vec2 destEnd;
    
    uniform highp float WindowWidth;
    uniform highp float WindowHeight;
    
    void main(void)
    {
        lowp vec4 front = texture2D(samplerFront, vTex);
        lowp vec4 back = texture2D(samplerBack, mix(destStart, destEnd, vTex));
    
        vec2 v_rgbNW;
        vec2 v_rgbNE;
        vec2 v_rgbSW;
        vec2 v_rgbSE;
        vec2 v_rgbM;
    
        vec4 color;
        mediump vec2 inverseVP = vec2(1.0 / WindowWidth, 1.0 / WindowHeight);
        vec3 rgbNW = texture2D(samplerFront, v_rgbNW).xyz;
        vec3 rgbNE = texture2D(samplerFront, v_rgbNE).xyz;
        vec3 rgbSW = texture2D(samplerFront, v_rgbSW).xyz;
        vec3 rgbSE = texture2D(samplerFront, v_rgbSE).xyz;
        vec4 texColor = texture2D(samplerFront, v_rgbM);
        vec3 rgbM  = texColor.xyz;
        vec3 luma = vec3(0.299, 0.587, 0.114);
        float lumaNW = dot(rgbNW, luma);
        float lumaNE = dot(rgbNE, luma);
        float lumaSW = dot(rgbSW, luma);
        float lumaSE = dot(rgbSE, luma);
        float lumaM  = dot(rgbM,  luma);
        float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
        float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
        
        mediump vec2 dir;
        dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));
        dir.y =  ((lumaNW + lumaSW) - (lumaNE + lumaSE));
        
        float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) *
                              (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN);
        
        float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce);
        dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX),
                  max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),
                  dir * rcpDirMin)) * inverseVP;
        
        vec3 rgbA = 0.5 * ( 
    	texture2D(samplerFront, vTex * inverseVP + dir * (1.0 / 3.0 - 0.5)).xyz +
            texture2D(samplerFront, vTex * inverseVP + dir * (2.0 / 3.0 - 0.5)).xyz);
        vec3 rgbB = rgbA * 0.5 + 0.25 * (
            texture2D(samplerFront, vTex * inverseVP + dir * -0.5).xyz +
            texture2D(samplerFront, vTex * inverseVP + dir * 0.5).xyz);
    
        float lumaB = dot(rgbB, luma);
        if ((lumaB < lumaMin) || (lumaB > lumaMax))
            color = vec4(rgbA, texColor.a);
        else
            color = vec4(rgbB, texColor.a);
    
        gl_FragColor = mix(gl_FragColor, color);
    }
    [/code:3gbyn4a7]
  • *moved to a more appropriate section.

  • ErekT I am not an expert of glsl , I think Mr rojohound can help better than me

    but the correct version of the Antialiasing glsl fx is like this.

    This was converted to C2 but really quickly .. you can integrate Boolean var for disable or enable fx;

    /////////////////////////////////////////////////////////
    // FXAA effect
    
    #ifdef GL_ES
    precision mediump float;
    #endif
    
    uniform mediump sampler2D samplerFront;
    varying vec2 vTex;
    uniform mediump float pixelWidth;
    uniform mediump float pixelHeight;
    vec2 iResolution = vec2( 1./pixelWidth, 1./pixelHeight);
     
    
    //uniform lowp sampler2D tex;
    //uniform mediump vec2 fragCoord;
    uniform mediump float WindowWidth;
    uniform mediump float WindowHeight;
    
    #ifndef FXAA_REDUCE_MIN
        #define FXAA_REDUCE_MIN   (1.0/ 128.0)
    #endif
    #ifndef FXAA_REDUCE_MUL
        #define FXAA_REDUCE_MUL   (1.0 / 8.0)
    #endif
    #ifndef FXAA_SPAN_MAX
        #define FXAA_SPAN_MAX     8.0
    #endif
    
    vec4 fxaa_2_0(sampler2D tex, vec2 fragCoord, vec2 resolution,
                vec2 v_rgbNW, vec2 v_rgbNE, 
                vec2 v_rgbSW, vec2 v_rgbSE, 
                vec2 v_rgbM) {
        vec4 color;
        mediump vec2 inverseVP = vec2(1.0 / resolution.x, 1.0 / resolution.y);
        vec3 rgbNW = texture2D(tex, v_rgbNW).xyz;
        vec3 rgbNE = texture2D(tex, v_rgbNE).xyz;
        vec3 rgbSW = texture2D(tex, v_rgbSW).xyz;
        vec3 rgbSE = texture2D(tex, v_rgbSE).xyz;
        vec4 texColor = texture2D(tex, v_rgbM);
        vec3 rgbM  = texColor.xyz;
        vec3 luma = vec3(0.299, 0.587, 0.114);
        float lumaNW = dot(rgbNW, luma);
        float lumaNE = dot(rgbNE, luma);
        float lumaSW = dot(rgbSW, luma);
        float lumaSE = dot(rgbSE, luma);
        float lumaM  = dot(rgbM,  luma);
        float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
        float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
        
        mediump vec2 dir;
        dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));
        dir.y =  ((lumaNW + lumaSW) - (lumaNE + lumaSE));
        
        float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) *
                              (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN);
        
        float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce);
        dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX),
                  max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),
                  dir * rcpDirMin)) * inverseVP;
        
        vec3 rgbA = 0.5 * (
            texture2D(tex, fragCoord * inverseVP + dir * (1.0 / 3.0 - 0.5)).xyz +
            texture2D(tex, fragCoord * inverseVP + dir * (2.0 / 3.0 - 0.5)).xyz);
        vec3 rgbB = rgbA * 0.5 + 0.25 * (
            texture2D(tex, fragCoord * inverseVP + dir * -0.5).xyz +
            texture2D(tex, fragCoord * inverseVP + dir * 0.5).xyz);
    
        float lumaB = dot(rgbB, luma);
        if ((lumaB < lumaMin) || (lumaB > lumaMax))
            color = vec4(rgbA, texColor.a);
        else
            color = vec4(rgbB, texColor.a);
        return color;
    }
    
    //To save 9 dependent texture reads, you can compute
    //these in the vertex shader and use the optimized
    //frag.glsl function in your frag shader. 
    
    //This is best suited for mobile devices, like iOS.
    
    void texcoords_3_1(vec2 fragCoord, vec2 resolution,
    			out vec2 v_rgbNW, out vec2 v_rgbNE,
    			out vec2 v_rgbSW, out vec2 v_rgbSE,
    			out vec2 v_rgbM) {
    	vec2 inverseVP = 1.0 / resolution.xy;
    	v_rgbNW = (fragCoord + vec2(-1.0, -1.0)) * inverseVP;
    	v_rgbNE = (fragCoord + vec2(1.0, -1.0)) * inverseVP;
    	v_rgbSW = (fragCoord + vec2(-1.0, 1.0)) * inverseVP;
    	v_rgbSE = (fragCoord + vec2(1.0, 1.0)) * inverseVP;
    	v_rgbM = vec2(fragCoord * inverseVP);
    }
    
    vec4 apply_1_2(sampler2D tex, vec2 fragCoord, vec2 resolution) {
    	mediump vec2 v_rgbNW;
    	mediump vec2 v_rgbNE;
    	mediump vec2 v_rgbSW;
    	mediump vec2 v_rgbSE;
    	mediump vec2 v_rgbM;
    
    	//compute the texture coords
    	texcoords_3_1(fragCoord, resolution, v_rgbNW, v_rgbNE, v_rgbSW, v_rgbSE, v_rgbM);
    	
    	//compute FXAA
    	return fxaa_2_0(tex, fragCoord, resolution, v_rgbNW, v_rgbNE, v_rgbSW, v_rgbSE, v_rgbM);
    }
    
    void main() {
      vec2 uv = 1.*vTex;
     // uv.y = 1.0 - uv.y;
    
      //can also use gl_FragCoord.xy
      vec2 fragCoord = uv * iResolution; 
    
      vec4 color;
      // if (enabled) {
           color = apply_1_2(samplerFront, fragCoord, iResolution);
      // } else {
        //  color = texture2D(samplerFront, uv);
      // }
    
      gl_FragColor = color;
    }
    [/code:17ngs3nv] 
    
    .xml file is not accepting int or boolean variable; just percent or float ;
    So look the original source and converted source ..and meditate or play with online editor like glslsandbox... 
    good luck
    when you want learn something .. 
    allow time minimum 4   hour/day during 30day you will become beginner
    allow time minimum 8   hour/day during 60day you will become confirmed
    allow time minimum 12 hour/day during 120day you will become expert
    allow time minimum 16 hour/day during 365day you will become master
    I am BEGINNER ;
  • Thanks a bunch for that It's interesting to see how you structure things by breaking them up into separate functions.

    I made some progress with my own conversion as well. It doesn't blend with the background like it should and there's some hefty artifacting going on, but it's a start.

    Gigatron:

    ErekT:

    There's also some kind of interpolation weirdness in both our conversions (mine especially) that needs addressing.

    Finally, if I want to assign the shader to a separate layer that affects everything underneath I need to read from samplerBack, do shader magic to it, and then write the result to samplerFront which represents the layer in question. Right?

    /////////////////////////////////////////////////////////
    // FXAA effect
    
    #ifndef FXAA_REDUCE_MIN
        #define FXAA_REDUCE_MIN   (1.0/ 128.0)
    #endif
    #ifndef FXAA_REDUCE_MUL
        #define FXAA_REDUCE_MUL   (1.0 / 8.0)
    #endif
    #ifndef FXAA_SPAN_MAX
        #define FXAA_SPAN_MAX     8.0
    #endif
    
    precision lowp float;
    
    varying mediump vec2 vTex;
    uniform lowp sampler2D samplerFront;
    uniform lowp sampler2D samplerBack;
    uniform mediump vec2 destStart;
    uniform mediump vec2 destEnd;
    
    uniform highp float WindowsWidth;
    uniform highp float WindowsHeight;
    
    void main(void)
    {
        lowp vec4 front = texture2D(samplerFront, vTex);
        lowp vec4 back = texture2D(samplerBack, mix(destStart, destEnd, vTex));
    
        mediump vec2 resolution = vec2(WindowsWidth, WindowsHeight);
        mediump vec2 inverseVP = vec2(1.0 / WindowsWidth, 1.0 / WindowsHeight);
        vec3 rgbNW = texture2D(samplerFront, vTex + (vec2(-1.0,-1.0)/resolution)).xyz;
        vec3 rgbNE = texture2D(samplerFront, vTex + (vec2(1.0,-1.0)/resolution)).xyz;
        vec3 rgbSW = texture2D(samplerFront, vTex + (vec2(-1.0,1.0)/resolution)).xyz;
        vec3 rgbSE = texture2D(samplerFront, vTex + (vec2(1.0,1.0)/resolution)).xyz;
        vec3 rgbM  = texture2D(samplerFront, vTex).xyz;
    
        vec3 luma = vec3(0.299, 0.587, 0.114);
        float lumaNW = dot(rgbNW, luma);
        float lumaNE = dot(rgbNE, luma);
        float lumaSW = dot(rgbSW, luma);
        float lumaSE = dot(rgbSE, luma);
        float lumaM  = dot(rgbM,  luma);
    
        float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
        float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
        
        mediump vec2 dir;
        dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));
        dir.y =  ((lumaNW + lumaSW) - (lumaNE + lumaSE));
        
        float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) *
                              (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN);
        
        float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce);
        dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX),
                  max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),
                  dir * rcpDirMin)) / resolution;
        
        vec3 rgbA = 0.5 * ( 
    	texture2D(samplerFront, vTex + dir * (1.0 / 3.0 - 0.5)).xyz +
            texture2D(samplerFront, vTex + dir * (2.0 / 3.0 - 0.5)).xyz);
        vec3 rgbB = rgbA * 0.5 + 0.25 * (
            texture2D(samplerFront, vTex + dir * -0.5).xyz +
            texture2D(samplerFront, vTex + dir * 0.5).xyz);
    
        float lumaB = dot(rgbB, luma);
        if((lumaB < lumaMin) || (lumaB > lumaMax))
            gl_FragColor.xyz=rgbA;
        else
            gl_FragColor.xyz=rgbB;
    
    }
    [/code:1rpu4wdf]
  • Here is the topic where i started to understand glsl.. (RojoHound glsl help) and never used samplerBack..

  • if someone try this little tool ..

    consider you have .xml file and empty .fx file ;

    Go to shadertoy copy a simple fx and past into this tool ; click to convert; and copy code on your .fx

    file; As i said complex and compacted fx are not working yet;

    http://gigatron3k.free.fr/html5/C2/FX/stc

  • Gigatron

    if someone try this little tool ..

    consider you have .xml file and empty .fx file ;

    Go to shadertoy copy a simple fx and past into this tool ; click to convert; and copy code on your .fx

    file; As i said complex and compacted fx are not working yet;

    http://gigatron3k.free.fr/html5/C2/FX/stc

    Hell's Teeth!

    I'd already tried to convert this shader from Shadertoy, and failed but your converter worked first time <img src="{SMILIES_PATH}/icon_e_smile.gif" alt=":)" title="Smile">

    Only slight issue is it's upside down, but still - hot damn!

    Download if interested

  • Only slight issue is it's upside down, but still - hot damn!

    Download if interested

    Good work ..

    To flip fx vertically ... add line 68 :v=-v; //sorry of course talking about y axis ... so v.y=-v.y; same but better sens and not affect x axis

  • Thanks, Gigatron. Working perfectly now

    So many toys to explore :>

    Just successfully converted a cute tilable water shader - https://www.shadertoy.com/view/MdlXz8

    BTW. Have also managed to add a couple of Parameters. Such fun!

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