Jump to content

Uv in filters


Exca
 Share

Recommended Posts

Is there a way to get coordinates from 0...1 in filters that map to the actual viewing area rather than the texture size.

For example I want to tint an object so that it gradually changes color based on the distance from center point.

Doing that with this:

varying vec2 vTextureCoord;

uniform sampler2D uSampler;

void main(void)
{
	float dist = length(vTextureCoord - vec2(0.5, 0.5));
	gl_FragColor = dist * texture2D(uSampler, vTextureCoord);
}

Provides wrong results (sometimes correct) as the actual display area might not be in the 0-1 area.

One way to fix this would be to pass an uniform with the position and dimensions of current display. But I'm wondering if there's something that's built in to pixi already.

Link to comment
Share on other sites

That is also because pixi-v4 uses power-of-two framebuffers. If you want 400x400 it will give you 512x512. That's why you have to use some matrices with "calculateNormalizedScreenSpaceMatrix" method, I understand that its not obvious for now, but we'll make it better with docs :)

You can paste it to http://pixijs.github.io/examples/index.html?s=basics&f=container.js&title=Container&v=dev and see that it works

//============FILTER

function VignetteFilter(options) {
  var opts = options || {};
  PIXI.Filter.call(this,null,fragShader);
  this.uniforms.amount = opts.amount || 0.5;
  this.uniforms.size = opts.size || 0.5;
  this.uniforms.mappedMatrix = new PIXI.Matrix();
} 

VignetteFilter.prototype = Object.create(PIXI.Filter.prototype);
VignetteFilter.prototype.constructor = VignetteFilter;

Object.defineProperties(VignetteFilter.prototype, {size: { get: function () {return this.uniforms.size;},set: function (value) {this.uniforms.size = value;}},amount: {get: function () {return this.uniforms.amount;},set: function (value) {this.uniforms.amount = value;}}});

VignetteFilter.prototype.apply = function (filterManager, input, output)
{
    filterManager.calculateNormalizedScreenSpaceMatrix(this.uniforms.mappedMatrix);
     // draw the filter...
    filterManager.applyFilter(this, input, output);
};

var fragShader = [
    "uniform sampler2D uSampler;",
    "uniform float size;",
    "uniform float amount;",
    "varying vec2 vTextureCoord;",
    "uniform mat3 mappedMatrix;",
    "void main() {",
    "vec4 color = texture2D(uSampler, vTextureCoord);",
    "vec3 mapCoord = vec3(vTextureCoord, 1.0) * mappedMatrix;",
    "float dist = distance(mapCoord.xy, vec2(0.5, 0.5));",
    "color.rgb *= smoothstep(0.8, size * 0.799, dist * (amount + size));",
    "gl_FragColor = color;",
    "}"
].join('');

//=============DEMO

filters = [];
function addFilter(f){
    filters.push(f);
    stage.filters = filters;
}

function removeFilter(f){
    filters.splice(filters.indexOf(f),1);
    if (filters.length <= 0)
      stage.filters = undefined;
  else
    stage.filters = filters;
}

var ripples = [];
function ripple() {
    this.donutScale = 0;
    this.sprite = PIXI.Sprite.fromImage('http://i.imgur.com/OfOCy3G.png');
    this.sprite.anchor.set(0.5);  
    this.displacementFilter = new PIXI.filters.DisplacementFilter(this.sprite);
    stage.addChild(this.sprite);
    ripples.push(this);
    addFilter(this.displacementFilter);
    this.sprite.position.copy(mousePosition);
    this.update = function(){
        if (this.donutScale < 10) {
          this.donutScale += 0.1;
          this.sprite.scale.set(this.donutScale);
          this.displacementFilter.scale.set(120 - (120 * (this.donutScale / 10)));

          if (this.donutScale >= 10)
              this.remove();
        }
    },
    this.remove = function() {
       ripples.splice(ripples.indexOf(this), 1);
       removeFilter(this.displacementFilter);
    }
}

document.addEventListener("click", function() {
  new ripple();
});


var renderer = PIXI.autoDetectRenderer(800, 600);
document.body.appendChild(renderer.view);

// create the root of the scene graph
var stage = new PIXI.Container();
stage.interactive = true;
var mousePosition = new PIXI.Point();
stage.on('mousemove', onPointerMove).on('touchmove', onPointerMove);
function onPointerMove(eventData) { mousePosition.copy(eventData.data.global);}

var container = new PIXI.Container();
stage.addChild(container);

var vignetteFilter = new VignetteFilter({size: 0.2, amount: 1});
addFilter(vignetteFilter);


var bg = PIXI.Sprite.fromImage('_assets/bkg-grass.jpg');
bg.width = renderer.width;
bg.height = renderer.height;
bg.alpha = 0.4;
container.addChild(bg);

var padding = 100;
var bounds = new PIXI.Rectangle(-padding, -padding, renderer.width + padding * 2, renderer.height + padding * 2);
var maggots = [];

for (var i = 0; i < 1000; i++)
{
    var maggot =  PIXI.Sprite.fromImage('_assets/maggot.png');
    maggot.anchor.set(0.5);
    container.addChild(maggot);
    maggot.direction = Math.random() * Math.PI * 2;
    maggot.speed = 1;
    maggot.turnSpeed = Math.random() - 0.8;
    maggot.position.x = Math.random() * bounds.width;
    maggot.position.y = Math.random() * bounds.height;
    maggot.scale.set(1 + Math.random() * 0.3);
    maggot.original = new PIXI.Point();
    maggot.original.copy(maggot.scale);
   // maggot.blendMode = 1; - IT WORKS THAT WAY
    maggot.blendMode = 0; // DOESNT WORK THAT WAY
    maggots.push(maggot);

}

var count = 0;
function animate() {
    for (var i = ripples.length - 1; i >= 0; i--) {
      ripples[i].update();
    }

    count += 0.05;
    for (var i = 0; i < maggots.length; i++)
    {
        var maggot = maggots[i];
        maggot.direction += maggot.turnSpeed * 0.01;
        maggot.position.x += Math.sin(maggot.direction) * maggot.speed;
        maggot.position.y += Math.cos(maggot.direction) * maggot.speed;
        maggot.rotation = -maggot.direction - Math.PI/2;
        maggot.scale.x = maggot.original.x + Math.sin(count) * 0.2;

        // wrap the maggots around as the crawl
        if (maggot.position.x < bounds.x)
            maggot.position.x += bounds.width;
        else if (maggot.position.x > bounds.x + bounds.width)
            maggot.position.x -= bounds.width;

        if (maggot.position.y < bounds.y)
            maggot.position.y += bounds.height;
        else if (maggot.position.y > bounds.y + bounds.height)
            maggot.position.y -= bounds.height;
    }

    renderer.render(stage);
    requestAnimationFrame(animate);
}
animate();

 

 

Link to comment
Share on other sites

  • 2 months later...

Hi,

Sorry for bringing this up again, but I'm working with a very simple filter (sepia) on a Sprite, directly on the JS, not using the shader code.

How can I implement this fix on something that simple?

http://codepen.io/rhernando/pen/63fefb2a49e6d93b49342e037cfc6889?editors=0010

Commenting out line 36 fixes the issue, ie, not applying the filter to the sprite.

Thanks,

Rodrigo.

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...