radixzz

vTextureCoord and custom filters on Pixi v4

Recommended Posts

Hi guys!

I'm trying to figure out how to apply some custom frag shader into a filter. The intented effect is a simple crt warp over a sprite.

Here is what I got so far: https://jsfiddle.net/djq6kjx4/1/ but It should look something like the image in the attachment.

As you can see from the example above the warp effect is mostly visible to one corner. Now I'm starting with shaders but I think the reason is that vTextureCoord is somehow off?

I tried to use the mapCoords and unmapCoords from https://github.com/pixijs/pixi-filters/blob/master/src/pixelate/pixelate.frag similarly without success (I have no Idea what those do). :unsure:

Some time after I tried to use gl_fragCoord directly like this:

vec2 coord = gl_FragCoord.xy / dimensions.xy;

wich seems to do the trick but the texture comes out flippled. Im sure it can be fixed but I don't think this is a good path to follow. Right?

 Any hint would be much appreciated :) Thanks

warp.png

Share this post


Link to post
Share on other sites

Filters are working with region on renderTexture, not the full texture, that's why mapCoord / unmapCoord is needed. Also you can't use gl_FragCoord, because it can be either framebuffer either resulting canvas, framebuffer can have different size than screen, and canvas can be flipped.

mapCoord/unmapCoord and "uvs" ( vTextureCoord ) are our trade-off to use multiple filters at once and to use pool of pow2 renderTextures.

The problem is, they are in pixels, so you need dimensions.

    coord = mapCoord(coord ) / dimensions;
    coord = warp( coord );
    coord = unmapCoord(coord * dimensions);

 

But you already have them! Or, you can compute them automagically:

//that's better move to your filter class

filter.apply = function(filterManager, input, output)
{
  this.uniforms.dimensions[0] = input.sourceFrame.width
  this.uniforms.dimensions[1] = input.sourceFrame.height

  // draw the filter...
  filterManager.applyFilter(this, input, output);
}

 

https://jsfiddle.net/60e5pp8d/1/

Also, you can remove division (/dimensions) and filterArea if you take into account what filterArea is really is:

            filterArea[0] = output.size.width;
            filterArea[1] = output.size.height;
            filterArea[2] = input.sourceFrame.x;
            filterArea[3] = input.sourceFrame.y;

You can calculate  the real params you need in "filter.apply", and reduce our code that way it'll look better :)

I'm very sorry that there weren't that kind shader there before, and that we have to hack that.

I make a promise to fix that in my next big overhaul of filters, that'll be soon!

 

Share this post


Link to post
Share on other sites
On 2/22/2017 at 9:57 AM, ivan.popelyshev said:

Filters are working with region on renderTexture, not the full texture, that's why mapCoord / unmapCoord is needed. Also you can't use gl_FragCoord, because it can be either framebuffer either resulting canvas, framebuffer can have different size than screen, and canvas can be flipped.

mapCoord/unmapCoord and "uvs" ( vTextureCoord ) are our trade-off to use multiple filters at once and to use pool of pow2 renderTextures.

The problem is, they are in pixels, so you need dimensions.


    coord = mapCoord(coord ) / dimensions;
    coord = warp( coord );
    coord = unmapCoord(coord * dimensions);

 

But you already have them! Or, you can compute them automagically:


//that's better move to your filter class

filter.apply = function(filterManager, input, output)
{
  this.uniforms.dimensions[0] = input.sourceFrame.width
  this.uniforms.dimensions[1] = input.sourceFrame.height

  // draw the filter...
  filterManager.applyFilter(this, input, output);
}

 

https://jsfiddle.net/60e5pp8d/1/

Also, you can remove division (/dimensions) and filterArea if you take into account what filterArea is really is:


            filterArea[0] = output.size.width;
            filterArea[1] = output.size.height;
            filterArea[2] = input.sourceFrame.x;
            filterArea[3] = input.sourceFrame.y;

You can calculate  the real params you need in "filter.apply", and reduce our code that way it'll look better :)

I'm very sorry that there weren't that kind shader there before, and that we have to hack that.

I make a promise to fix that in my next big overhaul of filters, that'll be soon!

 

just did test, mask is not working...

Share this post


Link to post
Share on other sites
On 2/24/2017 at 7:49 AM, tywang2006 said:

I make a promise to fix that in my next big overhaul of filters, that'll be soon!

Cool to hear!

I think clear documentation for how the coordinates/uvs actually work would help things a lot. Same for the FilterManager. I'm still not sure what exactly that does, even after reading through the sources.

I'd be happy to help write docs, but I lack the knowledge to do so here.

Share this post


Link to post
Share on other sites

I'm having similar problem understanding this conversion between the coordinates.

I'm trying to create a filter that creates an animated "growing circle", like wave, that grows with "time".

I would like to generally set the center to [0.5, 0.5] so that it centers on the sprite. However, it doesn't seem like so and moving the sprite's position also makes it changes.

