Exca Posted July 13, 2016 Share Posted July 13, 2016 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. Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted July 13, 2016 Share Posted July 13, 2016 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(); Quote Link to comment Share on other sites More sharing options...
Exca Posted July 13, 2016 Author Share Posted July 13, 2016 Thanks, that worked. Quote Link to comment Share on other sites More sharing options...
Rodrigo Posted October 4, 2016 Share Posted October 4, 2016 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. Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted October 5, 2016 Share Posted October 5, 2016 Use 4.0.2 instead of 4.0.1. The version you use had bug with filters. Rodrigo 1 Quote Link to comment Share on other sites More sharing options...
Rodrigo Posted October 5, 2016 Share Posted October 5, 2016 Awesome!!, works great. Thanks Ivan!! Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.