GPUFramebuffer: Add recursive downsampling function.
This special case function enables rendering to a miplevel while using the miplevels above as texture input. This is needed for some algorithm (i.e. creating a min-max depth pyramid texture).
This commit is contained in:
parent
fe2ff3fc89
commit
ed59d03bfc
|
@ -202,6 +202,9 @@ void DRW_framebuffer_texture_layer_attach(struct GPUFrameBuffer *fb, struct GPUT
|
|||
void DRW_framebuffer_cubeface_attach(struct GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int face, int mip);
|
||||
void DRW_framebuffer_texture_detach(struct GPUTexture *tex);
|
||||
void DRW_framebuffer_blit(struct GPUFrameBuffer *fb_read, struct GPUFrameBuffer *fb_write, bool depth);
|
||||
void DRW_framebuffer_recursive_downsample(
|
||||
struct GPUFrameBuffer *fb, struct GPUTexture *tex, int num_iter,
|
||||
void (*callback)(void *userData, int level), void *userData);
|
||||
void DRW_framebuffer_viewport_size(struct GPUFrameBuffer *fb_read, int x, int y, int w, int h);
|
||||
void DRW_framebuffer_free(struct GPUFrameBuffer *fb);
|
||||
#define DRW_FRAMEBUFFER_FREE_SAFE(fb) do { \
|
||||
|
|
|
@ -2137,6 +2137,12 @@ void DRW_framebuffer_blit(struct GPUFrameBuffer *fb_read, struct GPUFrameBuffer
|
|||
GPU_framebuffer_blit(fb_read, 0, fb_write, 0, depth);
|
||||
}
|
||||
|
||||
void DRW_framebuffer_recursive_downsample(
|
||||
struct GPUFrameBuffer *fb, struct GPUTexture *tex, int num_iter,
|
||||
void (*callback)(void *userData, int level), void *userData)
|
||||
{
|
||||
GPU_framebuffer_recursive_downsample(fb, tex, num_iter, callback, userData);
|
||||
}
|
||||
void DRW_framebuffer_viewport_size(struct GPUFrameBuffer *UNUSED(fb_read), int x, int y, int w, int h)
|
||||
{
|
||||
glViewport(x, y, w, h);
|
||||
|
|
|
@ -75,6 +75,10 @@ void GPU_framebuffer_blit(
|
|||
GPUFrameBuffer *fb_read, int read_slot,
|
||||
GPUFrameBuffer *fb_write, int write_slot, bool use_depth);
|
||||
|
||||
void GPU_framebuffer_recursive_downsample(
|
||||
GPUFrameBuffer *fb, struct GPUTexture *tex, int num_iter,
|
||||
void (*callback)(void *userData, int level), void *userData);
|
||||
|
||||
/* GPU OffScreen
|
||||
* - wrapper around framebuffer and texture for simple offscreen drawing
|
||||
* - changes size if graphics card can't support it */
|
||||
|
|
|
@ -142,16 +142,7 @@ bool GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slo
|
|||
else
|
||||
attachment = GL_COLOR_ATTACHMENT0 + slot;
|
||||
|
||||
#if defined(WITH_GL_PROFILE_COMPAT)
|
||||
/* Workaround for Mac & Mesa compatibility profile, remove after we switch to core profile */
|
||||
/* glFramebufferTexture was introduced in 3.2. It is *not* available in the ARB FBO extension */
|
||||
if (GLEW_VERSION_3_2)
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, attachment, GPU_texture_opengl_bindcode(tex), mip); /* normal core call, same as below */
|
||||
else
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GPU_texture_target(tex), GPU_texture_opengl_bindcode(tex), mip);
|
||||
#else
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, attachment, GPU_texture_opengl_bindcode(tex), mip);
|
||||
#endif
|
||||
|
||||
if (GPU_texture_depth(tex))
|
||||
fb->depthtex = tex;
|
||||
|
@ -250,16 +241,7 @@ void GPU_framebuffer_texture_detach(GPUTexture *tex)
|
|||
attachment = GL_COLOR_ATTACHMENT0 + fb_attachment;
|
||||
}
|
||||
|
||||
#if defined(WITH_GL_PROFILE_COMPAT)
|
||||
/* Workaround for Mac & Mesa compatibility profile, remove after we switch to core profile */
|
||||
/* glFramebufferTexture was introduced in 3.2. It is *not* available in the ARB FBO extension */
|
||||
if (GLEW_VERSION_3_2)
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, attachment, 0, 0); /* normal core call, same as below */
|
||||
else
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GPU_texture_target(tex), 0, 0);
|
||||
#else
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, attachment, 0, 0);
|
||||
#endif
|
||||
|
||||
GPU_texture_framebuffer_set(tex, NULL, -1);
|
||||
}
|
||||
|
@ -554,6 +536,63 @@ void GPU_framebuffer_blit(GPUFrameBuffer *fb_read, int read_slot, GPUFrameBuffer
|
|||
glDrawBuffer(GL_COLOR_ATTACHMENT0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this if you need to custom downsample your texture and use the previous mip level as input.
|
||||
* This function only takes care of the correct texture handling. It execute the callback for each texture level.
|
||||
**/
|
||||
void GPU_framebuffer_recursive_downsample(
|
||||
GPUFrameBuffer *fb, GPUTexture *tex, int num_iter, void (*callback)(void *userData, int level), void *userData)
|
||||
{
|
||||
int current_dim[2] = {GPU_texture_width(tex), GPU_texture_height(tex)};
|
||||
GLenum attachment;
|
||||
|
||||
/* Manually setup framebuffer to not use GPU_texture_framebuffer_set() */
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
|
||||
GG.currentfb = fb->object;
|
||||
|
||||
if (GPU_texture_stencil(tex) && GPU_texture_depth(tex))
|
||||
attachment = GL_DEPTH_STENCIL_ATTACHMENT;
|
||||
else if (GPU_texture_depth(tex))
|
||||
attachment = GL_DEPTH_ATTACHMENT;
|
||||
else
|
||||
attachment = GL_COLOR_ATTACHMENT0;
|
||||
|
||||
/* last bound prevails here, better allow explicit control here too */
|
||||
glDrawBuffer(GL_COLOR_ATTACHMENT0);
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||
|
||||
for (int i=1; i < num_iter+1 && (current_dim[0] > 1 && current_dim[1] > 1); i++) {
|
||||
|
||||
/* calculate next viewport size */
|
||||
current_dim[0] /= 2;
|
||||
current_dim[1] /= 2;
|
||||
|
||||
/* ensure that the viewport size is always at least 1x1 */
|
||||
CLAMP_MIN(current_dim[0], 1);
|
||||
CLAMP_MIN(current_dim[1], 1);
|
||||
|
||||
glViewport(0, 0, current_dim[0], current_dim[1]);
|
||||
|
||||
/* bind next level for rendering but first restrict fetches only to previous level */
|
||||
GPU_texture_bind(tex, 0);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, i-1);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, i-1);
|
||||
GPU_texture_unbind(tex);
|
||||
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, GPU_texture_opengl_bindcode(tex), i);
|
||||
|
||||
callback(userData, i);
|
||||
}
|
||||
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, attachment, 0, 0);
|
||||
|
||||
/* reset mipmap level range for the depth image */
|
||||
GPU_texture_bind(tex, 0);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, num_iter - 1);
|
||||
GPU_texture_unbind(tex);
|
||||
}
|
||||
|
||||
/* GPUOffScreen */
|
||||
|
||||
struct GPUOffScreen {
|
||||
|
|
Loading…
Reference in New Issue