Jump to content

Can DisplacementFilter be implemented using the vertex shader?


Recommended Posts

PIXI's DisplacementFilter works by using a (mostly) default vertex shader and does the actual displacement work in the fragment shader. In the fragment shader, it reads the x & y displacements from the red and green color channels of the displacement map. Then to determine what color should go at (x,y), it samples the color at (x + x_displacement, y + y_displacement).

I wonder if this can be flipped around so that the displacement work is done in the vertex shader by displacing vertices according to the displacement map. For this to work, I think the displacements would be stored at the source pixel instead of at the destination pixel, so displacement vectors go in the opposite direction.

I'm asking because in the application I'm developing I want to be able to extrapolate displacements outside the ordinary range. In the default DisplacementFilter I can vary displacementFilter.scale to change the warp smoothly from zero to full displacement. But I can't just plug in 150% to get an even larger displacement, or put -50% to go the other direction (because changing the scale only affects pixels that already get displaced). But if displacements were interpreted as vertex shifts, I believe I could do just that.

Is this feasible? Has anyone already experimented along these lines? I've begun sketching on some code, but it's not working. No errors, but also no displacement. I hesitate to share it because I honestly don't quite know what I'm doing yet when it comes to shaders. But oh well, here it is. Please go easy on me. :)

Vertex shader:

attribute vec2 aVertexPosition;

uniform mat3 projectionMatrix;
uniform mat3 filterMatrix;

varying vec2 vTextureCoord;

uniform vec4 inputSize;
uniform vec4 outputFrame;
uniform vec4 inputClamp;

uniform vec2 scale;
uniform mat2 rotation;
uniform sampler2D mapSampler;

vec2 filterTextureCoord(void)
    return aVertexPosition * (outputFrame.zw * inputSize.zw);

void main(void)
    vTextureCoord = filterTextureCoord();
    vec2 vFilterCoord = ( filterMatrix * vec3( vTextureCoord, 1.0)  ).xy;

    vec4 map = texture2D(mapSampler, vFilterCoord);

    map -= 0.5;
    map.xy = scale * inputSize.zw * (rotation * map.xy);

    vec2 position = aVertexPosition * max(outputFrame.zw, vec2(0.)) + outputFrame.xy;
    gl_Position = vec4((projectionMatrix * vec3(position + map.xy, 1.0)).xy, 0.0, 1.0);


Fragment shader (just the default):

varying vec2 vTextureCoord;

uniform sampler2D uSampler;

void main(void)
  gl_FragColor = texture2D(uSampler, vTextureCoord);


Link to comment
Share on other sites

I believe you need a PIXI.SimplePlane but with custom shader.


Cant show Plane example, but here's what I had in v4 with CUSTOM mesh, I didnt port it to v5 yet: https://gameofbombs.github.io/examples-heaven/#/mesh/plane.js

I need to move it anyway, so maybe next week :) For now you can try v5 SimplePlane + custom MeshMaterial: just re-assign "shader" or "material" property, its the same.

Link to comment
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.

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.


  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...