How to get a consistent 'relative' pixelSize in effect stacks?

  • In working on the port of the h & v big Blur, I have found interesting behavior with the effect uniform pixelSize. I am wondering about the best way to handle this.

    The first effect and second effect have different 'relative' pixelSize, so it's not possible to use the same value multiplied by pixelSize to blur each. The first effect renders to offscreen FB from source texture from spritesheet, the second effect renders to Canvas FB from the offscreen FB. It seems like due to differences between the two, the pixelSize is relatively different (e.g. between spritesheet texture and offscreen FB texture.) What's the best method to make these similar?

    I am going to experiment with using must-predraw to see if it would make the behavior consistent (then both will render to offscreen FB first and use that texture.)

    Here's an example of the uniforms from one frame of render (captured by Spector.js):

    Another interesting thing for me was how srcOriginEnd and srcOriginStart can be flipped in terms of which one is higher (at least for the Y value), so I cannot just use clamp (vTex, srcOriginStart, srcOriginEnd) to clamp to vTex to the texture bounds, I had to create a 'new' clamp function which uses min and max of the two.

    	mediump vec2 newTex = vTex + vec2(halfPixelHeight, pos * realSizeH);
    	newTex.x = clamp(newTex.x,min(srcOriginStart.x, srcOriginEnd.x),max(srcOriginStart.x, srcOriginEnd.x));
    	newTex.y = clamp(newTex.y,min(srcOriginStart.y, srcOriginEnd.y),max(srcOriginStart.y, srcOriginEnd.y));
    

    Here's the example plugins:

    construct.net/en/make-games/addons/347/bigblurh

    construct.net/en/make-games/addons/346/bigblurv

    Note the example project has opacity set to 99% to add yet another effect to the stack and make the behavior consistent. Set the opacity to 100% to see similar results as above.

  • Adding must-predraw 'true' seemed to do the trick - now I have consistent behavior and another draw is required.

    I would be interested to hear if this is the right approach Ashley

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • pixelSize is the size of a pixel on the source surface. AFAICT it is working correctly. I guess you actually want the size of a pixel on the destination surface? There isn't a uniform specified for that yet.

  • I am not looking for a destination size.

    I was looking to have effects that use pixelSize to have the same behavior regardless if there is only one effect applied to a sprite or if there are multiple effects applied to sprite (e.g. requires multiple webgl draws, some to the intermediate surface and the final one to the canvas surface.) From my experimenting it seems to have different behavior. For example for bur if I offset a texture sample by widthScale * pixelSize.x, I seem to get a different visual result depending on whether only one effect is used or if multiple effects are used (e.g. set opacity to 99%). I will work on creating an example and experimenting more to see if it's an issue in my effect or something else that I don't expect.

    Another question, while I work on that. How do you suggest clamping texture samples to stay within the sprite's image? Originally I was using clamp(uv, srcOriginStart, srcOriginEnd) which works when only one effect is used, but that does not seem to work on all platforms when doing multiple effects and the Y axis for SrcOrigin* gets flipped for using the framebuffer as texture vs the image as texture (in particular on iOS it fails.)

    My workaround, for now, is to use:

    newTex.x = clamp(newTex.x,min(srcOriginStart.x, srcOriginEnd.x),max(srcOriginStart.x, srcOriginEnd.x));
    newTex.y = clamp(newTex.y,min(srcOriginStart.y, srcOriginEnd.y),max(srcOriginStart.y, srcOriginEnd.y));
    

    Do you have other suggestions?

  • pixelSize is the size of a pixel in texels on the source surface. AFAIK it works correctly; adding pixelSize.x to the source sampler will sample an adjacent pixel from the source surface. Several built-in effects use this and they work correctly. The source surface can indeed be different sizes depending on the stage in the effects compositor, resulting in different values for pixelSize. This is the correct behavior. If the different values cause your effect to render incorrectly, you are probably using it wrong (hence I guessed you were using it on the destination surface instead of source surface, which is also why it would start working when you pre-draw).

    Several of the 80+ built-in effects also use clamping to the object box, and they all work correctly with the typical clamping too. So I'm not sure what you are doing and why it wouldn't work. As before, I'd guess you're doing something wrong in your shader code. It can be hard to take in to account all the subtleties of the effect compositor.

  • Ashley thanks for the reply. I do think it could be an issue with my understanding, so I made a very simple effect using pixelSize, shifting the texture using a variable amount passed through as a uniform. I expect to have the same result regardless of effect stacking or opacity. Should I not expect that, or am I using pixelSize incorrectly?

    Here's the simple shader.

    void main(void)
    {
     mediump vec4 c = texture2D(samplerFront, vTex);
    	c += texture2D(samplerFront, vTex + (pixelSize * shiftAmount))/2.0;
    	gl_FragColor = c;
    }
    

    Here's the simple project with the simple effect bundled.

    kindeyegames.com/forumfiles/ShiftTest.c3p

    Thanks for the help in understanding this.

    Here are the results (I expected them all to match. It looks like the Y axis inverts and the relative amount also changes in terms of the distance of the shift.)

  • Ashley I think I'm going to assume that for distortion effects (or effects where we adjust the texture sampling coordinates), I will always enable must-predraw so I can get consistent behavior with srcOriginStart, srcOriginEnd, and relative impact and 'direction' of pixelSize, regardless if only one effect is used or more than one effect is used (or opacity is used.)

    I think there also may be cases where I can also use the normlization technique (n= (vTex-srcOriginStart)/(srcOriginEnd-srcOriginStart)) and then I can use clamp(newN, 0.0,1.0) and perhaps then it won't matter if must-predraw is used.

Jump to:
Active Users
There are 1 visitors browsing this topic (0 users and 1 guests)