I've applied the "mapCoord" as suggested.

Please see: https://jsfiddle.net/3j9xxutf/1/

Share this post


Link to post
Share on other sites

@pdl.dev And your fix: 1. ignore zw 2. newCenter = center

 

varying vec2 vTextureCoord;

uniform sampler2D uSampler;
uniform vec4 filterArea;

uniform vec2 dimensions;

uniform float time;
uniform vec2 center;
uniform vec4 color;
uniform float size;     

vec2 mapCoord( vec2 coord )
{
coord *= filterArea.xy;

return coord;
}

void main()
{
vec2 uv = vTextureCoord;
vec4 finalColor;
vec2 mappedCoord = mapCoord(uv) / dimensions;
vec2 newCenter = center;

float r = distance(mappedCoord, newCenter);
float value = smoothstep(time-size,time,r) - smoothstep(time+size, time, r);

finalColor += value * color;
finalColor.w = 1.0;

if (value < 1.0 && value > 0.0)
{
  gl_FragColor = mix(texture2D(uSampler, uv), finalColor, 1.0);
}
else
{
  gl_FragColor = texture2D(uSampler, uv);
}

}

 

Share this post


Link to post
Share on other sites

I tried this example in v5, it seems that it didn't work as expected any more.

I have no idea why

image.thumb.png.468d3014a8f2bad38d5618ec853cd410.png

class CrtWarpFilter extends PIXI.Filter {
  constructor() {
    super(null, `
precision mediump float;

varying vec2 vTextureCoord;
uniform sampler2D uSampler;
uniform highp vec4 inputSize;
uniform highp vec4 outputFrame;

vec2 mapCoord( vec2 coord )
{
    coord *= inputSize.xy;
    coord += outputFrame.xy;

    return coord;
}

vec2 unmapCoord( vec2 coord )
{
    coord -= outputFrame.xy;
    coord /= inputSize.xy;

    return coord;
}

vec2 warpAmount = vec2( 2.0 / 34.0, 1.0 / 16.0 );

vec2 warp(vec2 pos)
{
  pos = pos * 2.0 - 1.0;
  pos *= vec2(
    1.0 + (pos.y * pos.y) * warpAmount.x,
    1.0 + (pos.x * pos.x) * warpAmount.y
  );
  return pos * 0.5 + 0.5;
}
 
void main() {
  vec2 coord = vTextureCoord;
  coord = mapCoord(coord ) / outputFrame.zw;
  coord = warp( coord );
  coord = unmapCoord(coord * outputFrame.zw);
  gl_FragColor = texture2D( uSampler, coord );
}
    `);
  }
}

 

Edited by Oliver Zhou

Share this post


Link to post
Share on other sites

Dear @Oliver Zhou !

What can I say?

Welcome to the forums!

I'm glad you tried that thing and get the result. I can help with small problems.

OK, here it is: https://jsfiddle.net/Hackerham/0vftxLzn/17/

1. There is a problem with precision - same uniforms used in vertex/fragment (inputSize, outputFrame) require same precision. If you use old devices that dont have highp - well, we can always stuff them in "dimensions" uniform like before to get rid of that.

Honestly, its one of new problems that were spawned in v5. We try to fix old ones - get new ones :) However you either solved that on your own either you used legacy mode and "filterArea" uniform that comes with it, the real help follows:

2. To center coords by center of sprite - I removed "-=" from mapping , it doesnt work with screen pixels anymore, its filterArea pixels.

3. To get rid of bleeding problem you encountered - "filter.padding=1; filter.autoFit = false".

And, like for any other v5 filters thread, I recommend to look at https://pixijs.io/examples/#/mesh-and-shaders/triangle-textured.js in case you need only one sprite affected and not whole container - UV manipulation is easier than those renderTexture inputs/outputs. We had a thread today where I posted the result for different shader, 

 

Share this post


Link to post
Share on other sites

Oh, I see your playground. I don't know why didnt you encounter precision issue, its a miracle. Btw, one of other problems is that "precision" in second line (not first one) actually forces pixi to spawn one more "precision" before that and maybe it somehow works...

Yes, just apply 2 and 3 to your playground and you'll get good result.

Share this post


Link to post
Share on other sites
10 minutes ago, ivan.popelyshev said:

Oh, I see your playground. I don't know why didnt you encounter precision issue, its a miracle. Btw, one of other problems is that "precision" in second line (not first one) actually forces pixi to spawn one more "precision" before that and maybe it somehow works...

Yes, just apply 2 and 3 to your playground and you'll get good result.

Thanks for you immediate help, Ivan.

I see it finally works well😀.

I can understand 2, could you please elaborate 3 a little bit for me?

I don't quite get it.

Thanks in advance.

 

 

Share this post


Link to post
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...

  • Recently Browsing   0 members

    No registered users viewing this page.