24 bit RGB Color Comparison

I want to compare two 24 bit rgb colors in one pass without texture lookups and draw the pixel/fragment if both colors are equal. Someone says you have to calculate the differences of each rgb component with register combiners, perform a dot3 product with (1,1,1) to sum the differences up and store the result in alpha and then use the alpha test. If the result is zero the colors are equal. But if the differences are i.e. (-0.3,0.3,0) the result will be zero, too. Is there any strategy that works ?

Use a signed subtract before doing DOT3. Choose the operand so, that your ‘chroma key’ (I suppose) produces a result of (0.5;0.5;0.5). DOT3 will then - and only then - produce zero.

Sorry, but i don’t understand. I want this for 24 bit objectID shadowmaps. Both operants can freely change! And I want to know if they are equal. Performing a signed subtract will change nothing!?

Whoops. Apparently, I’m currently using signed add:

//texture environments should be configured to use GL_COMBINE_ARB
glActiveTextureARB(GL_TEXTURE0_ARB);
glTexEnvfv(GL_TEXTURE_ENV,GL_TEXTURE_ENV_COLOR,inverted_chroma_col);
glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_ADD_SIGNED_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_RGB_ARB,GL_TEXTURE_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE1_RGB_ARB,GL_CONSTANT_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND0_RGB_ARB,GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND1_RGB_ARB,GL_ONE_MINUS_SRC_COLOR);

glActiveTextureARB(GL_TEXTURE1_ARB);
glEnable(GL_TEXTURE_2D);

glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_DOT3_RGBA_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_RGB_ARB,GL_PREVIOUS_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE1_RGB_ARB,GL_PREVIOUS_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND0_RGB_ARB,GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND1_RGB_ARB,GL_SRC_COLOR);

glAlphaFunc(GL_NOTEQUAL,0.0f);
glEnable(GL_ALPHA_TEST);

Try it, inverted_chroma_col should be a pointer to four floats, representing the inverted ‘invisible’ color. Eg, if you want (0.25;0.5;1.0) to be invisible, inverted_chroma_col should be (0.75f;0.5f;0.0f;1.0f). Alpha isn’t really relevant, but use an array of four floats anyway.
You can build a stencil mask with this, and then render again in a second pass.
Note that if you happen to work on ATI Radeon 7xxx, there’s driver bug that produces rather ‘interesting’ results when you perform DOT3 in the third texture environment. Second environment is fine though.

[This message has been edited by zeckensack (edited 04-22-2002).]

1.) What you are doing doesn’t work in all cases, for example:
chroma color = ( 0.5/0.5/0.5)
texture = ( 0.6/0.4/0.5)
difference = (-0.1/0.1/ 0)
result after dot3 = 0 (doesn’t work)
2.) Question: Why do you use a inverted_chroma_color and then GL_ONE_MINUS_SRC_COLOR ?
3.) I’m useing a Asus V8460 UltraTD (GF4 Ti 4600) so no problems with bugs, I think.
4.) I don’t want to do chroma keying. I want to compare two textures so there is no static chroma color and just useing the second texture instead of it doesn’t work (see 1.).

Originally posted by Liquid:
1.) What you are doing doesn’t work in all cases, for example:
chroma color = ( 0.5/0.5/0.5)
texture = ( 0.6/0.4/0.5)
difference = (-0.1/0.1/ 0)
result after dot3 = 0 (doesn’t work)
2.) Question: Why do you use a inverted_chroma_color and then GL_ONE_MINUS_SRC_COLOR ?

Whoops again. This was taken from work in progress code in a path I don’t currently use and test because of the Radeon problem.

  1. Of course it should be either GL_ONE_MINUS_SRC_COLOR with the regular color key, or GL_SRC_COLOR with the inverted one. Sorry for the confusion.
  2. It does work. Signed add with the inverted key works like this, for each component:
    sadd=tex_component-key_component+0.5
    DOT3 works like this
    result=(sadd.red-0.5)^2+(sadd.green-0.5)^2+(sadd.blue-0.5)^2
    So, basically signed add gives me a bias, so that I can pass the correct value into the next stage without implicit clamping messing around with it. DOT3 will subtract that bias automatically. The result can only be zero if all incoming components are 0.5. The components can’t cancel each other out as you’re taking the squares. Squares are always positive.

3.) I’m useing a Asus V8460 UltraTD (GF4 Ti 4600) so no problems with bugs, I think.
4.) I don’t want to do chroma keying. I want to compare two textures so there is no static chroma color and just useing the second texture instead of it doesn’t work (see 1.).

Bummer. I can’t help you then. If you have another texture environment to burn, it would work, how many do you have?
Maybe you should consider fragment shaders for this special problem.

GF4 Ti has got 4 texture environments, I think. I didn’t want to use pixelshaders(GL_NV_TEXTURE_SHADER) because I want to make it run even on a GeForce 256. Oh, I thought you do a dot3 product with (1/1/1). Sorry, I can’t read It is clear that
sadd=tex_component-key_component+0.5, but dot3 works like this (in your implementation)
result=(2*(sadd.red-0.5))^2+(2*(sadd.green-0.5))^2+(2*(sadd.blue-0.5))^2
But this doesn’t make any difference, because all sqared components are in the theory >= 0 and only sadd=(0.5/0.5/0.5) will result in 0. But there’s a problem why this doesn’t work, either. Theoretically i.e.(1/255)^2 is >0 but because of precision problems it is 0 in practice! I’ve tried this before asking this forum and it doesn’t work. If your chroma color is (1/255, 1/255, 1/255) and your texture is (0, 0, 0) it should not be drawn. Please try this.