flowen Posted June 11, 2017 Share Posted June 11, 2017 Hi, this is my first time using shaders and the new filters in pixi v4, so please bare with me First of all I'm a bit confused by the term (custom) filter.. Is that the same as the user of a shader? I assume it is. Second I tried using this example. I got it to work in pixi 3.x but somehow I can't figure out what i'm doing wrong in v4. no error messages, just a black canvas. My goal is to create custom button hovers with PIXI, using shaders, etc. I tried 2 different ways but... alas, same black canvas HTML: <a href="#" class="btn btn-one"> <canvas></canvas> <span class="title">button effect one</span> </a> shader.frag: precision mediump float; uniform vec2 mouse; uniform vec2 resolution; uniform float time; void main() { gl_FragColor = vec4( sin(time), mouse.x/resolution.x, mouse.y/resolution.y, 1.0); } JS: var btnOne = document.querySelector('.btn-one'); var width = btnOne.clientWidth; var height = btnOne.clientHeight; var app = new PIXI.Application({ width: width, height: height, view: btnOne.querySelector('canvas') }); btnOne.append(app.view); // create rect to fill the button and apply shaders to const rect = new PIXI.Graphics() .beginFill(0x00ff00) .drawRect(0, 0, width, height); app.stage.addChild(rect); // Stop application wait for load to finish app.stop(); PIXI.loader.add('shader', 'shader.frag') .load(onLoaded); var simpleShader; var uniforms = {}; uniforms.mouse = { type: 'v2', value: { x:0, y:0 } } uniforms.time = { type: 'f', value: 0 } uniforms.resolution = { type: 'v2', value:{ x: width, y: height} } function onLoaded (loader,res) { // Create the new filter, arguments: (vertexShader, fragmentShader, uniforms) simpleShader = new PIXI.Filter(null, res.shader.data, uniforms); rect.filters = [simpleShader]; app.start(); // bind mouse to shader effects btnOne.onmousemove = function(evt) { // Get the mouse position mousePos = { x: evt.clientX, y: evt.clientY } // Assigning a new value lets Pixi know to update the uniform in the shader // But doing something like uniforms.mouse.x = 0, won't update in this current version of Pixi simpleShader.uniforms.mouse.value = mousePos; } // apply the filter rect.filters = [simpleShader]; // Animate the filter app.ticker.add(function(delta) { simpleShader.uniforms.time.value += 0.1 }); } I read the post about creating filters in v4, but to a beginner it's just confusing as I don't understand a lot of the terminology used. Anyone can (hint how to) fix this so I can continue my explorations programming shaders? ivan.popelyshev 1 Quote Link to comment Share on other sites More sharing options...
Taz Posted June 12, 2017 Share Posted June 12, 2017 I don't think you can apply a Pixi filter to an HTML element like that. Is there an example/tutorial that does that? You could also use PIXI.Text and respond to its mouse events to manually create the behavior of anchor button. And apply/remove filter to the text on mouse over/out. Quote Link to comment Share on other sites More sharing options...
flowen Posted June 12, 2017 Author Share Posted June 12, 2017 @Jinz Thanks for your reply! My thought is that Pixi injects a canvas element within the .button. Rendering sprites was not a problem at all, but now with a shader I have no clue what's going (wr)on(g). Even without uniforms it won't display anything so I think i've been setting things up incorrectly or perhaps there's some limitation within pixi? Later on I want to automate it and inject it in every .button and thus create some crazy button effects.. If someone has a different suggestion to do this, would appreciate it! Quote Link to comment Share on other sites More sharing options...
Taz Posted June 12, 2017 Share Posted June 12, 2017 Neat I didn't know you could do that. I spotted a problem in your code. You're using Pixi's loader to load a file named 'shader.frag', but your shader code isn't in a separate file named 'shader.frag', it's in your HTML file. I think you need to either 1) make the file 'shader.frag' and put your shader code there or 2) leave the shader code where it is, but get the script element and pass it's innerHtml as the shader source parameter. Quote Link to comment Share on other sites More sharing options...
flowen Posted June 12, 2017 Author Share Posted June 12, 2017 @Jinz Oops! Basically I tried 2 different ways, loading by html string or loading by file. Both didn't work but accidentally mixed it up in this thread. Fixed it now. Quote Link to comment Share on other sites More sharing options...
flowen Posted June 12, 2017 Author Share Posted June 12, 2017 When I simply display a color for the shader, it's working. But once I try mixing in uniforms, I only get a black canvas. There's surely something simple I'm not seeing so I just keep on trying updated the code in topic Quote Link to comment Share on other sites More sharing options...
Exca Posted June 12, 2017 Share Posted June 12, 2017 If you're using V4 then the uniforms should be used without .value. So for example simpleShader.mouse = mousePos; You can also skip defining the uniforms if you want. Pixi detects all uniforms in shader code and populates the uniforms -object with correct ones. Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted June 12, 2017 Share Posted June 12, 2017 Im too tired to fix that example now Can anyone do that for me? And I hope we'll fix that all in v5. Making shaders/filters for v4 is not that easy Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted June 12, 2017 Share Posted June 12, 2017 Open http://pixijs.github.io/examples/?v=v4.5.2#/basics/custom-filter.js , paste it there. I have background sprite, and on top im placing container with filter, and specify filterArea as whole screen. In update i modify the uniforms of the filter. I also use "app.screen" instead of "app.renderer" for width and height, because it will take care of resolution stuff (devicePixelRatio), and that rectangle can be assigned as filter area. And if you really want to use grass texture, apply filter to background and start using textureCoord and sampler and other stuff... I dont remember exactly, look in the demo shader (http://pixijs.github.io/examples/required/assets/basics/shader.frag) var app = new PIXI.Application(); document.body.appendChild(app.view); // Create background image var background = PIXI.Sprite.fromImage("required/assets/bkg-grass.jpg"); background.width = app.screen.width; background.height = app.screen.height; app.stage.addChild(background); var shaderFrag = ` precision mediump float; uniform vec2 mouse; uniform vec2 resolution; uniform float time; void main() { gl_FragColor = vec4( sin(time), mouse.x/resolution.x, mouse.y/resolution.y, 0.5); } `; var container = new PIXI.Container(); container.filterArea = app.screen; app.stage.addChild(container); var filter = new PIXI.Filter(null, shaderFrag); container.filters = [filter]; // Animate the filter app.ticker.add(function(delta) { var v2 = filter.uniforms.mouse; var global = app.renderer.plugins.interaction.mouse.global; v2[0] = global.x; v2[1] = global.y; filter.uniforms.mouse = v2; v2 = filter.uniforms.resolution; v2[0] = app.screen.width; v2[1] = app.screen.height; filter.uniforms.resolution = v2; }); flowen 1 Quote Link to comment Share on other sites More sharing options...
flowen Posted June 12, 2017 Author Share Posted June 12, 2017 5 hours ago, Exca said: If you're using V4 then the uniforms should be used without .value. So for example simpleShader.mouse = mousePos; You can also skip defining the uniforms if you want. Pixi detects all uniforms in shader code and populates the uniforms -object with correct ones. I see thanks! @ivan.popelyshev Ivan! Thanks so much for fixing the problem To be honest it does look a little wonky.. would've never thought (and didn't read anywhere) that I would need an filterArea. I tried mixing your code with my 'setup' code, but that gave me another error ( Uncaught TypeError: Cannot read property 'value' of undefined ) which I guess is some uniform that cannot be read.. Anyways, enough for today! Thanks again for answering, even though you're tired. You da man! ivan.popelyshev 1 Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted June 12, 2017 Share Posted June 12, 2017 Glad that helped\. Look, i've added it in examples: http://pixijs.github.io/examples/?v=v4.5.3#/filters/filter-mouse.js FilterArea is a sure way to set the size of filter rectangle. I dont like how "container.width" and "container.height" is calculated. "app.screen" was added by me exactly for that - if screen resizes, that rectangle will also be changed. Quote Link to comment Share on other sites More sharing options...
Slaus Posted January 20, 2018 Share Posted January 20, 2018 (edited) Sample at http://pixijs.github.io/examples/?v=v4.5.3#/filters/filter-mouse.js fails for me with error Cannot ready property 'location' of undefined at VertexArrayObject.js:171 and 'location' is shader.attributes.aTextureCoord passed from Quad.js:98. But sample http://pixijs.io/examples/?v=v4.5.2#/basics/custom-filter.js works somehow. When I change any line at filter-mouse.js sample with vTextureCoord to anything else it also stops working. WebGL Inspector shows that that custom filter (when it's not working) is the only having no aTextureCoord attribute, so shader.attributes.aTextureCoord is undefined. Shader builder program optimizes it somehow so that it doesn't have such attribute anymore maybe? Edit: oh, I guess it's the same issue as described in https://github.com/pixijs/pixi.js/issues/4476 Ivan was mentioning about it occurring because some sampler optimizes out aTextureCoord attribute. Is there a way trick the optimizer so that it won't remove it? Thanks in advance ^^ (eagerly waiting for pixi v5 in the meantime) Edited January 20, 2018 by Slaus reference found ivan.popelyshev 1 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.