diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2019-02-22 06:00:19 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2019-02-22 06:03:59 +0300 |
commit | e35b7e73267fc02817538cd67e72e5c278dec878 (patch) | |
tree | 907f08ad2f8bbafc142e0771bcc8af5f448c038d /source/blender/gpu/intern | |
parent | bfbf3b9558ecd808423ed4146d8d5bd5bd4adf8a (diff) |
GPUBuffers: Fix/cleanup multires implementation
The multires sculpt drawing was a not working in smooth mode.
Also hidding was not supported by the wireframe overlay and flat shaded
faces.
Codewise it is cleaner and index buffers are only updated if the
smoothing changes.
Diffstat (limited to 'source/blender/gpu/intern')
-rw-r--r-- | source/blender/gpu/intern/gpu_buffers.c | 364 |
1 files changed, 155 insertions, 209 deletions
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c index 71c55da690a..85459c4de40 100644 --- a/source/blender/gpu/intern/gpu_buffers.c +++ b/source/blender/gpu/intern/gpu_buffers.c @@ -364,79 +364,134 @@ GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build( /** \name Grid PBVH * \{ */ -static void gpu_pbvh_grid_fill_fast_buffer(GPU_PBVH_Buffers *buffers, int totgrid, int gridsize) +static void gpu_pbvh_grid_fill_index_buffers( + GPU_PBVH_Buffers *buffers, + int *grid_indices, + uint visible_quad_len, + int totgrid, + int gridsize) { GPUIndexBufBuilder elb, elb_lines; + GPUIndexBufBuilder elb_fast, elb_lines_fast; + + GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, 2 * visible_quad_len, INT_MAX); + GPU_indexbuf_init(&elb_fast, GPU_PRIM_TRIS, 2 * totgrid, INT_MAX); + GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, 2 * totgrid * gridsize * (gridsize - 1), INT_MAX); + GPU_indexbuf_init(&elb_lines_fast, GPU_PRIM_LINES, 4 * totgrid, INT_MAX); + if (buffers->smooth) { - GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, 4 * totgrid, INT_MAX); - GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, 2 * totgrid, INT_MAX); - for (int i = 0; i < totgrid; i++) { - const uint v0 = i * gridsize * gridsize + gridsize - 1; - const uint v1 = i * gridsize * gridsize; - const uint v2 = (i + 1) * gridsize * gridsize - gridsize; - const uint v3 = (i + 1) * gridsize * gridsize - 1; - - GPU_indexbuf_add_tri_verts(&elb, v0, v1, v2); - GPU_indexbuf_add_tri_verts(&elb, v3, v0, v2); - - GPU_indexbuf_add_line_verts(&elb_lines, v0, v1); - GPU_indexbuf_add_line_verts(&elb_lines, v1, v2); - GPU_indexbuf_add_line_verts(&elb_lines, v2, v3); - GPU_indexbuf_add_line_verts(&elb_lines, v3, v0); + uint offset = 0; + const uint grid_vert_len = gridsize * gridsize; + for (int i = 0; i < totgrid; i++, offset += grid_vert_len) { + uint v0, v1, v2, v3; + bool grid_visible = false; + + BLI_bitmap *gh = buffers->grid_hidden[grid_indices[i]]; + + for (int j = 0; j < gridsize - 1; ++j) { + for (int k = 0; k < gridsize - 1; ++k) { + /* Skip hidden grid face */ + if (gh && paint_is_grid_face_hidden( + gh, gridsize, k, j)) + { + continue; + } + /* Indices in a Clockwise QUAD disposition. */ + v0 = offset + j * gridsize + k; + v1 = v0 + 1; + v2 = v1 + gridsize; + v3 = v2 - 1; + + GPU_indexbuf_add_tri_verts(&elb, v0, v2, v1); + GPU_indexbuf_add_tri_verts(&elb, v0, v3, v2); + + GPU_indexbuf_add_line_verts(&elb_lines, v0, v1); + GPU_indexbuf_add_line_verts(&elb_lines, v0, v3); + + if (j + 2 == gridsize) { + GPU_indexbuf_add_line_verts(&elb_lines, v2, v3); + } + grid_visible = true; + } + GPU_indexbuf_add_line_verts(&elb_lines, v1, v2); + } + + if (grid_visible) { + /* Grid corners */ + v0 = offset + gridsize - 1; + v1 = offset; + v2 = offset + grid_vert_len - 1; + v3 = offset + grid_vert_len - gridsize; + + GPU_indexbuf_add_tri_verts(&elb_fast, v0, v2, v1); + GPU_indexbuf_add_tri_verts(&elb_fast, v0, v3, v2); + + GPU_indexbuf_add_line_verts(&elb_lines_fast, v0, v1); + GPU_indexbuf_add_line_verts(&elb_lines_fast, v1, v2); + GPU_indexbuf_add_line_verts(&elb_lines_fast, v2, v3); + GPU_indexbuf_add_line_verts(&elb_lines_fast, v3, v0); + } } } else { - GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, 4 * totgrid, INT_MAX); - 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] = {0, 0, 0, 0}; + uint offset = 0; + const uint grid_vert_len = SQUARE(gridsize - 1) * 4; + for (int i = 0; i < totgrid; i++, offset += grid_vert_len) { + bool grid_visible = false; + + BLI_bitmap *gh = buffers->grid_hidden[grid_indices[i]]; + + uint v0, v1, v2, v3; 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; + /* Skip hidden grid face */ + if (gh && paint_is_grid_face_hidden( + gh, gridsize, k, j)) + { + continue; } + /* VBO data are in a Clockwise QUAD disposition. */ + v0 = offset + (j * (gridsize - 1) + k) * 4; + v1 = v0 + 1; + v2 = v0 + 2; + v3 = v0 + 3; - if (is_grid_start && is_row_start) { - grid_indices[0] = vbo_index_offset + 0; - } - if (is_grid_start && is_row_end) { - grid_indices[1] = vbo_index_offset + 2; - } - if (is_grid_end && is_row_start) { - grid_indices[2] = vbo_index_offset + 1; - } - if (is_grid_end && is_row_end) { - grid_indices[3] = vbo_index_offset + 3; - } - vbo_index_offset += 4; + GPU_indexbuf_add_tri_verts(&elb, v0, v2, v1); + GPU_indexbuf_add_tri_verts(&elb, v0, v3, v2); + + GPU_indexbuf_add_line_verts(&elb_lines, v0, v1); + GPU_indexbuf_add_line_verts(&elb_lines, v0, v3); - if (is_row_end && !(is_grid_end && is_last_grid)) { - vbo_index_offset += 1; + if (j + 2 == gridsize) { + GPU_indexbuf_add_line_verts(&elb_lines, v2, v3); } + grid_visible = true; } + GPU_indexbuf_add_line_verts(&elb_lines, v1, v2); + } + + if (grid_visible) { + /* Grid corners */ + v0 = offset; + v1 = offset + (gridsize - 1) * 4 - 3; + v2 = offset + grid_vert_len - 2; + v3 = offset + grid_vert_len - (gridsize - 1) * 4 + 3; + + GPU_indexbuf_add_tri_verts(&elb_fast, v0, v2, v1); + GPU_indexbuf_add_tri_verts(&elb_fast, v0, v3, v2); + + GPU_indexbuf_add_line_verts(&elb_lines_fast, v0, v1); + GPU_indexbuf_add_line_verts(&elb_lines_fast, v1, v2); + GPU_indexbuf_add_line_verts(&elb_lines_fast, v2, v3); + GPU_indexbuf_add_line_verts(&elb_lines_fast, v3, v0); } - 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); - - GPU_indexbuf_add_line_verts(&elb_lines, grid_indices[0], grid_indices[1]); - GPU_indexbuf_add_line_verts(&elb_lines, grid_indices[1], grid_indices[3]); - GPU_indexbuf_add_line_verts(&elb_lines, grid_indices[2], grid_indices[3]); - GPU_indexbuf_add_line_verts(&elb_lines, grid_indices[2], grid_indices[0]); } } - buffers->index_buf_fast = GPU_indexbuf_build(&elb); - buffers->index_lines_buf_fast = GPU_indexbuf_build(&elb_lines); + + buffers->index_buf = GPU_indexbuf_build(&elb); + buffers->index_buf_fast = GPU_indexbuf_build(&elb_fast); + buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines); + buffers->index_lines_buf_fast = GPU_indexbuf_build(&elb_lines_fast); } void GPU_pbvh_grid_buffers_update( @@ -449,37 +504,49 @@ void GPU_pbvh_grid_buffers_update( bool empty_mask = true; int i, j, k, x, y; - buffers->smooth = grid_flag_mats[grid_indices[0]].flag & ME_SMOOTH; + const bool smooth = true;//grid_flag_mats[grid_indices[0]].flag & ME_SMOOTH; /* Build VBO */ const int has_mask = key->has_mask; - uint vert_count = totgrid * key->grid_area; + uint vert_per_grid = (smooth) ? key->grid_area : (SQUARE(key->grid_size - 1) * 4); + uint vert_count = totgrid * vert_per_grid; + + if (buffers->smooth != smooth) { + buffers->smooth = smooth; + GPU_BATCH_DISCARD_SAFE(buffers->triangles); + GPU_BATCH_DISCARD_SAFE(buffers->triangles_fast); + GPU_BATCH_DISCARD_SAFE(buffers->lines); + GPU_BATCH_DISCARD_SAFE(buffers->lines_fast); - if (!buffers->smooth) { - vert_count = totgrid * SQUARE(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; + GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf); + GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf_fast); + GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf); + GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf_fast); } - GPU_BATCH_DISCARD_SAFE(buffers->triangles); - GPU_BATCH_DISCARD_SAFE(buffers->triangles_fast); - GPU_BATCH_DISCARD_SAFE(buffers->lines); - GPU_BATCH_DISCARD_SAFE(buffers->lines_fast); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf_fast); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf_fast); + if (buffers->index_buf == NULL) { + uint visible_quad_len = BKE_pbvh_count_grid_quads((BLI_bitmap **)buffers->grid_hidden, + grid_indices, + totgrid, + key->grid_size); - if (buffers->index_buf_fast == NULL && key->grid_size > 2) { - gpu_pbvh_grid_fill_fast_buffer(buffers, totgrid, key->grid_size); + /* totally hidden node, return here to avoid BufferData with zero below. */ + if (visible_quad_len == 0) { + return; + } + + gpu_pbvh_grid_fill_index_buffers(buffers, grid_indices, visible_quad_len, totgrid, key->grid_size); } uint vbo_index_offset = 0; /* Build VBO */ if (gpu_pbvh_vert_buf_data_set(buffers, vert_count)) { GPUIndexBufBuilder elb_lines; - GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, totgrid * key->grid_area * 2, vert_count); + + if (buffers->index_lines_buf == NULL) { + GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, totgrid * key->grid_area * 2, vert_count); + } for (i = 0; i < totgrid; ++i) { CCGElem *grid = grids[grid_indices[i]]; @@ -500,13 +567,6 @@ void GPU_pbvh_grid_buffers_update( GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.msk, vbo_index, &fmask); empty_mask = empty_mask && (fmask == 0.0f); } - - if (x + 1 < key->grid_size) { - GPU_indexbuf_add_line_verts(&elb_lines, vbo_index, vbo_index + 1); - } - if (y + 1 < key->grid_size) { - GPU_indexbuf_add_line_verts(&elb_lines, vbo_index, vbo_index + key->grid_size); - } vbo_index += 1; } } @@ -515,18 +575,11 @@ void GPU_pbvh_grid_buffers_update( 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), + CCG_grid_elem(key, grid, k + 1, j), + CCG_grid_elem(key, grid, k + 1, j + 1), + CCG_grid_elem(key, grid, k, j + 1), }; float *co[4] = { CCG_elem_co(key, elems[0]), @@ -537,65 +590,38 @@ void GPU_pbvh_grid_buffers_update( float fno[3]; short no_short[3]; - normal_quad_v3(fno, co[0], co[1], co[2], co[3]); + /* Note: Clockwise indices ordering, that's why we invert order here. */ + normal_quad_v3(fno, co[3], co[2], co[1], co[0]); 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.pos, vbo_index + 0, co[0]); + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index + 0, no_short); + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, vbo_index + 1, co[1]); 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.pos, vbo_index + 3, co[3]); GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index + 3, no_short); - GPU_indexbuf_add_line_verts(&elb_lines, vbo_index, vbo_index + 1); - GPU_indexbuf_add_line_verts(&elb_lines, vbo_index, vbo_index + 2); - if (is_row_end) { - GPU_indexbuf_add_line_verts(&elb_lines, vbo_index + 2, vbo_index + 3); - } - if (is_grid_end) { - GPU_indexbuf_add_line_verts(&elb_lines, vbo_index + 1, vbo_index + 3); - } - 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 + 0, &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 (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_size - 1) * (key->grid_size - 1) * 4; + vbo_index_offset += SQUARE(key->grid_size - 1) * 4; } } - buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines); - - gpu_pbvh_batch_init(buffers, buffers->smooth ? GPU_PRIM_TRIS : GPU_PRIM_TRI_STRIP); + gpu_pbvh_batch_init(buffers, GPU_PRIM_TRIS); } buffers->grids = grids; @@ -608,72 +634,11 @@ void GPU_pbvh_grid_buffers_update( //printf("node updated %p\n", buffers); } -/* Build the element array buffer of grid indices using either - * ushorts or uints. */ -#define FILL_QUAD_BUFFER(max_vert_, tot_quad_, buffer_) \ - { \ - int offset = 0; \ - int i, j, k; \ - \ - GPUIndexBufBuilder elb; \ - GPU_indexbuf_init( \ - &elb, GPU_PRIM_TRIS, tot_quad_ * 2, max_vert_); \ - \ - /* Fill the buffer */ \ - for (i = 0; i < totgrid; ++i) { \ - BLI_bitmap *gh = NULL; \ - if (grid_hidden) \ - gh = grid_hidden[(grid_indices)[i]]; \ - \ - for (j = 0; j < gridsize - 1; ++j) { \ - for (k = 0; k < gridsize - 1; ++k) { \ - /* Skip hidden grid face */ \ - if (gh && paint_is_grid_face_hidden( \ - gh, gridsize, k, j)) \ - { \ - continue; \ - } \ - GPU_indexbuf_add_generic_vert(&elb, offset + j * gridsize + k + 1); \ - GPU_indexbuf_add_generic_vert(&elb, offset + j * gridsize + k); \ - GPU_indexbuf_add_generic_vert(&elb, offset + (j + 1) * gridsize + k); \ - \ - GPU_indexbuf_add_generic_vert(&elb, offset + (j + 1) * gridsize + k + 1); \ - GPU_indexbuf_add_generic_vert(&elb, offset + j * gridsize + k + 1); \ - GPU_indexbuf_add_generic_vert(&elb, offset + (j + 1) * gridsize + k); \ - } \ - } \ - \ - offset += gridsize * gridsize; \ - } \ - buffer_ = GPU_indexbuf_build(&elb); \ - } (void)0 -/* end FILL_QUAD_BUFFER */ - -static GPUIndexBuf *gpu_get_grid_buffer( - int gridsize, uint *totquad, - /* remove this arg when GPU gets base-vertex support! */ - int totgrid) -{ - /* used in the FILL_QUAD_BUFFER macro */ - BLI_bitmap * const *grid_hidden = NULL; - const int *grid_indices = NULL; - - /* Build new VBO */ - *totquad = (gridsize - 1) * (gridsize - 1) * totgrid; - int max_vert = gridsize * gridsize * totgrid; - - GPUIndexBuf *mres_buffer; - FILL_QUAD_BUFFER(max_vert, *totquad, mres_buffer); - - return mres_buffer; -} - GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build( - int *grid_indices, int totgrid, BLI_bitmap **grid_hidden, int gridsize, const CCGKey *UNUSED(key)) + int totgrid, + BLI_bitmap **grid_hidden) { GPU_PBVH_Buffers *buffers; - int totquad; - int fully_visible_totquad = (gridsize - 1) * (gridsize - 1) * totgrid; buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers"); buffers->grid_hidden = grid_hidden; @@ -681,25 +646,6 @@ GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build( buffers->show_mask = false; - /* Count the number of quads */ - totquad = BKE_pbvh_count_grid_quads(grid_hidden, grid_indices, totgrid, gridsize); - - /* totally hidden node, return here to avoid BufferData with zero below. */ - if (totquad == 0) - return buffers; - - /* 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); - } - else { - uint max_vert = totgrid * gridsize * gridsize; - buffers->tot_quad = totquad; - - FILL_QUAD_BUFFER(max_vert, totquad, buffers->index_buf); - } - return buffers; } |