views:

163

answers:

3

Hi,
I have two textures generated using a fragment shader. I want to be able to count the number of texels in each texture that are above some colour intensity. My question is how can this be done? My initial thought is to count these texels using the fragment shader before generating the texture. However, this would require some sort of global counter. I can't use occlusion queries because the textures are created from other textures. I'm using OpenGL 2.1. Any ideas appreciated.
Thanks

A: 

You could always run a pixel shader on the framebuffer that sets all pixels above the threshold to white and the rest to black. Then grab a picture of the framebuffer and count the number of white pixels...

I'm presuming that you are not going to need to do this every single frame. If you are, you probably going to have to change your requirements...

Mikepote
Yes, this needs to be done each frame. Well, roughly 500 times per 30fps.
Brett
Just found this http://stackoverflow.com/questions/99906/count-image-similarity-on-gpu-opengl-occlusionquery, which is pretty much what i'm trying to achieve. I want to count the similarity between images. Does anybody have any knowledge of this technique? Does it work?
Brett
A: 

I've done this using a vertex and fragment shader.

I declare a point vertex for each pixel in the texture and render them.

I declare an offscreen render texture that is 1D and is the length of the number of buckets I want. You could make this 1 bucket but it will slow you down while each fragment is waiting to write to the same pixel. I've found 32 usually works pretty well for me.

Set the blend mode to additive.

In the vertex shader I mod gl_VertexID by the number of buckets and set that range between -1<->1.

Sample the texture for each vertex (which is really equal to each pixel) and set the gl_Color to white for valid pixel and black for not (basically 1 or 0).

Do a readback on the 1D texture and sum up the values. This will be the count of pixels.

A second way I've done it in the past is to do the first pass to an offscreen texture that is the same size as the input and classify the input as 1 or 0. Next, render to a texture that is half the width and height and sample 4 times add and write. Keep doing this until you get to a 1x1 and read the value back.

Jose
A: 

Thanks for the ideas,
I found a simple way I think is the most efficient. I initially thought occlusion queries could only be used with geometry but they can also be used with textures.

  1. Turn on occlusion queries
  2. Render the image using a fragment shader and discard texels below required color intensity
  3. Retrieve number of texels passing drawing test from query
Brett