pokrishka Posted April 1, 2016 Share Posted April 1, 2016 Hi there guys. Say I want to make a filter that does something to original texture after it was blurred with Blur filter. Here's the PIXI blur filter: BlurFilter.prototype.applyFilter = function (renderer, input, output) { var renderTarget = renderer.filterManager.getRenderTarget(true); this.blurXFilter.applyFilter(renderer, input, renderTarget); this.blurYFilter.applyFilter(renderer, renderTarget, output); renderer.filterManager.returnRenderTarget(renderTarget); }; Is there a way for me to store original input texture and use it as a uniform for my filter, kinda like that: this.myFilter.originalTexture = input.texture; this.blurXFilter.applyFilter(renderer, input, renderTarget); this.blurYFilter.applyFilter(renderer, renderTarget, renderTargetTemp); this.myFilter.applyFilter(renderer, renderTargetTemp, output); I tried getting input.texture however input.texture is an empty WebGLTexture object at that point. Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted April 1, 2016 Share Posted April 1, 2016 That's actually very good idea, may be the same mechanism can be used to make custom blendmodes Quote Link to comment Share on other sites More sharing options...
pokrishka Posted April 1, 2016 Author Share Posted April 1, 2016 Well, once it works lol So far I'm trying to get efficient glow filter. Current custom PIXI glow filter is rather slow since it does quite a lot of computation per each pixel. Blur, on the other hand, is very well optimized and mixing blurred data with real data will allow for calculating both outter and inner glow without having to go around each pixel over set distance in all directions, with precision defined by arbitrary "quality" parameter. Quote Link to comment Share on other sites More sharing options...
pokrishka Posted April 4, 2016 Author Share Posted April 4, 2016 So, does anybody have an idea how can this be achieved? Quote Link to comment Share on other sites More sharing options...
xerver Posted April 4, 2016 Share Posted April 4, 2016 The reason you can't use it in the way you have there is because the uniform is looking for a PIXI.Texture object (which PIXI.RenderTexture also inherits from). And the value you are assigning there is a PIXI.RenderTarget. You might be able to create a RenderTexture object, and manually assign the `.textureBuffer` data to that render target: https://github.com/pixijs/pixi.js/blob/5d385885324e97369fd29b686e9e90eb4cefd14a/src/core/textures/RenderTexture.js#L133-L134 Then assign that RenderTexture to your uniform value, and that may work. You may also need to also manually call `.syncUniforms` since you are changing uniform values mid-render: https://github.com/pixijs/pixi.js/blob/5d385885324e97369fd29b686e9e90eb4cefd14a/src/core/renderers/webgl/shaders/Shader.js#L469 That might work? This would be a first-class feature if WebGL had multiple render targets, but as it is there is only 1 target and X inputs. And we expected that extra inputs would be setup as uniforms beforehand. This case wasn't really considered, so that's our fault! Quote Link to comment Share on other sites More sharing options...
pokrishka Posted April 4, 2016 Author Share Posted April 4, 2016 EDITED: This post is irrelevant now Quote Link to comment Share on other sites More sharing options...
pokrishka Posted April 5, 2016 Author Share Posted April 5, 2016 EDITED: This post is irrelevant now Quote Link to comment Share on other sites More sharing options...
pokrishka Posted April 6, 2016 Author Share Posted April 6, 2016 Ok since this proved to be harder than I thought I figured I'd give a try to a different approach which would be to combine 2 filters instead of making a single one: This combination does the job: var blurFilter = new PIXI.filters.BlurFilter(); var tintFilter = new TintFilter(); tintFilter.originalTexture = shape.texture; shape.filters = [blurFilter, tintFilter]; Here how the resulting glow looks like once we use original texture values to colorize blurred version (both outter and inner glow present): However that only happens when the renderer size is the same as texture, when it's larger this is what I get: How do I limit this uniform to the size of the Sprite being filtered? Here's the shader I used for the glow, once I get this working I will make it customizable so you could set distance, color and strength: 'precision mediump float;', 'varying vec2 vTextureCoord;', 'uniform sampler2D texture;', 'uniform sampler2D originalTexture;', 'void main(void) {', ' vec4 originalColor = texture2D(originalTexture, vTextureCoord);', ' vec4 currentColor = texture2D(texture, vTextureCoord);', ' if (originalColor.a == 0.0) {', ' gl_FragColor = vec4(1.0 * currentColor.a, 0.0, 0.0, currentColor.a);', ' } else {', ' vec4 innerGlow = vec4(1.0 * (1.0 - currentColor.a), 0.0, 0.0, (1.0 - currentColor.a));', ' gl_FragColor = mix(innerGlow, originalColor, currentColor.a);', ' };', '}' Quote Link to comment Share on other sites More sharing options...
xerver Posted April 6, 2016 Share Posted April 6, 2016 Have you looked at the glow filter in extras? https://github.com/pixijs/pixi-extra-filters/blob/master/src/filters/glow/GlowFilter.js Quote Link to comment Share on other sites More sharing options...
pokrishka Posted April 11, 2016 Author Share Posted April 11, 2016 On 06.04.2016 at 5:56 PM, xerver said: Have you looked at the glow filter in extras? https://github.com/pixijs/pixi-extra-filters/blob/master/src/filters/glow/GlowFilter.js Yeah, that's the point, this filter seems rather slow to me. I've been working on some sophisticated glow with animated patterns based on that glow filter and noticed it starts lagging pretty hard even on my home PC which isn't that great but well above low-end machines. Looking at how the computations are done in it I figured there's way too many steps to calculate values and I thought of using well-optimized blur technique instead. Here, I've created a Codepen with my glow filter: http://codepen.io/waterplea/pen/oxpReQ I haven't done benchmarking but while I was working on it and comparing it to the actual GlowFilter, it seemed much faster. Especially on big shapes. The number of blur passes could be increased if it gets not enough for a complex shape, but that is still faster - that glow filter from the extras takes each pixel and then goes around it over the distance and calculates the weight of each pixel's glow, that is way too slow to use in games. The only problem is, my glow filter, as it is now, requires some heavy preliminary settings, like this: glowFilter.originalTexture = shape.texture; glowFilter.xMultiplier = renderer.width / shape.texture.width; glowFilter.yMultiplier = renderer.height / shape.texture.height; glowFilter.xOffset = shape.x / renderer.width; glowFilter.yOffset = shape.y / renderer.height; And since it also has padding introduced, you have to update offsets each time you change glow distance. All of these settings could be done mid-render if I get access to the texture - the question I initally asked in this thread. There must be a way to do so, if I can implement it - this glow will be feasible for actual use in animation, games etc, unlike the GlowFilter from the extras. Quote Link to comment Share on other sites More sharing options...
pokrishka Posted April 11, 2016 Author Share Posted April 11, 2016 So, to reiterate on the blocking issue, if I have this code: this.tintFilter.syncUniform(this.tintFilter.originalTexture); I'm getting a ton of this error in console: WebGL: INVALID_OPERATION: uniform1i: location not for current program Looks like I have to set the current program for the renderer to which I need to syncUniforms, but I don't know how to do that, I don't know how to access actual shader of my filter (it says shader is empty and it only has fragmentSrc as a string, basically). Quote Link to comment Share on other sites More sharing options...
pokrishka Posted June 9, 2016 Author Share Posted June 9, 2016 Bumpity bump. Nobody wants a fast glow filter? Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted June 9, 2016 Share Posted June 9, 2016 I made a plugin that adds Overlay blendMode (https://github.com/pixijs/pixi-picture) , you can use the same approach to create your blend filter. At the moment it is the only way to take current render target as an input Quote Link to comment Share on other sites More sharing options...
pokrishka Posted June 9, 2016 Author Share Posted June 9, 2016 1 hour ago, ivan.popelyshev said: I made a plugin that adds Overlay blendMode (https://github.com/pixijs/pixi-picture) , you can use the same approach to create your blend filter. At the moment it is the only way to take current render target as an input Thanks, Ivan, I will give it a look! 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.