5
\$\begingroup\$

I am looking for a way to determine the most extreme color values for all of the texels in a texture. So for a texture consisting only of black and white texels, the extreme values should be (0,0,0) and (1,1,1) expressed in RGB format. For a color gradient from red to green I should get the values (1,0,0) and (0,1,0).

Now obviously I could do this on the CPU by iterating over all the pixels/texels of the texture and keeping track of the color values found to be most apart from each other, but this is probably relatively slow, so I am looking for a way to do this using the GPU/shaders.

Is this possible using shaders? I am not experienced with GPGPU, so a solution in HLSL/GLSL would be preferred. Or maybe there is a fast algorithm I could use on the CPU?

\$\endgroup\$
9
\$\begingroup\$

The task is actually highly parallelisable on the GPU.

Here is an algorithm that should work, assuming e.g. a 1024×1024 source texture ST.

  • create a 256×256 render target, RT1
  • run a fragment shader that reads from ST and writes to RT1 and does the following:
    • for each fragment in the render target
      • get the (x,y) fragment coordinates
      • sample 16 pixels from ST at (4x+i, 4y+j) for (i,j) in [0,3]×[0,3]
      • write the max value in RT1
  • create a 64×64 render target, RT2
  • run the previous shader, reading from RT1 and writing to RT2
  • […]
  • create a 1×1 render target, RT5
  • run the previous shader, reading from RT4 and writing to RT5

Each iteration of the process divides the number of pixels by sixteen. In the end, you get the maximum value in your single 1×1 texture in only five steps.

You can do the same for the minimum value, or devise a more complex shader that computes both the min and max. You can also play with how much you divide the resolution each time, depending on how many texture reads your GPU can do.

You can read about min/max textures in this article.

Here are the five steps of the algorithm when used on this 1024×1024 image:

algorithm steps

\$\endgroup\$
  • \$\begingroup\$ This is neat, I had not thought of doing it this way at all. \$\endgroup\$ – Josh Jul 1 '14 at 21:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.