Shader question

For developers using the Construct 2 Javascript SDK

Post » Thu Nov 26, 2015 12:02 am

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 :P 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?
B
39
S
16
G
6
Posts: 543
Reputation: 7,619

Post » Thu Nov 26, 2015 1:05 am

Might require a tick or two, but yes it's doable.
Canvas, or Paster plug would help.
Image ImageImage
B
170
S
50
G
178
Posts: 8,378
Reputation: 112,925

Post » Thu Nov 26, 2015 1:08 am

Cool, thanks :D I'll check those out.
B
39
S
16
G
6
Posts: 543
Reputation: 7,619

Post » Thu Nov 26, 2015 1:44 am

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.
Scirra Employee
B
154
S
53
G
17
Posts: 710
Reputation: 17,850

Post » Thu Nov 26, 2015 4:05 am

Yeah, Canvas or Paster lets you paste objects into them, where the system grab takes the whole screen.
Image ImageImage
B
170
S
50
G
178
Posts: 8,378
Reputation: 112,925

Post » Thu Nov 26, 2015 10:48 pm

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:
Code: Select all
<?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>



The shader itself:
Code: Select all
/////////////////////////////////////////////////////////
// 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);
}


EDIT:
Seems 'int' isn't acceptable syntax so I replaced it with a float for now.
B
39
S
16
G
6
Posts: 543
Reputation: 7,619

Post » Thu Nov 26, 2015 11:17 pm

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:
Code: Select all
/////////////////////////////////////////////////////////
// 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);
}
B
39
S
16
G
6
Posts: 543
Reputation: 7,619

Post » Fri Nov 27, 2015 8:02 am

*moved to a more appropriate section.
If your vision so exceeds your ability, then look to something closer.
Moderator
B
136
S
31
G
86
Posts: 5,481
Reputation: 59,748

Post » Fri Nov 27, 2015 11:34 am

@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;

Code: Select all
/////////////////////////////////////////////////////////
// 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;
}


.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 ;
B
66
S
24
G
29
Posts: 823
Reputation: 22,644

Post » Fri Nov 27, 2015 1:18 pm

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:
Image
ErekT:
Image

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?

Code: Select all
/////////////////////////////////////////////////////////
// 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;

}
B
39
S
16
G
6
Posts: 543
Reputation: 7,619

Next

Return to Javascript SDK

Who is online

Users browsing this forum: No registered users and 0 guests