Merge branch 'master' into blender2.8
authorCampbell Barton <ideasman42@gmail.com>
Thu, 11 May 2017 12:15:58 +0000 (22:15 +1000)
committerCampbell Barton <ideasman42@gmail.com>
Thu, 11 May 2017 12:16:23 +0000 (22:16 +1000)
1  2 
source/blender/blenkernel/intern/pbvh.c
source/blender/draw/engines/eevee/shaders/effect_motion_blur_frag.glsl
source/blender/gpu/GPU_buffers.h
source/blender/gpu/intern/gpu_buffers.c

index 02b4479df4fb175ef643e40f0a0358772f0147d9,dacaad8d7039c01542c2e10aa76ed3964acdd96c..69028a0c96cd714a059e11e0255efc925c91b0ca
@@@ -1163,10 -1163,10 +1165,10 @@@ static void pbvh_draw_BB(PBVH *bvh
        for (int a = 0; a < bvh->totnode; a++) {
                PBVHNode *node = &bvh->nodes[a];
  
-               GPU_draw_pbvh_BB(node->vb.bmin, node->vb.bmax, ((node->flag & PBVH_Leaf) != 0), pos);
 -              GPU_pbvh_BB_draw(node->vb.bmin, node->vb.bmax, ((node->flag & PBVH_Leaf) != 0));
++              GPU_pbvh_BB_draw(node->vb.bmin, node->vb.bmax, ((node->flag & PBVH_Leaf) != 0), pos);
        }
  
 -      GPU_pbvh_BB_draw_end();
 +      immUnbindProgram();
  }
  
  static int pbvh_flush_bb(PBVH *bvh, PBVHNode *node, int flag)
