diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2018-09-14 13:19:41 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2018-09-14 13:20:01 +0300 |
commit | e37479ad895c0bfb12dd0456cc520e1b73b99878 (patch) | |
tree | a33fe5ada0f3a8e2619090e4a715a51ed9915a5a /source | |
parent | 1d76fbf3df69db6939145b5a1cac7a5d6a482375 (diff) |
GPUBuffers: Rework support for pbvh grids + fast navigate
Flat shaded grids are now rendered as a long triangle strip with
degenerate triangles.
Smooth shaded grids are not changed.
Also add back fast navigate. The only difference with 2.79 is that fast
navigate + flat shading will show slitly "incorrect" smooth face. But that's too
much effort to fix for what it is.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/draw/intern/draw_manager_data.c | 12 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_buffers.c | 288 |
2 files changed, 189 insertions, 111 deletions
diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c index 592bb2b8dec..d0cac271674 100644 --- a/source/blender/draw/intern/draw_manager_data.c +++ b/source/blender/draw/intern/draw_manager_data.c @@ -542,9 +542,19 @@ static void sculpt_draw_cb( Object *ob = user_data; PBVH *pbvh = ob->sculpt->pbvh; + const DRWContextState *drwctx = DRW_context_state_get(); + int fast_mode = 0; + + if (drwctx->evil_C != NULL) { + Paint *p = BKE_paint_get_active_from_context(drwctx->evil_C); + if (p && (p->flags & PAINT_FAST_NAVIGATE)) { + fast_mode = drwctx->rv3d->rflag & RV3D_NAVIGATING; + } + } + if (pbvh) { BKE_pbvh_draw_cb( - pbvh, NULL, NULL, false, false, + pbvh, NULL, NULL, fast_mode, false, (void (*)(void *, GPUBatch *))draw_fn, shgroup); } } diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c index cd3290d1901..5d34cdbb6fb 100644 --- a/source/blender/gpu/intern/gpu_buffers.c +++ b/source/blender/gpu/intern/gpu_buffers.c @@ -131,7 +131,7 @@ static bool gpu_pbvh_vert_buf_data_set(GPU_PBVH_Buffers *buffers, uint vert_len) return buffers->vert_buf->data != NULL; } -static void gpu_pbvh_batch_init(GPU_PBVH_Buffers *buffers) +static void gpu_pbvh_batch_init(GPU_PBVH_Buffers *buffers, GPUPrimType prim) { /* force flushing to the GPU */ if (buffers->vert_buf->data) { @@ -140,15 +140,14 @@ static void gpu_pbvh_batch_init(GPU_PBVH_Buffers *buffers) if (buffers->triangles == NULL) { buffers->triangles = GPU_batch_create( - GPU_PRIM_TRIS, buffers->vert_buf, + prim, buffers->vert_buf, /* can be NULL */ buffers->index_buf); } if ((buffers->triangles_fast == NULL) && buffers->index_buf_fast) { buffers->triangles_fast = GPU_batch_create( - GPU_PRIM_TRIS, buffers->vert_buf, - /* can be NULL */ + prim, buffers->vert_buf, buffers->index_buf_fast); } } @@ -235,7 +234,7 @@ void GPU_pbvh_mesh_buffers_update( } } - gpu_pbvh_batch_init(buffers); + gpu_pbvh_batch_init(buffers, GPU_PRIM_TRIS); } } @@ -324,6 +323,67 @@ GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build( return buffers; } +static void gpu_pbvh_grid_fill_fast_buffer(GPU_PBVH_Buffers *buffers, int totgrid, int gridsize) +{ + GPUIndexBufBuilder elb; + if (buffers->smooth) { + GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, 6 * totgrid, INT_MAX); + for (int i = 0; i < totgrid; i++) { + GPU_indexbuf_add_generic_vert(&elb, i * gridsize * gridsize + gridsize - 1); + GPU_indexbuf_add_generic_vert(&elb, i * gridsize * gridsize); + GPU_indexbuf_add_generic_vert(&elb, (i + 1) * gridsize * gridsize - gridsize); + GPU_indexbuf_add_generic_vert(&elb, (i + 1) * gridsize * gridsize - 1); + GPU_indexbuf_add_generic_vert(&elb, i * gridsize * gridsize + gridsize - 1); + GPU_indexbuf_add_generic_vert(&elb, (i + 1) * gridsize * gridsize - gridsize); + } + } + else { + GPU_indexbuf_init_ex(&elb, GPU_PRIM_TRI_STRIP, 5 * totgrid, INT_MAX, true); + uint vbo_index_offset = 0; + for (int i = 0; i < totgrid; i++) { + uint grid_indices[4]; + for (int j = 0; j < gridsize - 1; j++) { + for (int k = 0; k < gridsize - 1; k++) { + const bool is_row_start = (k == 0); + const bool is_row_end = (k == gridsize - 2); + const bool is_grid_start = (j == 0); + const bool is_grid_end = (j == gridsize - 2); + const bool is_first_grid = (i == 0); + const bool is_last_grid = (i == totgrid - 1); + + if (is_row_start && !(is_grid_start && is_first_grid)) { + vbo_index_offset += 1; + } + + if (is_grid_start && is_row_start) { + grid_indices[0] = vbo_index_offset + 0; + } + else if (is_grid_start && is_row_end) { + grid_indices[1] = vbo_index_offset + 2; + } + else if (is_grid_end && is_row_start) { + grid_indices[2] = vbo_index_offset + 1; + } + else if (is_grid_end && is_row_end) { + grid_indices[3] = vbo_index_offset + 3; + } + vbo_index_offset += 4; + + if (is_row_end && !(is_grid_end && is_last_grid)) { + vbo_index_offset += 1; + } + } + } + GPU_indexbuf_add_generic_vert(&elb, grid_indices[1]); + GPU_indexbuf_add_generic_vert(&elb, grid_indices[0]); + GPU_indexbuf_add_generic_vert(&elb, grid_indices[3]); + GPU_indexbuf_add_generic_vert(&elb, grid_indices[2]); + GPU_indexbuf_add_primitive_restart(&elb); + } + } + buffers->index_buf_fast = GPU_indexbuf_build(&elb); +} + void GPU_pbvh_grid_buffers_update( GPU_PBVH_Buffers *buffers, CCGElem **grids, const DMFlagMat *grid_flag_mats, int *grid_indices, @@ -337,89 +397,134 @@ void GPU_pbvh_grid_buffers_update( buffers->smooth = grid_flag_mats[grid_indices[0]].flag & ME_SMOOTH; /* Build VBO */ - if (buffers->index_buf) { - const int has_mask = key->has_mask; + const int has_mask = key->has_mask; - uint vbo_index_offset = 0; - /* Build VBO */ - if (gpu_pbvh_vert_buf_data_set(buffers, totgrid * key->grid_area)) { - for (i = 0; i < totgrid; ++i) { - CCGElem *grid = grids[grid_indices[i]]; - int vbo_index = vbo_index_offset; + uint vert_count = totgrid * key->grid_area; + if (!buffers->smooth) { + vert_count = totgrid * (key->grid_size - 1) * (key->grid_size - 1) * 4; + /* Count strip restart verts (2 verts between each row and grid) */ + vert_count += ((totgrid - 1) + totgrid * (key->grid_size - 2)) * 2; + } + + if (buffers->smooth && buffers->index_buf == NULL) { + /* Not sure if really needed. */ + GPU_BATCH_DISCARD_SAFE(buffers->triangles_fast); + GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf_fast); + } + else if (!buffers->smooth && buffers->index_buf != NULL) { + /* Discard unecessary index buffers. */ + GPU_BATCH_DISCARD_SAFE(buffers->triangles); + GPU_BATCH_DISCARD_SAFE(buffers->triangles_fast); + GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf); + GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf_fast); + } + + if (buffers->index_buf_fast == NULL) { + gpu_pbvh_grid_fill_fast_buffer(buffers, totgrid, key->grid_size); + } + + uint vbo_index_offset = 0; + /* Build VBO */ + if (gpu_pbvh_vert_buf_data_set(buffers, vert_count)) { + for (i = 0; i < totgrid; ++i) { + CCGElem *grid = grids[grid_indices[i]]; + int vbo_index = vbo_index_offset; + + if (buffers->smooth) { for (y = 0; y < key->grid_size; y++) { for (x = 0; x < key->grid_size; x++) { CCGElem *elem = CCG_grid_elem(key, grid, x, y); GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, vbo_index, CCG_elem_co(key, elem)); - if (buffers->smooth) { - short no_short[3]; - normal_float_to_short_v3(no_short, CCG_elem_no(key, elem)); - GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index, no_short); + short no_short[3]; + normal_float_to_short_v3(no_short, CCG_elem_no(key, elem)); + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index, no_short); - if (has_mask && show_mask) { - float fmask = *CCG_elem_mask(key, elem); - GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.msk, vbo_index, &fmask); - empty_mask = empty_mask && (fmask == 0.0f); - } + if (has_mask && show_mask) { + float fmask = *CCG_elem_mask(key, elem); + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.msk, vbo_index, &fmask); + empty_mask = empty_mask && (fmask == 0.0f); } vbo_index += 1; } } + vbo_index_offset += key->grid_area; + } + else { + for (j = 0; j < key->grid_size - 1; j++) { + for (k = 0; k < key->grid_size - 1; k++) { + const bool is_row_start = (k == 0); + const bool is_row_end = (k == key->grid_size - 2); + const bool is_grid_start = (j == 0); + const bool is_grid_end = (j == key->grid_size - 2); + const bool is_first_grid = (i == 0); + const bool is_last_grid = (i == totgrid - 1); + + CCGElem *elems[4] = { + CCG_grid_elem(key, grid, k, j + 1), + CCG_grid_elem(key, grid, k + 1, j + 1), + CCG_grid_elem(key, grid, k + 1, j), + CCG_grid_elem(key, grid, k, j) + }; + float *co[4] = { + CCG_elem_co(key, elems[0]), + CCG_elem_co(key, elems[1]), + CCG_elem_co(key, elems[2]), + CCG_elem_co(key, elems[3]) + }; + + float fno[3]; + short no_short[3]; + normal_quad_v3(fno, co[0], co[1], co[2], co[3]); + normal_float_to_short_v3(no_short, fno); + + if (is_row_start && !(is_grid_start && is_first_grid)) { + /* Duplicate first vert + * (only pos is needed since the triangle will be degenerate) */ + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, vbo_index, co[3]); + vbo_index += 1; + vbo_index_offset += 1; + } + + /* Note indices orders (3, 0, 2, 1); we are drawing a triangle strip. */ + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, vbo_index, co[3]); + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index, no_short); + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, vbo_index + 1, co[0]); + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index + 1, no_short); + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, vbo_index + 2, co[2]); + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index + 2, no_short); + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, vbo_index + 3, co[1]); + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index + 3, no_short); + + if (has_mask && show_mask) { + float fmask = (*CCG_elem_mask(key, elems[0]) + + *CCG_elem_mask(key, elems[1]) + + *CCG_elem_mask(key, elems[2]) + + *CCG_elem_mask(key, elems[3])) * 0.25f; + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.msk, vbo_index, &fmask); + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.msk, vbo_index + 1, &fmask); + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.msk, vbo_index + 2, &fmask); + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.msk, vbo_index + 3, &fmask); + empty_mask = empty_mask && (fmask == 0.0f); + } - if (!buffers->smooth) { - for (j = 0; j < key->grid_size - 1; j++) { - for (k = 0; k < key->grid_size - 1; k++) { - CCGElem *elems[4] = { - CCG_grid_elem(key, grid, k, j + 1), - CCG_grid_elem(key, grid, k + 1, j + 1), - CCG_grid_elem(key, grid, k + 1, j), - CCG_grid_elem(key, grid, k, j) - }; - float fno[3]; - - normal_quad_v3(fno, - CCG_elem_co(key, elems[0]), - CCG_elem_co(key, elems[1]), - CCG_elem_co(key, elems[2]), - CCG_elem_co(key, elems[3])); - - vbo_index = vbo_index_offset + ((j + 1) * key->grid_size + k); - short no_short[3]; - normal_float_to_short_v3(no_short, fno); - GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index, no_short); - - /* Copy normal to first row and last column. */ - if (k == key->grid_size - 2) { - const int next_vbo_index = vbo_index_offset + ((j + 1) * key->grid_size + k + 1); - GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, next_vbo_index, no_short); - } - if (j == 0) { - int prev_vbo_index = vbo_index_offset + ((j) * key->grid_size + k); - GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, prev_vbo_index, no_short); - } - if (j == 0 && k == key->grid_size - 2) { - int diag_vbo_index = vbo_index_offset + ((j) * key->grid_size + k + 1); - GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, diag_vbo_index, no_short); - } - - if (has_mask && show_mask) { - float fmask = (*CCG_elem_mask(key, elems[0]) + - *CCG_elem_mask(key, elems[1]) + - *CCG_elem_mask(key, elems[2]) + - *CCG_elem_mask(key, elems[3])) * 0.25f; - GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.msk, vbo_index, &fmask); - empty_mask = empty_mask && (fmask == 0.0f); - } + if (is_row_end && !(is_grid_end && is_last_grid)) { + /* Duplicate last vert + * (only pos is needed since the triangle will be degenerate) */ + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, vbo_index + 4, co[1]); + vbo_index += 1; + vbo_index_offset += 1; } + + vbo_index += 4; } } - - vbo_index_offset += key->grid_area; + vbo_index_offset += (key->grid_size - 1) * (key->grid_size - 1) * 4; } - - gpu_pbvh_batch_init(buffers); } + + gpu_pbvh_batch_init(buffers, buffers->smooth ? GPU_PRIM_TRIS : GPU_PRIM_TRI_STRIP); } buffers->grids = grids; @@ -492,21 +597,6 @@ static GPUIndexBuf *gpu_get_grid_buffer( return mres_buffer; } -#define FILL_FAST_BUFFER() \ -{ \ - GPUIndexBufBuilder elb; \ - GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, 6 * totgrid, INT_MAX); \ - for (int i = 0; i < totgrid; i++) { \ - GPU_indexbuf_add_generic_vert(&elb, i * gridsize * gridsize + gridsize - 1); \ - GPU_indexbuf_add_generic_vert(&elb, i * gridsize * gridsize); \ - GPU_indexbuf_add_generic_vert(&elb, (i + 1) * gridsize * gridsize - gridsize); \ - GPU_indexbuf_add_generic_vert(&elb, (i + 1) * gridsize * gridsize - 1); \ - GPU_indexbuf_add_generic_vert(&elb, i * gridsize * gridsize + gridsize - 1); \ - GPU_indexbuf_add_generic_vert(&elb, (i + 1) * gridsize * gridsize - gridsize); \ - } \ - buffers->index_buf_fast = GPU_indexbuf_build(&elb); \ -} (void)0 - GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build( int *grid_indices, int totgrid, BLI_bitmap **grid_hidden, int gridsize, const CCGKey *UNUSED(key)) { @@ -527,9 +617,8 @@ GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build( if (totquad == 0) return buffers; - /* create and fill indices of the fast buffer too */ - FILL_FAST_BUFFER(); - + /* TODO(fclem) this needs a bit of cleanup. It's only needed for smooth grids. + * Could be moved to the update function somehow. */ if (totquad == fully_visible_totquad) { buffers->index_buf = gpu_get_grid_buffer(gridsize, &buffers->tot_quad, totgrid); buffers->has_hidden = false; @@ -545,20 +634,6 @@ GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build( buffers->is_index_buf_global = false; } -#ifdef USE_BASE_ELEM - /* Build coord/normal VBO */ - if (GLEW_ARB_draw_elements_base_vertex /* 3.2 */) { - int i; - buffers->baseelemarray = MEM_mallocN(sizeof(int) * totgrid * 2, "GPU_PBVH_Buffers.baseelemarray"); - buffers->baseindex = MEM_mallocN(sizeof(void *) * totgrid, "GPU_PBVH_Buffers.baseindex"); - for (i = 0; i < totgrid; i++) { - buffers->baseelemarray[i] = buffers->tot_quad * 6; - buffers->baseelemarray[i + totgrid] = i * key->grid_area; - buffers->baseindex[i] = NULL; - } - } -#endif - return buffers; } @@ -796,7 +871,7 @@ void GPU_pbvh_bmesh_buffers_update( buffers->show_mask = !empty_mask; - gpu_pbvh_batch_init(buffers); + gpu_pbvh_batch_init(buffers, GPU_PRIM_TRIS); } GPU_PBVH_Buffers *GPU_pbvh_bmesh_buffers_build(bool smooth_shading) @@ -833,13 +908,6 @@ void GPU_pbvh_buffers_free(GPU_PBVH_Buffers *buffers) GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf_fast); GPU_VERTBUF_DISCARD_SAFE(buffers->vert_buf); -#ifdef USE_BASE_ELEM - if (buffers->baseelemarray) - MEM_freeN(buffers->baseelemarray); - if (buffers->baseindex) - MEM_freeN(buffers->baseindex); -#endif - MEM_freeN(buffers); } } |