OGL blending

hi,
I am doing some real-time image processing using OGL and stuck by the blending function.

I need to compute the absolute difference between several images.
Iout = abs(I1-I2), or Iout = sqr(I1-I2).

Is there anyway to compute this completely in OGL, either using blending function or multi-texture£¿

any help is appreciated.

No, I think the closest blending mode available is GL_EXT_blend_subtract. But that simply subtracts and then clamps the output. And there aren’t many consumer cards available that support that extension. And I don’t know of any cards that support abs or sqrt in hardware. Then again, OpenGL really wasn’t designed to do DSP.

[This message has been edited by DFrey (edited 01-08-2001).]

I just came to the realization that you can produce the abs of the difference in just a few passes on a Geforce, or any card that supports both GL_EXT_blend_minmax and GL_EXT_blend_subtract.

I can think of doing this in several pass.

First render Iout1 = I1-I2
then render Iout2 = I2-I1,
then blend Iout1 and Iout2 using blending function blend_max

The only problem with this method is how to store the intermediate result Iout1. I really don’t want to use glRead/Write pixel for bandwidth reasons. If multi-texture supports substraction, this seems to be a doable solution.

You can do this with NV_register_combiners to do the subtraction AND the clamped sum:

const0 = (0,0,0,1);
{
  alpha
  {
    discard = tex0;
    discard = tex1 * -const0;
    spare0 = sum();
  }
}
{
  alpha
  {
    discard = tex0 * -const0;
    discard = tex1;
    spare1 = sum();
  }
}
fragment.a = spare0 + spare1;

This works because spare0 and spare1 are clamped to the range [0,1] before the sum.

Hope this helps…
Cass

Thank you for the reply.
I never used the register combiner myself.
My first question is that why discard is not clamped.

To be exact, I need to evaluate the following equation on a per pixel basis

Alpha = sum(abs(Ii-I0)), i= 1…4

Originally, I was think about doing this with the accumulation buffer.
Do you think it is possible to compute this with the register combiner?

Thanks lot!!!

Yang,

The register combiners work in the range [-1,1], and there’s no absolute value. You can, however, calculate the absolute value of a difference as

abs(Ii-I0) = clamp(0,1, Ii-I0) + clamp(0,1, I0-Ii)

And you can calculate the sum by doing this in 4 passes with additive blending (glBlendFunc(GL_ONE,GL_ONE)).

I would encourage you to read the NV_register_combiners spec to better understand all the options available.

Hope this helps -
Cass

hi, cass,
Thank you for your help.
I look through the NV_register_combiner spec.
I am not sure how to do the sum for the alpha value in the final combiner stage.
It seemed to me the G register is just a map from combiner register to the output.

Can I map a input register to more than one variables (say spare0 --> A and B) during the combiner stage?
I think I could compute (a-b)^2 this way.

thank you.

ruigang

Ugh. You’re right. You can do this sum for the RGB, but not fragment alpha.

Here is an alternative that MIGHT be acceptable.

in combiner 0 alpha, calculate tex0 + (1-tex1). Since tex0 & tex1 are in the 0 to 1 range, output is in the 0 to 2 range. Scale output by 1/2, and we now have it back into the 0 to 1 range. Store this in spare 0 alpha.

in combiner 1 alpha:
A = 1
B = spare 0 alpha - 0.5
C = -1
D = spare 0 alpha - 0.5
use the mux function and scale the output by 2. Store the result in spare 0 alpha

in the final combiner, select spare 0 alpha into G

If I figured everything correctly, this should get you the absolute value of tex0-tex1. The one thing to note here is that since we scale by 1/2 before storing to spare 0, you will lose some precision in the calculation (unless the register combiners’ registers have at least 9 bits of preceission, and I cant remember if they do or not).

Tada!!!