Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2018-09-14 13:19:41 +0300
committerClément Foucault <foucault.clem@gmail.com>2018-09-14 13:20:01 +0300
commite37479ad895c0bfb12dd0456cc520e1b73b99878 (patch)
treea33fe5ada0f3a8e2619090e4a715a51ed9915a5a /source
parent1d76fbf3df69db6939145b5a1cac7a5d6a482375 (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.c12
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c288
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);
}
}