mts

Members
  • Content Count

    6
  • Joined

  • Last visited

  • Days Won

    1

Everything posted by mts

  1. Thanks Ivan for you answer again! I understand that you are very busy and that you don't have time. I would be very grateful if you could take a look at this post again on the weekend and help me understand better the excellent PIXI.js.
  2. Hi Ivan, sorry to bother you again. As you advised, I adapted(tried) the displacement filter example. However, I get the same result, although I noticed that the rotation uniform indeed changes according to the sprite.rotation. So I am missing something here. What I get as a result now: How I adapted the code: ... const sprite = new PIXI.Sprite.from( 'https://static4.depositphotos.com/1006994/298/v/450/depositphotos_2983099-stock-illustration-grunge-design.jpg' ); sprite.anchor.set(0.5); sprite.x = renderer.width / 2; sprite.y = renderer.height / 2; sprite.rotation = Math.PI/6; setTimeout(() => { sprite.filters = [generateGradientFilter(sprite)]; }, 300); ... function gradientVertexShader() { return ` attribute vec2 aVertexPosition; uniform mat3 projectionMatrix; uniform mat3 filterMatrix; varying vec2 vTextureCoord; varying vec2 vFilterCoord; uniform vec4 inputSize; uniform vec4 outputFrame; vec4 filterVertexPosition( void ) { vec2 position = aVertexPosition * max(outputFrame.zw, vec2(0.)) + outputFrame.xy; return vec4((projectionMatrix * vec3(position, 1.0)).xy, 0.0, 1.0); } vec2 filterTextureCoord( void ) { return aVertexPosition * (outputFrame.zw * inputSize.zw); } void main(void) { gl_Position = filterVertexPosition(); vTextureCoord = filterTextureCoord(); vFilterCoord = ( filterMatrix * vec3( vTextureCoord, 1.0) ).xy; } `; } function generateGradientFilter(sprite) { // rectangular gradient const squareGradientShader = ` precision highp float; uniform vec3 colors[4]; uniform float steps[4]; uniform float centerX; uniform float centerY; uniform vec4 inputSize; uniform vec4 outputFrame; varying vec2 vTextureCoord; uniform sampler2D uSampler; uniform vec2 scale; uniform mat2 rotation; uniform vec4 inputClamp; varying vec2 vFilterCoord; void main() { vec4 map = texture2D(uSampler, vFilterCoord); map -= 0.5; map.xy = scale * inputSize.zw * (rotation * map.xy); vec2 uv = vTextureCoord * inputSize.xy / outputFrame.zw; //vec2 uv = vTextureCoord; vec2 gradXY = abs(uv - vec2(centerX, centerY)); // 0.5 is centerX, centerY float dist = pow(max(gradXY.x, gradXY.y) * 2.0, 2.0); float start = steps[0]; for (int i = 1; i < 4; i++) { float end = steps[i]; if (dist >= start && dist <= end) { gl_FragColor = vec4(mix(colors[i - 1], colors[i], (dist-start) / (end-start)), 1.); break; } start = end; } gl_FragColor = texture2D(uSampler, clamp(vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y), inputClamp.xy, inputClamp.zw)) * gl_FragColor; } `; const filter = new PIXI.Filter(gradientVertexShader(), squareGradientShader, { centerX: 0.5, centerY: 0.5, colors: [1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0], steps: [0, 0.2921, 0.3452, 1], scale: { x: sprite.scale.x, y: sprite.scale.y }, rotation: new Float32Array([1, 0, 0, 1]), }); filter.apply = function (filterManager, input, output, clearMode) { // fill maskMatrix with _normalized sprite texture coords_ const maskMatrix = new PIXI.Matrix(); this.uniforms.filterMatrix = filterManager.calculateSpriteMatrix(maskMatrix, sprite); // Extract rotation from world transform const wt = sprite.worldTransform; const lenX = Math.sqrt((wt.a * wt.a) + (wt.b * wt.b)); const lenY = Math.sqrt((wt.c * wt.c) + (wt.d * wt.d)); if (lenX !== 0 && lenY !== 0) { this.uniforms.rotation[0] = wt.a / lenX; this.uniforms.rotation[1] = wt.b / lenX; this.uniforms.rotation[2] = wt.c / lenY; this.uniforms.rotation[3] = wt.d / lenY; console.log('rotation', this.uniforms.rotation); } // draw the filter... filterManager.applyFilter(this, input, output, clearMode); } return filter; } What is suspicious to me: vec4 map = texture2D(uSampler, vFilterCoord); I don't have a map here so I used uSampler. Is this ok? vec2 uv = vTextureCoord * inputSize.xy / outputFrame.zw; I copied frorm here https://github.com/pixijs/pixi.js/wiki/v5-Creating-filters. Not clear what it does but it was guesswork which seemed to get me closer. One thing I could maybe try is to use mapSampler by creating a RenderTexturer and running the gradient filter on it then using that as a map. Although I have no idea if that could work. Can you also explain this: map -= 0.5; map.xy = scale * inputSize.zw * (rotation * map.xy); Why -0.5? What do the multiplications do? Can you help on this?
  3. Can you give me some instructions for the mesh in this case? My end use case is to make a sprite, or a rectangle, or a mesh as you say that will have this black/white gradient applied to be used as mask. Can I use a mesh as a mask? If so, do I pass aVertexPosition to it in format of four rectangle coordinate pairs? I tried, but can you tell me what is the error I am having? Will vTextureCoord work in the mesh? Should I be using a renderTexture or some other construct with the mesh? I noticed I am not able to set an anchor to a mesh. Is this normal? Also, generally, filters combined with sprite rotation, scaling, do not work the way I expect them to. I am guessing it's because I don't understand which matrix does what in the shader and how to use them to get what I need.
  4. Thanks Ivan for your reply. Unfortunately I don't see how to use mesh for this, since it looks more complicated than the sprite. Also, doing anchor.set on it causes error where anchor is undefined. When I try to apply my shader to this mesh, I get the following message: GeometrySystem.ts:276 Uncaught Error: shader and geometry incompatible, geometry missing the "aTextureCoord" attribute at r.checkCompatibility (GeometrySystem.ts:276) at r.initGeometryVao (GeometrySystem.ts:317) at r.bind (GeometrySystem.ts:180) at r._renderDefault (Mesh.ts:330) at r._render (Mesh.ts:297) at r.e.render (Container.ts:545) at e.render (Container.ts:550) at e.render (Container.ts:550) at r.render (Renderer.ts:404) at t.render (Application.ts:119) Here is what I am trying to accomplish: I am expecting the gradient to actually rotate with the sprite it's applied on. This is the shader I am using: precision highp float; uniform vec3 colors[4]; uniform float steps[4]; uniform float centerX; uniform float centerY; uniform vec4 inputSize; uniform vec4 inputPixel; uniform vec4 outputFrame; varying vec2 vTextureCoord; uniform sampler2D uSampler; uniform vec4 rotation; void main() { vec2 uv = (vTextureCoord * inputSize.xy / outputFrame.zw); vec2 gradXY = abs(uv - vec2(centerX, centerY)); // 0.5 is centerX, centerY float dist = pow(max(gradXY.x, gradXY.y) * 2.0, 2.0); float start = steps[0]; for (int i = 1; i < 4; i++) { float end = steps[i]; if (dist >= start && dist <= end) { gl_FragColor = texture2D(uSampler, vTextureCoord) * vec4(mix(colors[i - 1], colors[i], (dist-start) / (end-start)), 1.); break; } start = end; } } Uniforms passed: { centerX: 0.5, centerY: 0.5, colors: [1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0], steps: [0, 0.2921, 0.3452, 1] } Can you direct me how to achieve this?
  5. Hello! I have an issue as described in this SO question: https://stackoverflow.com/questions/64216121/pixi-js-mask-not-being-applied-on-sprite I have put up a bounty as well hoping that someone will direct me to a solution.
  6. Hello! I am trying to implement an array of various animations, some of which require shaders. I am working on an image transition in using a displacement shader from an empty texture -> image. The sprite is rotated when first added to the container. However, after I apply my shader, the sprite reverts to default rotation. I have asked a question on Stackoverflow, in order to not repeat myself I will post the link here: https://stackoverflow.com/questions/64175920/pixi-js-sprite-loses-rotation-after-applying-filter Thank you very much!