alpha mask with threshold and filter (alike)

soundyi's icon

Hi there,

I am trying to achieve some flexible techniques for alpha masking using jit.gl.bfg as an example input for the grayscale texture inside a jit.gl.pix.

One of the grayscale texture color channels should be used for the alpha channel of an input texture (image or generative compositing).

What I want to achieve : at a certain threshold e.g. 0.5, I want the given "grayscale & upcoming alpha" values to falloff very quickly, but nevertheless smooth enough preventing staircases to occur - which currently happens in the most simple implementation (no smoothing) in the attached patcher.

At least I guess the staircases that become visible in the jit window are caused by this abrupt value changes when using perlin or simplex noise in the jit.gl.bfg.

Theoretically I could think of using the threshold implementation in the jit.gl.pix as in the attached patcher and appending a Gaussian blur after that, but that does not feel right.

Or in other words : I am looking for a gen based solution inside the given jit.gl.pix that gives my room for creative variation like modulating parameters with jit.motion and alike ... and conceptually I think about something in the lines of an audio filter with variable "db per octave".

Easing functions using exponential logic (like in the ease package) have a similar behavior, but currently I have no clue how to integrate them (although the functions are also available in GenExpr format).

The second patcher shows a function with a simple fall off at a threshold (at 0.5) to make it obvious what I am aiming for and the image is screenshot of it.

Any ideas are welcome ;-)

simple falloff
Max Patch
Copy patch and select New From Clipboard in Max.
Max Patch
Copy patch and select New From Clipboard in Max.

2K's icon

Use [smoothstep] instead of [>]

Matteo Marson's icon

Hi,

Can't you replicate the same function using jit.gen math operators or codebox?

soundyi's icon

@2K : thanks, but I don't get yet ;-) ... could you explain you idea a little bit more detailed or integrate it into that attached patcher?

I get it that smoothstep can be used for interpolation, but I don't understand how it could replace the > operator that just drives the selector and hence 2 paths : a) let alpha through as it and b) do some math to implement a quick falloff.

I could think of smoothstep as 1 part of the solution though, but I would need a "driver" that is fed into the 3rd inlet which controls how quickly the target alpha is set to 0 ... so the question is : whats the math for the 3rd inlet?

soundyi's icon

@Matteo ... that is what I wrap my head around, but it got twirled ;-)

The problem I got stuck on is, that I don't have control over f(x) - which is in the current example essentially a Perlin noise function.

Or in other words : I have to implement a post-processor and have no control over x, nor can I expect what the next y = f(x) will be in the surrounding of the pixel I am calculation the alpha for.

But I am quite sure that my conceptional approach thinking in f(x) is wrong in jit.gl.pix land - although the same math can be used, but one has to think it from the pixel (and only the current pixel as it is a shader running in parallel on the GPU - hence no linearity of a function).

Hence I guess I have to think it somehow the other way around ... think it from result - still waiting for a spark that lights my brain ;-).

Rob Ramirez's icon

I believe this is what 2K is suggesting


Max Patch
Copy patch and select New From Clipboard in Max.

soundyi's icon

Thanks @Rob ... that looks promising & now I got it.

Meanwhile another approach came to my mind, also using smoothstep, preserving the cutoff frequency alike approach using selector, as this mighty make the result more visually predictable (everything above the threshold stays as it is in the grayscale mask - hence adjusting its parameter is more predictable for the outcome - at least I visually think so ;-).

What I called driver above should be a logarithmic or exponential expression using the grayscale value from the mask. As the only "thing" we have in a shader is the current value, hence the driver must be based on the grayscale value, but I am not sure about the visual effect.

I will follow up on this tomorrow, using a 1 dim approach, so that I see the numerical values in a function curve visualized by plot~, using jit.mo.perlin for a 1 dim grayscale mask, to make it 100% clear how the values fall off.

2K's icon

This is what I had in mind. Hope its useful!

Max Patch
Copy patch and select New From Clipboard in Max.

soundyi's icon

@2K, thanks for patching it out ... this is brilliant !

I still have to digest it to fully understand the logic - how the values are transformed and kept in boundaries - but just playing around with the parameters and having a quick look at your patch makes it obvious to me that smoothstep is capable of way more things than I have imagined until today.

I guess one key for this kind of creative coding with smoothstep is the perspective of thinking in jit.gl.pix land ... it's a mind shift compared to every procedural kind of thinking to construct things or imagery.

Your patch had already created a bunch of creative sparks for me and implements more than I have expected - this is awesome !! ... thank you so much for making your idea & technique comprehensible.

The scope patcher is also great, which most likely will save me some time in the future, developing other creative goodies in jit.gl.pix land ... its the same perspective thing - you don't need numbers if you got the right visual tool (visualization) at your disposal - thanks for sharing.

soundyi's icon

@2K ... and anyone interested ;-)

on the way understand the alpha mask patch provide by 2K - whose alpha masking technique with smoothstep is as simple as great (brilliance often corresponds to simplicity), I found out that I have a different understanding of clamp than the C74 docs, or the docs on smoothstep are misleading, because they are too mathematical dense ;-)

The docs say : the returned value is clamped between 0 and 1 ... but if you look at the screenshot (taken from the attached & slightly modified patcher of 2K), it looks like the values are scaled.

Threshold min & max set the boundaries to 0.4 and 0.8 and I had expected by reading "clamped" in the C74 docs, that the resulting interpolation of smoothstep will be in the range of 0.4 to 0.8, as these values are in the range of 0 and 1, hence no clamp takes effect.

But the resulting interpolation values from smoothstep range from 0 to 1 - which is fine for my application (as the 2 threshold values control the grayscale value "sampling" of the alpha mask and projects it into the full alpha channel value range), but I just want to understand how smoothstep works, to apply it "with confidence" (;-) in other use cases as well.

Maybe my irritation is the result of not understanding what the docs mean by : The slope (i.e. derivative) of the smoothstep function starts at 0 and ends at 0 ... so in the end is about missing help patchers for gen that explain the gen operators in context & by example and not in 2 sentences in mathized developer language like the docs do ;-).

smoothstep plot
Max Patch
Copy patch and select New From Clipboard in Max.

soundyi's icon

oh, one thing I have forgotten - the reason might be that smoothstep interpolation control value is outside the bounds of the 2 values to interpolate between - as the texture delivers values from 0 to 1 and the values to interpolate between are 0.4 and 0.8.

As the docs say : "... based on a third one that should be between the first two".

Should sounds nice, but guesswork in software (or it docs) is as strange as in nature. The sun should rise every morning, breathing energy into life ... but what happens if that's not / no more the case ? ;-) ;-) ;-).

soundyi's icon

the missing docs from Amazing Max Stuff : Jitter's GEN from zero to Hero - Ep. 03 : smoothstep, mix

And his visualization of the smoothstep "interpolation curve" makes it clear, why smoothstep is great for a falloff when working with grayscale masks - there are no abrupt changes at the start and end values at which smoothstep is applied (if you want to use it like a filter at a cut-off frequency e.g.), and hence no staircases in the output.

The curve visualization is essentially the same what is shown in the screenshot above, but the way he explains and shows it, makes it clear.