Sign in to follow this  
rolnxyz

Pixi Filter and pixel size

Recommended Posts

Hi, I'm trying to learn how to pass and use textures in PIXI.Filter. I have a game that uses a complex filter that takes multiple textures and behaves differently depending on the color of the pixel of each texture. It's too complicated to post here.

The main problem I have is: I don't know how to measure the width / height of a pixel of the texture I'm passing inside my shader.

Here I have a very simple filter that illustrates my issue:

I want to create a filter that I pass the following "u" shape texture

image.png.df7b1e26b92062f182ee1ca239cae1de.png

 

 

 

 

 

 

 

 

 

the filter uses that shape to generate a red drop shadow like this:

 

image.png.4ac05a8c41559b8d6e9b52e51ea5cb6d.png

The problem is the shader messes up and doesn't calculate properly the length of a pixel resulting on this:

image.png.50c827a69d7ad030740e80ebcf0a609c.png

I was expecting to have a perfect stair going up, and I was expecting more steps on the stair (see algorithm below).

Does anyone know what I'm doing wrong?

Here's a link to a codepen illustrating the issue:

https://codepen.io/alvaromartinlop/pen/abOvzxb?editors=0010

Here's the vertex shader:

attribute vec2 aVertexPosition;
attribute vec2 aTextureCoord;

uniform mat3 projectionMatrix;
varying vec2 vTextureCoord;

uniform mat3 shadowMapMatrix;
varying vec2 vShadowMapCoord;

void main(void)
{
    gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);

    vTextureCoord = aTextureCoord;
    vShadowMapCoord = (shadowMapMatrix * vec3(aTextureCoord, 1.0)).xy;   
}

Here's the frag shader:

precision highp float;

varying vec2 vTextureCoord;
uniform vec4 inputPixel; // Problem is here

varying vec2 vShadowMapCoord;
uniform sampler2D shadowMapTexture;

void main() {
  vec4 shadowColor = vec4(1, 0, 0, 1);

  vec2 displacementCoord = vShadowMapCoord;
  vec4 shadowMapColor = texture2D(shadowMapTexture, vShadowMapCoord);
  vec4 finalColor;
  vec4 translateColor;

  vec2 translate = vec2(inputPixel.z,-inputPixel.w);
  for(int i= 0; i < 10; i++) {
    displacementCoord -= translate;
    translateColor = texture2D(shadowMapTexture, displacementCoord);
    if (translateColor.x > 0.0 && shadowMapColor.x == 0.0) {
      finalColor = shadowColor;
      break;
    }
  }
	gl_FragColor = finalColor;
}

Clearly the issue is with inputPixel, displacementCoord is not decrementing properly on each iteration in the for loop.

Here's how I calculate the matrix for the texture

  public apply(
    filterManager: systems.FilterSystem,
    input: RenderTexture,
    output: RenderTexture,
    clearMode: boolean
  ): void {
    this.uniforms.shadowMapMatrix = filterManager.calculateSpriteMatrix(
      this._matrix,
      this._shadowMapSprite
    );
    filterManager.applyFilter(this, input, output, clearMode);
  }

So the question is. How do I properly calculate inputPixel so that I don't have the irregular staircase problem?

Thanks.

Share this post


Link to post
Share on other sites

Hello, fellow shaders enthusiast and blurshadow slayer!

Welcome to the forums!

Well, first I have to notify you that if you dont use `uSampler` , you dont actually need to use Filter, you can write mesh shader: https://pixijs.io/examples/#/mesh-and-shaders/triangle-textured.js and put your texture size through uniforms.

Filter is supposed to process whatever is inside container, not to just paint something else instead. Its also used in case you need multiple passes.

Even if you dont use `uSampler`, its still calculated in temporary RenderTexture that you dont see, and inputPixel is calculated for it.

PixiJS takes 128x128 temporary texture , and inputPixel is (128,128,1/128,1/128). Your texture size is (80,80). 

When I put 1/80 to your shader-  it looks fine.

Either you pass your texture size as a uniform, either you get rid of filter and write mesh shader. You have to pass texture size as a uniform anyway ;)

Edited by ivan.popelyshev

Share this post


Link to post
Share on other sites

Ah nice, I totally missed it creates a 128x128 temporary texture, makes sense why inputPixel doesn't work.
Yea I see what you are saying about uSampler, my game shader does use uSampler, I updated the codepen and verified your recommendations work, I updated the uniforms in my game shader and everything is good now.
Also mesh shaders are great, found about them the other day. I love pixi js!
Thanks!

Share this post


Link to post
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...
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.