[Stencyl 3.5] Image / Actor shaders

mdotedot

  • Posts: 1654
Taking a little break from the 3D Library. I wanted to do some image effects.
Stencyl does have a few image manipulation blocks: Brightness, Saturation, Sepia, Grayscale among others. As well as some Blur/Bloom effects.
And you can use fade tweening.

But I needed a Sharpen filter which I couldn't find.

So, I created another Engine-Extension: (For Stencyl 3.5 only!)

Tested:
  • HTML5
  • Android (in BlueStacks and native)
  • Flash does not support GLSL Shaders!
  • Mac OSX Native
  • iOS (Simulator)
  • Windows






Work In Progress!
Stencyl 3.5 Extension

Running Example:
HTML5 Demo

The .Stencyl file:
  Stencyl 3.5 file

« Last Edit: October 08, 2018, 12:32:07 am by mdotedot »
Proud member of the League of Idiotic Stencylers! Doing things in Stencyl that probably shouldn't be done.

mdotedot

  • Posts: 1654
Development Log:

After some investigations on BitmapData manipulations I stumble upon Shaders. In Stencyl you can have fullscreen shaders, but I saw a comment on the Discord channel made by Justin that in 3.5 you can use image shaders.

Most of the code examples use a construction where you extend a shader class and add some Fragment Source Code.

Like this: (example from Justin)

Code: [Select]
class MyShader extends openfl.display.Shader {
   
    @:glFragmentSource(
       
        "varying float vAlpha;
        varying vec2 vTexCoord;
        uniform sampler2D uImage0;
       
        void main(void) {
           
            gl_FragColor  = texture2D (uImage0, vTexCoord);
           
        }"
       
    )
   
   
    public function new () {
       
        super ();
       
    }

}


This worked just fine! But creating a class for each effect didn't seem flexible to m.e.

So I investigated other ways to use dynamic code in the shader.


Some openfl examples indicated that you could set the variable like so:

Code: [Select]
var shader = new Shader ();
shader.glFragmentSource = "  ... GLSL Code ";

// And then:

// bitmap.filters = [ new ShaderFilter (shader) ];
// or
// bitmap.shader = shader;
Custom Shader reference

But that failed in Stencyl.

It took me a while and diving into the sources from openfl and Stencyl I did find a way where you need to create a shader and set both the Vertex and Fragment code:

Code: [Select]
shader.glFragmentSource=code;
shader.glVertexSource=_vert;


But that didn't made it effective as I needed to tell the engine that it was ' dirty '.

Apparently you need to set or get the shader.data to make it initialize again.

So this part of the code made it all happen:

Code: [Select]
var _vert="attribute vec4 openfl_Position; attribute vec2 openfl_TextureCoord; varying vec2 openfl_TextureCoordv; uniform mat4 openfl_Matrix; uniform vec2 openfl_TextureSize;void main(void){openfl_TextureCoordv = openfl_TextureCoord; gl_Position = openfl_Matrix * openfl_Position;}";

var bitmap=new Bitmap(image); // Make a Bitmap from the BitmapData

var shader=new Shader();

shader.glFragmentSource=code; // variable passed from extension
shader.glVertexSource=_vert;

var data=shader.data; // This makes the glfragmentSource and glVertexSource active

Next thing was to set the uniform variables using an engine-extension block.

My 3D Library knowledge came to the rescue and I use HaXe Reflection to set the data variables.
      

Currently I am porting some shader code found on the internet from this source:      
Some examples are ported from this resource: Wagner Fragment Shaders


And .. now is my vacation over and I have to work again tomorrow ...


Proud member of the League of Idiotic Stencylers! Doing things in Stencyl that probably shouldn't be done.


mdotedot

  • Posts: 1654

Updated fist post with new .stencyl and Extension.

Now we can do timer / mouse effects:


Proud member of the League of Idiotic Stencylers! Doing things in Stencyl that probably shouldn't be done.

HopFrog

  • Posts: 49
Wow this is seriously cool. Thanks!


mdotedot

  • Posts: 1654
There is an issue with preprocessor statements in the GLSL code.

If you come across this, here are some hints to rewrite the code:

Suppose this is the code you find online:
Code: [Select]

varying vec2 vTexCoord;
uniform sampler2D uImage0;
uniform float uTime;

void main() {
   
    vec2 texCoord = vTexCoord;
    vec2 iResolution = vec2(320.0, 240.0);
   
    float main_a=1.0;
float main_b=2.0;
float main_c=3.0;
   

#define   afunc( R, G, B) {
const vec3 tst = vec3(R, G, B);
main_a = R*G*B;
main_b = R/G/B;
main_c = (R*G)*B;
}
afunc(23./255.,171./255., 116./255.);
afunc(44./255.,230./255., 126./255.);
afunc(213./255.,140./255., 216./255.);
afunc(35./255.,46./255., 161./255.);
afunc(26./255.,41./255., 165./255.);

#undef afunc

    gl_FragColor = vec4(vec3(main_a,main_b,main_c), 1.0);

}


It will generate errors  like these :       invalid character: #define

*  remove all the comments
* varying vec2 vTextCoord   changing to :   varying vec2 openfl_TextureCoordv;
* uniform sampler2D uImage0; becomes    :   uniform sampler2D openfl_Texture;
*  vec2 texCoord = vTexCoord;   becomes   :   vec2 texCoord = openfl_TextureCoordv;

Do not inline the function in the main method.

So use public variables for the members that are changed inside the function.
   
   
Ported code:

Code: [Select]
varying vec2 openfl_TextureCoordv;
uniform sampler2D openfl_Texture;

float main_a = 0.1;
float main_b = 0.1;
float main_c = 0.1;


void afunc(float R, float G, float B){
vec3 tst = vec3(R, G, B);

main_a = R*G*B;
main_b = R/G/B;
main_c = (R*G)*B;

}

void main() {
   
    vec2 texCoord = openfl_TextureCoordv;
    vec2 iResolution = vec2(320.0, 240.0);
   
afunc(23./255.,171./255., 116./255.);
afunc(44./255.,230./255., 126./255.);
afunc(213./255.,140./255., 216./255.);
afunc(35./255.,46./255., 161./255.);
afunc(26./255.,41./255., 165./255.);

        gl_FragColor = vec4(vec3(main_a,main_b,main_c), 1.0);

}



(Example gives bright green image: just for demonstration purposes)


Proud member of the League of Idiotic Stencylers! Doing things in Stencyl that probably shouldn't be done.

Apamaster

  • Posts: 129
How do I apply the shader to an image? I saw the file but I can't find a way to apply a wave to an image that I'm going to use as a background.

mdotedot

  • Posts: 1654
Upload the example .stencyl file so I can see what you are attempting to do.
Proud member of the League of Idiotic Stencylers! Doing things in Stencyl that probably shouldn't be done.

FMStudioGameDev

  • Posts: 233
Hey,  does anybody have a copy of the Demo stencyl project? The link in the first post is not working anymore and without an example or any documentation is pretty hard to understand how to use the blocks.
Thanks in advance!

LIBERADO

  • *
  • Posts: 2720
I'm spanish, excuse me for my bad English.
I'm not a private teacher. Please, post your questions in the public forum.

FMStudioGameDev

  • Posts: 233
Awesome, thanks a lot mate!