I want to use opengl to do image processing, and the following is the core source code:
for(int i=0; i < 256; i++)
for(int j=0; j < 256; j++)
//call the display function to get a result
glReadPixels(0, 0, 512, 512, GL_LUMINANCE, GL_FLOAT, pImage);
I know the bottleneck lies in calling glReadPixels so frequently? But I don’t know how to improve its performance, could you give me some suggestions?
Thank you in advance!
There is not much you can do about it, transfering data from the GPU’s memory to ram is always expensive and difficult to get around.
Try different formats.
GL_LUMINANCE, GL_FLOAT doesn’t sound fast.
If you’re on a 32 bit true color pixelformat try using GL_BGRA8 and GL_UNSIGNED_BYTE. Do the luminance calculation in the postprocessing.
Or even better, depending on what your post processing does, do it on the GPU with fragment shaders and read the final image.
He is calling glReadPixels() from within two nested loops going from 0 to 255 resulting in 65536 calls to glReadPixels() that sounds very odd.
I dont know what exactly you are doing but you may want to think it over and reduce the number of calls to glReadPixels(). Perhaps you can get away with partial updates or something alike?
Perhaps it would be more informative if you describe what it is you’re doing, rather than how you’re going about it. Maybe someone has done it before in a completely different (more efficient) way.
Thanks for your suggestions:)
I now have 256 images and want to process each image using Opengl in the inner loop. After the processing, I will read it from the framebuffer and weight the image, and save it into the memory. After processing all the 256 images, I will sum the processed results which are in the memory and get the final result. Through set different parameters, I get 256 different results in the outer loop:)
I think whether I can setup a texture matrix first which has a size of 256 to store the 256 different results got from the inner loop. After one inner loop, I send the data from the framebuffer to the texture matrix, and after the all inner loops I summed the data stored in the texture matrix and read the final result through glReadPixels?
But I don’t know how to transfer the data from the framebuffer to a texture and sum all the textures using GPU? Could someone give me some advices?
Just now I got to know how to transfer the data from the framebuffer to the texture memory using glCopyTexImage2D. But what puzzles me now is how to weight an image and sum the data in the texture matrix through the graphics card? By this way I can reduce the calling glReadPixels from 256*256 to 256 times.
Any advices will be appreciated:)Thank you.
You can get a weighted sum by drawing a textured quad with the vertex colors set to the weight, and with additive blending enabled. Alternatively, you could place the weight in the texture environment constant color. Keep in mind that the sum will be clamped to [0,1] in each pass, so you may need to scale your weights accordingly.
What kind of post-processing are you doing? Specifically, how long does it take? My concern is that if you are spending a good deal of time on the CPU processing the image it’s likely the time spent in ReadPixels will be proportionately insignificant. Have you benched your post-processing code? Just some things to consider.
First I have 256 images and want to process each one using Opengl, then I will read them from the framebuffer and weight each image just like the source code mentioned above. In the post processing function, I will calculate the weights for each image according to an algorithm and different pixel has different weight in one image. After weighting the images, finally I will sum all the weighted images and get a result.
To avoid calling glReadPixels frequently, I decide to setup a texture matrix in the graphics’s card and save the temporay images in the matrix. Also I can pre-calculate the weight images and save them as textures too. So now what i am concerning is how to weight the images in the texture matrix using the weight texture? and sum the result using Opengl? I don’t know whether I have explained my question clearly:)Could you help me? Thank you
So now what i am concerning is how to weight the images in the texture matrix using the weight texture? and sum the result using Opengl?
If you have a weight texture for each image, then multi-texturing, along with additive blending, might do the trick.
- Make sure the tex env mode is MODULATE.
- Set BlendFunc(ONE,ONE).
- Clear background*.
- Put your image texture in unit 0.
- Put your weight texture in unit 1.
- Draw a quad with unit texture coords.
- Repeat steps 2 - 5 for each image.
- Read result.
*You could omit the Clear() in step 2 if you render the first image with BlendFunc(ONE,ZERO).
You could also stuff more image/weight pairs into more texture units and do some clever combining to make it work in fewer passes. But the procedure above will work on 2 texture unit hardware.
Thanks for your suggestions! I’ll try it:)Thank you~
Thanks for your suggestions! I’ll try it.Thank you.