@@@ -1739,8 -1739,26 +1741,8 @@@ void BKE_pbvh_node_draw(PBVHNode *node
  {
        PBVHNodeDrawData *data = data_v;
  
 -#if 0
 -      /* XXX: Just some quick code to show leaf nodes in different colors */
 -      float col[3];
 -      float spec[3] = {0.0f, 0.0f, 0.0f};
 -
 -      if (0) { //is_partial) {
 -              col[0] = (rand() / (float)RAND_MAX); col[1] = col[2] = 0.6;
 -      }
 -      else {
 -              srand((long long)node);
 -              for (int i = 0; i < 3; ++i)
 -                      col[i] = (rand() / (float)RAND_MAX) * 0.3 + 0.7;
 -      }
 -
 -      GPU_basic_shader_colors(col, spec, 0, 1.0f);
 -      glColor3f(1, 0, 0);
 -#endif
 -
        if (!(node->flag & PBVH_FullyHidden)) {
-               GPU_draw_pbvh_buffers(node->draw_buffers,
+               GPU_pbvh_buffers_draw(node->draw_buffers,
                                 data->setMaterial,
                                 data->wireframe,
                                 data->fast);
@@@ -1845,67 -1863,6 +1847,67 @@@ void BKE_pbvh_draw(PBVH *bvh, float (*p
                pbvh_draw_BB(bvh);
  }
  
-               Batch *triangles = GPU_draw_pbvh_buffers_get_batch(node->draw_buffers, data->fast);
 +struct PBVHNodeDrawCallbackData {
 +
 +      void (*draw_fn)(void *user_data, Batch *batch);
 +      void *user_data;
 +      bool fast;
 +};
 +
 +static void pbvh_node_draw_cb(PBVHNode *node, void *data_v)
 +{
 +      struct PBVHNodeDrawCallbackData *data = data_v;
 +
 +      if (!(node->flag & PBVH_FullyHidden)) {
++              Batch *triangles = GPU_pbvh_buffers_batch_get(node->draw_buffers, data->fast);
 +              if (triangles != NULL) {
 +                      data->draw_fn(data->user_data, triangles);
 +              }
 +      }
 +}
 +
 +/**
 + * Version of #BKE_pbvh_draw that runs a callback.
 + */
 +void BKE_pbvh_draw_cb(
 +        PBVH *bvh, float (*planes)[4], float (*fnors)[3], bool fast,
 +        void (*draw_fn)(void *user_data, Batch *batch), void *user_data)
 +{
 +      struct PBVHNodeDrawCallbackData draw_data = {
 +              .fast = fast,
 +              .draw_fn = draw_fn,
 +              .user_data = user_data,
 +      };
 +      PBVHNode **nodes;
 +      int totnode;
 +
 +      for (int a = 0; a < bvh->totnode; a++)
 +              pbvh_node_check_diffuse_changed(bvh, &bvh->nodes[a]);
 +
 +      BKE_pbvh_search_gather(bvh, update_search_cb, SET_INT_IN_POINTER(PBVH_UpdateNormals | PBVH_UpdateDrawBuffers),
 +                             &nodes, &totnode);
 +
 +      pbvh_update_normals(bvh, nodes, totnode, fnors);
 +      pbvh_update_draw_buffers(bvh, nodes, totnode);
 +
 +      if (nodes) MEM_freeN(nodes);
 +
 +      if (planes) {
 +              BKE_pbvh_search_callback(
 +                      bvh, BKE_pbvh_node_planes_contain_AABB,
 +                      planes, pbvh_node_draw_cb, &draw_data);
 +      }
 +      else {
 +              BKE_pbvh_search_callback(
 +                      bvh, NULL,
 +                      NULL, pbvh_node_draw_cb, &draw_data);
 +      }
 +#if 0
 +      if (G.debug_value == 14)
 +              pbvh_draw_BB(bvh);
 +#endif
 +}
 +
  void BKE_pbvh_grids_update(PBVH *bvh, CCGElem **grids, void **gridfaces,
                             DMFlagMat *flagmats, BLI_bitmap **grid_hidden)
  {
index 1505e02bfb7da88c0092cb7440acbc3ef4ac6147,0000000000000000000000000000000000000000..8960b339a611205f56e084ff651000eb8ae219a6
mode 100644,000000..100644
--- /dev/null
@@@ -1,65 -1,0 +1,63 @@@
-       FragColor = vec4(0.0);
 +
 +uniform sampler2D colorBuffer;
 +uniform sampler2D depthBuffer;
 +
 +
 +/* current frame */
 +uniform mat4 currInvViewProjMatrix;
 +
 +/* past frame frame */
 +uniform mat4 pastViewProjMatrix;
 +
 +in vec4 uvcoordsvar;
 +
 +out vec4 FragColor;
 +
 +#define MAX_SAMPLE 64
 +
 +uniform int samples;
 +
 +float wang_hash_noise(uint s)
 +{
 +      uint seed = (uint(gl_FragCoord.x) * 1664525u + uint(gl_FragCoord.y)) + s;
 +
 +      seed = (seed ^ 61u) ^ (seed >> 16u);
 +      seed *= 9u;
 +      seed = seed ^ (seed >> 4u);
 +      seed *= 0x27d4eb2du;
 +      seed = seed ^ (seed >> 15u);
 +
 +      float value = float(seed);
 +      value *= 1.0 / 4294967296.0;
 +      return fract(value);
 +}
 +
 +void main()
 +{
 +      vec3 ndc_pos;
 +      ndc_pos.xy = uvcoordsvar.xy;
 +      ndc_pos.z = texture(depthBuffer, uvcoordsvar.xy).x;
 +
 +      float inv_samples = 1.0 / float(samples);
 +      float noise = 2.0 * wang_hash_noise(0u) * inv_samples;
 +
 +      /* Normalize Device Coordinates are [-1, +1]. */
 +      ndc_pos = ndc_pos * 2.0 - 1.0;
 +
 +      vec4 p = currInvViewProjMatrix * vec4(ndc_pos, 1.0);
 +      vec3 world_pos = p.xyz / p.w; /* Perspective divide */
 +
 +      /* Now find where was this pixel position
 +       * inside the past camera viewport */
 +      vec4 old_ndc = pastViewProjMatrix * vec4(world_pos, 1.0);
 +      old_ndc.xyz /= old_ndc.w; /* Perspective divide */
 +
 +      vec2 motion = (ndc_pos.xy - old_ndc.xy) * 0.25; /* 0.25 fit cycles ref */
 +
 +      float inc = 2.0 * inv_samples;
 +      float i = -1.0 + noise;
 +      for (int j = 0; j < samples && j < MAX_SAMPLE; j++) {
 +              FragColor += texture(colorBuffer, uvcoordsvar.xy + motion * i) * inv_samples;
 +              i += inc;
 +      }
 +}
index 661562e2e4c68b78caa848b17e59a39f6d624833,e4a837d0a5f3675782dc52baf9975f89168b7ba6..b4d271ed3b9e3118ff11428eb09a1b4fd8a42e30
@@@ -243,25 -242,29 +243,28 @@@ void GPU_pbvh_mesh_buffers_update
          const int *vert_indices, int totvert, const float *vmask,
          const int (*face_vert_indices)[3], bool show_diffuse_color);
  
- void GPU_update_bmesh_pbvh_buffers(GPU_PBVH_Buffers *buffers,
-                               struct BMesh *bm,
-                               struct GSet *bm_faces,
-                               struct GSet *bm_unique_verts,
-                               struct GSet *bm_other_verts,
-                               bool show_diffuse_color);
+ void GPU_pbvh_bmesh_buffers_update(
+         GPU_PBVH_Buffers *buffers,
+         struct BMesh *bm,
+         struct GSet *bm_faces,
+         struct GSet *bm_unique_verts,
+         struct GSet *bm_other_verts,
+         bool show_diffuse_color);
  
- void GPU_update_grid_pbvh_buffers(GPU_PBVH_Buffers *buffers, struct CCGElem **grids,
-                              const struct DMFlagMat *grid_flag_mats,
-                              int *grid_indices, int totgrid, const struct CCGKey *key,
-                              bool show_diffuse_color);
+ void GPU_pbvh_grid_buffers_update(
+         GPU_PBVH_Buffers *buffers, struct CCGElem **grids,
+         const struct DMFlagMat *grid_flag_mats,
+         int *grid_indices, int totgrid, const struct CCGKey *key,
+         bool show_diffuse_color);
  
  /* draw */
- void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial,
-                            bool wireframe, bool fast);
- struct Batch *GPU_draw_pbvh_buffers_get_batch(GPU_PBVH_Buffers *buffers, bool fast);
+ void GPU_pbvh_buffers_draw(
+         GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial,
+         bool wireframe, bool fast);
++struct Batch *GPU_pbvh_buffers_batch_get(GPU_PBVH_Buffers *buffers, bool fast);
  
 -/* debug PBVH draw*/
 -void GPU_pbvh_BB_draw(float min[3], float max[3], bool leaf);
 -void GPU_pbvh_BB_draw_init(void);
 -void GPU_pbvh_BB_draw_end(void);
 +/* debug PBVH draw */
- void GPU_draw_pbvh_BB(float min[3], float max[3], bool leaf, unsigned int pos);
++void GPU_pbvh_BB_draw(float min[3], float max[3], bool leaf, unsigned int pos);
  
  bool GPU_pbvh_buffers_diffuse_changed(GPU_PBVH_Buffers *buffers, struct GSet *bm_faces, bool show_diffuse_color);
  
index 8a3c0c91b65f5b4dbec123c6e575eda61d9a622c,9f1fe3a5a674b6b5a4c37856ad1b1cd1d9488ba4..81466d156eedb2fabeaeb00436a740edaabe55cf
@@@ -1473,23 -1435,32 +1473,23 @@@ static ElementList *gpu_get_grid_buffer
        return gridbuff->mres_buffer;
  }
  
 -#define FILL_FAST_BUFFER(type_) \
 +#define FILL_FAST_BUFFER() \
  { \
 -      type_ *buffer; \
 -      buffers->index_buf_fast = GPU_buffer_alloc(sizeof(type_) * 6 * totgrid); \
 -      buffer = GPU_buffer_lock(buffers->index_buf_fast, GPU_BINDING_INDEX); \
 -      if (buffer) { \
 -              int i; \
 -              for (i = 0; i < totgrid; i++) { \
 -                      int currentquad = i * 6; \
 -                      buffer[currentquad]     = i * gridsize * gridsize + gridsize - 1; \
 -                      buffer[currentquad + 1] = i * gridsize * gridsize; \
 -                      buffer[currentquad + 2] = (i + 1) * gridsize * gridsize - gridsize; \
 -                      buffer[currentquad + 3] = (i + 1) * gridsize * gridsize - 1; \
 -                      buffer[currentquad + 4] = i * gridsize * gridsize + gridsize - 1; \
 -                      buffer[currentquad + 5] = (i + 1) * gridsize * gridsize - gridsize; \
 -              } \
 -              GPU_buffer_unlock(buffers->index_buf_fast, GPU_BINDING_INDEX); \
 -      } \
 -      else { \
 -              GPU_buffer_free(buffers->index_buf_fast); \
 -              buffers->index_buf_fast = NULL; \
 +      ElementListBuilder elb; \
 +      ElementListBuilder_init(&elb, PRIM_TRIANGLES, 6 * totgrid, INT_MAX); \
 +      for (int i = 0; i < totgrid; i++) { \
 +              add_generic_vertex(&elb, i * gridsize * gridsize + gridsize - 1); \
 +              add_generic_vertex(&elb, i * gridsize * gridsize); \
 +              add_generic_vertex(&elb, (i + 1) * gridsize * gridsize - gridsize); \
 +              add_generic_vertex(&elb, (i + 1) * gridsize * gridsize - 1); \
 +              add_generic_vertex(&elb, i * gridsize * gridsize + gridsize - 1); \
 +              add_generic_vertex(&elb, (i + 1) * gridsize * gridsize - gridsize); \
        } \
 +      buffers->index_buf_fast = ElementList_build(&elb); \
  } (void)0
  
- GPU_PBVH_Buffers *GPU_build_grid_pbvh_buffers(
+ GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build(
 -        int *grid_indices, int totgrid, BLI_bitmap **grid_hidden, int gridsize, const CCGKey *key,
 +        int *grid_indices, int totgrid, BLI_bitmap **grid_hidden, int gridsize, const CCGKey *UNUSED(key),
          GridCommonGPUBuffer **grid_common_gpu_buffer)
  {
        GPU_PBVH_Buffers *buffers;
@@@ -1802,11 -1795,9 +1802,11 @@@ void GPU_pbvh_bmesh_buffers_update
                buffers->index_buf = NULL;
                buffers->is_index_buf_global = false;
        }
 +
 +      gpu_pbvh_batch_init(buffers);
  }
  
- GPU_PBVH_Buffers *GPU_build_bmesh_pbvh_buffers(bool smooth_shading)
+ GPU_PBVH_Buffers *GPU_pbvh_bmesh_buffers_build(bool smooth_shading)
  {
        GPU_PBVH_Buffers *buffers;
  
@@@ -1823,31 -1814,145 +1823,31 @@@ void GPU_pbvh_buffers_draw
          GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial,
          bool wireframe, bool fast)
  {
 -      bool do_fast = fast && buffers->index_buf_fast;
 -      /* sets material from the first face, to solve properly face would need to
 -       * be sorted in buckets by materials */
 -      if (setMaterial) {
 -              if (buffers->face_indices_len) {
 -                      const MLoopTri *lt = &buffers->looptri[buffers->face_indices[0]];
 -                      const MPoly *mp = &buffers->mpoly[lt->poly];
 -                      if (!setMaterial(mp->mat_nr + 1, NULL))
 -                              return;
 -              }
 -              else if (buffers->totgrid) {
 -                      const DMFlagMat *f = &buffers->grid_flag_mats[buffers->grid_indices[0]];
 -                      if (!setMaterial(f->mat_nr + 1, NULL))
 -                              return;
 -              }
 -              else {
 -                      if (!setMaterial(1, NULL))
 -                              return;
 +      UNUSED_VARS(wireframe, fast, setMaterial);
 +      bool do_fast = fast && buffers->triangles_fast;
 +      Batch *triangles = do_fast ? buffers->triangles_fast : buffers->triangles;
 +
 +      if (triangles) {
 +              if (triangles->interface == NULL) {
 +                      GPUBuiltinShader shader_id =
 +                              buffers->smooth ? GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR : GPU_SHADER_SIMPLE_LIGHTING_FLAT_COLOR;
 +                      GPUShader *shader = GPU_shader_get_builtin_shader(shader_id);
 +
 +                      Batch_set_program(
 +                              triangles,
 +                              GPU_shader_get_program(shader), GPU_shader_get_interface(shader));
                }
 +              Batch_draw(triangles);
        }
 +}
  
- Batch *GPU_draw_pbvh_buffers_get_batch(GPU_PBVH_Buffers *buffers, bool fast)
 -      if (buffers->vert_buf) {
 -              char *base = NULL;
 -              char *index_base = NULL;
 -              /* weak inspection of bound options, should not be necessary ideally */
 -              const int bound_options_old = GPU_basic_shader_bound_options();
 -              int bound_options_new = 0;
 -              glEnableClientState(GL_VERTEX_ARRAY);
 -              if (!wireframe) {
 -                      glEnableClientState(GL_NORMAL_ARRAY);
 -                      glEnableClientState(GL_COLOR_ARRAY);
 -
 -                      bound_options_new |= GPU_SHADER_USE_COLOR;
 -              }
 -
 -              GPU_buffer_bind(buffers->vert_buf, GPU_BINDING_ARRAY);
 -
 -              if (do_fast) {
 -                      GPU_buffer_bind(buffers->index_buf_fast, GPU_BINDING_INDEX);
 -              }
 -              else if (buffers->index_buf) {
 -                      GPU_buffer_bind(buffers->index_buf, GPU_BINDING_INDEX);
 -              }
 -
 -              if (wireframe) {
 -                      glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
 -              }
 -              else {
 -                      if ((buffers->smooth == false) && (buffers->face_indices_len == 0)) {
 -                              bound_options_new |= GPU_SHADER_FLAT_NORMAL;
 -                      }
 -              }
 -
 -              if (bound_options_new & ~bound_options_old) {
 -                      GPU_basic_shader_bind(bound_options_old | bound_options_new);
 -              }
 -
 -              if (buffers->tot_quad) {
 -                      const char *offset = base;
 -                      const bool drawall = !(buffers->has_hidden || do_fast);
 -
 -                      if (GLEW_ARB_draw_elements_base_vertex && drawall) {
 -
 -                              glVertexPointer(3, GL_FLOAT, sizeof(VertexBufferFormat),
 -                                              offset + offsetof(VertexBufferFormat, co));
 -                              if (!wireframe) {
 -                                      glNormalPointer(GL_SHORT, sizeof(VertexBufferFormat),
 -                                                      offset + offsetof(VertexBufferFormat, no));
 -                                      glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VertexBufferFormat),
 -                                                     offset + offsetof(VertexBufferFormat, color));
 -                              }
 -
 -                              glMultiDrawElementsBaseVertex(GL_TRIANGLES, buffers->baseelemarray, buffers->index_type,
 -                                                            (const void * const *)buffers->baseindex,
 -                                                            buffers->totgrid, &buffers->baseelemarray[buffers->totgrid]);
 -                      }
 -                      else {
 -                              int i, last = drawall ? buffers->totgrid : 1;
 -
 -                              /* we could optimize this to one draw call, but it would need more memory */
 -                              for (i = 0; i < last; i++) {
 -                                      glVertexPointer(3, GL_FLOAT, sizeof(VertexBufferFormat),
 -                                                      offset + offsetof(VertexBufferFormat, co));
 -                                      if (!wireframe) {
 -                                              glNormalPointer(GL_SHORT, sizeof(VertexBufferFormat),
 -                                                              offset + offsetof(VertexBufferFormat, no));
 -                                              glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VertexBufferFormat),
 -                                                             offset + offsetof(VertexBufferFormat, color));
 -                                      }
 -
 -                                      if (do_fast)
 -                                              glDrawElements(GL_TRIANGLES, buffers->totgrid * 6, buffers->index_type, index_base);
 -                                      else
 -                                              glDrawElements(GL_TRIANGLES, buffers->tot_quad * 6, buffers->index_type, index_base);
 -
 -                                      offset += buffers->gridkey.grid_area * sizeof(VertexBufferFormat);
 -                              }
 -                      }
 -              }
 -              else if (buffers->tot_tri) {
 -                      int totelem = buffers->tot_tri * 3;
 -
 -                      glVertexPointer(3, GL_FLOAT, sizeof(VertexBufferFormat),
 -                                      (void *)(base + offsetof(VertexBufferFormat, co)));
 -
 -                      if (!wireframe) {
 -                              glNormalPointer(GL_SHORT, sizeof(VertexBufferFormat),
 -                                              (void *)(base + offsetof(VertexBufferFormat, no)));
 -                              glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VertexBufferFormat),
 -                                             (void *)(base + offsetof(VertexBufferFormat, color)));
 -                      }
 -
 -                      if (buffers->index_buf)
 -                              glDrawElements(GL_TRIANGLES, totelem, buffers->index_type, index_base);
 -                      else
 -                              glDrawArrays(GL_TRIANGLES, 0, totelem);
 -              }
 -
 -              if (wireframe)
 -                      glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
 -
 -              GPU_buffer_unbind(buffers->vert_buf, GPU_BINDING_ARRAY);
 -              if (buffers->index_buf || do_fast)
 -                      GPU_buffer_unbind(do_fast ? buffers->index_buf_fast : buffers->index_buf, GPU_BINDING_INDEX);
 -
 -              glDisableClientState(GL_VERTEX_ARRAY);
 -              if (!wireframe) {
 -                      glDisableClientState(GL_NORMAL_ARRAY);
 -                      glDisableClientState(GL_COLOR_ARRAY);
 -              }
 -
 -              if (bound_options_new & ~bound_options_old) {
 -                      GPU_basic_shader_bind(bound_options_old);
 -              }
 -      }
