[Bf-blender-cvs] [7a3e06b9f7] temp-select-pick: Added back multi-pass occlusion queries

Campbell Barton noreply at git.blender.org
Tue Mar 7 16:20:07 CET 2017


Commit: 7a3e06b9f7847fd34021f90ad1d2119021b63659
Author: Campbell Barton
Date:   Sun Mar 5 19:12:24 2017 +1100
Branches: temp-select-pick
https://developer.blender.org/rB7a3e06b9f7847fd34021f90ad1d2119021b63659

Added back multi-pass occlusion queries

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

M	source/blender/editors/space_view3d/view3d_view.c
M	source/blender/editors/transform/transform_manipulator.c
M	source/blender/gpu/GPU_select.h
M	source/blender/gpu/intern/gpu_select.c

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

diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index ccf9f4d0d4..e23d01e679 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -1206,13 +1206,13 @@ short view3d_opengl_select(
 		ED_view3d_clipping_set(vc->rv3d);
 	
 	if (select_mode == VIEW3D_SELECT_DEPTH_SORT_NEAREST) {
-		GPU_select_begin(buffer, bufsize, &rect, GPU_SELECT_DEPTH_SORT_NEAREST);
+		GPU_select_begin(buffer, bufsize, &rect, GPU_SELECT_DEPTH_SORT_NEAREST, 0);
 	}
 	else if (select_mode == VIEW3D_SELECT_DEPTH_SORT_ALL) {
-		GPU_select_begin(buffer, bufsize, &rect, GPU_SELECT_DEPTH_SORT_ALL);
+		GPU_select_begin(buffer, bufsize, &rect, GPU_SELECT_DEPTH_SORT_ALL, 0);
 	}
 	else {
-		GPU_select_begin(buffer, bufsize, &rect, GPU_SELECT_ALL);
+		GPU_select_begin(buffer, bufsize, &rect, GPU_SELECT_ALL, 0);
 	}
 
 	view3d_select_loop(vc, scene, v3d, ar, use_obedit_skip);
diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c
index a1dd964ff1..1567cafeb0 100644
--- a/source/blender/editors/transform/transform_manipulator.c
+++ b/source/blender/editors/transform/transform_manipulator.c
@@ -1728,6 +1728,7 @@ static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, const int mval[2], fl
 	GLuint buffer[64];      // max 4 items per select, so large enuf
 	short hits;
 	const bool is_picksel = true;
+	const bool do_passes = GPU_select_query_check_active();
 
 	/* XXX check a bit later on this... (ton) */
 	extern void view3d_winmatrix_set(ARegion *ar, View3D *v3d, rctf *rect);
@@ -1747,7 +1748,10 @@ static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, const int mval[2], fl
 	view3d_winmatrix_set(ar, v3d, &rect);
 	mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
 
-	GPU_select_begin(buffer, 64, &selrect, GPU_SELECT_DEPTH_SORT_NEAREST);
+	if (do_passes)
+		GPU_select_begin(buffer, 64, &selrect, GPU_SELECT_NEAREST_FIRST_PASS, 0);
+	else
+		GPU_select_begin(buffer, 64, &selrect, GPU_SELECT_ALL, 0);
 
 	/* do the drawing */
 	if (v3d->twtype & V3D_MANIP_ROTATE) {
@@ -1761,6 +1765,22 @@ static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, const int mval[2], fl
 
 	hits = GPU_select_end();
 
+	if (do_passes) {
+		GPU_select_begin(buffer, 64, &selrect, GPU_SELECT_NEAREST_SECOND_PASS, hits);
+
+		/* do the drawing */
+		if (v3d->twtype & V3D_MANIP_ROTATE) {
+			if (G.debug_value == 3) draw_manipulator_rotate_cyl(v3d, rv3d, MAN_ROT_C & rv3d->twdrawflag, v3d->twtype, MAN_RGB, false, is_picksel);
+			else draw_manipulator_rotate(v3d, rv3d, MAN_ROT_C & rv3d->twdrawflag, v3d->twtype, false, is_picksel);
+		}
+		if (v3d->twtype & V3D_MANIP_SCALE)
+			draw_manipulator_scale(v3d, rv3d, MAN_SCALE_C & rv3d->twdrawflag, v3d->twtype, MAN_RGB, false, is_picksel);
+		if (v3d->twtype & V3D_MANIP_TRANSLATE)
+			draw_manipulator_translate(v3d, rv3d, MAN_TRANS_C & rv3d->twdrawflag, v3d->twtype, MAN_RGB, false, is_picksel);
+
+		GPU_select_end();
+	}
+
 	view3d_winmatrix_set(ar, v3d, NULL);
 	mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
 
diff --git a/source/blender/gpu/GPU_select.h b/source/blender/gpu/GPU_select.h
index 343484775f..92e870d406 100644
--- a/source/blender/gpu/GPU_select.h
+++ b/source/blender/gpu/GPU_select.h
@@ -37,11 +37,13 @@ struct rctf;
 /* flags for mode of operation */
 enum {
 	GPU_SELECT_ALL                      = 1,
-	GPU_SELECT_DEPTH_SORT_ALL           = 2,
-	GPU_SELECT_DEPTH_SORT_NEAREST       = 3,
+	GPU_SELECT_NEAREST_FIRST_PASS       = 2,
+	GPU_SELECT_NEAREST_SECOND_PASS      = 3,
+	GPU_SELECT_DEPTH_SORT_ALL           = 4,
+	GPU_SELECT_DEPTH_SORT_NEAREST       = 5,
 };
 
-void GPU_select_begin(unsigned int *buffer, unsigned int bufsize, const struct rctf *input, char mode);
+void GPU_select_begin(unsigned int *buffer, unsigned int bufsize, const struct rctf *input, char mode, int oldhits);
 bool GPU_select_load_id(unsigned int id);
 unsigned int GPU_select_end(void);
 bool GPU_select_query_check_active(void);
diff --git a/source/blender/gpu/intern/gpu_select.c b/source/blender/gpu/intern/gpu_select.c
index 1b0c410867..9bcbb6f635 100644
--- a/source/blender/gpu/intern/gpu_select.c
+++ b/source/blender/gpu/intern/gpu_select.c
@@ -52,6 +52,8 @@
 /* Alloc number for depths */
 #define ALLOC_DEPTHS 200
 
+#define SELECT_ID_NONE ((unsigned int)0xffffffff)
+
 typedef struct DepthID {
 	unsigned int id;
 	float depth;
@@ -142,7 +144,7 @@ static GPUQueryState g_query_state = {0};
 /**
  * initialize and provide buffer for results
  */
-void GPU_select_begin(unsigned int *buffer, unsigned int bufsize, const rctf *input, char mode)
+void GPU_select_begin(unsigned int *buffer, unsigned int bufsize, const rctf *input, char mode, int oldhits)
 {
 	g_query_state.select_is_active = true;
 	g_query_state.query_issued = false;
@@ -153,7 +155,7 @@ void GPU_select_begin(unsigned int *buffer, unsigned int bufsize, const rctf *in
 	g_query_state.buffer = buffer;
 	g_query_state.mode = mode;
 	g_query_state.index = 0;
-	g_query_state.oldhits = 0;
+	g_query_state.oldhits = oldhits;
 
 	if (!g_query_state.use_gpu_select) {
 		glSelectBuffer(bufsize, (GLuint *)buffer);
@@ -237,8 +239,21 @@ void GPU_select_begin(unsigned int *buffer, unsigned int bufsize, const rctf *in
 
 		/* occlusion queries operates on fragments that pass tests and since we are interested on all
 		 * objects in the view frustum independently of their order, we need to disable the depth test */
-		glDisable(GL_DEPTH_TEST);
-		glDepthMask(GL_FALSE);
+		if (mode == GPU_SELECT_ALL) {
+			glDisable(GL_DEPTH_TEST);
+			glDepthMask(GL_FALSE);
+		}
+		else if (mode == GPU_SELECT_NEAREST_FIRST_PASS) {
+			glClear(GL_DEPTH_BUFFER_BIT);
+			glEnable(GL_DEPTH_TEST);
+			glDepthMask(GL_TRUE);
+			glDepthFunc(GL_LEQUAL);
+		}
+		else if (mode == GPU_SELECT_NEAREST_SECOND_PASS) {
+			glEnable(GL_DEPTH_TEST);
+			glDepthMask(GL_FALSE);
+			glDepthFunc(GL_EQUAL);
+		}
 	}
 }
 
@@ -265,9 +280,9 @@ bool GPU_select_load_id(unsigned int id)
 			glReadPixels(UNPACK4(qsd->clip_readpixels), GL_DEPTH_COMPONENT, GL_FLOAT, qsd->rect_depth_test);
 			/* perform initial memcmp since most cases the array remains unchanged  */
 			if (memcmp(qsd->rect_depth, qsd->rect_depth_test, rect_len * sizeof(float)) != 0) {
+				const unsigned int prev_id = qsd->prev_id;
 				if (g_query_state.mode == GPU_SELECT_DEPTH_SORT_ALL) {
 					/* find the best depth for this pass and store in 'all.hits' */
-					const unsigned int prev_id = qsd->prev_id;
 					const float *prev = qsd->rect_depth;
 					const float *curr = qsd->rect_depth_test;
 					float depth_best = FLT_MAX;
@@ -289,13 +304,14 @@ bool GPU_select_load_id(unsigned int id)
 				}
 				else {
 					/* keep track each pixels ID in 'nearest.rect_id' */
-					const unsigned int prev_id = qsd->prev_id;
-					const float *prev = qsd->rect_depth;
-					const float *curr = qsd->rect_depth_test;
-					unsigned int *id_ptr = qsd->nearest.rect_id;
-					for (unsigned int i = 0; i < rect_len; i++, curr++, prev++, id_ptr++) {
-						if (*curr != *prev) {
-							*id_ptr = prev_id;
+					if (prev_id != SELECT_ID_NONE) {
+						const float *prev = qsd->rect_depth;
+						const float *curr = qsd->rect_depth_test;
+						unsigned int *id_ptr = qsd->nearest.rect_id;
+						for (unsigned int i = 0; i < rect_len; i++, curr++, prev++, id_ptr++) {
+							if (*curr != *prev) {
+								*id_ptr = prev_id;
+							}
 						}
 					}
 				}
@@ -321,6 +337,16 @@ bool GPU_select_load_id(unsigned int id)
 		g_query_state.id[g_query_state.active_query] = id;
 		g_query_state.active_query++;
 		g_query_state.query_issued = true;
+
+		if (g_query_state.mode == GPU_SELECT_NEAREST_SECOND_PASS && g_query_state.index < g_query_state.oldhits) {
+			if (g_query_state.buffer[g_query_state.index * 4 + 3] == id) {
+				g_query_state.index++;
+				return true;
+			}
+			else {
+				return false;
+			}
+		}
 	}
 
 	return true;
@@ -373,7 +399,7 @@ unsigned int GPU_select_end(void)
 				DepthID *depth_last = NULL;
 				for (unsigned int i = 0; i < qsd->rect_len; i++) {
 					const unsigned int id = qsd->nearest.rect_id[i];
-					if (id != 0xffffffff) {
+					if (id != SELECT_ID_NONE) {
 						const float depth = qsd->rect_depth[i];
 						if (depth_last == NULL || depth_last->id != id) {
 							DepthID *d = &depth_data[depth_data_len_first_pass++];
@@ -410,8 +436,8 @@ unsigned int GPU_select_end(void)
 		for (unsigned int i = 0; i < depth_data_len; i++) {
 			if (hits < maxhits) {
 				g_query_state.buffer[hits * 4] = 1;
-				g_query_state.buffer[hits * 4 + 1] = 0xFFFF;
-				g_query_state.buffer[hits * 4 + 2] = 0xFFFF;
+				g_query_state.buffer[hits * 4 + 1] = 0xFFFF;  /* TODO, depth near */
+				g_query_state.buffer[hits * 4 + 2] = 0xFFFF;  /* TODO, depth far */
 				g_query_state.buffer[hits * 4 + 3] = depth_data[i].id;
 
 				hits++;
@@ -449,15 +475,33 @@ unsigned int GPU_select_end(void)
 			unsigned int result;
 			glGetQueryObjectuiv(g_query_state.queries[i], GL_QUERY_RESULT, &result);
 			if (result > 0) {
-				int j;
-				/* search in buffer and make selected object first */
-				for (j = 0; j < g_query_state.oldhits; j++) {
-					if (g_query_state.buffer[j * 4 + 3] == g_query_state.id[i]) {
-						g_query_state.buffer[j * 4 + 1] = 0;
-						g_query_state.buffer[j * 4 + 2] = 0;
+				if (g_query_state.mode != GPU_SELECT_NEAREST_SECOND_PASS) {
+					int maxhits = g_query_state.bufsize / 4;
+
+					if (hits < maxhits) {
+						g_query_state.buffer[hits * 4] = 1;
+						g_query_state.buffer[hits * 4 + 1] = 0xFFFF;
+						g_query_state.buffer[hits * 4 + 2] = 0xFFFF;
+						g_query_state.buffer[hits * 4 + 3] = g_query_state.id[i];
+
+						hits++;
+					}
+					else {
+						hits = -1;
+						break;
 					}
 				}
-				break;
+				else {
+					int j;
+					/* search in buffer and make selected object first */
+					for (j = 0; j < g_query_state.oldhits; j++) {
+						if (g_query_state.buffer[j * 4 + 3] == g_query_state.id[i]) {
+							g_query_state.buffer[j * 4 + 1] = 0;
+							g_query_state.buffer[j * 4 + 2] = 0;
+						}
+					}
+					break;
+				}
 			}
 		}




More information about the Bf-blender-cvs mailing list