Jump to content

Phaser Filter UV Coordinate Mappings


jbattersby
 Share

Recommended Posts

Hi,
 
I'm somewhat confused about how the UV coordinates are allocated for sprites - my understanding is they should be ranging from 0.0 to 1.0 in both x and y directions. However, with the code below:
 

this.wavetest = this.game.add.sprite(this.game.width * 0.5,this.game.height * 0.5,'wave_test');      var fragmentSrc = [        "precision mediump float;",        "uniform sampler2D uSampler;",        "varying vec2 vTextureCoord;",        "void main(void) {",        "vec4 texColor = texture2D(uSampler, vTextureCoord);",        "if(vTextureCoord.x < 0.1){",        "texColor = vec4(1.0, 0.0, 1.0, 1.0);",        "}",        "gl_FragColor = texColor;",        "}"      ];      this.filter = new Phaser.Filter(this.game, null, fragmentSrc);      this.wavetest.filters = [this.filter];

I get the following result:
filter.png
 
What I expect it to do is show the pink for the first 1/10th width of the sprite, not some arbitrary amount exceeding half! Can anybody explain this to me?
 
I'm ultimately trying to shear and animate an array of sprites to create a wave effect that will encompass other objects. Fiddling with the fragment shader seems the only option to mimic modifying the vertices of a quad without resorting to something like three.js... which I may have to if this doesn't work out....

Link to comment
Share on other sites

UV coordinates are normalised, so yes 0 to 1.

 

There is nothing wrong with your shader code, it works fine for me here - but I'm using my own 512x512 texture (assets/textures/metal.png in the Phaser Examples repo if you want to try with it too)

 

Here's my complete code:

var game = new Phaser.Game(800, 600, Phaser.AUTO, 'phaser-example', { preload: preload, create: create });function preload() {    game.load.image('metal', 'assets/textures/metal.png');}var filter;var sprite;function create() {    var fragmentSrc = [        "precision mediump float;",        "varying vec2 vTextureCoord;",        "uniform sampler2D uSampler;",        "void main(void) {",            "vec4 texColor = texture2D(uSampler, vTextureCoord);",            "if (vTextureCoord.x < 0.1) {",                "texColor = vec4(1.0, 0.0, 1.0, 1.0);",            "}",                 "gl_FragColor = texColor;",        "}"    ];    //  Texture must be power-of-two sized or the filter will break    sprite = game.add.sprite(0, 0, 'metal');    filter = new Phaser.Filter(game, null, fragmentSrc);    sprite.filters = [ filter ];}

And it looks like this:

 

post-1-0-19920000-1433256892.png

Link to comment
Share on other sites

Very peculiar then, I get a similar effect with your texture (mine was also PoT (256x256)). Interestingly enough, the same amount of pink is covered in both textures:

 

filter2.jpg

 

It seems reminiscent of a problem I had before when I was moving the sprite (with texture repeat on) and the sprite acted as a mask over a repeated texture in the background. This is running on 2.2.2 via a yeoman generator btw (as provided by codevinsky)

Link to comment
Share on other sites

You should try it against 2.3 (my screen shot above was against 2.4-dev) as 2.3 contains a vastly updated version of Pixi compared to 2.2. Unless the result we're seeing is hardware related, although I wouldn't have thought so for this specifically. But you never know.

Link to comment
Share on other sites

Same result with 2.3 and 2.4 unfortunately :/

 

Like you I'm not convinced its a hardware issue - I first reported this on a Macbook Pro Retina, 13", Early 2013 but I've just viewed this though my LAN on a Windows 7 tower and it does exactly the same. Its reporting Pixi.js 2.2.8... is this correct?

 

Could be the yeoman generator but I'm not convinced of that either unless its left out a crucial setup step....

Link to comment
Share on other sites

Hang on.... does the same happen for you when you set the canvas size to 1920x1080? Issue should be: texture remains the same size but the pink area will increase....

 

Because with my original generator stuff, setting it to 800x600 "fixes" it.....

Link to comment
Share on other sites

Ahh yes, that would make sense!

 

When reading the texel is relative to the texture size, but writing it out again you're now dealing in screen space, not texture space. If you want to clamp the write to the specific texture area you'll need to do some texture width / screen width normalisation.

Link to comment
Share on other sites

Ok, so if I change the code to this it works as expected:

<!doctype html><html>    <head>        <meta charset="UTF-8" />        <title>hello phaser!</title>        <script src="phaser.min.js"></script>    </head>    <body>    <script type="text/javascript">    window.onload = function() {        var game = new Phaser.Game(800, 600, Phaser.AUTO, 'phaser-example', { preload: preload, create: create, update: update });		function preload() {		    game.load.image('metal', 'metal.png');		}		var filter;		var sprite;		function create() {			var fragmentSrc = [				"precision mediump float;",				"varying vec2 vTextureCoord;",				"uniform sampler2D uSampler;",				"uniform vec2      resolution;",				"void main(void) {",					"vec2 uv = vTextureCoord / vec2(resolution.x/800.0, resolution.y/600.0);",					"vec4 texColor = texture2D(uSampler, vTextureCoord);",					"if (uv.x < 0.1) {",						"texColor = vec4(1.0, 0.0, 1.0, 1.0);",					"}",					"gl_FragColor = texColor;",				"}"			];			//  Texture must be power-of-two sized or the filter will break			sprite = game.add.sprite(0, 0, 'metal');			var customUniforms = {				viewportX:{				type: "float",				value: this.game.width},				viewportY:{				type: "float",				value: this.game.height},			};			filter = new Phaser.Filter(game, null, fragmentSrc);			filter.setResolution(512, 512);				sprite.filters = [ filter ];		}		function update()		{			sprite.x += 1;		}    };    </script>    </body></html>

I'd prefer not to hard code viewport values into the fragment but I'm confused by how custom uniforms should be passed (would prefer a vec2, say, viewport.xy) into the filter....

 

In any case, why is it not implied that the filter should apply to the texture/object space as oppose to the screen space? If I wanted a whole screen filter, shouldn't I apply it to the renderer or a sprite matching the size of it?

Link to comment
Share on other sites

Fragment shaders output in window space.

 

Passing uniforms is easy:

    var customUniforms = {        iChannel0: { type: 'sampler2D', value: sprite.texture, textureData: { repeat: true } }    };    filter = new Phaser.Filter(game, customUniforms, fragmentSrc);

A vec2 type would be '2f'.

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

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