James
James

Reputation: 1766

How do you get the pixel location and image size in a fabric js filter's fragment shader?

How do you get the pixel location and image size inside the fragment shader for the WebGL version of a FabricJS filter? If you just have to pass it in as a uniform is the information available inside the filter or does it need to be passed to the filter as an option?

Upvotes: 2

Views: 351

Answers (1)

AndreaBogazzi
AndreaBogazzi

Reputation: 14741

Ok so, i ll try to navigate in the code and remember, i do not touch that part of code often.

In the base filter class there is a method called createProgram. This method is going to return an object that contains a property called uniformLocations.

This property holds an object that is returned from each filter getUniformLocations method. This method again returns the object using the gl.getUniformLocation from the webgl context.

Now fabric has a convention that in the uniforms uStepW and uStepH you will have what percentage of the unit is a pixel.

In the webgl context the width and height are 1, a pixel is like uStepH by uStepW, that are tipically float like 0.001231432432 and i think the image is in pixels:

width: 1 / uStepW
height: 1 / uStepH

fabric also uses vTexCoord varying to indicate the position (i think because is pretty standard in webgl tutorials all over the internet). So the pixel position is likely:

x: vTextCoord.x / uStepW
y: vTextCoord.y / uStepH

You can look at the webgl filter pixelate in the fabricJS repo to better understand how to access those variables in your own filter. In that filter the method getUniformLocations is returning uStepW and uStepH, but that is unnecessary since the basic filter is going to do the same for us.

So those informations are always available and a fabricjs fragment shader that uses them looks like this:

    /**
     * Fragment source for the Pixelate program
     */
    fragmentSource: 'precision highp float;\n' +
      'uniform sampler2D uTexture;\n' +
      'uniform float uBlocksize;\n' +
      'uniform float uStepW;\n' +
      'uniform float uStepH;\n' +
      'varying vec2 vTexCoord;\n' +
      'void main() {\n' +
        'float blockW = uBlocksize * uStepW;\n' +
        'float blockH = uBlocksize * uStepW;\n' +
        'int posX = int(vTexCoord.x / blockW);\n' +
        'int posY = int(vTexCoord.y / blockH);\n' +
        'float fposX = float(posX);\n' +
        'float fposY = float(posY);\n' +
        'vec2 squareCoords = vec2(fposX * blockW, fposY * blockH);\n' +
        'vec4 color = texture2D(uTexture, squareCoords);\n' +
        'gl_FragColor = color;\n' +
      '}',

Now, said so, i do not think you need to know those things in a webgl filter, unless you are doing something particular.

This kind of question to me smells of the XY problem, but since i'm not a WEBGL expert at all, i may be wrong. If you are trying to build a filter and you think you need these informations to progress further, you could do better at explaining also what are you trying to build.

Upvotes: 1

Related Questions