florentd Posted May 12, 2018 Share Posted May 12, 2018 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 More sharing options...
Gold Finch Posted May 12, 2018 Share Posted May 12, 2018 Try changing 'int x = int(mod(gl_FragCoord.x, 4));', 'int y = int(mod(gl_FragCoord.y, 4));', to 'int x = int(mod(gl_FragCoord.x, 4.0));', 'int y = int(mod(gl_FragCoord.y, 4.0));', Link to comment Share on other sites More sharing options...
florentd Posted June 4, 2018 Author Share Posted June 4, 2018 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 More sharing options...
Gold Finch Posted June 8, 2018 Share Posted June 8, 2018 Hi, I have had a look at http://alex-charlton.com/posts/Dithering_on_the_GPU/ and I have attempted to implement it in Phaser3. I have put the source code on github. https://github.com/neilbgames/Phaser3-implementation-of-http-alex-charlton.com-posts-Dithering_on_the_GPU- florentd 1 Link to comment Share on other sites More sharing options...
florentd Posted June 11, 2018 Author Share Posted June 11, 2018 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 More sharing options...
Gold Finch Posted June 15, 2018 Share Posted June 15, 2018 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 More sharing options...
florentd Posted June 29, 2018 Author Share Posted June 29, 2018 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 More sharing options...
Recommended Posts