++Batch *GPU_pbvh_buffers_batch_get(GPU_PBVH_Buffers *buffers, bool fast)
 +{
 +      return (fast && buffers->triangles_fast) ?
 +              buffers->triangles_fast : buffers->triangles;
  }
  
 -bool GPU_pbvh_buffers_diffuse_changed(
 -        GPU_PBVH_Buffers *buffers, GSet *bm_faces, bool show_diffuse_color)
 +bool GPU_pbvh_buffers_diffuse_changed(GPU_PBVH_Buffers *buffers, GSet *bm_faces, bool show_diffuse_color)
  {
        float diffuse_color[4];
        bool use_matcaps = GPU_material_use_matcaps_get();
        return !equals_v3v3(diffuse_color, buffers->diffuse_color);
  }
  
- void GPU_free_pbvh_buffers(GPU_PBVH_Buffers *buffers)
+ void GPU_pbvh_buffers_free(GPU_PBVH_Buffers *buffers)
  {
        if (buffers) {
 -              if (buffers->vert_buf)
 -                      GPU_buffer_free(buffers->vert_buf);
 -              if (buffers->index_buf && !buffers->is_index_buf_global)
 -                      GPU_buffer_free(buffers->index_buf);
 -              if (buffers->index_buf_fast)
 -                      GPU_buffer_free(buffers->index_buf_fast);
 +              BATCH_DISCARD_SAFE(buffers->triangles);
 +              BATCH_DISCARD_SAFE(buffers->triangles_fast);
 +              if (!buffers->is_index_buf_global) {
 +                      ELEMENTLIST_DISCARD_SAFE(buffers->index_buf);
 +              }
 +              ELEMENTLIST_DISCARD_SAFE(buffers->index_buf_fast);
 +              VertexBuffer_discard(buffers->vert_buf);
 +
 +#ifdef USE_BASE_ELEM
                if (buffers->baseelemarray)
                        MEM_freeN(buffers->baseelemarray);
                if (buffers->baseindex)
@@@ -1928,57 -2029,59 +1928,57 @@@ void GPU_pbvh_multires_buffers_free(Gri
  }
  
  /* debug function, draws the pbvh BB */
- void GPU_draw_pbvh_BB(float min[3], float max[3], bool leaf, unsigned int pos)
 -void GPU_pbvh_BB_draw(float min[3], float max[3], bool leaf)
++void GPU_pbvh_BB_draw(float min[3], float max[3], bool leaf, unsigned int pos)
  {
 -      const float quads[4][4][3] = {
 -              {
 -                      {min[0], min[1], min[2]},
 -                      {max[0], min[1], min[2]},
 -                      {max[0], min[1], max[2]},
 -                      {min[0], min[1], max[2]}
 -              },
 +      if (leaf)
 +              immUniformColor4f(0.0, 1.0, 0.0, 0.5);
 +      else
 +              immUniformColor4f(1.0, 0.0, 0.0, 0.5);
  
 -              {
 -                      {min[0], min[1], min[2]},
 -                      {min[0], max[1], min[2]},
 -                      {min[0], max[1], max[2]},
 -                      {min[0], min[1], max[2]}
 -              },
 +      /* TODO(merwin): revisit this after we have mutable VertexBuffers
 +       * could keep a static batch & index buffer, change the VBO contents per draw
 +       */
  
 -              {
 -                      {max[0], max[1], min[2]},
 -                      {max[0], min[1], min[2]},
 -                      {max[0], min[1], max[2]},
 -                      {max[0], max[1], max[2]}
 -              },
 +      immBegin(PRIM_LINES, 24);
  
 -              {
 -                      {max[0], max[1], min[2]},
 -                      {min[0], max[1], min[2]},
 -                      {min[0], max[1], max[2]},
 -                      {max[0], max[1], max[2]}
 -              },
 -      };
 +      /* top */
 +      immVertex3f(pos, min[0], min[1], max[2]);
 +      immVertex3f(pos, min[0], max[1], max[2]);
  
 -      if (leaf)
 -              glColor4f(0.0, 1.0, 0.0, 0.5);
 -      else
 -              glColor4f(1.0, 0.0, 0.0, 0.5);
 +      immVertex3f(pos, min[0], max[1], max[2]);
 +      immVertex3f(pos, max[0], max[1], max[2]);
  
 -      glVertexPointer(3, GL_FLOAT, 0, &quads[0][0][0]);
 -      glDrawArrays(GL_QUADS, 0, 16);
 -}
 +      immVertex3f(pos, max[0], max[1], max[2]);
 +      immVertex3f(pos, max[0], min[1], max[2]);
  
 -void GPU_pbvh_BB_draw_init(void)
 -{
 -      glPushAttrib(GL_ENABLE_BIT);
 -      glDisable(GL_CULL_FACE);
 -      glEnableClientState(GL_VERTEX_ARRAY);
 -      glDisableClientState(GL_COLOR_ARRAY);
 -      glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
 -      glEnable(GL_BLEND);
 -}
 +      immVertex3f(pos, max[0], min[1], max[2]);
 +      immVertex3f(pos, min[0], min[1], max[2]);
  
 -void GPU_pbvh_BB_draw_end(void)
 -{
 -      glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
 -      glPopAttrib();
 +      /* bottom */
 +      immVertex3f(pos, min[0], min[1], min[2]);
 +      immVertex3f(pos, min[0], max[1], min[2]);
 +
 +      immVertex3f(pos, min[0], max[1], min[2]);
 +      immVertex3f(pos, max[0], max[1], min[2]);
 +
 +      immVertex3f(pos, max[0], max[1], min[2]);
 +      immVertex3f(pos, max[0], min[1], min[2]);
 +
 +      immVertex3f(pos, max[0], min[1], min[2]);
 +      immVertex3f(pos, min[0], min[1], min[2]);
 +
 +      /* sides */
 +      immVertex3f(pos, min[0], min[1], min[2]);
 +      immVertex3f(pos, min[0], min[1], max[2]);
 +
 +      immVertex3f(pos, min[0], max[1], min[2]);
 +      immVertex3f(pos, min[0], max[1], max[2]);
 +
 +      immVertex3f(pos, max[0], max[1], min[2]);
 +      immVertex3f(pos, max[0], max[1], max[2]);
 +
 +      immVertex3f(pos, max[0], min[1], min[2]);
 +      immVertex3f(pos, max[0], min[1], max[2]);
 +
 +      immEnd();
  }