Reputation: 4144
Shortly: I need a quick way to resize the buffer image and then return the pixels to me to save them to file etc.
Currently I first use glReadPixels(), and then I go through the pixels myself to resize them with my own resize function.
Is there any way to speed up this resizing, for example make OpenGL do the work for me? I think I could use glGetTexImage() with miplevel and mipmapping enabled, but as I noticed earlier, that function is bugged on my GFX card, so I can't use it.
I only need one miplevel, which could be anything from 1 to 4, but not all of them, to conserve some GPU memory. So is it possible to generate only one miplevel of wanted size?
Note: i dont think i can use multisampling, because i need pixel precise rendering for stencil tests, so if i rendered it with multisampling, it would make blurry pixels and they would fail with stencil test and masking and result would be incorrect (AFAIK). Edit: i only want to scale the colors (RGBA) buffer!
Upvotes: 4
Views: 2782
Reputation: 70206
If you have OpenGL 3.0 or alternatively EXT_framebuffer_blit
available (very likely -- all nVidia cards since around 2005, all ATI cards since around 2008 have it, and even Intel HD graphics claims to support it), then you can glBlitFramebuffer[EXT]
into a smaller framebuffer (with a respectively smaller rectangle) and have the graphics card do the work.
Note that you cannot ever safely rescale inside the same frambuffer even if you were to say "I don't need the original", because overlapped blits are undefined (allowed, but undefined).
Or, you can of course just draw a fullscreen quad with a simple downscaling pixel shader (aniso decimation, if you want).
In fact, since you mention stencil in your last paragraph... if it is stencil (or depth) that you want to rescale, then you most definitively want to draw a fullscreen quad with a shader, because it will very likely not give the desired result otherwise. Usually, one will choose a max
filter rather than interpolation in such a case (e.g. what reasonable, meaningful result could interpolating a stencil value of 0 and a value of 10 give -- something else is needed, such as "any nonzero" or "max value in sample area").
Upvotes: 3
Reputation: 162297
Create a framebuffer of the desired target size and draw your source image with a full-resized-buffer-sized textured quad. Then read the resized framebuffer contents using glReadPixels.
Psuedocode:
unbind_texture(OriginalSizeFBOattachmentColorTex);
glBindFramebuffer(OriginalSizeFBO);
render_picture();
glBindFramebuffer(TargetSizeFBO); // TargetSizeFBO used a Renderbuffer color attachment
glBindTexture(OriginalSizeFBOattachmentColorTex);
glViewport(TargetSize);
render_full_viewport_quad_with_texture();
glReadPixels(...);
Upvotes: 2