blending two textures to subtract


I am blending two textures with GL and the setup: GL_ONE, GL_ONE and GL_FUNC_ADD and everything went fine.
Now I generate the secondary complement (don’t know if its so called in english…? ~(value)+1) and blend this generated texture to the first one.
Normally it is the same as a subtraction but in this case I receive correct values only if the result of the subtraction is negative and always the value 1 if the result is positive.
I am interpreting the byte-values as signed!
Logically this should work! Where is my fault?
I cannot use GL_SUBTRACT (?) because the values are clamped to ]0,1[.


If I understood well, you want to use Two’s Complement (it seems to be the actual english term) instead of GL_SUBTRACT because you expect it to behave differently ?

Anyway, GPU do math in saturate arithmetics. So for one byte data, going from 0 to 255, if you do 255+5 you still get 255. All the intermediary results are clamped to [0,1].

It makes sense for lighting. If you add up several white lights, you don’t expect the result to be black or gray.

I would suggest to use GL_SUBTRACT, but adjust the color range in order to avoid the ‘edges’ : map all your incoming color interval from [0,1] to [0.25,0.75], do your subtraction, then adjust the result range back to [0,1]

What do you need this for ? More general info about your goal can help.

Thanks for your answer!

here are some example values to see how different both results are:

  1. GL-SUBTRACT: 20-50 = 0; 50-20=30
  2. Two’s complement: 20-50=-30; 50-20=30

=> with the two’s complement and a byte interpreted as signed byte, I get negative values. the target is to calculate the euclidean distance between two textures, where every pixel is interpreted as 4D-vector (red, green, blue, alpha). it is necessary for me to have a fast algorithm. i tried mapping color-values but it is too slow.

as written in my last statement, it works if the result is negative (e.g. 20-50=-30) but not if it is positive (e.g. 50-20 is always 1)!

Any other idea?


No idea about the positive values giving only 1 as result.
As I told you values don’t wrap (neither from underflow nor overflow), so you must be hitting some clamping.

To precise and correct my suggestion :

  • let’s work on 4D RGBA space, with incoming range being [0,1].

  • let all textures values c1 be replaced by c2:
    c2 = 0.5 + c1 * 0.5

(c2 range is now [0.5,1])

  • draw texture 1 without blending

  • blend with GL_SUBTRACT the texture 2
    scene range is now [0,1], which represent [-1,1] actually. That way there can be no clamping, but you halve the calculation precision.

OK, if I understood you right it is also necessary to reduce the value range (?) of the second texture to ]0,0.5[.

It seems to be a good idea. I’ll try it and hope it will be fast enough!

Thank you!

>> it is also necessary to reduce the value range (?) of the second texture to ]0,0.5[

You are right, I forgot this one. By the way the range includes both 0 and 0.5 right ? Mathematicians prefer to be precise : it is [0,0.5] :stuck_out_tongue:

About speed : it depends on your case, but to avoid recomputing texture values on the CPU, you can draw texture 1 with full color range, then classic blend with a black quad having 0.5 alpha, then additive blend a 0.5 grey quad.
For texture 2, just skip the grey quad. Either you have enought space left on back or frontbuffer to do both textures, or you have to go for copytexsubimage or pbuffers.

It should be possible to do most of this with multitexture, but I am not too used to it.