Jump to content

Creating custom filter


florentd
 Share

Recommended Posts

Hello, 

I'm trying to create a custom Filter in Phaser to make dithering.

I used this great resource as a reference: http://alex-charlton.com/posts/Dithering_on_the_GPU/

Here is my code (I modified the DotScreenFilter code): 

PIXI.DotScreenFilter = function()
{
    PIXI.AbstractFilter.call( this );

    this.passes = [this];

    // set the uniforms
    this.uniforms = {
        scale: {type: '1f', value:1},
        angle: {type: '1f', value:5},
        dimensions:   {type: '4fv', value:[0,0,0,0]},
        indexMatrix4x4: {type: '16i',value:[0,  8,  2,  10, 12, 4,  14, 6,3,  11, 1,  9,15, 7,  13, 5]}
    };

    this.fragmentSrc = [
    'precision mediump float;',
    'varying vec2 vTextureCoord;',
    'varying vec4 vColor;',
    'uniform vec4 dimensions;',
    'uniform sampler2D uSampler;',

    'uniform float angle;',
    'uniform float scale;',
    'uniform int indexMatrix4x4[16];',

    'float indexValue() {',
    'int x = int(mod(gl_FragCoord.x, 4));',
    'int y = int(mod(gl_FragCoord.y, 4));',
    'return float(indexMatrix4x4[(x + y * 4)]) / 16.0;',
    '}',

    'float dither(float color) {',
    'float closestColor = (color < 0.5) ? 0.0 : 1.0;',
    'float secondClosestColor = 1.0 - closestColor;',
    'float d = indexValue();',
    'float distance = abs(closestColor - color);',
    'return (distance < d) ? closestColor : secondClosestColor;',
    '}',


    'void main() {',
    'gl_FragColor = vec4(vec3(dither(vColor.a)), 1);',

    '}'
    ];
};

PIXI.DotScreenFilter.prototype = Object.create( PIXI.AbstractFilter.prototype );
PIXI.DotScreenFilter.prototype.constructor = PIXI.DotScreenFilter;

/**
 * The scale of the effect.
 * @property scale
 * @type Number
 */
 Object.defineProperty(PIXI.DotScreenFilter.prototype, 'scale', {
    get: function() {
        return this.uniforms.scale.value;
    },
    set: function(value) {
        this.dirty = true;
        this.uniforms.scale.value = value;
    }
});
 
/**
 * The radius of the effect.
 * @property angle
 * @type Number
 */
 Object.defineProperty(PIXI.DotScreenFilter.prototype, 'angle', {
    get: function() {
        return this.uniforms.angle.value;
    },
    set: function(value) {
        this.dirty = true;
        this.uniforms.angle.value = value;
    }
});
 

When I run it,

i got these errors:

Quote

ERROR: 0:10: 'mod' : no matching overloaded function found (phaser.min.js, line 7)
ERROR: 0:11: 'mod' : no matching overloaded function found

 

Any ideas what is wrong ?

 


 

Link to comment
Share on other sites

  • 4 weeks later...

Thanks a lot for your response (and sorry for my late response).

anyway, I got now this error:

Quote

ERROR: 0:12: '[]' : Index expression must be constant

It seems that there is a lot of conversion error between int and float.

This is the original code I want to adapt as a shader in phase and I really struggle !

 

in float color;
out vec4 frag_color;

const int indexMatrix4x4[16] = int[](0,  8,  2,  10,
                                     12, 4,  14, 6,
                                     3,  11, 1,  9,
                                     15, 7,  13, 5);

float indexValue() {
    int x = int(mod(gl_FragCoord.x, 4));
    int y = int(mod(gl_FragCoord.y, 4));
    return indexMatrix4x4[(x + y * 4)] / 16.0;
}

float dither(float color) {
    float closestColor = (color < 0.5) ? 0 : 1;
    float secondClosestColor = 1 - closestColor;
    float d = indexValue();
    float distance = abs(closestColor - color);
    return (distance < d) ? closestColor : secondClosestColor;
}

void main () {
    fragColor = vec4(vec3(dither(color)), 1);
}

Any insight to adapt it for phaser ?

Link to comment
Share on other sites

Wow ! The effect is nice.

