Comparing two textures in gpu

Hi,

i would like to compare two textures in the gpu. i haven’t found any straight way to do this so i though i’ll substract the two textures and then count the zero pixels of the output texture. In that way i will see how many pixels the two textures have the same.

I have found how to substract the textures using cg but i don’t know how to count the zero pixels and then ouput the result.

The reason i need this is because i’m using genetic programming to create pictures of buildings and compare it with the original picture of the building(which is the input of the program). The aim is of course to produce the original picture.Genetic programming simulations take so much time so i thought i would speed up the proccess if i made the comparing of the textures in the gpu.

If someone can help me with this problem will be greately appreciated.

Unless you are using floating point render target textures, the simple subtraction is not good idea because negative values are clamped to zero for ordinary RGB targets.

One idea is to create shader that compares both values and outputs color with alpha 1 if both pixels are the same and 0 otherwise. Then you set alpha test so fragments with alpha lower than 1 are discarded. You can then use one from GL_*_occlusion_query extensions to count number of fragment that still exist.

its not possible (except for very small textures), since theres a maximum number of texture lookups u can perform.
i suppose u could mipmap them and then compare the pixels in a smaller mipmap levels (from the 2 textures) though this will sometimes say they are the same when theyre not, but it should be able to cull away 99% of the incorrect matches.
with the remaining 1% of textures, u could do a more thorough comparrision.

would this work ?

Draw a full screen quad and discard where the difference between your textures is zero, setting the stencil where that frag passes (could even stick abs(tex1-tex2) into alpha and set up alpha blending to do the reject for you).

Then use an occlusion query and draw another FSQ with stencil test enabled.

The result of the occlusion query gives number of frags that passed (after stencil/depth test).

:slight_smile:

That’s essentially the same as Komat’s method, except you do two passes for no reason. You can use the occlusion query on the first pass directly since alpha test kills the fragments.

Originally posted by zed:
its not possible (except for very small textures), since theres a maximum number of texture lookups u can perform.
On R300 there’s a texture lookup limit, but on R420 and up there’s no texture lookup limit. But either way, you only need to sample once from each texture if you’re using the occlusion query method.

Originally posted by Humus:
That’s essentially the same as Komat’s method, except you do two passes for no reason.
That’ll teach me to not just read the top post :rolleyes:

Thanks for all the responses.
I’m not very experienced with opengl or cg and i appreciate any help.
komat: so the shader outputs the texture with alpha 1 if both pixels are the same and 0 otherwise. this part will be done in gpu and the rest in cpu right?
sed and hummus: what’s that texture lookup limit? I don’t understand. are you talking about the profiles in cg? If thats the case i will only be comparing two textures each time i use this shader.
pocketmoon: appreciate your response.
I’ll try it and tell you how it goes

so the shader outputs the texture with alpha 1 if both pixels are the same and 0 otherwise. this part will be done in gpu and the rest in cpu right?

If you do everything from my post, entire test will be done on GPU. CPU will get number of pixels that are the same.


sed and hummus: what’s that texture lookup limit? I don’t understand. are you talking about the profiles in cg?

There is limit how many samples from texture the shader can take during calculation of color of single fragment (one run of the main function). It may be caused by limited number of texture instructions allowed in shader on old HW or by limited number of instructions dynamically executed on looping capable HW or it may be limited by time, the driver or os will wait for GPU reaction before it considers GPU locked.

it must be just me, but what the hell is zed talking about?

Well, the way I read it, he was thinking of doing it all in a single shader execution. That would work if the card allows large number of instructions executed. On R520 it could certainly be done with nested loops. IIRC nVidia has a limitation of at most 65535 instructions executed, so you’d get a problem if the textures are 128x128 or larger I guess (assuming 2 TEX + 2 ALU for each comparison). Anyway, the bigger problem would be that it would be inefficient, because it would serialize the operation and only use a single pipe on the card.

yes sorry i was talking out my ass, must of been the fish+chips i just ate, even though it would work on some hardware ( but it has many flaws like humus pointed out )

i like your approach, zed. it possesses a certain… je ne sais quoi.

Originally posted by zed:
yes sorry i was talking out my ass, must of been the fish+chips i just ate, even though it would work on some hardware ( but it has many flaws like humus pointed out )
smoked haddock is a description of the preparation technique, not a suggested method of consumption, zed.

LOL!

why didn’t you tell me earlier- i’ve been sitting here for 2 hours trying to ignite the fish in my mouth…

As i understand it i will make 2 fragment shader programs. the first one is the part to set the alpha in the output color. My code is:

struct OUT{
float4 color: COLOR
}

OUT compTex(float2 TexCoordInit: TEXCOORD0,
float2 TexCoordRes: TEXCOORD1,
unifrom sampler2D tex1,
unifotm sampler2D tex2)
{

float4 tex1Color=tex2D(tex1, TexCoordInit);
float4 tex2Color=tex2D(tex2, TexCoordRes);

if(tex1Color==tex2Color)
color=(1,1,1,1);
else
//else set alpha to 0
color=(0,0,0,0);

}

I don’t know how to do the alpha test.this is supposed to be done in the other shader program? im really confused as i have read that the shader program only acts in one pixel individually at a time. how am i going to use the occlusion query extension in a shader?

As i understand it i will make 2 fragment shader programs.

There will be only one program. Your program is good however you probably should compare difference between both values with some small value instead of comparing both values directly because otherwise the comparison is susceptible to optimalizations that may be done by compiler and drivers.


I don’t know how to do the alpha test.this is supposed to be done in the other shader program?

Alpha test is fixed function setup that compares alpha generated by shader with user specified value using user specified function and discards fragment if test fails. See documentation of glAlphaFunc for description how to set it. In your case it may be something like:


im really confused as i have read that the shader program only acts in one pixel individually at a time. how am i going to use the occlusion query extension in a shader?

Occlusion query is not extension of the shader. It is independent on the shader. One from occlusions query extensions is ARB_occlusion_query .

Its use is simple. At start of the program you will call glGenQueriesARB function to generate identifier for query. Rendering is then done in following way:

// start counting of number of passed samples (if multisampling is disabled, it is number of fragments).

glBeginQueryARB( GL_SAMPLES_PASSED_ARB, id_from_gen_queries) ;

 ...... here you will render the image using the comparison shader .....

// end counting.

EndQueryARB( GL_SAMPLES_PASSED_ARB ) ;

// determine number of samples that pass the test which means they are the same.

GLuint sampleCount;
glGetQueryObjectuivARB( id_from_gen_queries, GL_QUERY_RESULT_ARB, &sampleCount )  ;

it worked. thank you very much:)

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.