[Bf-blender-cvs] [ed59d03bfca] blender2.8: GPUFramebuffer: Add recursive downsampling function.

Clément Foucault noreply at git.blender.org
Thu Jun 22 04:01:05 CEST 2017


Commit: ed59d03bfcac7e0b21c82febe6b6f2f786b62034
Author: Clément Foucault
Date:   Thu Jun 22 02:01:58 2017 +0200
Branches: blender2.8
https://developer.blender.org/rBed59d03bfcac7e0b21c82febe6b6f2f786b62034

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).

===================================================================

M	source/blender/draw/intern/DRW_render.h
M	source/blender/draw/intern/draw_manager.c
M	source/blender/gpu/GPU_framebuffer.h
M	source/blender/gpu/intern/gpu_framebuffer.c

===================================================================

diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index aa6b836be17..07e9abcbd47 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -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 { \
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index d01f7f5823e..e390ab33c69 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -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);
diff --git a/source/blender/gpu/GPU_framebuffer.h b/source/blender/gpu/GPU_framebuffer.h
index 6778930f61c..a079d12b469 100644
--- a/source/blender/gpu/GPU_framebuffer.h
+++ b/source/blender/gpu/GPU_framebuffer.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 */
diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c
index d791f839e20..ddf0e83309c 100644
--- a/source/blender/gpu/intern/gpu_framebuffer.c
+++ b/source/blender/gpu/intern/gpu_framebuffer.c
@@ -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 {




More information about the Bf-blender-cvs mailing list