It works in firefox, but not in Chrome and Safari. And I was trying to implement dithering on the screen (like a post-processing effect), and not only on a texture, but It seems really complicated with my current knowledge of shaders. (sorry, if it sound ungrateful, your code is great ! )

Link to comment
Share on other sites

Hi 

I don't know how to apply a filter to a group of game objects with Phaser 3.  However I have managed to apply the dither filter to a group using Phaser CE.

https://github.com/neilbgames/My-attempt-at-implementing-http-alex-charlton.com-posts-Dithering_on_the_GPU-using-PhaserCE

I understand that Phaser CE code doesn't belong in this section but I thought I would post this in case it may be useful. 

Link to comment
Share on other sites

  • 2 weeks later...

Thanks for your help Gold Finch :)

I finally succeed, so for the 3 peoples in the world who (maybe) want to do a dither effect with shader in Phaser, here is my code:

 

PIXI.dither = function()
{
    PIXI.AbstractFilter.call( this );
 
    this.passes = [this];
 
    // set the uniforms
    this.uniforms = {
        scale: {type: '1f', value:1},
        angle: {type: '1f', value:5},
        dimensions:   {type: '4fv', value:[0,0,0,0]}
    };

    this.fragmentSrc = [
  
        'precision mediump float;',

            'uniform sampler2D uSampler;',
            'varying vec2 vTextureCoord;',
            'float scale = 0.5;',
            'float find_closest(int x, int y, float c0) {',
                
          'vec4 dither0 = vec4( 1.0, 33.0, 9.0, 41.0);',
                'vec4 dither1 = vec4(49.0, 17.0, 57.0, 25.0);',
                'vec4 dither2 = vec4(13.0, 45.0, 5.0, 37.0);',
                'vec4 dither3 = vec4(61.0, 29.0, 53.0, 21.0);',

                'float limit = 0.0;',
                'float value = 0.0;',
                
                'vec4 dither;',
                
                'if(x == 0) {',
                    'dither = dither0;',
                '} else if(x == 1) {',
                    'dither = dither1;',
                '} else if(x == 2) {',
                    'dither = dither2;',
                '} else if(x == 3) {',
                    'dither = dither3;',
                '}',
                
                'if(x < 5) {',
                    'if(y == 0) {',
                        'value = dither[0];',
                    '} else if(y == 1) {',
                        'value = dither[1];',
                    '} else if(y == 2) {',
                        'value = dither[2];',
                    '} else if(y == 3) {',
                        'value = dither[3];',
                    '}',
                
                    'limit = (value + 1.0) / 64.0;',
                '}',
                'if(c0 < limit) {',
                    'return 0.0;',
                '} else {',
                    'return 1.0;',
                '}',
            '}',
            'void main() {',
                
                   'vec3 lum = vec3(0.299, 0.587, 0.114);',
                'float grayscale = dot(texture2D(uSampler, vTextureCoord).rgb, lum);',
                'vec3 rgb = texture2D(uSampler, vTextureCoord).rgb;',
                'vec2 xy = gl_FragCoord.xy * scale;',
                'int x = int(mod(xy.x, 4.0));',
                'int y = int(mod(xy.y, 4.0));',
                'vec3 finalRGB;',
                'finalRGB.r = find_closest(x, y, rgb.r);',
                'finalRGB.g = find_closest(x, y, rgb.g);',
                'finalRGB.b = find_closest(x, y, rgb.b);',
                'gl_FragColor = vec4(finalRGB, 1.0);',
            '}'
    ];
};

PIXI.dither.prototype = Object.create( PIXI.AbstractFilter.prototype );
PIXI.dither.prototype.constructor = PIXI.dither;
 
/**
 * The scale of the effect.
 * @property scale
 * @type Number
 */
Object.defineProperty(PIXI.dither.prototype, 'scale', {
    get: function() {
        return this.uniforms.scale.value;
    },
    set: function(value) {
        this.dirty = true;
        this.uniforms.scale.value = value;
    }
});
 
/**
 * The radius of the effect.
 * @property angle
 * @type Number
 */
Object.defineProperty(PIXI.dither.prototype, 'angle', {
    get: function() {
        return this.uniforms.angle.value;
    },
    set: function(value) {
        this.dirty = true;
        this.uniforms.angle.value = value;
    }
});
 
    

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...