So in that old pseudocode I did not apply the holdout !

It does a modified deep merge where the samples from B are merged with the
next sample from A. The flattened image will match the holdout result in
RGB, but the alpha will be the regular combined alpha, with no hole.

Since we want the final alpha to have a hole in it, but we want to make
sure flattened RGB values match the previous code it feels like we need to
keep track of the accumulated regular deep merge alpha and the accumulated
output deep alpha. We can also use those restrictions regarding the
flattened RGB value and alpha to figure out what S' should be:

    acc_output_a = 0     // accumulated output alpha
    acc_merged_a = 0     // accumulated alpha for deep merge

    walking near to far in the combined set of source and holdout samples:

        S = next closest sample

        // contributions to output image only come from source image samples
        if S from source:

            // S' : sample to be inserted to the new image

            // the incremental contribution from this source sample and the
new
            // holdout samples has to match the contribution from the new
output
            // sample, so :
            //
            // S' * (1 - acc_output_a) == S * (1 - acc_merged_a)

            S' = S * (1 - acc_merged_a) / (1 - acc_output_a)

            // only source samples contribute to output alpha
            acc_output_a += S.a * (1 - acc_merged_a)

            if acc_output_a >= 1
                return

        // both deep source and holdout images contribute to merged alpha
        acc_merged_a += S.a * (1 - acc_merged_a)


The simplicity looks convincing...

How does that look with the previous example cases?

holdout source source
A=1 A=1 A=1        ----> increasing Z --->

Would end up outputting [(0,0,0,0), (0,0,0,0]

With the second one:

holdout source source
A=0.9 A=1 A=1        ----> increasing Z --->

Would end up with

sample 0:

acc_holdout_a = 0

acc_merge_a = 0

output = []


sample 1:

acc_holdout_a = 0.1

acc_merge_a = 1

output = [(r1 * 0.1, g1 * 0.1, b1 * 0.1, 0.1)]


sample 2:

acc_holdout_a = 0.1

acc_merge_a = 1

output = [(r1 * 0.1, g1 * 0.1, b1 * 0.1, 0.1), (0, 0, 0, 0)]


We can always skip the non contributing samples in the real code,

r

On Thu, Jun 29, 2017 at 11:54 PM, Nathan Rusch <[email protected]>
wrote:

> I believe Nuke's DeepHoldout node will actually remove samples from the
> source image if they are fully occluded by samples from the holdout image
> (that is, if the cumulative alpha of the holdout samples occluding a given
> source sample hits 1.0).
>
> The DeepMerge node in 'holdout' mode behaves similarly, although it gives
> you a choice in whether to drop the fully occluded source samples, or keep
> them around with zero opacity.
>
> Larry, my gut says your original pseudocode is more correct, as I don't
> think the holdout alpha should be reset after encountering a source sample
> in a forward depth traversal. However, I would also expect the alphas of
> consecutive holdout samples to be combined using straight addition, rather
> than modulating the alpha contribution of every new sample by the combined
> alpha of all preceding holdout samples.
> -Nathan
>
>
> On 6/29/2017 6:23 PM, Ramon Montoya Vozmediano wrote:
>
> The Nuke node (DeepHoldout) works with deep images but outputs only flat
> images. looks like it merges and flattens A and B together, ignoring RGB
> channels for B.
>
> Does it make sense for a holdout sample to affect all subsequent samples
> in the stack?
>
> It should affect the accumulated opacity along the stack, but because its
> opacity should be imputed to the next source sample (that sample might be
> far away, but lets keep things simple)
>
> And since we know how to comp one or more holdout samples on top of a
> source sample:
>
>     holdout_alpha = 0    // accumulated holdout-ness
>     walking near to far in the combined set of source and holdout samples:
>         S = next closest sample
>         if S from holdout:
>             holdout_alpha += (1 - holdout_alpha) * S.alpha
>         else :  // S is from source image
>             S'.rgb   =             *0 +* (1 - holdout_alpha) * S.rgb
>             S'.alpha = *holdout_alpha +* (1 - holdout_alpha) * S.alpha
>             copy S' to result image
> *            holdout_alpha = 0*
>
> I think that will work,
>
> r
>
> On Thu, Jun 29, 2017 at 6:25 PM, Larry Gritz <[email protected]> wrote:
>
>> For regular 2D images, the "holdout" operation (or just "out" in
>> Porter/Duff speak) is the compositing operation where (A out B) is that B
>> blocks A by B's alpha amount, but it doesn't contribute any color or
>> opacity of its own. That is, A with a B-shaped hole cut in it. If B has
>> alpha=1, the resulting pixel will be completely transparent. If B has
>> alpha=0.75, the result will have A, but with its color and opacity
>> multiplied by 0.25.
>>
>> We're on the same page, yes?
>>
>> OK, so my real question is what the "deep holdout" operation actually
>> does. If A is the "source" image, and B is the "holdout" image, we have the
>> intuition that B's samples should block any farther samples of A, but
>> without contributing samples itself.  But I'm having real trouble figuring
>> out the correct behavior for a stack of interleaved A and B samples. Nuke
>> supports a deep holdout operation, but the docs aren't specific about
>> exactly what it does.
>>
>> I've tried walking front to back, keeping an accumulated holdout alpha
>> and multiplying by that as we copy source to result. Here's the sketch:
>>
>>     holdout_alpha = 0    // accumulated holdout-ness
>>     walking near to far in the combined set of source and holdout samples:
>>         S = next closest sample
>>         if S from holdout:
>>             holdout_alpha += (1-holdout_alpha)*S.alpha
>>         else :  // S is from source image
>>             S' = S * (1-holdout_alpha)
>>             copy S' to result image
>>
>> For a "flat-equivalent" image of one holdout sample closer than one
>> source sample, it matches what I expect for the 2D flat holdout operation.
>> But it doesn't seem to give me what I'm looking for in many circumstances
>> involving multiple depth samples of the source.
>>
>> Can somebody bail me out here and spell out what the correct behavior of
>> a deep holdout operation ought to be?
>>
>> --
>> Larry Gritz
>> [email protected]
>>
>>
>> _______________________________________________
>> Oiio-dev mailing list
>> [email protected]
>> http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org
>>
>
>
>
> _______________________________________________
> Oiio-dev mailing 
> [email protected]http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org
>
>
>
> _______________________________________________
> Oiio-dev mailing list
> [email protected]
> http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org
>
>
_______________________________________________
Oiio-dev mailing list
[email protected]
http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org

Reply via email to