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).
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.
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
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.
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:
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);
//else set alpha to 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.
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.