[Bf-committers] Occlusion Query based selection

Brecht Van Lommel brechtvanlommel at pandora.be
Sat Dec 3 16:21:28 CET 2011


Hi,

Yes, it would be good to avoid GL_SELECT when possible. Making a
common interface that can use a different method depending on the
graphics card support seems the way to go.

Regarding occlusion queries, is there any way around counting the
number of queries needed in advance? It seems like this could make the
code a bit complicated. Maybe an alternative would be to do color
coded drawing as we do for mesh selection, but to an offscreen buffer
to avoid interference with regular drawing and multisample issues.

Brecht.

2011/12/3 Αντώνης Ρυακιωτάκης <kalast at gmail.com>:
> Hi, recently I have become aware of a user complaint
>
> http://blenderartists.org/forum/showthread.php?238426-why-is-gl_select-still-used-to-select-objects-in-Blender
>
>  about slow selection. This is not a new issue and stems from the fact
> that selection uses glRenderMode(GL_SELECT) under the hood. This runs
> on the CPU and lags on heavy scenes since it effectively uses a
> software rasterizer. There is a better way to do this, using GPU based
> occlusion queries. This provides the same information but running
> through the GPU so it should be no slower than navigating the view(In
> theory). I thought of using some color encoded index+color buffer
> readback to do this but I thought that occlusion queries would fit the
> current scheme better. Unfortunately I have discovered that the
> selection scheme is a bit more involved in the selection workings,
> especially when it comes to armatures. I will have to look into this a
> bit further but my first idea is maybe use a selection buffer-like
> interface that uses occlusion queries behind the scenes. Thoughts?
>
> Oh, I forgot the goodies:
>
> build for windows:
>
> graphicall.org/747/
>
> And patch:
>
> Index: release/scripts/startup/bl_ui/space_userpref.py
> ===================================================================
> --- release/scripts/startup/bl_ui/space_userpref.py     (revision 42368)
> +++ release/scripts/startup/bl_ui/space_userpref.py     (working copy)
> @@ -436,6 +436,10 @@
>         col.prop(system, "gl_texture_limit", text="Limit Size")
>         col.prop(system, "texture_time_out", text="Time Out")
>         col.prop(system, "texture_collection_rate", text="Collection Rate")
> +        col.label(text="Selection")
> +        sub = col.column()
> +        sub.active = system.gpu_selection_support
> +        sub.prop(system, "use_gpu_selection")
>
>         col.separator()
>         col.separator()
> Index: source/blender/makesdna/DNA_userdef_types.h
> ===================================================================
> --- source/blender/makesdna/DNA_userdef_types.h (revision 42368)
> +++ source/blender/makesdna/DNA_userdef_types.h (working copy)
> @@ -391,7 +391,8 @@
>
>        short widget_unit;              /* defaults to 20 for 72 DPI setting */
>        short anisotropic_filter;
> -       /*short pad[3];                 */
> +       short gpu_selection;
> +       short pad[3];
>
>        float ndof_sensitivity; /* overall sensitivity of 3D mouse */
>        int ndof_flag;                  /* flags for 3D mouse */
> @@ -552,6 +553,10 @@
>  #define USER_DISABLE_VBO               8
>  #define USER_DISABLE_AA                        16
>
> +/* occlusion culling-based gpu selection */
> +#define USER_GPU_SELECTION                     1
> +#define USER_GPU_SELECTION_DUMMY       2
> +
>  /* wm draw method */
>  #define USER_DRAW_TRIPLE               0
>  #define USER_DRAW_OVERLAP              1
> Index: source/blender/makesrna/intern/rna_userdef.c
> ===================================================================
> --- source/blender/makesrna/intern/rna_userdef.c        (revision 42368)
> +++ source/blender/makesrna/intern/rna_userdef.c        (working copy)
> @@ -46,6 +46,8 @@
>
>  #include "BKE_sound.h"
>
> +#include "GL/glew.h"
> +
>  #ifdef RNA_RUNTIME
>
>  #include "DNA_object_types.h"
> @@ -302,6 +304,11 @@
>        WM_main_add_notifier(NC_WINDOW, NULL);
>  }
>
> +static int rna_Scene_GPU_selection_supported(PointerRNA *ptr)
> +{
> +       return GLEW_ARB_occlusion_query;
> +}
> +
>  #else
>
>  static void rna_def_userdef_theme_ui_font_style(BlenderRNA *brna)
> @@ -2850,6 +2857,14 @@
>        RNA_def_property_ui_text(prop, "Text Anti-aliasing", "Draw user
> interface text anti-aliased");
>        RNA_def_property_update(prop, 0, "rna_userdef_text_update");
>
> +       prop= RNA_def_property(srna, "gpu_selection_support", PROP_BOOLEAN,
> PROP_NONE);
> +       RNA_def_property_boolean_sdna(prop, NULL, "gpu_selection",
> USER_GPU_SELECTION_DUMMY);
> +       RNA_def_property_boolean_funcs(prop,
> "rna_Scene_GPU_selection_supported", NULL);
> +
> +       prop= RNA_def_property(srna, "use_gpu_selection", PROP_BOOLEAN, PROP_NONE);
> +       RNA_def_property_boolean_sdna(prop, NULL, "gpu_selection",
> USER_GPU_SELECTION);
> +       RNA_def_property_ui_text(prop, "GPU selection support", "Use GPU
> occlusion queries to accelerate selection");
> +
>  #if 0
>        prop= RNA_def_property(srna, "verse_master", PROP_STRING, PROP_NONE);
>        RNA_def_property_string_sdna(prop, NULL, "versemaster");
> Index: source/blender/makesrna/intern/rna_scene.c
> ===================================================================
> --- source/blender/makesrna/intern/rna_scene.c  (revision 42368)
> +++ source/blender/makesrna/intern/rna_scene.c  (working copy)
> @@ -1291,7 +1291,6 @@
>        if(camera)
>                DAG_id_tag_update(&camera->id, 0);
>  }
> -
>  #else
>
>  static void rna_def_transform_orientation(BlenderRNA *brna)
> Index: source/blender/editors/space_view3d/view3d_view.c
> ===================================================================
> --- source/blender/editors/space_view3d/view3d_view.c   (revision 42368)
> +++ source/blender/editors/space_view3d/view3d_view.c   (working copy)
> @@ -1178,6 +1178,10 @@
>        rctf rect;
>        short code, hits;
>        char dt, dtx;
> +       char use_gpu_selection = GLEW_ARB_occlusion_query &&
> (U.gpu_selection & USER_GPU_SELECTION);
> +       // count issued queries (number of objects in scene)
> +       int num_of_queries = 0;
> +       unsigned int *queries;
>
>        G.f |= G_PICKSEL;
>
> @@ -1206,10 +1210,30 @@
>        if(vc->rv3d->rflag & RV3D_CLIPPING)
>                view3d_set_clipping(vc->rv3d);
>
> -       glSelectBuffer( bufsize, (GLuint *)buffer);
> -       glRenderMode(GL_SELECT);
> -       glInitNames();  /* these two calls whatfor? It doesnt work otherwise */
> -       glPushName(-1);
> +       if(!use_gpu_selection){
> +               glSelectBuffer( bufsize, (GLuint *)buffer);
> +               glRenderMode(GL_SELECT);
> +               glInitNames();  /* these two calls whatfor? It doesnt work otherwise */
> +               glPushName(-1);
> +       }else{
> +               /* count number of objects */
> +               Base *base;
> +
> +               for(base= scene->base.first; base; base= base->next) {
> +                       if(base->lay & v3d->lay) {
> +                               num_of_queries++;
> +                       }
> +               }
> +
> +               queries = MEM_mallocN(num_of_queries*sizeof(*queries) , "gpu
> selection queries");
> +               glGenQueriesARB(num_of_queries, queries);
> +
> +               /* 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 */
> +               glPushAttrib(GL_DEPTH_BUFFER_BIT);
> +               glDisable(GL_DEPTH_TEST);
> +       }
> +
>        code= 1;
>
>        if(vc->obedit && vc->obedit->type==OB_MBALL) {
> @@ -1232,7 +1256,11 @@
>                                        base->selcol= 0;
>                                else {
>                                        base->selcol= code;
> -                                       glLoadName(code);
> +                                       if(!use_gpu_selection){
> +                                               glLoadName(code);
> +                                       }else{
> +                                               glBeginQueryARB(GL_SAMPLES_PASSED_ARB, queries[code-1]);
> +                                       }
>                                        draw_object(scene, ar, v3d, base, DRAW_PICKING|DRAW_CONSTCOLOR);
>
>                                        /* we draw group-duplicators for selection too */
> @@ -1263,15 +1291,45 @@
>                                                free_object_duplilist(lb);
>                                        }
>                                        code++;
> +                                       if(use_gpu_selection){
> +                                               glEndQueryARB(GL_SAMPLES_PASSED_ARB);
> +                                       }
>                                }
>                        }
>                }
>                v3d->xray= FALSE;       // restore
>        }
> +       if(!use_gpu_selection){
> +               glPopName();    /* see above (pushname) */
> +               hits= glRenderMode(GL_RENDER);
> +       }else{
> +               int i;
> +               hits = 0;
> +
> +               for(i = 0; i < num_of_queries; i++)
> +               {
> +                       unsigned int result;
> +                       glGetQueryObjectuivARB(queries[i], GL_QUERY_RESULT_ARB, &result);
> +                       if(result > 0){
> +                               if(hits < bufsize){
> +                                       buffer[hits*4] = hits;
> +                                       buffer[hits*4+1] = 0;
> +                                       buffer[hits*4+2] = 0;
> +                                       buffer[hits*4+3] = i+1;
> +
> +                                       hits++;
> +                               }else{
> +                                       hits = -1;
> +                                       break;
> +                               }
> +                       }
> +               }
> +
> +               glDeleteQueriesARB(num_of_queries, queries);
> +               MEM_freeN(queries);
> +               glPopAttrib();
> +       }
>
> -       glPopName();    /* see above (pushname) */
> -       hits= glRenderMode(GL_RENDER);
> -
>        G.f &= ~G_PICKSEL;
>        setwinmatrixview3d(ar, v3d, NULL);
>        mul_m4_m4m4(vc->rv3d->persmat, vc->rv3d->viewmat, vc->rv3d->winmat);
> Index: source/blender/editors/interface/resources.c
> ===================================================================
> --- source/blender/editors/interface/resources.c        (revision 42368)
> +++ source/blender/editors/interface/resources.c        (working copy)
> @@ -1679,6 +1679,10 @@
>                }
>        }
>
> +       if (bmain->versionfile < 260 || (bmain->versionfile == 260 &&
> bmain->subversionfile < 5)) {
> +               U.gpu_selection = 1;
> +       }
> +
>        /* GL Texture Garbage Collection (variable abused above!) */
>        if (U.textimeout == 0) {
>                U.texcollectrate = 60;
> _______________________________________________
> Bf-committers mailing list
> Bf-committers at blender.org
> http://lists.blender.org/mailman/listinfo/bf-committers


More information about the Bf-committers mailing list