diff options
author | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:17:24 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:21:24 +0300 |
commit | e12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 (patch) | |
tree | 8cf3453d12edb177a218ef8009357518ec6cab6a /source/blender/draw/engines/gpencil | |
parent | b3dabc200a4b0399ec6b81f2ff2730d07b44fcaa (diff) |
ClangFormat: apply to source, most of intern
Apply clang format as proposed in T53211.
For details on usage and instructions for migrating branches
without conflicts, see:
https://wiki.blender.org/wiki/Tools/ClangFormat
Diffstat (limited to 'source/blender/draw/engines/gpencil')
36 files changed, 6796 insertions, 6547 deletions
diff --git a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c index 972ada22b50..76ec0a61b8c 100644 --- a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c +++ b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c @@ -42,311 +42,317 @@ /* verify if exist a non instanced version of the object */ static bool gpencil_has_noninstanced_object(Object *ob_instance) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - const ViewLayer *view_layer = draw_ctx->view_layer; - Object *ob = NULL; - for (Base *base = view_layer->object_bases.first; base; base = base->next) { - ob = base->object; - if (ob->type != OB_GPENCIL) { - continue; - } - /* object must be visible (invisible objects don't create VBO data) */ - if (!(DRW_object_visibility_in_active_context(ob) & OB_VISIBLE_SELF)) { - continue; - } - /* is not duplicated and the name is equals */ - if ((ob->base_flag & BASE_FROM_DUPLI) == 0) { - if (STREQ(ob->id.name, ob_instance->id.name)) { - return true; - } - } - } - - return false; + const DRWContextState *draw_ctx = DRW_context_state_get(); + const ViewLayer *view_layer = draw_ctx->view_layer; + Object *ob = NULL; + for (Base *base = view_layer->object_bases.first; base; base = base->next) { + ob = base->object; + if (ob->type != OB_GPENCIL) { + continue; + } + /* object must be visible (invisible objects don't create VBO data) */ + if (!(DRW_object_visibility_in_active_context(ob) & OB_VISIBLE_SELF)) { + continue; + } + /* is not duplicated and the name is equals */ + if ((ob->base_flag & BASE_FROM_DUPLI) == 0) { + if (STREQ(ob->id.name, ob_instance->id.name)) { + return true; + } + } + } + + return false; } /* add a gpencil object to cache to defer drawing */ -tGPencilObjectCache *gpencil_object_cache_add( - tGPencilObjectCache *cache_array, Object *ob, - int *gp_cache_size, int *gp_cache_used) +tGPencilObjectCache *gpencil_object_cache_add(tGPencilObjectCache *cache_array, + Object *ob, + int *gp_cache_size, + int *gp_cache_used) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - tGPencilObjectCache *cache_elem = NULL; - RegionView3D *rv3d = draw_ctx->rv3d; - View3D *v3d = draw_ctx->v3d; - tGPencilObjectCache *p = NULL; - - /* By default a cache is created with one block with a predefined number of free slots, - if the size is not enough, the cache is reallocated adding a new block of free slots. - This is done in order to keep cache small */ - if (*gp_cache_used + 1 > *gp_cache_size) { - if ((*gp_cache_size == 0) || (cache_array == NULL)) { - p = MEM_callocN(sizeof(struct tGPencilObjectCache) * GP_CACHE_BLOCK_SIZE, "tGPencilObjectCache"); - *gp_cache_size = GP_CACHE_BLOCK_SIZE; - } - else { - *gp_cache_size += GP_CACHE_BLOCK_SIZE; - p = MEM_recallocN(cache_array, sizeof(struct tGPencilObjectCache) * *gp_cache_size); - } - cache_array = p; - } - /* zero out all pointers */ - cache_elem = &cache_array[*gp_cache_used]; - memset(cache_elem, 0, sizeof(*cache_elem)); - - cache_elem->ob = ob; - cache_elem->gpd = (bGPdata *)ob->data; - cache_elem->name = BKE_id_to_unique_string_key(&ob->id); - - copy_v3_v3(cache_elem->loc, ob->obmat[3]); - copy_m4_m4(cache_elem->obmat, ob->obmat); - cache_elem->idx = *gp_cache_used; - - /* object is duplicated (particle) */ - if (ob->base_flag & BASE_FROM_DUPLI) { - /* Check if the original object is not in the viewlayer - * and cannot be managed as dupli. This is slower, but required to keep - * the particle drawing FPS and display instanced objects in scene - * without the original object */ - bool has_original = gpencil_has_noninstanced_object(ob); - cache_elem->is_dup_ob = (has_original) ? ob->base_flag & BASE_FROM_DUPLI : false; - } - else { - cache_elem->is_dup_ob = false; - } - - cache_elem->scale = mat4_to_scale(ob->obmat); - - /* save FXs */ - cache_elem->pixfactor = cache_elem->gpd->pixfactor; - cache_elem->shader_fx = ob->shader_fx; - - /* save wire mode (object mode is always primary option) */ - if (ob->dt == OB_WIRE) { - cache_elem->shading_type[0] = (int)OB_WIRE; - } - else { - if (v3d) { - cache_elem->shading_type[0] = (int)v3d->shading.type; - } - } - - /* shgrp array */ - cache_elem->tot_layers = 0; - int totgpl = BLI_listbase_count(&cache_elem->gpd->layers); - if (totgpl > 0) { - cache_elem->shgrp_array = MEM_callocN(sizeof(tGPencilObjectCache_shgrp) * totgpl, __func__); - } - - /* calculate zdepth from point of view */ - float zdepth = 0.0; - if (rv3d) { - if (rv3d->is_persp) { - zdepth = ED_view3d_calc_zfac(rv3d, ob->obmat[3], NULL); - } - else { - zdepth = -dot_v3v3(rv3d->viewinv[2], ob->obmat[3]); - } - } - else { - /* In render mode, rv3d is not available, so use the distance to camera. - * The real distance is not important, but the relative distance to the camera plane - * in order to sort by z_depth of the objects - */ - float vn[3] = { 0.0f, 0.0f, -1.0f }; /* always face down */ - float plane_cam[4]; - struct Object *camera = draw_ctx->scene->camera; - if (camera) { - mul_m4_v3(camera->obmat, vn); - normalize_v3(vn); - plane_from_point_normal_v3(plane_cam, camera->loc, vn); - zdepth = dist_squared_to_plane_v3(ob->obmat[3], plane_cam); - } - } - cache_elem->zdepth = zdepth; - /* increase slots used in cache */ - (*gp_cache_used)++; - - return cache_array; + const DRWContextState *draw_ctx = DRW_context_state_get(); + tGPencilObjectCache *cache_elem = NULL; + RegionView3D *rv3d = draw_ctx->rv3d; + View3D *v3d = draw_ctx->v3d; + tGPencilObjectCache *p = NULL; + + /* By default a cache is created with one block with a predefined number of free slots, + if the size is not enough, the cache is reallocated adding a new block of free slots. + This is done in order to keep cache small */ + if (*gp_cache_used + 1 > *gp_cache_size) { + if ((*gp_cache_size == 0) || (cache_array == NULL)) { + p = MEM_callocN(sizeof(struct tGPencilObjectCache) * GP_CACHE_BLOCK_SIZE, + "tGPencilObjectCache"); + *gp_cache_size = GP_CACHE_BLOCK_SIZE; + } + else { + *gp_cache_size += GP_CACHE_BLOCK_SIZE; + p = MEM_recallocN(cache_array, sizeof(struct tGPencilObjectCache) * *gp_cache_size); + } + cache_array = p; + } + /* zero out all pointers */ + cache_elem = &cache_array[*gp_cache_used]; + memset(cache_elem, 0, sizeof(*cache_elem)); + + cache_elem->ob = ob; + cache_elem->gpd = (bGPdata *)ob->data; + cache_elem->name = BKE_id_to_unique_string_key(&ob->id); + + copy_v3_v3(cache_elem->loc, ob->obmat[3]); + copy_m4_m4(cache_elem->obmat, ob->obmat); + cache_elem->idx = *gp_cache_used; + + /* object is duplicated (particle) */ + if (ob->base_flag & BASE_FROM_DUPLI) { + /* Check if the original object is not in the viewlayer + * and cannot be managed as dupli. This is slower, but required to keep + * the particle drawing FPS and display instanced objects in scene + * without the original object */ + bool has_original = gpencil_has_noninstanced_object(ob); + cache_elem->is_dup_ob = (has_original) ? ob->base_flag & BASE_FROM_DUPLI : false; + } + else { + cache_elem->is_dup_ob = false; + } + + cache_elem->scale = mat4_to_scale(ob->obmat); + + /* save FXs */ + cache_elem->pixfactor = cache_elem->gpd->pixfactor; + cache_elem->shader_fx = ob->shader_fx; + + /* save wire mode (object mode is always primary option) */ + if (ob->dt == OB_WIRE) { + cache_elem->shading_type[0] = (int)OB_WIRE; + } + else { + if (v3d) { + cache_elem->shading_type[0] = (int)v3d->shading.type; + } + } + + /* shgrp array */ + cache_elem->tot_layers = 0; + int totgpl = BLI_listbase_count(&cache_elem->gpd->layers); + if (totgpl > 0) { + cache_elem->shgrp_array = MEM_callocN(sizeof(tGPencilObjectCache_shgrp) * totgpl, __func__); + } + + /* calculate zdepth from point of view */ + float zdepth = 0.0; + if (rv3d) { + if (rv3d->is_persp) { + zdepth = ED_view3d_calc_zfac(rv3d, ob->obmat[3], NULL); + } + else { + zdepth = -dot_v3v3(rv3d->viewinv[2], ob->obmat[3]); + } + } + else { + /* In render mode, rv3d is not available, so use the distance to camera. + * The real distance is not important, but the relative distance to the camera plane + * in order to sort by z_depth of the objects + */ + float vn[3] = {0.0f, 0.0f, -1.0f}; /* always face down */ + float plane_cam[4]; + struct Object *camera = draw_ctx->scene->camera; + if (camera) { + mul_m4_v3(camera->obmat, vn); + normalize_v3(vn); + plane_from_point_normal_v3(plane_cam, camera->loc, vn); + zdepth = dist_squared_to_plane_v3(ob->obmat[3], plane_cam); + } + } + cache_elem->zdepth = zdepth; + /* increase slots used in cache */ + (*gp_cache_used)++; + + return cache_array; } /* add a shading group to the cache to create later */ -GpencilBatchGroup *gpencil_group_cache_add( - GpencilBatchGroup *cache_array, - bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *gps, - const short type, const bool onion, - const int vertex_idx, - int *grp_size, int *grp_used) +GpencilBatchGroup *gpencil_group_cache_add(GpencilBatchGroup *cache_array, + bGPDlayer *gpl, + bGPDframe *gpf, + bGPDstroke *gps, + const short type, + const bool onion, + const int vertex_idx, + int *grp_size, + int *grp_used) { - GpencilBatchGroup *cache_elem = NULL; - GpencilBatchGroup *p = NULL; - - /* By default a cache is created with one block with a predefined number of free slots, - if the size is not enough, the cache is reallocated adding a new block of free slots. - This is done in order to keep cache small */ - if (*grp_used + 1 > *grp_size) { - if ((*grp_size == 0) || (cache_array == NULL)) { - p = MEM_callocN(sizeof(struct GpencilBatchGroup) * GPENCIL_GROUPS_BLOCK_SIZE, "GpencilBatchGroup"); - *grp_size = GPENCIL_GROUPS_BLOCK_SIZE; - } - else { - *grp_size += GPENCIL_GROUPS_BLOCK_SIZE; - p = MEM_recallocN(cache_array, sizeof(struct GpencilBatchGroup) * *grp_size); - } - cache_array = p; - } - /* zero out all data */ - cache_elem = &cache_array[*grp_used]; - memset(cache_elem, 0, sizeof(*cache_elem)); - - cache_elem->gpl = gpl; - cache_elem->gpf = gpf; - cache_elem->gps = gps; - cache_elem->type = type; - cache_elem->onion = onion; - cache_elem->vertex_idx = vertex_idx; - - /* increase slots used in cache */ - (*grp_used)++; - - return cache_array; + GpencilBatchGroup *cache_elem = NULL; + GpencilBatchGroup *p = NULL; + + /* By default a cache is created with one block with a predefined number of free slots, + if the size is not enough, the cache is reallocated adding a new block of free slots. + This is done in order to keep cache small */ + if (*grp_used + 1 > *grp_size) { + if ((*grp_size == 0) || (cache_array == NULL)) { + p = MEM_callocN(sizeof(struct GpencilBatchGroup) * GPENCIL_GROUPS_BLOCK_SIZE, + "GpencilBatchGroup"); + *grp_size = GPENCIL_GROUPS_BLOCK_SIZE; + } + else { + *grp_size += GPENCIL_GROUPS_BLOCK_SIZE; + p = MEM_recallocN(cache_array, sizeof(struct GpencilBatchGroup) * *grp_size); + } + cache_array = p; + } + /* zero out all data */ + cache_elem = &cache_array[*grp_used]; + memset(cache_elem, 0, sizeof(*cache_elem)); + + cache_elem->gpl = gpl; + cache_elem->gpf = gpf; + cache_elem->gps = gps; + cache_elem->type = type; + cache_elem->onion = onion; + cache_elem->vertex_idx = vertex_idx; + + /* increase slots used in cache */ + (*grp_used)++; + + return cache_array; } /* get current cache data */ static GpencilBatchCache *gpencil_batch_get_element(Object *ob) { - return ob->runtime.gpencil_cache; + return ob->runtime.gpencil_cache; } /* verify if cache is valid */ static bool gpencil_batch_cache_valid(GpencilBatchCache *cache, bGPdata *gpd, int cfra) { - bool valid = true; - if (cache == NULL) { - return false; - } - - cache->is_editmode = GPENCIL_ANY_EDIT_MODE(gpd); - if (cfra != cache->cache_frame) { - valid = false; - } - else if (gpd->flag & GP_DATA_CACHE_IS_DIRTY) { - valid = false; - } - else if (gpd->flag & GP_DATA_PYTHON_UPDATED) { - gpd->flag &= ~GP_DATA_PYTHON_UPDATED; - valid = false; - } - else if (cache->is_editmode) { - valid = false; - } - else if (cache->is_dirty) { - valid = false; - } - - return valid; + bool valid = true; + if (cache == NULL) { + return false; + } + + cache->is_editmode = GPENCIL_ANY_EDIT_MODE(gpd); + if (cfra != cache->cache_frame) { + valid = false; + } + else if (gpd->flag & GP_DATA_CACHE_IS_DIRTY) { + valid = false; + } + else if (gpd->flag & GP_DATA_PYTHON_UPDATED) { + gpd->flag &= ~GP_DATA_PYTHON_UPDATED; + valid = false; + } + else if (cache->is_editmode) { + valid = false; + } + else if (cache->is_dirty) { + valid = false; + } + + return valid; } /* cache init */ static GpencilBatchCache *gpencil_batch_cache_init(Object *ob, int cfra) { - bGPdata *gpd = (bGPdata *)ob->data; + bGPdata *gpd = (bGPdata *)ob->data; - GpencilBatchCache *cache = gpencil_batch_get_element(ob); + GpencilBatchCache *cache = gpencil_batch_get_element(ob); - if (!cache) { - cache = MEM_callocN(sizeof(*cache), __func__); - ob->runtime.gpencil_cache = cache; - } - else { - memset(cache, 0, sizeof(*cache)); - } + if (!cache) { + cache = MEM_callocN(sizeof(*cache), __func__); + ob->runtime.gpencil_cache = cache; + } + else { + memset(cache, 0, sizeof(*cache)); + } - cache->is_editmode = GPENCIL_ANY_EDIT_MODE(gpd); + cache->is_editmode = GPENCIL_ANY_EDIT_MODE(gpd); - cache->is_dirty = true; + cache->is_dirty = true; - cache->cache_frame = cfra; + cache->cache_frame = cfra; - /* create array of derived frames equal to number of layers */ - cache->tot_layers = BLI_listbase_count(&gpd->layers); - CLAMP_MIN(cache->tot_layers, 1); - cache->derived_array = MEM_callocN(sizeof(struct bGPDframe) * cache->tot_layers, "Derived GPF"); + /* create array of derived frames equal to number of layers */ + cache->tot_layers = BLI_listbase_count(&gpd->layers); + CLAMP_MIN(cache->tot_layers, 1); + cache->derived_array = MEM_callocN(sizeof(struct bGPDframe) * cache->tot_layers, "Derived GPF"); - return cache; + return cache; } /* clear cache */ static void gpencil_batch_cache_clear(GpencilBatchCache *cache) { - if (!cache) { - return; - } - - GPU_BATCH_DISCARD_SAFE(cache->b_stroke.batch); - GPU_BATCH_DISCARD_SAFE(cache->b_point.batch); - GPU_BATCH_DISCARD_SAFE(cache->b_fill.batch); - GPU_BATCH_DISCARD_SAFE(cache->b_edit.batch); - GPU_BATCH_DISCARD_SAFE(cache->b_edlin.batch); - - MEM_SAFE_FREE(cache->b_stroke.batch); - MEM_SAFE_FREE(cache->b_point.batch); - MEM_SAFE_FREE(cache->b_fill.batch); - MEM_SAFE_FREE(cache->b_edit.batch); - MEM_SAFE_FREE(cache->b_edlin.batch); - - MEM_SAFE_FREE(cache->grp_cache); - cache->grp_size = 0; - cache->grp_used = 0; - - /* clear all frames derived data */ - for (int i = 0; i < cache->tot_layers; i++) { - bGPDframe *derived_gpf = &cache->derived_array[i]; - BKE_gpencil_free_frame_runtime_data(derived_gpf); - derived_gpf = NULL; - } - cache->tot_layers = 0; - MEM_SAFE_FREE(cache->derived_array); + if (!cache) { + return; + } + + GPU_BATCH_DISCARD_SAFE(cache->b_stroke.batch); + GPU_BATCH_DISCARD_SAFE(cache->b_point.batch); + GPU_BATCH_DISCARD_SAFE(cache->b_fill.batch); + GPU_BATCH_DISCARD_SAFE(cache->b_edit.batch); + GPU_BATCH_DISCARD_SAFE(cache->b_edlin.batch); + + MEM_SAFE_FREE(cache->b_stroke.batch); + MEM_SAFE_FREE(cache->b_point.batch); + MEM_SAFE_FREE(cache->b_fill.batch); + MEM_SAFE_FREE(cache->b_edit.batch); + MEM_SAFE_FREE(cache->b_edlin.batch); + + MEM_SAFE_FREE(cache->grp_cache); + cache->grp_size = 0; + cache->grp_used = 0; + + /* clear all frames derived data */ + for (int i = 0; i < cache->tot_layers; i++) { + bGPDframe *derived_gpf = &cache->derived_array[i]; + BKE_gpencil_free_frame_runtime_data(derived_gpf); + derived_gpf = NULL; + } + cache->tot_layers = 0; + MEM_SAFE_FREE(cache->derived_array); } /* get cache */ GpencilBatchCache *gpencil_batch_cache_get(Object *ob, int cfra) { - bGPdata *gpd = (bGPdata *)ob->data; - - GpencilBatchCache *cache = gpencil_batch_get_element(ob); - if (!gpencil_batch_cache_valid(cache, gpd, cfra)) { - if (cache) { - gpencil_batch_cache_clear(cache); - } - return gpencil_batch_cache_init(ob, cfra); - } - else { - return cache; - } + bGPdata *gpd = (bGPdata *)ob->data; + + GpencilBatchCache *cache = gpencil_batch_get_element(ob); + if (!gpencil_batch_cache_valid(cache, gpd, cfra)) { + if (cache) { + gpencil_batch_cache_clear(cache); + } + return gpencil_batch_cache_init(ob, cfra); + } + else { + return cache; + } } /* set cache as dirty */ void DRW_gpencil_batch_cache_dirty_tag(bGPdata *gpd) { - gpd->flag |= GP_DATA_CACHE_IS_DIRTY; + gpd->flag |= GP_DATA_CACHE_IS_DIRTY; } /* free batch cache */ void DRW_gpencil_batch_cache_free(bGPdata *UNUSED(gpd)) { - return; + return; } /* wrapper to clear cache */ void DRW_gpencil_freecache(struct Object *ob) { - if ((ob) && (ob->type == OB_GPENCIL)) { - gpencil_batch_cache_clear(ob->runtime.gpencil_cache); - MEM_SAFE_FREE(ob->runtime.gpencil_cache); - bGPdata *gpd = (bGPdata *)ob->data; - if (gpd) { - gpd->flag |= GP_DATA_CACHE_IS_DIRTY; - } - } + if ((ob) && (ob->type == OB_GPENCIL)) { + gpencil_batch_cache_clear(ob->runtime.gpencil_cache); + MEM_SAFE_FREE(ob->runtime.gpencil_cache); + bGPdata *gpd = (bGPdata *)ob->data; + if (gpd) { + gpd->flag |= GP_DATA_CACHE_IS_DIRTY; + } + } } diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c b/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c index 3bcc963c966..9e71791fbf3 100644 --- a/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c +++ b/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c @@ -34,7 +34,6 @@ #include "DRW_render.h" - #include "ED_gpencil.h" #include "ED_view3d.h" @@ -43,776 +42,873 @@ #include "gpencil_engine.h" /* Helper to add stroke point to vbo */ -static void gpencil_set_stroke_point( - GPUVertBuf *vbo, const bGPDspoint *pt, int idx, - uint pos_id, uint color_id, - uint thickness_id, uint uvdata_id, short thickness, - const float ink[4]) +static void gpencil_set_stroke_point(GPUVertBuf *vbo, + const bGPDspoint *pt, + int idx, + uint pos_id, + uint color_id, + uint thickness_id, + uint uvdata_id, + short thickness, + const float ink[4]) { - float alpha = ink[3] * pt->strength; - CLAMP(alpha, GPENCIL_STRENGTH_MIN, 1.0f); - float col[4]; - ARRAY_SET_ITEMS(col, ink[0], ink[1], ink[2], alpha); + float alpha = ink[3] * pt->strength; + CLAMP(alpha, GPENCIL_STRENGTH_MIN, 1.0f); + float col[4]; + ARRAY_SET_ITEMS(col, ink[0], ink[1], ink[2], alpha); - GPU_vertbuf_attr_set(vbo, color_id, idx, col); + GPU_vertbuf_attr_set(vbo, color_id, idx, col); - /* transfer both values using the same shader variable */ - float uvdata[2] = { pt->uv_fac, pt->uv_rot }; - GPU_vertbuf_attr_set(vbo, uvdata_id, idx, uvdata); + /* transfer both values using the same shader variable */ + float uvdata[2] = {pt->uv_fac, pt->uv_rot}; + GPU_vertbuf_attr_set(vbo, uvdata_id, idx, uvdata); - /* the thickness of the stroke must be affected by zoom, so a pixel scale is calculated */ - float thick = max_ff(pt->pressure * thickness, 1.0f); - GPU_vertbuf_attr_set(vbo, thickness_id, idx, &thick); + /* the thickness of the stroke must be affected by zoom, so a pixel scale is calculated */ + float thick = max_ff(pt->pressure * thickness, 1.0f); + GPU_vertbuf_attr_set(vbo, thickness_id, idx, &thick); - GPU_vertbuf_attr_set(vbo, pos_id, idx, &pt->x); + GPU_vertbuf_attr_set(vbo, pos_id, idx, &pt->x); } /* Helper to add a new fill point and texture coordinates to vertex buffer */ -static void gpencil_set_fill_point( - GPUVertBuf *vbo, int idx, bGPDspoint *pt, const float fcolor[4], float uv[2], - uint pos_id, uint color_id, uint text_id) +static void gpencil_set_fill_point(GPUVertBuf *vbo, + int idx, + bGPDspoint *pt, + const float fcolor[4], + float uv[2], + uint pos_id, + uint color_id, + uint text_id) { - GPU_vertbuf_attr_set(vbo, pos_id, idx, &pt->x); - GPU_vertbuf_attr_set(vbo, color_id, idx, fcolor); - GPU_vertbuf_attr_set(vbo, text_id, idx, uv); + GPU_vertbuf_attr_set(vbo, pos_id, idx, &pt->x); + GPU_vertbuf_attr_set(vbo, color_id, idx, fcolor); + GPU_vertbuf_attr_set(vbo, text_id, idx, uv); } static void gpencil_vbo_ensure_size(GpencilBatchCacheElem *be, int totvertex) { - if (be->vbo->vertex_alloc <= be->vbo_len + totvertex) { - uint newsize = be->vbo->vertex_alloc + (((totvertex / GPENCIL_VBO_BLOCK_SIZE) + 1) * GPENCIL_VBO_BLOCK_SIZE); - GPU_vertbuf_data_resize(be->vbo, newsize); - } + if (be->vbo->vertex_alloc <= be->vbo_len + totvertex) { + uint newsize = be->vbo->vertex_alloc + + (((totvertex / GPENCIL_VBO_BLOCK_SIZE) + 1) * GPENCIL_VBO_BLOCK_SIZE); + GPU_vertbuf_data_resize(be->vbo, newsize); + } } /* create batch geometry data for points stroke shader */ -void DRW_gpencil_get_point_geom(GpencilBatchCacheElem *be, bGPDstroke *gps, short thickness, const float ink[4]) +void DRW_gpencil_get_point_geom(GpencilBatchCacheElem *be, + bGPDstroke *gps, + short thickness, + const float ink[4]) { - int totvertex = gps->totpoints; - if (be->vbo == NULL) { - be->pos_id = GPU_vertformat_attr_add(&be->format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - be->color_id = GPU_vertformat_attr_add(&be->format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - be->thickness_id = GPU_vertformat_attr_add(&be->format, "thickness", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); - be->uvdata_id = GPU_vertformat_attr_add(&be->format, "uvdata", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - be->prev_pos_id = GPU_vertformat_attr_add(&be->format, "prev_pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - - be->vbo = GPU_vertbuf_create_with_format(&be->format); - GPU_vertbuf_data_alloc(be->vbo, be->tot_vertex); - be->vbo_len = 0; - } - gpencil_vbo_ensure_size(be, totvertex); - - /* draw stroke curve */ - const bGPDspoint *pt = gps->points; - float alpha; - float col[4]; - - for (int i = 0; i < gps->totpoints; i++, pt++) { - /* set point */ - alpha = ink[3] * pt->strength; - CLAMP(alpha, GPENCIL_STRENGTH_MIN, 1.0f); - ARRAY_SET_ITEMS(col, ink[0], ink[1], ink[2], alpha); - - float thick = max_ff(pt->pressure * thickness, 1.0f); - - GPU_vertbuf_attr_set(be->vbo, be->color_id, be->vbo_len, col); - GPU_vertbuf_attr_set(be->vbo, be->thickness_id, be->vbo_len, &thick); - - /* transfer both values using the same shader variable */ - float uvdata[2] = { pt->uv_fac, pt->uv_rot }; - GPU_vertbuf_attr_set(be->vbo, be->uvdata_id, be->vbo_len, uvdata); - - GPU_vertbuf_attr_set(be->vbo, be->pos_id, be->vbo_len, &pt->x); - - /* use previous point to determine stroke direction */ - bGPDspoint *pt2 = NULL; - if (i == 0) { - if (gps->totpoints > 1) { - /* extrapolate a point before first point */ - float fpt[3]; - pt2 = &gps->points[1]; - interp_v3_v3v3(fpt, &pt2->x, &pt->x, 1.5f); - GPU_vertbuf_attr_set(be->vbo, be->prev_pos_id, be->vbo_len, fpt); - } - else { - GPU_vertbuf_attr_set(be->vbo, be->prev_pos_id, be->vbo_len, &pt->x); - } - } - else { - pt2 = &gps->points[i - 1]; - GPU_vertbuf_attr_set(be->vbo, be->prev_pos_id, be->vbo_len, &pt2->x); - } - - be->vbo_len++; - } + int totvertex = gps->totpoints; + if (be->vbo == NULL) { + be->pos_id = GPU_vertformat_attr_add(&be->format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + be->color_id = GPU_vertformat_attr_add(&be->format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); + be->thickness_id = GPU_vertformat_attr_add( + &be->format, "thickness", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); + be->uvdata_id = GPU_vertformat_attr_add( + &be->format, "uvdata", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + be->prev_pos_id = GPU_vertformat_attr_add( + &be->format, "prev_pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + + be->vbo = GPU_vertbuf_create_with_format(&be->format); + GPU_vertbuf_data_alloc(be->vbo, be->tot_vertex); + be->vbo_len = 0; + } + gpencil_vbo_ensure_size(be, totvertex); + + /* draw stroke curve */ + const bGPDspoint *pt = gps->points; + float alpha; + float col[4]; + + for (int i = 0; i < gps->totpoints; i++, pt++) { + /* set point */ + alpha = ink[3] * pt->strength; + CLAMP(alpha, GPENCIL_STRENGTH_MIN, 1.0f); + ARRAY_SET_ITEMS(col, ink[0], ink[1], ink[2], alpha); + + float thick = max_ff(pt->pressure * thickness, 1.0f); + + GPU_vertbuf_attr_set(be->vbo, be->color_id, be->vbo_len, col); + GPU_vertbuf_attr_set(be->vbo, be->thickness_id, be->vbo_len, &thick); + + /* transfer both values using the same shader variable */ + float uvdata[2] = {pt->uv_fac, pt->uv_rot}; + GPU_vertbuf_attr_set(be->vbo, be->uvdata_id, be->vbo_len, uvdata); + + GPU_vertbuf_attr_set(be->vbo, be->pos_id, be->vbo_len, &pt->x); + + /* use previous point to determine stroke direction */ + bGPDspoint *pt2 = NULL; + if (i == 0) { + if (gps->totpoints > 1) { + /* extrapolate a point before first point */ + float fpt[3]; + pt2 = &gps->points[1]; + interp_v3_v3v3(fpt, &pt2->x, &pt->x, 1.5f); + GPU_vertbuf_attr_set(be->vbo, be->prev_pos_id, be->vbo_len, fpt); + } + else { + GPU_vertbuf_attr_set(be->vbo, be->prev_pos_id, be->vbo_len, &pt->x); + } + } + else { + pt2 = &gps->points[i - 1]; + GPU_vertbuf_attr_set(be->vbo, be->prev_pos_id, be->vbo_len, &pt2->x); + } + + be->vbo_len++; + } } /* create batch geometry data for stroke shader */ -void DRW_gpencil_get_stroke_geom(struct GpencilBatchCacheElem *be, bGPDstroke *gps, short thickness, const float ink[4]) +void DRW_gpencil_get_stroke_geom(struct GpencilBatchCacheElem *be, + bGPDstroke *gps, + short thickness, + const float ink[4]) { - bGPDspoint *points = gps->points; - int totpoints = gps->totpoints; - /* if cyclic needs more vertex */ - int cyclic_add = (gps->flag & GP_STROKE_CYCLIC) ? 1 : 0; - int totvertex = totpoints + cyclic_add + 2; - - if (be->vbo == NULL) { - be->pos_id = GPU_vertformat_attr_add(&be->format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - be->color_id = GPU_vertformat_attr_add(&be->format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - be->thickness_id = GPU_vertformat_attr_add(&be->format, "thickness", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); - be->uvdata_id = GPU_vertformat_attr_add(&be->format, "uvdata", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - - be->vbo = GPU_vertbuf_create_with_format(&be->format); - GPU_vertbuf_data_alloc(be->vbo, be->tot_vertex); - be->vbo_len = 0; - } - gpencil_vbo_ensure_size(be, totvertex); - - /* draw stroke curve */ - const bGPDspoint *pt = points; - for (int i = 0; i < totpoints; i++, pt++) { - /* first point for adjacency (not drawn) */ - if (i == 0) { - if (gps->flag & GP_STROKE_CYCLIC && totpoints > 2) { - gpencil_set_stroke_point( - be->vbo, &points[totpoints - 1], be->vbo_len, - be->pos_id, be->color_id, be->thickness_id, be->uvdata_id, thickness, ink); - be->vbo_len++; - } - else { - gpencil_set_stroke_point( - be->vbo, &points[1], be->vbo_len, - be->pos_id, be->color_id, be->thickness_id, be->uvdata_id, thickness, ink); - be->vbo_len++; - } - } - /* set point */ - gpencil_set_stroke_point( - be->vbo, pt, be->vbo_len, - be->pos_id, be->color_id, be->thickness_id, be->uvdata_id, thickness, ink); - be->vbo_len++; - } - - if (gps->flag & GP_STROKE_CYCLIC && totpoints > 2) { - /* draw line to first point to complete the cycle */ - gpencil_set_stroke_point( - be->vbo, &points[0], be->vbo_len, - be->pos_id, be->color_id, be->thickness_id, be->uvdata_id, thickness, ink); - be->vbo_len++; - /* now add adjacency point (not drawn) */ - gpencil_set_stroke_point( - be->vbo, &points[1], be->vbo_len, - be->pos_id, be->color_id, be->thickness_id, be->uvdata_id, thickness, ink); - be->vbo_len++; - } - /* last adjacency point (not drawn) */ - else { - gpencil_set_stroke_point( - be->vbo, &points[totpoints - 2], be->vbo_len, - be->pos_id, be->color_id, be->thickness_id, be->uvdata_id, thickness, ink); - be->vbo_len++; - } + bGPDspoint *points = gps->points; + int totpoints = gps->totpoints; + /* if cyclic needs more vertex */ + int cyclic_add = (gps->flag & GP_STROKE_CYCLIC) ? 1 : 0; + int totvertex = totpoints + cyclic_add + 2; + + if (be->vbo == NULL) { + be->pos_id = GPU_vertformat_attr_add(&be->format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + be->color_id = GPU_vertformat_attr_add(&be->format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); + be->thickness_id = GPU_vertformat_attr_add( + &be->format, "thickness", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); + be->uvdata_id = GPU_vertformat_attr_add( + &be->format, "uvdata", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + + be->vbo = GPU_vertbuf_create_with_format(&be->format); + GPU_vertbuf_data_alloc(be->vbo, be->tot_vertex); + be->vbo_len = 0; + } + gpencil_vbo_ensure_size(be, totvertex); + + /* draw stroke curve */ + const bGPDspoint *pt = points; + for (int i = 0; i < totpoints; i++, pt++) { + /* first point for adjacency (not drawn) */ + if (i == 0) { + if (gps->flag & GP_STROKE_CYCLIC && totpoints > 2) { + gpencil_set_stroke_point(be->vbo, + &points[totpoints - 1], + be->vbo_len, + be->pos_id, + be->color_id, + be->thickness_id, + be->uvdata_id, + thickness, + ink); + be->vbo_len++; + } + else { + gpencil_set_stroke_point(be->vbo, + &points[1], + be->vbo_len, + be->pos_id, + be->color_id, + be->thickness_id, + be->uvdata_id, + thickness, + ink); + be->vbo_len++; + } + } + /* set point */ + gpencil_set_stroke_point(be->vbo, + pt, + be->vbo_len, + be->pos_id, + be->color_id, + be->thickness_id, + be->uvdata_id, + thickness, + ink); + be->vbo_len++; + } + + if (gps->flag & GP_STROKE_CYCLIC && totpoints > 2) { + /* draw line to first point to complete the cycle */ + gpencil_set_stroke_point(be->vbo, + &points[0], + be->vbo_len, + be->pos_id, + be->color_id, + be->thickness_id, + be->uvdata_id, + thickness, + ink); + be->vbo_len++; + /* now add adjacency point (not drawn) */ + gpencil_set_stroke_point(be->vbo, + &points[1], + be->vbo_len, + be->pos_id, + be->color_id, + be->thickness_id, + be->uvdata_id, + thickness, + ink); + be->vbo_len++; + } + /* last adjacency point (not drawn) */ + else { + gpencil_set_stroke_point(be->vbo, + &points[totpoints - 2], + be->vbo_len, + be->pos_id, + be->color_id, + be->thickness_id, + be->uvdata_id, + thickness, + ink); + be->vbo_len++; + } } /* create batch geometry data for stroke shader */ -void DRW_gpencil_get_fill_geom(struct GpencilBatchCacheElem *be, Object *ob, bGPDstroke *gps, const float color[4]) +void DRW_gpencil_get_fill_geom(struct GpencilBatchCacheElem *be, + Object *ob, + bGPDstroke *gps, + const float color[4]) { - BLI_assert(gps->totpoints >= 3); - - /* Calculate triangles cache for filling area (must be done only after changes) */ - if ((gps->flag & GP_STROKE_RECALC_GEOMETRY) || (gps->tot_triangles == 0) || (gps->triangles == NULL)) { - DRW_gpencil_triangulate_stroke_fill(ob, gps); - } - - BLI_assert(gps->tot_triangles >= 1); - int totvertex = gps->tot_triangles * 3; - - if (be->vbo == NULL) { - be->pos_id = GPU_vertformat_attr_add(&be->format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - be->color_id = GPU_vertformat_attr_add(&be->format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - be->uvdata_id = GPU_vertformat_attr_add(&be->format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - - be->vbo = GPU_vertbuf_create_with_format(&be->format); - GPU_vertbuf_data_alloc(be->vbo, be->tot_vertex); - be->vbo_len = 0; - } - gpencil_vbo_ensure_size(be, totvertex); - - /* Draw all triangles for filling the polygon (cache must be calculated before) */ - bGPDtriangle *stroke_triangle = gps->triangles; - for (int i = 0; i < gps->tot_triangles; i++, stroke_triangle++) { - for (int j = 0; j < 3; j++) { - gpencil_set_fill_point( - be->vbo, be->vbo_len, &gps->points[stroke_triangle->verts[j]], color, stroke_triangle->uv[j], - be->pos_id, be->color_id, be->uvdata_id); - be->vbo_len++; - } - } + BLI_assert(gps->totpoints >= 3); + + /* Calculate triangles cache for filling area (must be done only after changes) */ + if ((gps->flag & GP_STROKE_RECALC_GEOMETRY) || (gps->tot_triangles == 0) || + (gps->triangles == NULL)) { + DRW_gpencil_triangulate_stroke_fill(ob, gps); + } + + BLI_assert(gps->tot_triangles >= 1); + int totvertex = gps->tot_triangles * 3; + + if (be->vbo == NULL) { + be->pos_id = GPU_vertformat_attr_add(&be->format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + be->color_id = GPU_vertformat_attr_add(&be->format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); + be->uvdata_id = GPU_vertformat_attr_add( + &be->format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + + be->vbo = GPU_vertbuf_create_with_format(&be->format); + GPU_vertbuf_data_alloc(be->vbo, be->tot_vertex); + be->vbo_len = 0; + } + gpencil_vbo_ensure_size(be, totvertex); + + /* Draw all triangles for filling the polygon (cache must be calculated before) */ + bGPDtriangle *stroke_triangle = gps->triangles; + for (int i = 0; i < gps->tot_triangles; i++, stroke_triangle++) { + for (int j = 0; j < 3; j++) { + gpencil_set_fill_point(be->vbo, + be->vbo_len, + &gps->points[stroke_triangle->verts[j]], + color, + stroke_triangle->uv[j], + be->pos_id, + be->color_id, + be->uvdata_id); + be->vbo_len++; + } + } } /* create batch geometry data for current buffer stroke shader */ GPUBatch *DRW_gpencil_get_buffer_stroke_geom(bGPdata *gpd, short thickness) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - Scene *scene = draw_ctx->scene; - ARegion *ar = draw_ctx->ar; - RegionView3D *rv3d = draw_ctx->rv3d; - ToolSettings *ts = scene->toolsettings; - Object *ob = draw_ctx->obact; - - tGPspoint *points = gpd->runtime.sbuffer; - int totpoints = gpd->runtime.sbuffer_size; - /* if cyclic needs more vertex */ - int cyclic_add = (gpd->runtime.sbuffer_sflag & GP_STROKE_CYCLIC) ? 1 : 0; - int totvertex = totpoints + cyclic_add + 2; - - static GPUVertFormat format = { 0 }; - static uint pos_id, color_id, thickness_id, uvdata_id; - if (format.attr_len == 0) { - pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - thickness_id = GPU_vertformat_attr_add(&format, "thickness", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); - uvdata_id = GPU_vertformat_attr_add(&format, "uvdata", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - } - - GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format); - GPU_vertbuf_data_alloc(vbo, totvertex); - - /* draw stroke curve */ - const tGPspoint *tpt = points; - bGPDspoint pt, pt2, pt3; - int idx = 0; - - /* get origin to reproject point */ - float origin[3]; - bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd); - ED_gp_get_drawing_reference(scene, ob, gpl, ts->gpencil_v3d_align, origin); - - for (int i = 0; i < totpoints; i++, tpt++) { - ED_gpencil_tpoint_to_point(ar, origin, tpt, &pt); - ED_gp_project_point_to_plane(scene, ob, rv3d, origin, ts->gp_sculpt.lock_axis - 1, &pt); - - /* first point for adjacency (not drawn) */ - if (i == 0) { - if (gpd->runtime.sbuffer_sflag & GP_STROKE_CYCLIC && totpoints > 2) { - ED_gpencil_tpoint_to_point(ar, origin, &points[totpoints - 1], &pt2); - gpencil_set_stroke_point( - vbo, &pt2, idx, - pos_id, color_id, thickness_id, uvdata_id, thickness, gpd->runtime.scolor); - idx++; - } - else { - ED_gpencil_tpoint_to_point(ar, origin, &points[1], &pt2); - gpencil_set_stroke_point( - vbo, &pt2, idx, - pos_id, color_id, thickness_id, uvdata_id, thickness, gpd->runtime.scolor); - idx++; - } - } - - /* set point */ - gpencil_set_stroke_point( - vbo, &pt, idx, - pos_id, color_id, thickness_id, uvdata_id, thickness, gpd->runtime.scolor); - idx++; - } - - /* last adjacency point (not drawn) */ - if (gpd->runtime.sbuffer_sflag & GP_STROKE_CYCLIC && totpoints > 2) { - /* draw line to first point to complete the cycle */ - ED_gpencil_tpoint_to_point(ar, origin, &points[0], &pt2); - gpencil_set_stroke_point( - vbo, &pt2, idx, - pos_id, color_id, thickness_id, uvdata_id, thickness, gpd->runtime.scolor); - idx++; - /* now add adjacency point (not drawn) */ - ED_gpencil_tpoint_to_point(ar, origin, &points[1], &pt3); - gpencil_set_stroke_point( - vbo, &pt3, idx, - pos_id, color_id, thickness_id, uvdata_id, thickness, gpd->runtime.scolor); - idx++; - } - /* last adjacency point (not drawn) */ - else { - ED_gpencil_tpoint_to_point(ar, origin, &points[totpoints - 2], &pt2); - gpencil_set_stroke_point( - vbo, &pt2, idx, - pos_id, color_id, thickness_id, uvdata_id, thickness, gpd->runtime.scolor); - idx++; - } - - return GPU_batch_create_ex(GPU_PRIM_LINE_STRIP_ADJ, vbo, NULL, GPU_BATCH_OWNS_VBO); + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene = draw_ctx->scene; + ARegion *ar = draw_ctx->ar; + RegionView3D *rv3d = draw_ctx->rv3d; + ToolSettings *ts = scene->toolsettings; + Object *ob = draw_ctx->obact; + + tGPspoint *points = gpd->runtime.sbuffer; + int totpoints = gpd->runtime.sbuffer_size; + /* if cyclic needs more vertex */ + int cyclic_add = (gpd->runtime.sbuffer_sflag & GP_STROKE_CYCLIC) ? 1 : 0; + int totvertex = totpoints + cyclic_add + 2; + + static GPUVertFormat format = {0}; + static uint pos_id, color_id, thickness_id, uvdata_id; + if (format.attr_len == 0) { + pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); + thickness_id = GPU_vertformat_attr_add(&format, "thickness", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); + uvdata_id = GPU_vertformat_attr_add(&format, "uvdata", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + } + + GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format); + GPU_vertbuf_data_alloc(vbo, totvertex); + + /* draw stroke curve */ + const tGPspoint *tpt = points; + bGPDspoint pt, pt2, pt3; + int idx = 0; + + /* get origin to reproject point */ + float origin[3]; + bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd); + ED_gp_get_drawing_reference(scene, ob, gpl, ts->gpencil_v3d_align, origin); + + for (int i = 0; i < totpoints; i++, tpt++) { + ED_gpencil_tpoint_to_point(ar, origin, tpt, &pt); + ED_gp_project_point_to_plane(scene, ob, rv3d, origin, ts->gp_sculpt.lock_axis - 1, &pt); + + /* first point for adjacency (not drawn) */ + if (i == 0) { + if (gpd->runtime.sbuffer_sflag & GP_STROKE_CYCLIC && totpoints > 2) { + ED_gpencil_tpoint_to_point(ar, origin, &points[totpoints - 1], &pt2); + gpencil_set_stroke_point(vbo, + &pt2, + idx, + pos_id, + color_id, + thickness_id, + uvdata_id, + thickness, + gpd->runtime.scolor); + idx++; + } + else { + ED_gpencil_tpoint_to_point(ar, origin, &points[1], &pt2); + gpencil_set_stroke_point(vbo, + &pt2, + idx, + pos_id, + color_id, + thickness_id, + uvdata_id, + thickness, + gpd->runtime.scolor); + idx++; + } + } + + /* set point */ + gpencil_set_stroke_point( + vbo, &pt, idx, pos_id, color_id, thickness_id, uvdata_id, thickness, gpd->runtime.scolor); + idx++; + } + + /* last adjacency point (not drawn) */ + if (gpd->runtime.sbuffer_sflag & GP_STROKE_CYCLIC && totpoints > 2) { + /* draw line to first point to complete the cycle */ + ED_gpencil_tpoint_to_point(ar, origin, &points[0], &pt2); + gpencil_set_stroke_point( + vbo, &pt2, idx, pos_id, color_id, thickness_id, uvdata_id, thickness, gpd->runtime.scolor); + idx++; + /* now add adjacency point (not drawn) */ + ED_gpencil_tpoint_to_point(ar, origin, &points[1], &pt3); + gpencil_set_stroke_point( + vbo, &pt3, idx, pos_id, color_id, thickness_id, uvdata_id, thickness, gpd->runtime.scolor); + idx++; + } + /* last adjacency point (not drawn) */ + else { + ED_gpencil_tpoint_to_point(ar, origin, &points[totpoints - 2], &pt2); + gpencil_set_stroke_point( + vbo, &pt2, idx, pos_id, color_id, thickness_id, uvdata_id, thickness, gpd->runtime.scolor); + idx++; + } + + return GPU_batch_create_ex(GPU_PRIM_LINE_STRIP_ADJ, vbo, NULL, GPU_BATCH_OWNS_VBO); } /* create batch geometry data for current buffer point shader */ GPUBatch *DRW_gpencil_get_buffer_point_geom(bGPdata *gpd, short thickness) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - Scene *scene = draw_ctx->scene; - ARegion *ar = draw_ctx->ar; - RegionView3D *rv3d = draw_ctx->rv3d; - ToolSettings *ts = scene->toolsettings; - Object *ob = draw_ctx->obact; - - tGPspoint *points = gpd->runtime.sbuffer; - int totpoints = gpd->runtime.sbuffer_size; - - static GPUVertFormat format = { 0 }; - static uint pos_id, color_id, thickness_id, uvdata_id; - if (format.attr_len == 0) { - pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - thickness_id = GPU_vertformat_attr_add(&format, "thickness", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); - uvdata_id = GPU_vertformat_attr_add(&format, "uvdata", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - } - - GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format); - GPU_vertbuf_data_alloc(vbo, totpoints); - - /* draw stroke curve */ - const tGPspoint *tpt = points; - bGPDspoint pt; - int idx = 0; - - /* get origin to reproject point */ - float origin[3]; - bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd); - ED_gp_get_drawing_reference(scene, ob, gpl, ts->gpencil_v3d_align, origin); - - for (int i = 0; i < totpoints; i++, tpt++) { - ED_gpencil_tpoint_to_point(ar, origin, tpt, &pt); - ED_gp_project_point_to_plane(scene, ob, rv3d, origin, ts->gp_sculpt.lock_axis - 1, &pt); - - /* set point */ - gpencil_set_stroke_point( - vbo, &pt, idx, - pos_id, color_id, thickness_id, uvdata_id, - thickness, gpd->runtime.scolor); - idx++; - } - - return GPU_batch_create_ex(GPU_PRIM_POINTS, vbo, NULL, GPU_BATCH_OWNS_VBO); + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene = draw_ctx->scene; + ARegion *ar = draw_ctx->ar; + RegionView3D *rv3d = draw_ctx->rv3d; + ToolSettings *ts = scene->toolsettings; + Object *ob = draw_ctx->obact; + + tGPspoint *points = gpd->runtime.sbuffer; + int totpoints = gpd->runtime.sbuffer_size; + + static GPUVertFormat format = {0}; + static uint pos_id, color_id, thickness_id, uvdata_id; + if (format.attr_len == 0) { + pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); + thickness_id = GPU_vertformat_attr_add(&format, "thickness", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); + uvdata_id = GPU_vertformat_attr_add(&format, "uvdata", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + } + + GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format); + GPU_vertbuf_data_alloc(vbo, totpoints); + + /* draw stroke curve */ + const tGPspoint *tpt = points; + bGPDspoint pt; + int idx = 0; + + /* get origin to reproject point */ + float origin[3]; + bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd); + ED_gp_get_drawing_reference(scene, ob, gpl, ts->gpencil_v3d_align, origin); + + for (int i = 0; i < totpoints; i++, tpt++) { + ED_gpencil_tpoint_to_point(ar, origin, tpt, &pt); + ED_gp_project_point_to_plane(scene, ob, rv3d, origin, ts->gp_sculpt.lock_axis - 1, &pt); + + /* set point */ + gpencil_set_stroke_point( + vbo, &pt, idx, pos_id, color_id, thickness_id, uvdata_id, thickness, gpd->runtime.scolor); + idx++; + } + + return GPU_batch_create_ex(GPU_PRIM_POINTS, vbo, NULL, GPU_BATCH_OWNS_VBO); } /* create batch geometry data for current buffer control point shader */ GPUBatch *DRW_gpencil_get_buffer_ctrlpoint_geom(bGPdata *gpd) { - bGPDcontrolpoint *cps = gpd->runtime.cp_points; - int totpoints = gpd->runtime.tot_cp_points; - - const DRWContextState *draw_ctx = DRW_context_state_get(); - Scene *scene = draw_ctx->scene; - ToolSettings *ts = scene->toolsettings; - - if (ts->gp_sculpt.guide.use_guide) { - totpoints++; - } - - static GPUVertFormat format = { 0 }; - static uint pos_id, color_id, size_id; - if (format.attr_len == 0) { - pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - size_id = GPU_vertformat_attr_add(&format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); - color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - } - - GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format); - GPU_vertbuf_data_alloc(vbo, totpoints); - - int idx = 0; - for (int i = 0; i < gpd->runtime.tot_cp_points; i++) { - bGPDcontrolpoint *cp = &cps[i]; - - GPU_vertbuf_attr_set(vbo, color_id, idx, cp->color); - - /* scale size */ - float size = cp->size * 0.8f; - GPU_vertbuf_attr_set(vbo, size_id, idx, &size); - - GPU_vertbuf_attr_set(vbo, pos_id, idx, &cp->x); - idx++; - } - - if (ts->gp_sculpt.guide.use_guide) { - float size = 10 * 0.8f; - float color[4]; - float position[3]; - if (ts->gp_sculpt.guide.reference_point == GP_GUIDE_REF_CUSTOM) { - UI_GetThemeColor4fv(TH_GIZMO_PRIMARY, color); - copy_v3_v3(position, ts->gp_sculpt.guide.location); - } - else if (ts->gp_sculpt.guide.reference_point == GP_GUIDE_REF_OBJECT && ts->gp_sculpt.guide.reference_object != NULL) { - UI_GetThemeColor4fv(TH_GIZMO_SECONDARY, color); - copy_v3_v3(position, ts->gp_sculpt.guide.reference_object->loc); - } - else { - UI_GetThemeColor4fv(TH_REDALERT, color); - copy_v3_v3(position, scene->cursor.location); - } - GPU_vertbuf_attr_set(vbo, pos_id, idx, position); - GPU_vertbuf_attr_set(vbo, size_id, idx, &size); - GPU_vertbuf_attr_set(vbo, color_id, idx, color); - } - - return GPU_batch_create_ex(GPU_PRIM_POINTS, vbo, NULL, GPU_BATCH_OWNS_VBO); + bGPDcontrolpoint *cps = gpd->runtime.cp_points; + int totpoints = gpd->runtime.tot_cp_points; + + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene = draw_ctx->scene; + ToolSettings *ts = scene->toolsettings; + + if (ts->gp_sculpt.guide.use_guide) { + totpoints++; + } + + static GPUVertFormat format = {0}; + static uint pos_id, color_id, size_id; + if (format.attr_len == 0) { + pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + size_id = GPU_vertformat_attr_add(&format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); + color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); + } + + GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format); + GPU_vertbuf_data_alloc(vbo, totpoints); + + int idx = 0; + for (int i = 0; i < gpd->runtime.tot_cp_points; i++) { + bGPDcontrolpoint *cp = &cps[i]; + + GPU_vertbuf_attr_set(vbo, color_id, idx, cp->color); + + /* scale size */ + float size = cp->size * 0.8f; + GPU_vertbuf_attr_set(vbo, size_id, idx, &size); + + GPU_vertbuf_attr_set(vbo, pos_id, idx, &cp->x); + idx++; + } + + if (ts->gp_sculpt.guide.use_guide) { + float size = 10 * 0.8f; + float color[4]; + float position[3]; + if (ts->gp_sculpt.guide.reference_point == GP_GUIDE_REF_CUSTOM) { + UI_GetThemeColor4fv(TH_GIZMO_PRIMARY, color); + copy_v3_v3(position, ts->gp_sculpt.guide.location); + } + else if (ts->gp_sculpt.guide.reference_point == GP_GUIDE_REF_OBJECT && + ts->gp_sculpt.guide.reference_object != NULL) { + UI_GetThemeColor4fv(TH_GIZMO_SECONDARY, color); + copy_v3_v3(position, ts->gp_sculpt.guide.reference_object->loc); + } + else { + UI_GetThemeColor4fv(TH_REDALERT, color); + copy_v3_v3(position, scene->cursor.location); + } + GPU_vertbuf_attr_set(vbo, pos_id, idx, position); + GPU_vertbuf_attr_set(vbo, size_id, idx, &size); + GPU_vertbuf_attr_set(vbo, color_id, idx, color); + } + + return GPU_batch_create_ex(GPU_PRIM_POINTS, vbo, NULL, GPU_BATCH_OWNS_VBO); } /* create batch geometry data for current buffer fill shader */ GPUBatch *DRW_gpencil_get_buffer_fill_geom(bGPdata *gpd) { - if (gpd == NULL) { - return NULL; - } - - const tGPspoint *points = gpd->runtime.sbuffer; - int totpoints = gpd->runtime.sbuffer_size; - if (totpoints < 3) { - return NULL; - } - - const DRWContextState *draw_ctx = DRW_context_state_get(); - Scene *scene = draw_ctx->scene; - ARegion *ar = draw_ctx->ar; - ToolSettings *ts = scene->toolsettings; - Object *ob = draw_ctx->obact; - - /* get origin to reproject point */ - float origin[3]; - bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd); - ED_gp_get_drawing_reference(scene, ob, gpl, ts->gpencil_v3d_align, origin); - - int tot_triangles = totpoints - 2; - /* allocate memory for temporary areas */ - uint (*tmp_triangles)[3] = MEM_mallocN(sizeof(*tmp_triangles) * tot_triangles, __func__); - float (*points2d)[2] = MEM_mallocN(sizeof(*points2d) * totpoints, __func__); - - /* Convert points to array and triangulate - * Here a cache is not used because while drawing the information changes all the time, so the cache - * would be recalculated constantly, so it is better to do direct calculation for each function call - */ - for (int i = 0; i < totpoints; i++) { - const tGPspoint *pt = &points[i]; - points2d[i][0] = pt->x; - points2d[i][1] = pt->y; - } - BLI_polyfill_calc(points2d, (uint)totpoints, 0, tmp_triangles); - - static GPUVertFormat format = { 0 }; - static uint pos_id, color_id; - if (format.attr_len == 0) { - pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - } - - GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format); - - /* draw triangulation data */ - if (tot_triangles > 0) { - GPU_vertbuf_data_alloc(vbo, tot_triangles * 3); - - const tGPspoint *tpt; - bGPDspoint pt; - - int idx = 0; - for (int i = 0; i < tot_triangles; i++) { - for (int j = 0; j < 3; j++) { - tpt = &points[tmp_triangles[i][j]]; - ED_gpencil_tpoint_to_point(ar, origin, tpt, &pt); - GPU_vertbuf_attr_set(vbo, pos_id, idx, &pt.x); - GPU_vertbuf_attr_set(vbo, color_id, idx, gpd->runtime.sfill); - idx++; - } - } - } - - /* clear memory */ - if (tmp_triangles) { - MEM_freeN(tmp_triangles); - } - if (points2d) { - MEM_freeN(points2d); - } - - return GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO); + if (gpd == NULL) { + return NULL; + } + + const tGPspoint *points = gpd->runtime.sbuffer; + int totpoints = gpd->runtime.sbuffer_size; + if (totpoints < 3) { + return NULL; + } + + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene = draw_ctx->scene; + ARegion *ar = draw_ctx->ar; + ToolSettings *ts = scene->toolsettings; + Object *ob = draw_ctx->obact; + + /* get origin to reproject point */ + float origin[3]; + bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd); + ED_gp_get_drawing_reference(scene, ob, gpl, ts->gpencil_v3d_align, origin); + + int tot_triangles = totpoints - 2; + /* allocate memory for temporary areas */ + uint(*tmp_triangles)[3] = MEM_mallocN(sizeof(*tmp_triangles) * tot_triangles, __func__); + float(*points2d)[2] = MEM_mallocN(sizeof(*points2d) * totpoints, __func__); + + /* Convert points to array and triangulate + * Here a cache is not used because while drawing the information changes all the time, so the cache + * would be recalculated constantly, so it is better to do direct calculation for each function call + */ + for (int i = 0; i < totpoints; i++) { + const tGPspoint *pt = &points[i]; + points2d[i][0] = pt->x; + points2d[i][1] = pt->y; + } + BLI_polyfill_calc(points2d, (uint)totpoints, 0, tmp_triangles); + + static GPUVertFormat format = {0}; + static uint pos_id, color_id; + if (format.attr_len == 0) { + pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); + } + + GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format); + + /* draw triangulation data */ + if (tot_triangles > 0) { + GPU_vertbuf_data_alloc(vbo, tot_triangles * 3); + + const tGPspoint *tpt; + bGPDspoint pt; + + int idx = 0; + for (int i = 0; i < tot_triangles; i++) { + for (int j = 0; j < 3; j++) { + tpt = &points[tmp_triangles[i][j]]; + ED_gpencil_tpoint_to_point(ar, origin, tpt, &pt); + GPU_vertbuf_attr_set(vbo, pos_id, idx, &pt.x); + GPU_vertbuf_attr_set(vbo, color_id, idx, gpd->runtime.sfill); + idx++; + } + } + } + + /* clear memory */ + if (tmp_triangles) { + MEM_freeN(tmp_triangles); + } + if (points2d) { + MEM_freeN(points2d); + } + + return GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO); } /* Draw selected verts for strokes being edited */ -void DRW_gpencil_get_edit_geom(struct GpencilBatchCacheElem *be, bGPDstroke *gps, float alpha, short dflag) +void DRW_gpencil_get_edit_geom(struct GpencilBatchCacheElem *be, + bGPDstroke *gps, + float alpha, + short dflag) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - Object *ob = draw_ctx->obact; - bGPdata *gpd = ob->data; - const bool is_weight_paint = (gpd) && (gpd->flag & GP_DATA_STROKE_WEIGHTMODE); - - int vgindex = ob->actdef - 1; - if (!BLI_findlink(&ob->defbase, vgindex)) { - vgindex = -1; - } - - /* Get size of verts: - * - The selected state needs to be larger than the unselected state so that - * they stand out more. - * - We use the theme setting for size of the unselected verts - */ - float bsize = UI_GetThemeValuef(TH_GP_VERTEX_SIZE); - float vsize; - if ((int)bsize > 8) { - vsize = 10.0f; - bsize = 8.0f; - } - else { - vsize = bsize + 2; - } - - /* for now, we assume that the base color of the points is not too close to the real color */ - float selectColor[4]; - UI_GetThemeColor3fv(TH_GP_VERTEX_SELECT, selectColor); - selectColor[3] = alpha; - - float unselectColor[4]; - UI_GetThemeColor3fv(TH_GP_VERTEX, unselectColor); - unselectColor[3] = alpha; - - if (be->vbo == NULL) { - be->pos_id = GPU_vertformat_attr_add(&be->format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - be->color_id = GPU_vertformat_attr_add(&be->format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - be->thickness_id = GPU_vertformat_attr_add(&be->format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); - - be->vbo = GPU_vertbuf_create_with_format(&be->format); - GPU_vertbuf_data_alloc(be->vbo, be->tot_vertex); - be->vbo_len = 0; - } - gpencil_vbo_ensure_size(be, gps->totpoints); - - /* Draw start and end point differently if enabled stroke direction hint */ - bool show_direction_hint = (dflag & GP_DATA_SHOW_DIRECTION) && (gps->totpoints > 1); - - /* Draw all the stroke points (selected or not) */ - bGPDspoint *pt = gps->points; - MDeformVert *dvert = gps->dvert; - - float fcolor[4]; - float fsize = 0; - for (int i = 0; i < gps->totpoints; i++, pt++) { - /* weight paint */ - if (is_weight_paint) { - float weight = (dvert && dvert->dw && (vgindex > -1)) ? defvert_find_weight(dvert, vgindex) : 0.0f; - float hue = 2.0f * (1.0f - weight) / 3.0f; - hsv_to_rgb(hue, 1.0f, 1.0f, &selectColor[0], &selectColor[1], &selectColor[2]); - selectColor[3] = 1.0f; - copy_v4_v4(fcolor, selectColor); - fsize = vsize; - } - else { - if (show_direction_hint && i == 0) { - /* start point in green bigger */ - ARRAY_SET_ITEMS(fcolor, 0.0f, 1.0f, 0.0f, 1.0f); - fsize = vsize + 4; - } - else if (show_direction_hint && (i == gps->totpoints - 1)) { - /* end point in red smaller */ - ARRAY_SET_ITEMS(fcolor, 1.0f, 0.0f, 0.0f, 1.0f); - fsize = vsize + 1; - } - else if (pt->flag & GP_SPOINT_SELECT) { - copy_v4_v4(fcolor, selectColor); - fsize = vsize; - } - else { - copy_v4_v4(fcolor, unselectColor); - fsize = bsize; - } - } - - GPU_vertbuf_attr_set(be->vbo, be->color_id, be->vbo_len, fcolor); - GPU_vertbuf_attr_set(be->vbo, be->thickness_id, be->vbo_len, &fsize); - GPU_vertbuf_attr_set(be->vbo, be->pos_id, be->vbo_len, &pt->x); - be->vbo_len++; - if (gps->dvert != NULL) { - dvert++; - } - } + const DRWContextState *draw_ctx = DRW_context_state_get(); + Object *ob = draw_ctx->obact; + bGPdata *gpd = ob->data; + const bool is_weight_paint = (gpd) && (gpd->flag & GP_DATA_STROKE_WEIGHTMODE); + + int vgindex = ob->actdef - 1; + if (!BLI_findlink(&ob->defbase, vgindex)) { + vgindex = -1; + } + + /* Get size of verts: + * - The selected state needs to be larger than the unselected state so that + * they stand out more. + * - We use the theme setting for size of the unselected verts + */ + float bsize = UI_GetThemeValuef(TH_GP_VERTEX_SIZE); + float vsize; + if ((int)bsize > 8) { + vsize = 10.0f; + bsize = 8.0f; + } + else { + vsize = bsize + 2; + } + + /* for now, we assume that the base color of the points is not too close to the real color */ + float selectColor[4]; + UI_GetThemeColor3fv(TH_GP_VERTEX_SELECT, selectColor); + selectColor[3] = alpha; + + float unselectColor[4]; + UI_GetThemeColor3fv(TH_GP_VERTEX, unselectColor); + unselectColor[3] = alpha; + + if (be->vbo == NULL) { + be->pos_id = GPU_vertformat_attr_add(&be->format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + be->color_id = GPU_vertformat_attr_add(&be->format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); + be->thickness_id = GPU_vertformat_attr_add( + &be->format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); + + be->vbo = GPU_vertbuf_create_with_format(&be->format); + GPU_vertbuf_data_alloc(be->vbo, be->tot_vertex); + be->vbo_len = 0; + } + gpencil_vbo_ensure_size(be, gps->totpoints); + + /* Draw start and end point differently if enabled stroke direction hint */ + bool show_direction_hint = (dflag & GP_DATA_SHOW_DIRECTION) && (gps->totpoints > 1); + + /* Draw all the stroke points (selected or not) */ + bGPDspoint *pt = gps->points; + MDeformVert *dvert = gps->dvert; + + float fcolor[4]; + float fsize = 0; + for (int i = 0; i < gps->totpoints; i++, pt++) { + /* weight paint */ + if (is_weight_paint) { + float weight = (dvert && dvert->dw && (vgindex > -1)) ? defvert_find_weight(dvert, vgindex) : + 0.0f; + float hue = 2.0f * (1.0f - weight) / 3.0f; + hsv_to_rgb(hue, 1.0f, 1.0f, &selectColor[0], &selectColor[1], &selectColor[2]); + selectColor[3] = 1.0f; + copy_v4_v4(fcolor, selectColor); + fsize = vsize; + } + else { + if (show_direction_hint && i == 0) { + /* start point in green bigger */ + ARRAY_SET_ITEMS(fcolor, 0.0f, 1.0f, 0.0f, 1.0f); + fsize = vsize + 4; + } + else if (show_direction_hint && (i == gps->totpoints - 1)) { + /* end point in red smaller */ + ARRAY_SET_ITEMS(fcolor, 1.0f, 0.0f, 0.0f, 1.0f); + fsize = vsize + 1; + } + else if (pt->flag & GP_SPOINT_SELECT) { + copy_v4_v4(fcolor, selectColor); + fsize = vsize; + } + else { + copy_v4_v4(fcolor, unselectColor); + fsize = bsize; + } + } + + GPU_vertbuf_attr_set(be->vbo, be->color_id, be->vbo_len, fcolor); + GPU_vertbuf_attr_set(be->vbo, be->thickness_id, be->vbo_len, &fsize); + GPU_vertbuf_attr_set(be->vbo, be->pos_id, be->vbo_len, &pt->x); + be->vbo_len++; + if (gps->dvert != NULL) { + dvert++; + } + } } /* Draw lines for strokes being edited */ -void DRW_gpencil_get_edlin_geom(struct GpencilBatchCacheElem *be, bGPDstroke *gps, float alpha, short UNUSED(dflag)) +void DRW_gpencil_get_edlin_geom(struct GpencilBatchCacheElem *be, + bGPDstroke *gps, + float alpha, + short UNUSED(dflag)) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - Object *ob = draw_ctx->obact; - bGPdata *gpd = ob->data; - const bool is_weight_paint = (gpd) && (gpd->flag & GP_DATA_STROKE_WEIGHTMODE); - - int vgindex = ob->actdef - 1; - if (!BLI_findlink(&ob->defbase, vgindex)) { - vgindex = -1; - } - - float selectColor[4]; - UI_GetThemeColor3fv(TH_GP_VERTEX_SELECT, selectColor); - selectColor[3] = alpha; - float linecolor[4]; - copy_v4_v4(linecolor, gpd->line_color); - - if (be->vbo == NULL) { - be->pos_id = GPU_vertformat_attr_add(&be->format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - be->color_id = GPU_vertformat_attr_add(&be->format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - - be->vbo = GPU_vertbuf_create_with_format(&be->format); - GPU_vertbuf_data_alloc(be->vbo, be->tot_vertex); - be->vbo_len = 0; - } - gpencil_vbo_ensure_size(be, gps->totpoints); - - /* Draw all the stroke lines (selected or not) */ - bGPDspoint *pt = gps->points; - MDeformVert *dvert = gps->dvert; - - float fcolor[4]; - for (int i = 0; i < gps->totpoints; i++, pt++) { - /* weight paint */ - if (is_weight_paint) { - float weight = (dvert && dvert->dw && (vgindex > -1)) ? defvert_find_weight(dvert, vgindex) : 0.0f; - float hue = 2.0f * (1.0f - weight) / 3.0f; - hsv_to_rgb(hue, 1.0f, 1.0f, &selectColor[0], &selectColor[1], &selectColor[2]); - selectColor[3] = 1.0f; - copy_v4_v4(fcolor, selectColor); - } - else { - if (pt->flag & GP_SPOINT_SELECT) { - copy_v4_v4(fcolor, selectColor); - } - else { - copy_v4_v4(fcolor, linecolor); - } - } - - GPU_vertbuf_attr_set(be->vbo, be->color_id, be->vbo_len, fcolor); - GPU_vertbuf_attr_set(be->vbo, be->pos_id, be->vbo_len, &pt->x); - be->vbo_len++; - - if (gps->dvert != NULL) { - dvert++; - } - } + const DRWContextState *draw_ctx = DRW_context_state_get(); + Object *ob = draw_ctx->obact; + bGPdata *gpd = ob->data; + const bool is_weight_paint = (gpd) && (gpd->flag & GP_DATA_STROKE_WEIGHTMODE); + + int vgindex = ob->actdef - 1; + if (!BLI_findlink(&ob->defbase, vgindex)) { + vgindex = -1; + } + + float selectColor[4]; + UI_GetThemeColor3fv(TH_GP_VERTEX_SELECT, selectColor); + selectColor[3] = alpha; + float linecolor[4]; + copy_v4_v4(linecolor, gpd->line_color); + + if (be->vbo == NULL) { + be->pos_id = GPU_vertformat_attr_add(&be->format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + be->color_id = GPU_vertformat_attr_add(&be->format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); + + be->vbo = GPU_vertbuf_create_with_format(&be->format); + GPU_vertbuf_data_alloc(be->vbo, be->tot_vertex); + be->vbo_len = 0; + } + gpencil_vbo_ensure_size(be, gps->totpoints); + + /* Draw all the stroke lines (selected or not) */ + bGPDspoint *pt = gps->points; + MDeformVert *dvert = gps->dvert; + + float fcolor[4]; + for (int i = 0; i < gps->totpoints; i++, pt++) { + /* weight paint */ + if (is_weight_paint) { + float weight = (dvert && dvert->dw && (vgindex > -1)) ? defvert_find_weight(dvert, vgindex) : + 0.0f; + float hue = 2.0f * (1.0f - weight) / 3.0f; + hsv_to_rgb(hue, 1.0f, 1.0f, &selectColor[0], &selectColor[1], &selectColor[2]); + selectColor[3] = 1.0f; + copy_v4_v4(fcolor, selectColor); + } + else { + if (pt->flag & GP_SPOINT_SELECT) { + copy_v4_v4(fcolor, selectColor); + } + else { + copy_v4_v4(fcolor, linecolor); + } + } + + GPU_vertbuf_attr_set(be->vbo, be->color_id, be->vbo_len, fcolor); + GPU_vertbuf_attr_set(be->vbo, be->pos_id, be->vbo_len, &pt->x); + be->vbo_len++; + + if (gps->dvert != NULL) { + dvert++; + } + } } -static void set_grid_point( - GPUVertBuf *vbo, int idx, float col_grid[4], - uint pos_id, uint color_id, - float v1, float v2, const int axis) +static void set_grid_point(GPUVertBuf *vbo, + int idx, + float col_grid[4], + uint pos_id, + uint color_id, + float v1, + float v2, + const int axis) { - GPU_vertbuf_attr_set(vbo, color_id, idx, col_grid); - - float pos[3]; - /* Set the grid in the selected axis */ - switch (axis) { - case GP_LOCKAXIS_X: - { - ARRAY_SET_ITEMS(pos, 0.0f, v1, v2); - break; - } - case GP_LOCKAXIS_Y: - { - ARRAY_SET_ITEMS(pos, v1, 0.0f, v2); - break; - } - case GP_LOCKAXIS_Z: - default: /* view aligned */ - { - ARRAY_SET_ITEMS(pos, v1, v2, 0.0f); - break; - } - } - - GPU_vertbuf_attr_set(vbo, pos_id, idx, pos); + GPU_vertbuf_attr_set(vbo, color_id, idx, col_grid); + + float pos[3]; + /* Set the grid in the selected axis */ + switch (axis) { + case GP_LOCKAXIS_X: { + ARRAY_SET_ITEMS(pos, 0.0f, v1, v2); + break; + } + case GP_LOCKAXIS_Y: { + ARRAY_SET_ITEMS(pos, v1, 0.0f, v2); + break; + } + case GP_LOCKAXIS_Z: + default: /* view aligned */ + { + ARRAY_SET_ITEMS(pos, v1, v2, 0.0f); + break; + } + } + + GPU_vertbuf_attr_set(vbo, pos_id, idx, pos); } /* Draw grid lines */ GPUBatch *DRW_gpencil_get_grid(Object *ob) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - Scene *scene = draw_ctx->scene; - ToolSettings *ts = scene->toolsettings; - View3D *v3d = draw_ctx->v3d; - bGPdata *gpd = (bGPdata *)ob->data; - const bool do_center = (gpd->grid.lines <= 0) ? false : true; - - float col_grid[4]; - - /* verify we have something to draw and valid values */ - if (gpd->grid.scale[0] == 0.0f) { - gpd->grid.scale[0] = 1.0f; - } - if (gpd->grid.scale[1] == 0.0f) { - gpd->grid.scale[1] = 1.0f; - } - - if (v3d->overlay.gpencil_grid_opacity < 0.1f) { - v3d->overlay.gpencil_grid_opacity = 0.1f; - } - - /* set color */ - copy_v3_v3(col_grid, gpd->grid.color); - col_grid[3] = v3d->overlay.gpencil_grid_opacity; - - const int axis = ts->gp_sculpt.lock_axis; - - const char *grid_unit = NULL; - const int gridlines = (gpd->grid.lines <= 0) ? 1 : gpd->grid.lines; - const float grid_w = gpd->grid.scale[0] * ED_scene_grid_scale(scene, &grid_unit); - const float grid_h = gpd->grid.scale[1] * ED_scene_grid_scale(scene, &grid_unit); - const float space_w = (grid_w / gridlines); - const float space_h = (grid_h / gridlines); - const float offset[2] = { gpd->grid.offset[0], gpd->grid.offset[1] }; - - const uint vertex_len = 2 * (gridlines * 4 + 2); - - static GPUVertFormat format = { 0 }; - static uint pos_id, color_id; - if (format.attr_len == 0) { - pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - } - - GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format); - GPU_vertbuf_data_alloc(vbo, vertex_len); - - int idx = 0; - - for (int a = 1; a <= gridlines; a++) { - const float line_w = a * space_w; - const float line_h = a * space_h; - - set_grid_point(vbo, idx, col_grid, pos_id, color_id, -grid_w + offset[0], -line_h + offset[1], axis); - idx++; - set_grid_point(vbo, idx, col_grid, pos_id, color_id, +grid_w + offset[0], -line_h + offset[1], axis); - idx++; - set_grid_point(vbo, idx, col_grid, pos_id, color_id, -grid_w + offset[0], +line_h + offset[1], axis); - idx++; - set_grid_point(vbo, idx, col_grid, pos_id, color_id, +grid_w + offset[0], +line_h + offset[1], axis); - idx++; - - set_grid_point(vbo, idx, col_grid, pos_id, color_id, -line_w + offset[0], -grid_h + offset[1], axis); - idx++; - set_grid_point(vbo, idx, col_grid, pos_id, color_id, -line_w + offset[0], +grid_h + offset[1], axis); - idx++; - set_grid_point(vbo, idx, col_grid, pos_id, color_id, +line_w + offset[0], -grid_h + offset[1], axis); - idx++; - set_grid_point(vbo, idx, col_grid, pos_id, color_id, +line_w + offset[0], +grid_h + offset[1], axis); - idx++; - } - /* center lines */ - if (do_center) { - set_grid_point(vbo, idx, col_grid, pos_id, color_id, -grid_w + offset[0], 0.0f + offset[1], axis); - idx++; - set_grid_point(vbo, idx, col_grid, pos_id, color_id, +grid_w + offset[0], 0.0f + offset[1], axis); - idx++; - - set_grid_point(vbo, idx, col_grid, pos_id, color_id, 0.0f + offset[0], -grid_h + offset[1], axis); - idx++; - set_grid_point(vbo, idx, col_grid, pos_id, color_id, 0.0f + offset[0], +grid_h + offset[1], axis); - idx++; - } - return GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO); + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene = draw_ctx->scene; + ToolSettings *ts = scene->toolsettings; + View3D *v3d = draw_ctx->v3d; + bGPdata *gpd = (bGPdata *)ob->data; + const bool do_center = (gpd->grid.lines <= 0) ? false : true; + + float col_grid[4]; + + /* verify we have something to draw and valid values */ + if (gpd->grid.scale[0] == 0.0f) { + gpd->grid.scale[0] = 1.0f; + } + if (gpd->grid.scale[1] == 0.0f) { + gpd->grid.scale[1] = 1.0f; + } + + if (v3d->overlay.gpencil_grid_opacity < 0.1f) { + v3d->overlay.gpencil_grid_opacity = 0.1f; + } + + /* set color */ + copy_v3_v3(col_grid, gpd->grid.color); + col_grid[3] = v3d->overlay.gpencil_grid_opacity; + + const int axis = ts->gp_sculpt.lock_axis; + + const char *grid_unit = NULL; + const int gridlines = (gpd->grid.lines <= 0) ? 1 : gpd->grid.lines; + const float grid_w = gpd->grid.scale[0] * ED_scene_grid_scale(scene, &grid_unit); + const float grid_h = gpd->grid.scale[1] * ED_scene_grid_scale(scene, &grid_unit); + const float space_w = (grid_w / gridlines); + const float space_h = (grid_h / gridlines); + const float offset[2] = {gpd->grid.offset[0], gpd->grid.offset[1]}; + + const uint vertex_len = 2 * (gridlines * 4 + 2); + + static GPUVertFormat format = {0}; + static uint pos_id, color_id; + if (format.attr_len == 0) { + pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); + } + + GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format); + GPU_vertbuf_data_alloc(vbo, vertex_len); + + int idx = 0; + + for (int a = 1; a <= gridlines; a++) { + const float line_w = a * space_w; + const float line_h = a * space_h; + + set_grid_point( + vbo, idx, col_grid, pos_id, color_id, -grid_w + offset[0], -line_h + offset[1], axis); + idx++; + set_grid_point( + vbo, idx, col_grid, pos_id, color_id, +grid_w + offset[0], -line_h + offset[1], axis); + idx++; + set_grid_point( + vbo, idx, col_grid, pos_id, color_id, -grid_w + offset[0], +line_h + offset[1], axis); + idx++; + set_grid_point( + vbo, idx, col_grid, pos_id, color_id, +grid_w + offset[0], +line_h + offset[1], axis); + idx++; + + set_grid_point( + vbo, idx, col_grid, pos_id, color_id, -line_w + offset[0], -grid_h + offset[1], axis); + idx++; + set_grid_point( + vbo, idx, col_grid, pos_id, color_id, -line_w + offset[0], +grid_h + offset[1], axis); + idx++; + set_grid_point( + vbo, idx, col_grid, pos_id, color_id, +line_w + offset[0], -grid_h + offset[1], axis); + idx++; + set_grid_point( + vbo, idx, col_grid, pos_id, color_id, +line_w + offset[0], +grid_h + offset[1], axis); + idx++; + } + /* center lines */ + if (do_center) { + set_grid_point( + vbo, idx, col_grid, pos_id, color_id, -grid_w + offset[0], 0.0f + offset[1], axis); + idx++; + set_grid_point( + vbo, idx, col_grid, pos_id, color_id, +grid_w + offset[0], 0.0f + offset[1], axis); + idx++; + + set_grid_point( + vbo, idx, col_grid, pos_id, color_id, 0.0f + offset[0], -grid_h + offset[1], axis); + idx++; + set_grid_point( + vbo, idx, col_grid, pos_id, color_id, 0.0f + offset[0], +grid_h + offset[1], axis); + idx++; + } + return GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO); } diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c index 8ecee86d92b..320b621f903 100644 --- a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c +++ b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c @@ -61,1010 +61,1060 @@ #define TEXTURE 4 #define PATTERN 5 -#define GP_SET_SRC_GPS(src_gps) if (src_gps) src_gps = src_gps->next +#define GP_SET_SRC_GPS(src_gps) \ + if (src_gps) \ + src_gps = src_gps->next /* Get number of vertex for using in GPU VBOs */ -static void gpencil_calc_vertex( - GPENCIL_StorageList *stl, tGPencilObjectCache *cache_ob, - GpencilBatchCache *cache, bGPdata *gpd, - int cfra_eval) +static void gpencil_calc_vertex(GPENCIL_StorageList *stl, + tGPencilObjectCache *cache_ob, + GpencilBatchCache *cache, + bGPdata *gpd, + int cfra_eval) { - if (!cache->is_dirty) { - return; - } - - Object *ob = cache_ob->ob; - const DRWContextState *draw_ctx = DRW_context_state_get(); - const bool main_onion = draw_ctx->v3d != NULL ? (draw_ctx->v3d->gp_flag & V3D_GP_SHOW_ONION_SKIN) : true; - const bool playing = stl->storage->is_playing; - const bool overlay = draw_ctx->v3d != NULL ? (bool)((draw_ctx->v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) : true; - const bool do_onion = (bool)((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0) && - overlay && main_onion && DRW_gpencil_onion_active(gpd) && !playing; - - const bool time_remap = BKE_gpencil_has_time_modifiers(ob); - const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); - - cache_ob->tot_vertex = 0; - cache_ob->tot_triangles = 0; - - for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { - bGPDframe *init_gpf = NULL; - const bool is_onion = ((do_onion) && (gpl->onion_flag & GP_LAYER_ONIONSKIN)); - if (gpl->flag & GP_LAYER_HIDE) { - continue; - } - - /* if multiedit or onion skin need to count all frames of the layer */ - if ((is_multiedit) || (is_onion)) { - init_gpf = gpl->frames.first; - } - else { - /* verify time modifiers */ - if ((time_remap) && (!stl->storage->simplify_modif)) { - int remap_cfra = BKE_gpencil_time_modifier( - draw_ctx->depsgraph, draw_ctx->scene, ob, gpl, cfra_eval, - stl->storage->is_render); - init_gpf = BKE_gpencil_layer_getframe(gpl, remap_cfra, GP_GETFRAME_USE_PREV); - } - else { - init_gpf = gpl->actframe; - } - } - - if (init_gpf == NULL) { - continue; - } - - for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) { - for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { - cache_ob->tot_vertex += gps->totpoints + 3; - cache_ob->tot_triangles += gps->totpoints - 1; - } - if ((!is_multiedit) && (!is_onion)) { - break; - } - } - } - - cache->b_fill.tot_vertex = cache_ob->tot_triangles * 3; - cache->b_stroke.tot_vertex = cache_ob->tot_vertex; - cache->b_point.tot_vertex = cache_ob->tot_vertex; - cache->b_edit.tot_vertex = cache_ob->tot_vertex; - cache->b_edlin.tot_vertex = cache_ob->tot_vertex; - - /* some modifiers can change the number of points */ - int factor = 0; - GpencilModifierData *md; - for (md = ob->greasepencil_modifiers.first; md; md = md->next) { - const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type); - /* only modifiers that change size */ - if (mti && mti->getDuplicationFactor) { - factor = mti->getDuplicationFactor(md); - - cache->b_fill.tot_vertex *= factor; - cache->b_stroke.tot_vertex *= factor; - cache->b_point.tot_vertex *= factor; - cache->b_edit.tot_vertex *= factor; - cache->b_edlin.tot_vertex *= factor; - } - } + if (!cache->is_dirty) { + return; + } + + Object *ob = cache_ob->ob; + const DRWContextState *draw_ctx = DRW_context_state_get(); + const bool main_onion = draw_ctx->v3d != NULL ? + (draw_ctx->v3d->gp_flag & V3D_GP_SHOW_ONION_SKIN) : + true; + const bool playing = stl->storage->is_playing; + const bool overlay = draw_ctx->v3d != NULL ? + (bool)((draw_ctx->v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) : + true; + const bool do_onion = (bool)((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0) && overlay && + main_onion && DRW_gpencil_onion_active(gpd) && !playing; + + const bool time_remap = BKE_gpencil_has_time_modifiers(ob); + const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); + + cache_ob->tot_vertex = 0; + cache_ob->tot_triangles = 0; + + for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { + bGPDframe *init_gpf = NULL; + const bool is_onion = ((do_onion) && (gpl->onion_flag & GP_LAYER_ONIONSKIN)); + if (gpl->flag & GP_LAYER_HIDE) { + continue; + } + + /* if multiedit or onion skin need to count all frames of the layer */ + if ((is_multiedit) || (is_onion)) { + init_gpf = gpl->frames.first; + } + else { + /* verify time modifiers */ + if ((time_remap) && (!stl->storage->simplify_modif)) { + int remap_cfra = BKE_gpencil_time_modifier( + draw_ctx->depsgraph, draw_ctx->scene, ob, gpl, cfra_eval, stl->storage->is_render); + init_gpf = BKE_gpencil_layer_getframe(gpl, remap_cfra, GP_GETFRAME_USE_PREV); + } + else { + init_gpf = gpl->actframe; + } + } + + if (init_gpf == NULL) { + continue; + } + + for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) { + for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { + cache_ob->tot_vertex += gps->totpoints + 3; + cache_ob->tot_triangles += gps->totpoints - 1; + } + if ((!is_multiedit) && (!is_onion)) { + break; + } + } + } + + cache->b_fill.tot_vertex = cache_ob->tot_triangles * 3; + cache->b_stroke.tot_vertex = cache_ob->tot_vertex; + cache->b_point.tot_vertex = cache_ob->tot_vertex; + cache->b_edit.tot_vertex = cache_ob->tot_vertex; + cache->b_edlin.tot_vertex = cache_ob->tot_vertex; + + /* some modifiers can change the number of points */ + int factor = 0; + GpencilModifierData *md; + for (md = ob->greasepencil_modifiers.first; md; md = md->next) { + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type); + /* only modifiers that change size */ + if (mti && mti->getDuplicationFactor) { + factor = mti->getDuplicationFactor(md); + + cache->b_fill.tot_vertex *= factor; + cache->b_stroke.tot_vertex *= factor; + cache->b_point.tot_vertex *= factor; + cache->b_edit.tot_vertex *= factor; + cache->b_edlin.tot_vertex *= factor; + } + } } /* Helper for doing all the checks on whether a stroke can be drawn */ -static bool gpencil_can_draw_stroke( - struct MaterialGPencilStyle *gp_style, const bGPDstroke *gps, - const bool onion, const bool is_mat_preview) +static bool gpencil_can_draw_stroke(struct MaterialGPencilStyle *gp_style, + const bGPDstroke *gps, + const bool onion, + const bool is_mat_preview) { - /* skip stroke if it doesn't have any valid data */ - if ((gps->points == NULL) || (gps->totpoints < 1) || (gp_style == NULL)) { - return false; - } - - /* if mat preview render always visible */ - if (is_mat_preview) { - return true; - } - - /* check if the color is visible */ - if ((gp_style == NULL) || - (gp_style->flag & GP_STYLE_COLOR_HIDE) || - (onion && (gp_style->flag & GP_STYLE_COLOR_ONIONSKIN))) - { - return false; - } - - /* stroke can be drawn */ - return true; + /* skip stroke if it doesn't have any valid data */ + if ((gps->points == NULL) || (gps->totpoints < 1) || (gp_style == NULL)) { + return false; + } + + /* if mat preview render always visible */ + if (is_mat_preview) { + return true; + } + + /* check if the color is visible */ + if ((gp_style == NULL) || (gp_style->flag & GP_STYLE_COLOR_HIDE) || + (onion && (gp_style->flag & GP_STYLE_COLOR_ONIONSKIN))) { + return false; + } + + /* stroke can be drawn */ + return true; } /* calc bounding box in 2d using flat projection data */ -static void gpencil_calc_2d_bounding_box( - const float(*points2d)[2], int totpoints, float minv[2], float maxv[2]) +static void gpencil_calc_2d_bounding_box(const float (*points2d)[2], + int totpoints, + float minv[2], + float maxv[2]) { - minv[0] = points2d[0][0]; - minv[1] = points2d[0][1]; - maxv[0] = points2d[0][0]; - maxv[1] = points2d[0][1]; - - for (int i = 1; i < totpoints; i++) { - /* min */ - if (points2d[i][0] < minv[0]) { - minv[0] = points2d[i][0]; - } - if (points2d[i][1] < minv[1]) { - minv[1] = points2d[i][1]; - } - /* max */ - if (points2d[i][0] > maxv[0]) { - maxv[0] = points2d[i][0]; - } - if (points2d[i][1] > maxv[1]) { - maxv[1] = points2d[i][1]; - } - } - /* use a perfect square */ - if (maxv[0] > maxv[1]) { - maxv[1] = maxv[0]; - } - else { - maxv[0] = maxv[1]; - } + minv[0] = points2d[0][0]; + minv[1] = points2d[0][1]; + maxv[0] = points2d[0][0]; + maxv[1] = points2d[0][1]; + + for (int i = 1; i < totpoints; i++) { + /* min */ + if (points2d[i][0] < minv[0]) { + minv[0] = points2d[i][0]; + } + if (points2d[i][1] < minv[1]) { + minv[1] = points2d[i][1]; + } + /* max */ + if (points2d[i][0] > maxv[0]) { + maxv[0] = points2d[i][0]; + } + if (points2d[i][1] > maxv[1]) { + maxv[1] = points2d[i][1]; + } + } + /* use a perfect square */ + if (maxv[0] > maxv[1]) { + maxv[1] = maxv[0]; + } + else { + maxv[0] = maxv[1]; + } } /* calc texture coordinates using flat projected points */ static void gpencil_calc_stroke_fill_uv( - const float(*points2d)[2], int totpoints, float minv[2], float maxv[2], float(*r_uv)[2]) + const float (*points2d)[2], int totpoints, float minv[2], float maxv[2], float (*r_uv)[2]) { - float d[2]; - d[0] = maxv[0] - minv[0]; - d[1] = maxv[1] - minv[1]; - for (int i = 0; i < totpoints; i++) { - r_uv[i][0] = (points2d[i][0] - minv[0]) / d[0]; - r_uv[i][1] = (points2d[i][1] - minv[1]) / d[1]; - } + float d[2]; + d[0] = maxv[0] - minv[0]; + d[1] = maxv[1] - minv[1]; + for (int i = 0; i < totpoints; i++) { + r_uv[i][0] = (points2d[i][0] - minv[0]) / d[0]; + r_uv[i][1] = (points2d[i][1] - minv[1]) / d[1]; + } } /* recalc the internal geometry caches for fill and uvs */ -static void DRW_gpencil_recalc_geometry_caches( - Object *ob, bGPDlayer *gpl, MaterialGPencilStyle *gp_style, bGPDstroke *gps) +static void DRW_gpencil_recalc_geometry_caches(Object *ob, + bGPDlayer *gpl, + MaterialGPencilStyle *gp_style, + bGPDstroke *gps) { - if (gps->flag & GP_STROKE_RECALC_GEOMETRY) { - /* Calculate triangles cache for filling area (must be done only after changes) */ - if ((gps->tot_triangles == 0) || (gps->triangles == NULL)) { - if ((gps->totpoints > 2) && - ((gp_style->fill_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH) || - (gp_style->fill_style > 0) || (gpl->blend_mode != eGplBlendMode_Normal))) - { - DRW_gpencil_triangulate_stroke_fill(ob, gps); - } - } - - /* calc uv data along the stroke */ - ED_gpencil_calc_stroke_uv(ob, gps); - - /* clear flag */ - gps->flag &= ~GP_STROKE_RECALC_GEOMETRY; - } + if (gps->flag & GP_STROKE_RECALC_GEOMETRY) { + /* Calculate triangles cache for filling area (must be done only after changes) */ + if ((gps->tot_triangles == 0) || (gps->triangles == NULL)) { + if ((gps->totpoints > 2) && + ((gp_style->fill_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH) || (gp_style->fill_style > 0) || + (gpl->blend_mode != eGplBlendMode_Normal))) { + DRW_gpencil_triangulate_stroke_fill(ob, gps); + } + } + + /* calc uv data along the stroke */ + ED_gpencil_calc_stroke_uv(ob, gps); + + /* clear flag */ + gps->flag &= ~GP_STROKE_RECALC_GEOMETRY; + } } -static void set_wireframe_color( - Object *ob, bGPDlayer *gpl, View3D *v3d, - GPENCIL_StorageList *stl, - MaterialGPencilStyle *gp_style, int id, const bool is_fill) +static void set_wireframe_color(Object *ob, + bGPDlayer *gpl, + View3D *v3d, + GPENCIL_StorageList *stl, + MaterialGPencilStyle *gp_style, + int id, + const bool is_fill) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - World *world = draw_ctx->scene->world; - - float color[4]; - if (((gp_style->stroke_rgba[3] < GPENCIL_ALPHA_OPACITY_THRESH) || - (((gp_style->flag & GP_STYLE_STROKE_SHOW) == 0))) && - (gp_style->fill_rgba[3] >= GPENCIL_ALPHA_OPACITY_THRESH)) - { - copy_v4_v4(color, gp_style->fill_rgba); - } - else { - copy_v4_v4(color, gp_style->stroke_rgba); - } - float alpha = color[3]; - - /* wire color */ - if ((v3d) && (id > -1)) { - const char type = ( - (stl->shgroups[id].shading_type[0] == OB_WIRE) ? - v3d->shading.wire_color_type : - v3d->shading.color_type); - /* if fill and wire, use background color */ - if ((is_fill) && (stl->shgroups[id].shading_type[0] == OB_WIRE)) { - if (v3d->shading.background_type == V3D_SHADING_BACKGROUND_THEME) { - UI_GetThemeColor4fv(TH_BACK, stl->shgroups[id].wire_color); - stl->shgroups[id].wire_color[3] = 1.0f; - } - else if (v3d->shading.background_type == V3D_SHADING_BACKGROUND_WORLD) { - color[0] = world->horr; - color[1] = world->horg; - color[2] = world->horb; - color[3] = 1.0f; - linearrgb_to_srgb_v4(stl->shgroups[id].wire_color, color); - } - else { - copy_v3_v3(color, v3d->shading.background_color); - color[3] = 1.0f; - linearrgb_to_srgb_v4(stl->shgroups[id].wire_color, color); - } - return; - } - - /* strokes */ - switch (type) { - case V3D_SHADING_SINGLE_COLOR: - { - if (stl->shgroups[id].shading_type[0] == OB_WIRE) { - UI_GetThemeColor4fv(TH_WIRE, color); - } - else { - copy_v3_v3(color, v3d->shading.single_color); - } - color[3] = alpha; - linearrgb_to_srgb_v4(stl->shgroups[id].wire_color, color); - break; - } - case V3D_SHADING_OBJECT_COLOR: - { - copy_v4_v4(color, ob->color); - color[3] = alpha; - linearrgb_to_srgb_v4(stl->shgroups[id].wire_color, color); - break; - } - case V3D_SHADING_RANDOM_COLOR: - { - uint gpl_hash = 1; - uint ob_hash = BLI_ghashutil_strhash_p_murmur(ob->id.name); - if (gpl) { - gpl_hash = BLI_ghashutil_strhash_p_murmur(gpl->info); - } - - float hue = BLI_hash_int_01(ob_hash * gpl_hash); - float hsv[3] = { hue, 0.40f, 0.8f }; - float wire_col[3]; - hsv_to_rgb_v(hsv, &wire_col[0]); - - stl->shgroups[id].wire_color[0] = wire_col[0]; - stl->shgroups[id].wire_color[1] = wire_col[1]; - stl->shgroups[id].wire_color[2] = wire_col[2]; - stl->shgroups[id].wire_color[3] = alpha; - break; - } - default: - { - copy_v4_v4(stl->shgroups[id].wire_color, color); - break; - } - } - } - else { - copy_v4_v4(stl->shgroups[id].wire_color, color); - } - - /* if solid, the alpha must be set to 1.0 */ - if (stl->shgroups[id].shading_type[0] == OB_SOLID) { - stl->shgroups[id].wire_color[3] = 1.0f; - } + const DRWContextState *draw_ctx = DRW_context_state_get(); + World *world = draw_ctx->scene->world; + + float color[4]; + if (((gp_style->stroke_rgba[3] < GPENCIL_ALPHA_OPACITY_THRESH) || + (((gp_style->flag & GP_STYLE_STROKE_SHOW) == 0))) && + (gp_style->fill_rgba[3] >= GPENCIL_ALPHA_OPACITY_THRESH)) { + copy_v4_v4(color, gp_style->fill_rgba); + } + else { + copy_v4_v4(color, gp_style->stroke_rgba); + } + float alpha = color[3]; + + /* wire color */ + if ((v3d) && (id > -1)) { + const char type = ((stl->shgroups[id].shading_type[0] == OB_WIRE) ? + v3d->shading.wire_color_type : + v3d->shading.color_type); + /* if fill and wire, use background color */ + if ((is_fill) && (stl->shgroups[id].shading_type[0] == OB_WIRE)) { + if (v3d->shading.background_type == V3D_SHADING_BACKGROUND_THEME) { + UI_GetThemeColor4fv(TH_BACK, stl->shgroups[id].wire_color); + stl->shgroups[id].wire_color[3] = 1.0f; + } + else if (v3d->shading.background_type == V3D_SHADING_BACKGROUND_WORLD) { + color[0] = world->horr; + color[1] = world->horg; + color[2] = world->horb; + color[3] = 1.0f; + linearrgb_to_srgb_v4(stl->shgroups[id].wire_color, color); + } + else { + copy_v3_v3(color, v3d->shading.background_color); + color[3] = 1.0f; + linearrgb_to_srgb_v4(stl->shgroups[id].wire_color, color); + } + return; + } + + /* strokes */ + switch (type) { + case V3D_SHADING_SINGLE_COLOR: { + if (stl->shgroups[id].shading_type[0] == OB_WIRE) { + UI_GetThemeColor4fv(TH_WIRE, color); + } + else { + copy_v3_v3(color, v3d->shading.single_color); + } + color[3] = alpha; + linearrgb_to_srgb_v4(stl->shgroups[id].wire_color, color); + break; + } + case V3D_SHADING_OBJECT_COLOR: { + copy_v4_v4(color, ob->color); + color[3] = alpha; + linearrgb_to_srgb_v4(stl->shgroups[id].wire_color, color); + break; + } + case V3D_SHADING_RANDOM_COLOR: { + uint gpl_hash = 1; + uint ob_hash = BLI_ghashutil_strhash_p_murmur(ob->id.name); + if (gpl) { + gpl_hash = BLI_ghashutil_strhash_p_murmur(gpl->info); + } + + float hue = BLI_hash_int_01(ob_hash * gpl_hash); + float hsv[3] = {hue, 0.40f, 0.8f}; + float wire_col[3]; + hsv_to_rgb_v(hsv, &wire_col[0]); + + stl->shgroups[id].wire_color[0] = wire_col[0]; + stl->shgroups[id].wire_color[1] = wire_col[1]; + stl->shgroups[id].wire_color[2] = wire_col[2]; + stl->shgroups[id].wire_color[3] = alpha; + break; + } + default: { + copy_v4_v4(stl->shgroups[id].wire_color, color); + break; + } + } + } + else { + copy_v4_v4(stl->shgroups[id].wire_color, color); + } + + /* if solid, the alpha must be set to 1.0 */ + if (stl->shgroups[id].shading_type[0] == OB_SOLID) { + stl->shgroups[id].wire_color[3] = 1.0f; + } } /* create shading group for filling */ -static DRWShadingGroup *DRW_gpencil_shgroup_fill_create( - GPENCIL_e_data *e_data, GPENCIL_Data *vedata, DRWPass *pass, - GPUShader *shader, Object *ob, bGPdata *gpd, bGPDlayer *gpl, - MaterialGPencilStyle *gp_style, int id, int shading_type[2]) +static DRWShadingGroup *DRW_gpencil_shgroup_fill_create(GPENCIL_e_data *e_data, + GPENCIL_Data *vedata, + DRWPass *pass, + GPUShader *shader, + Object *ob, + bGPdata *gpd, + bGPDlayer *gpl, + MaterialGPencilStyle *gp_style, + int id, + int shading_type[2]) { - GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; - const DRWContextState *draw_ctx = DRW_context_state_get(); - View3D *v3d = draw_ctx->v3d; - - /* e_data.gpencil_fill_sh */ - DRWShadingGroup *grp = DRW_shgroup_create(shader, pass); - - DRW_shgroup_uniform_vec4(grp, "color2", gp_style->mix_rgba, 1); - - /* set style type */ - switch (gp_style->fill_style) { - case GP_STYLE_FILL_STYLE_SOLID: - stl->shgroups[id].fill_style = SOLID; - break; - case GP_STYLE_FILL_STYLE_GRADIENT: - if (gp_style->gradient_type == GP_STYLE_GRADIENT_LINEAR) { - stl->shgroups[id].fill_style = GRADIENT; - } - else { - stl->shgroups[id].fill_style = RADIAL; - } - break; - case GP_STYLE_FILL_STYLE_CHESSBOARD: - stl->shgroups[id].fill_style = CHESS; - break; - case GP_STYLE_FILL_STYLE_TEXTURE: - if (gp_style->flag & GP_STYLE_FILL_PATTERN) { - stl->shgroups[id].fill_style = PATTERN; - } - else { - stl->shgroups[id].fill_style = TEXTURE; - } - break; - default: - stl->shgroups[id].fill_style = GP_STYLE_FILL_STYLE_SOLID; - break; - } - DRW_shgroup_uniform_int(grp, "fill_type", &stl->shgroups[id].fill_style, 1); - - DRW_shgroup_uniform_float(grp, "mix_factor", &gp_style->mix_factor, 1); - - DRW_shgroup_uniform_float(grp, "gradient_angle", &gp_style->gradient_angle, 1); - DRW_shgroup_uniform_float(grp, "gradient_radius", &gp_style->gradient_radius, 1); - DRW_shgroup_uniform_float(grp, "pattern_gridsize", &gp_style->pattern_gridsize, 1); - DRW_shgroup_uniform_vec2(grp, "gradient_scale", gp_style->gradient_scale, 1); - DRW_shgroup_uniform_vec2(grp, "gradient_shift", gp_style->gradient_shift, 1); - - DRW_shgroup_uniform_float(grp, "texture_angle", &gp_style->texture_angle, 1); - DRW_shgroup_uniform_vec2(grp, "texture_scale", gp_style->texture_scale, 1); - DRW_shgroup_uniform_vec2(grp, "texture_offset", gp_style->texture_offset, 1); - DRW_shgroup_uniform_float(grp, "texture_opacity", &gp_style->texture_opacity, 1); - DRW_shgroup_uniform_float(grp, "layer_opacity", &gpl->opacity, 1); - - stl->shgroups[id].texture_mix = gp_style->flag & GP_STYLE_COLOR_TEX_MIX ? 1 : 0; - DRW_shgroup_uniform_int(grp, "texture_mix", &stl->shgroups[id].texture_mix, 1); - - stl->shgroups[id].texture_flip = gp_style->flag & GP_STYLE_COLOR_FLIP_FILL ? 1 : 0; - DRW_shgroup_uniform_int(grp, "texture_flip", &stl->shgroups[id].texture_flip, 1); - - stl->shgroups[id].xray_mode = (ob->dtx & OB_DRAWXRAY) ? GP_XRAY_FRONT : GP_XRAY_3DSPACE; - DRW_shgroup_uniform_int(grp, "xraymode", &stl->shgroups[id].xray_mode, 1); - DRW_shgroup_uniform_int(grp, "drawmode", (const int *) &gpd->draw_mode, 1); - - /* viewport x-ray */ - stl->shgroups[id].is_xray = (ob->dt == OB_WIRE) ? 1 : stl->storage->is_xray; - DRW_shgroup_uniform_int(grp, "viewport_xray", (const int *)&stl->shgroups[id].is_xray, 1); - - /* shading type */ - stl->shgroups[id].shading_type[0] = GPENCIL_USE_SOLID(stl) ? (int)OB_RENDER : shading_type[0]; - if (v3d) { - stl->shgroups[id].shading_type[1] = ( - (stl->shgroups[id].shading_type[0] == OB_WIRE) ? - v3d->shading.wire_color_type : - v3d->shading.color_type); - } - - DRW_shgroup_uniform_int(grp, "shading_type", &stl->shgroups[id].shading_type[0], 2); - - /* wire color */ - set_wireframe_color(ob, gpl, v3d, stl, gp_style, id, true); - DRW_shgroup_uniform_vec4(grp, "wire_color", stl->shgroups[id].wire_color, 1); - - /* image texture */ - if ((gp_style->flag & GP_STYLE_COLOR_TEX_MIX) || - (gp_style->fill_style & GP_STYLE_FILL_STYLE_TEXTURE)) - { - ImBuf *ibuf; - Image *image = gp_style->ima; - ImageUser iuser = { NULL }; - void *lock; - - iuser.ok = true; - - ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock); - - if (ibuf == NULL || ibuf->rect == NULL) { - BKE_image_release_ibuf(image, ibuf, NULL); - } - else { - GPUTexture *texture = GPU_texture_from_blender(gp_style->ima, &iuser, GL_TEXTURE_2D, true); - DRW_shgroup_uniform_texture(grp, "myTexture", texture); - - stl->shgroups[id].texture_clamp = gp_style->flag & GP_STYLE_COLOR_TEX_CLAMP ? 1 : 0; - DRW_shgroup_uniform_int(grp, "texture_clamp", &stl->shgroups[id].texture_clamp, 1); - - BKE_image_release_ibuf(image, ibuf, NULL); - } - } - else { - /* if no texture defined, need a blank texture to avoid errors in draw manager */ - DRW_shgroup_uniform_texture(grp, "myTexture", e_data->gpencil_blank_texture); - stl->shgroups[id].texture_clamp = 0; - DRW_shgroup_uniform_int(grp, "texture_clamp", &stl->shgroups[id].texture_clamp, 1); - } - - return grp; + GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + View3D *v3d = draw_ctx->v3d; + + /* e_data.gpencil_fill_sh */ + DRWShadingGroup *grp = DRW_shgroup_create(shader, pass); + + DRW_shgroup_uniform_vec4(grp, "color2", gp_style->mix_rgba, 1); + + /* set style type */ + switch (gp_style->fill_style) { + case GP_STYLE_FILL_STYLE_SOLID: + stl->shgroups[id].fill_style = SOLID; + break; + case GP_STYLE_FILL_STYLE_GRADIENT: + if (gp_style->gradient_type == GP_STYLE_GRADIENT_LINEAR) { + stl->shgroups[id].fill_style = GRADIENT; + } + else { + stl->shgroups[id].fill_style = RADIAL; + } + break; + case GP_STYLE_FILL_STYLE_CHESSBOARD: + stl->shgroups[id].fill_style = CHESS; + break; + case GP_STYLE_FILL_STYLE_TEXTURE: + if (gp_style->flag & GP_STYLE_FILL_PATTERN) { + stl->shgroups[id].fill_style = PATTERN; + } + else { + stl->shgroups[id].fill_style = TEXTURE; + } + break; + default: + stl->shgroups[id].fill_style = GP_STYLE_FILL_STYLE_SOLID; + break; + } + DRW_shgroup_uniform_int(grp, "fill_type", &stl->shgroups[id].fill_style, 1); + + DRW_shgroup_uniform_float(grp, "mix_factor", &gp_style->mix_factor, 1); + + DRW_shgroup_uniform_float(grp, "gradient_angle", &gp_style->gradient_angle, 1); + DRW_shgroup_uniform_float(grp, "gradient_radius", &gp_style->gradient_radius, 1); + DRW_shgroup_uniform_float(grp, "pattern_gridsize", &gp_style->pattern_gridsize, 1); + DRW_shgroup_uniform_vec2(grp, "gradient_scale", gp_style->gradient_scale, 1); + DRW_shgroup_uniform_vec2(grp, "gradient_shift", gp_style->gradient_shift, 1); + + DRW_shgroup_uniform_float(grp, "texture_angle", &gp_style->texture_angle, 1); + DRW_shgroup_uniform_vec2(grp, "texture_scale", gp_style->texture_scale, 1); + DRW_shgroup_uniform_vec2(grp, "texture_offset", gp_style->texture_offset, 1); + DRW_shgroup_uniform_float(grp, "texture_opacity", &gp_style->texture_opacity, 1); + DRW_shgroup_uniform_float(grp, "layer_opacity", &gpl->opacity, 1); + + stl->shgroups[id].texture_mix = gp_style->flag & GP_STYLE_COLOR_TEX_MIX ? 1 : 0; + DRW_shgroup_uniform_int(grp, "texture_mix", &stl->shgroups[id].texture_mix, 1); + + stl->shgroups[id].texture_flip = gp_style->flag & GP_STYLE_COLOR_FLIP_FILL ? 1 : 0; + DRW_shgroup_uniform_int(grp, "texture_flip", &stl->shgroups[id].texture_flip, 1); + + stl->shgroups[id].xray_mode = (ob->dtx & OB_DRAWXRAY) ? GP_XRAY_FRONT : GP_XRAY_3DSPACE; + DRW_shgroup_uniform_int(grp, "xraymode", &stl->shgroups[id].xray_mode, 1); + DRW_shgroup_uniform_int(grp, "drawmode", (const int *)&gpd->draw_mode, 1); + + /* viewport x-ray */ + stl->shgroups[id].is_xray = (ob->dt == OB_WIRE) ? 1 : stl->storage->is_xray; + DRW_shgroup_uniform_int(grp, "viewport_xray", (const int *)&stl->shgroups[id].is_xray, 1); + + /* shading type */ + stl->shgroups[id].shading_type[0] = GPENCIL_USE_SOLID(stl) ? (int)OB_RENDER : shading_type[0]; + if (v3d) { + stl->shgroups[id].shading_type[1] = ((stl->shgroups[id].shading_type[0] == OB_WIRE) ? + v3d->shading.wire_color_type : + v3d->shading.color_type); + } + + DRW_shgroup_uniform_int(grp, "shading_type", &stl->shgroups[id].shading_type[0], 2); + + /* wire color */ + set_wireframe_color(ob, gpl, v3d, stl, gp_style, id, true); + DRW_shgroup_uniform_vec4(grp, "wire_color", stl->shgroups[id].wire_color, 1); + + /* image texture */ + if ((gp_style->flag & GP_STYLE_COLOR_TEX_MIX) || + (gp_style->fill_style & GP_STYLE_FILL_STYLE_TEXTURE)) { + ImBuf *ibuf; + Image *image = gp_style->ima; + ImageUser iuser = {NULL}; + void *lock; + + iuser.ok = true; + + ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock); + + if (ibuf == NULL || ibuf->rect == NULL) { + BKE_image_release_ibuf(image, ibuf, NULL); + } + else { + GPUTexture *texture = GPU_texture_from_blender(gp_style->ima, &iuser, GL_TEXTURE_2D, true); + DRW_shgroup_uniform_texture(grp, "myTexture", texture); + + stl->shgroups[id].texture_clamp = gp_style->flag & GP_STYLE_COLOR_TEX_CLAMP ? 1 : 0; + DRW_shgroup_uniform_int(grp, "texture_clamp", &stl->shgroups[id].texture_clamp, 1); + + BKE_image_release_ibuf(image, ibuf, NULL); + } + } + else { + /* if no texture defined, need a blank texture to avoid errors in draw manager */ + DRW_shgroup_uniform_texture(grp, "myTexture", e_data->gpencil_blank_texture); + stl->shgroups[id].texture_clamp = 0; + DRW_shgroup_uniform_int(grp, "texture_clamp", &stl->shgroups[id].texture_clamp, 1); + } + + return grp; } /* check if some onion is enabled */ bool DRW_gpencil_onion_active(bGPdata *gpd) { - for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { - if (gpl->onion_flag & GP_LAYER_ONIONSKIN) { - return true; - } - } - return false; + for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { + if (gpl->onion_flag & GP_LAYER_ONIONSKIN) { + return true; + } + } + return false; } /* create shading group for strokes */ -DRWShadingGroup *DRW_gpencil_shgroup_stroke_create( - GPENCIL_e_data *e_data, GPENCIL_Data *vedata, DRWPass *pass, GPUShader *shader, Object *ob, - bGPdata *gpd, bGPDlayer *gpl, bGPDstroke *gps, - MaterialGPencilStyle *gp_style, int id, - bool onion, const float scale, const int shading_type[2]) +DRWShadingGroup *DRW_gpencil_shgroup_stroke_create(GPENCIL_e_data *e_data, + GPENCIL_Data *vedata, + DRWPass *pass, + GPUShader *shader, + Object *ob, + bGPdata *gpd, + bGPDlayer *gpl, + bGPDstroke *gps, + MaterialGPencilStyle *gp_style, + int id, + bool onion, + const float scale, + const int shading_type[2]) { - GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; - const float *viewport_size = DRW_viewport_size_get(); - const DRWContextState *draw_ctx = DRW_context_state_get(); - View3D *v3d = draw_ctx->v3d; - - /* e_data.gpencil_stroke_sh */ - DRWShadingGroup *grp = DRW_shgroup_create(shader, pass); - - DRW_shgroup_uniform_vec2(grp, "Viewport", viewport_size, 1); - - DRW_shgroup_uniform_float(grp, "pixsize", stl->storage->pixsize, 1); - - /* avoid wrong values */ - if ((gpd) && (gpd->pixfactor == 0.0f)) { - gpd->pixfactor = GP_DEFAULT_PIX_FACTOR; - } - - /* object scale and depth */ - if ((ob) && (id > -1)) { - stl->shgroups[id].obj_scale = scale; - DRW_shgroup_uniform_float(grp, "objscale", &stl->shgroups[id].obj_scale, 1); - stl->shgroups[id].keep_size = (int)((gpd) && (gpd->flag & GP_DATA_STROKE_KEEPTHICKNESS)); - DRW_shgroup_uniform_int(grp, "keep_size", &stl->shgroups[id].keep_size, 1); - - stl->shgroups[id].stroke_style = gp_style->stroke_style; - stl->shgroups[id].color_type = GPENCIL_COLOR_SOLID; - if ((gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE) && (!onion)) { - stl->shgroups[id].color_type = GPENCIL_COLOR_TEXTURE; - if (gp_style->flag & GP_STYLE_STROKE_PATTERN) { - stl->shgroups[id].color_type = GPENCIL_COLOR_PATTERN; - } - } - DRW_shgroup_uniform_int(grp, "color_type", &stl->shgroups[id].color_type, 1); - DRW_shgroup_uniform_float(grp, "pixfactor", &gpd->pixfactor, 1); - - stl->shgroups[id].caps_mode[0] = gps->caps[0]; - stl->shgroups[id].caps_mode[1] = gps->caps[1]; - DRW_shgroup_uniform_int(grp, "caps_mode", &stl->shgroups[id].caps_mode[0], 2); - - stl->shgroups[id].gradient_f = gps->gradient_f; - copy_v2_v2(stl->shgroups[id].gradient_s, gps->gradient_s); - DRW_shgroup_uniform_float(grp, "gradient_f", &stl->shgroups[id].gradient_f, 1); - - /* viewport x-ray */ - stl->shgroups[id].is_xray = (ob->dt == OB_WIRE) ? 1 : stl->storage->is_xray; - DRW_shgroup_uniform_int(grp, "viewport_xray", (const int *)&stl->shgroups[id].is_xray, 1); - - stl->shgroups[id].shading_type[0] = (GPENCIL_USE_SOLID(stl) || onion) ? (int)OB_RENDER : shading_type[0]; - if (v3d) { - stl->shgroups[id].shading_type[1] = ( - (stl->shgroups[id].shading_type[0] == OB_WIRE) ? - v3d->shading.wire_color_type : - v3d->shading.color_type); - } - DRW_shgroup_uniform_int(grp, "shading_type", &stl->shgroups[id].shading_type[0], 2); - - /* wire color */ - set_wireframe_color(ob, gpl, v3d, stl, gp_style, id, false); - DRW_shgroup_uniform_vec4(grp, "wire_color", stl->shgroups[id].wire_color, 1); - } - else { - stl->storage->obj_scale = 1.0f; - stl->storage->keep_size = 0; - stl->storage->pixfactor = GP_DEFAULT_PIX_FACTOR; - DRW_shgroup_uniform_float(grp, "objscale", &stl->storage->obj_scale, 1); - DRW_shgroup_uniform_int(grp, "keep_size", &stl->storage->keep_size, 1); - DRW_shgroup_uniform_int(grp, "color_type", &stl->storage->color_type, 1); - if (gpd) { - DRW_shgroup_uniform_float(grp, "pixfactor", &gpd->pixfactor, 1); - } - else { - DRW_shgroup_uniform_float(grp, "pixfactor", &stl->storage->pixfactor, 1); - } - const int zero[2] = { 0, 0 }; - DRW_shgroup_uniform_int(grp, "caps_mode", &zero[0], 2); - - DRW_shgroup_uniform_float(grp, "gradient_f", &stl->storage->gradient_f, 1); - - /* viewport x-ray */ - DRW_shgroup_uniform_int(grp, "viewport_xray", &stl->storage->is_xray, 1); - DRW_shgroup_uniform_int(grp, "shading_type", (const int *)&stl->storage->shade_render, 2); - } - - if ((gpd) && (id > -1)) { - stl->shgroups[id].xray_mode = (ob->dtx & OB_DRAWXRAY) ? GP_XRAY_FRONT : GP_XRAY_3DSPACE; - DRW_shgroup_uniform_int(grp, "xraymode", &stl->shgroups[id].xray_mode, 1); - } - else { - /* for drawing always on predefined z-depth */ - DRW_shgroup_uniform_int(grp, "xraymode", &stl->storage->xray, 1); - } - - /* image texture for pattern */ - if ((gp_style) && (gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE) && (!onion)) { - ImBuf *ibuf; - Image *image = gp_style->sima; - ImageUser iuser = { NULL }; - void *lock; - - iuser.ok = true; - - ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock); - - if (ibuf == NULL || ibuf->rect == NULL) { - BKE_image_release_ibuf(image, ibuf, NULL); - } - else { - GPUTexture *texture = GPU_texture_from_blender(gp_style->sima, &iuser, GL_TEXTURE_2D, true); - DRW_shgroup_uniform_texture(grp, "myTexture", texture); - - BKE_image_release_ibuf(image, ibuf, NULL); - } - } - else { - /* if no texture defined, need a blank texture to avoid errors in draw manager */ - DRW_shgroup_uniform_texture(grp, "myTexture", e_data->gpencil_blank_texture); - } - - return grp; + GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; + const float *viewport_size = DRW_viewport_size_get(); + const DRWContextState *draw_ctx = DRW_context_state_get(); + View3D *v3d = draw_ctx->v3d; + + /* e_data.gpencil_stroke_sh */ + DRWShadingGroup *grp = DRW_shgroup_create(shader, pass); + + DRW_shgroup_uniform_vec2(grp, "Viewport", viewport_size, 1); + + DRW_shgroup_uniform_float(grp, "pixsize", stl->storage->pixsize, 1); + + /* avoid wrong values */ + if ((gpd) && (gpd->pixfactor == 0.0f)) { + gpd->pixfactor = GP_DEFAULT_PIX_FACTOR; + } + + /* object scale and depth */ + if ((ob) && (id > -1)) { + stl->shgroups[id].obj_scale = scale; + DRW_shgroup_uniform_float(grp, "objscale", &stl->shgroups[id].obj_scale, 1); + stl->shgroups[id].keep_size = (int)((gpd) && (gpd->flag & GP_DATA_STROKE_KEEPTHICKNESS)); + DRW_shgroup_uniform_int(grp, "keep_size", &stl->shgroups[id].keep_size, 1); + + stl->shgroups[id].stroke_style = gp_style->stroke_style; + stl->shgroups[id].color_type = GPENCIL_COLOR_SOLID; + if ((gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE) && (!onion)) { + stl->shgroups[id].color_type = GPENCIL_COLOR_TEXTURE; + if (gp_style->flag & GP_STYLE_STROKE_PATTERN) { + stl->shgroups[id].color_type = GPENCIL_COLOR_PATTERN; + } + } + DRW_shgroup_uniform_int(grp, "color_type", &stl->shgroups[id].color_type, 1); + DRW_shgroup_uniform_float(grp, "pixfactor", &gpd->pixfactor, 1); + + stl->shgroups[id].caps_mode[0] = gps->caps[0]; + stl->shgroups[id].caps_mode[1] = gps->caps[1]; + DRW_shgroup_uniform_int(grp, "caps_mode", &stl->shgroups[id].caps_mode[0], 2); + + stl->shgroups[id].gradient_f = gps->gradient_f; + copy_v2_v2(stl->shgroups[id].gradient_s, gps->gradient_s); + DRW_shgroup_uniform_float(grp, "gradient_f", &stl->shgroups[id].gradient_f, 1); + + /* viewport x-ray */ + stl->shgroups[id].is_xray = (ob->dt == OB_WIRE) ? 1 : stl->storage->is_xray; + DRW_shgroup_uniform_int(grp, "viewport_xray", (const int *)&stl->shgroups[id].is_xray, 1); + + stl->shgroups[id].shading_type[0] = (GPENCIL_USE_SOLID(stl) || onion) ? (int)OB_RENDER : + shading_type[0]; + if (v3d) { + stl->shgroups[id].shading_type[1] = ((stl->shgroups[id].shading_type[0] == OB_WIRE) ? + v3d->shading.wire_color_type : + v3d->shading.color_type); + } + DRW_shgroup_uniform_int(grp, "shading_type", &stl->shgroups[id].shading_type[0], 2); + + /* wire color */ + set_wireframe_color(ob, gpl, v3d, stl, gp_style, id, false); + DRW_shgroup_uniform_vec4(grp, "wire_color", stl->shgroups[id].wire_color, 1); + } + else { + stl->storage->obj_scale = 1.0f; + stl->storage->keep_size = 0; + stl->storage->pixfactor = GP_DEFAULT_PIX_FACTOR; + DRW_shgroup_uniform_float(grp, "objscale", &stl->storage->obj_scale, 1); + DRW_shgroup_uniform_int(grp, "keep_size", &stl->storage->keep_size, 1); + DRW_shgroup_uniform_int(grp, "color_type", &stl->storage->color_type, 1); + if (gpd) { + DRW_shgroup_uniform_float(grp, "pixfactor", &gpd->pixfactor, 1); + } + else { + DRW_shgroup_uniform_float(grp, "pixfactor", &stl->storage->pixfactor, 1); + } + const int zero[2] = {0, 0}; + DRW_shgroup_uniform_int(grp, "caps_mode", &zero[0], 2); + + DRW_shgroup_uniform_float(grp, "gradient_f", &stl->storage->gradient_f, 1); + + /* viewport x-ray */ + DRW_shgroup_uniform_int(grp, "viewport_xray", &stl->storage->is_xray, 1); + DRW_shgroup_uniform_int(grp, "shading_type", (const int *)&stl->storage->shade_render, 2); + } + + if ((gpd) && (id > -1)) { + stl->shgroups[id].xray_mode = (ob->dtx & OB_DRAWXRAY) ? GP_XRAY_FRONT : GP_XRAY_3DSPACE; + DRW_shgroup_uniform_int(grp, "xraymode", &stl->shgroups[id].xray_mode, 1); + } + else { + /* for drawing always on predefined z-depth */ + DRW_shgroup_uniform_int(grp, "xraymode", &stl->storage->xray, 1); + } + + /* image texture for pattern */ + if ((gp_style) && (gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE) && (!onion)) { + ImBuf *ibuf; + Image *image = gp_style->sima; + ImageUser iuser = {NULL}; + void *lock; + + iuser.ok = true; + + ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock); + + if (ibuf == NULL || ibuf->rect == NULL) { + BKE_image_release_ibuf(image, ibuf, NULL); + } + else { + GPUTexture *texture = GPU_texture_from_blender(gp_style->sima, &iuser, GL_TEXTURE_2D, true); + DRW_shgroup_uniform_texture(grp, "myTexture", texture); + + BKE_image_release_ibuf(image, ibuf, NULL); + } + } + else { + /* if no texture defined, need a blank texture to avoid errors in draw manager */ + DRW_shgroup_uniform_texture(grp, "myTexture", e_data->gpencil_blank_texture); + } + + return grp; } /* create shading group for points */ -static DRWShadingGroup *DRW_gpencil_shgroup_point_create( - GPENCIL_e_data *e_data, GPENCIL_Data *vedata, DRWPass *pass, GPUShader *shader, Object *ob, - bGPdata *gpd, bGPDlayer *gpl, bGPDstroke *gps, - MaterialGPencilStyle *gp_style, int id, bool onion, - const float scale, const int shading_type[2]) +static DRWShadingGroup *DRW_gpencil_shgroup_point_create(GPENCIL_e_data *e_data, + GPENCIL_Data *vedata, + DRWPass *pass, + GPUShader *shader, + Object *ob, + bGPdata *gpd, + bGPDlayer *gpl, + bGPDstroke *gps, + MaterialGPencilStyle *gp_style, + int id, + bool onion, + const float scale, + const int shading_type[2]) { - GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; - const float *viewport_size = DRW_viewport_size_get(); - const DRWContextState *draw_ctx = DRW_context_state_get(); - View3D *v3d = draw_ctx->v3d; - - /* e_data.gpencil_stroke_sh */ - DRWShadingGroup *grp = DRW_shgroup_create(shader, pass); - - DRW_shgroup_uniform_vec2(grp, "Viewport", viewport_size, 1); - DRW_shgroup_uniform_float(grp, "pixsize", stl->storage->pixsize, 1); - - /* avoid wrong values */ - if ((gpd) && (gpd->pixfactor == 0.0f)) { - gpd->pixfactor = GP_DEFAULT_PIX_FACTOR; - } - - /* object scale and depth */ - if ((ob) && (id > -1)) { - stl->shgroups[id].obj_scale = scale; - DRW_shgroup_uniform_float(grp, "objscale", &stl->shgroups[id].obj_scale, 1); - stl->shgroups[id].keep_size = (int)((gpd) && (gpd->flag & GP_DATA_STROKE_KEEPTHICKNESS)); - DRW_shgroup_uniform_int(grp, "keep_size", &stl->shgroups[id].keep_size, 1); - - stl->shgroups[id].mode = gp_style->mode; - stl->shgroups[id].stroke_style = gp_style->stroke_style; - stl->shgroups[id].color_type = GPENCIL_COLOR_SOLID; - if ((gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE) && (!onion)) { - stl->shgroups[id].color_type = GPENCIL_COLOR_TEXTURE; - if (gp_style->flag & GP_STYLE_STROKE_PATTERN) { - stl->shgroups[id].color_type = GPENCIL_COLOR_PATTERN; - } - } - DRW_shgroup_uniform_int(grp, "color_type", &stl->shgroups[id].color_type, 1); - DRW_shgroup_uniform_int(grp, "mode", &stl->shgroups[id].mode, 1); - DRW_shgroup_uniform_float(grp, "pixfactor", &gpd->pixfactor, 1); - - stl->shgroups[id].gradient_f = gps->gradient_f; - copy_v2_v2(stl->shgroups[id].gradient_s, gps->gradient_s); - DRW_shgroup_uniform_float(grp, "gradient_f", &stl->shgroups[id].gradient_f, 1); - DRW_shgroup_uniform_vec2(grp, "gradient_s", stl->shgroups[id].gradient_s, 1); - - /* viewport x-ray */ - stl->shgroups[id].is_xray = (ob->dt == OB_WIRE) ? 1 : stl->storage->is_xray; - DRW_shgroup_uniform_int(grp, "viewport_xray", (const int *)&stl->shgroups[id].is_xray, 1); - - stl->shgroups[id].shading_type[0] = (GPENCIL_USE_SOLID(stl) || onion) ? (int)OB_RENDER : shading_type[0]; - if (v3d) { - stl->shgroups[id].shading_type[1] = ( - (stl->shgroups[id].shading_type[0] == OB_WIRE) ? - v3d->shading.wire_color_type : - v3d->shading.color_type); - } - DRW_shgroup_uniform_int(grp, "shading_type", &stl->shgroups[id].shading_type[0], 2); - - /* wire color */ - set_wireframe_color(ob, gpl, v3d, stl, gp_style, id, false); - DRW_shgroup_uniform_vec4(grp, "wire_color", stl->shgroups[id].wire_color, 1); - - } - else { - stl->storage->obj_scale = 1.0f; - stl->storage->keep_size = 0; - stl->storage->pixfactor = GP_DEFAULT_PIX_FACTOR; - stl->storage->mode = gp_style->mode; - DRW_shgroup_uniform_float(grp, "objscale", &stl->storage->obj_scale, 1); - DRW_shgroup_uniform_int(grp, "keep_size", &stl->storage->keep_size, 1); - DRW_shgroup_uniform_int(grp, "color_type", &stl->storage->color_type, 1); - DRW_shgroup_uniform_int(grp, "mode", &stl->storage->mode, 1); - if (gpd) { - DRW_shgroup_uniform_float(grp, "pixfactor", &gpd->pixfactor, 1); - } - else { - DRW_shgroup_uniform_float(grp, "pixfactor", &stl->storage->pixfactor, 1); - } - - DRW_shgroup_uniform_float(grp, "gradient_f", &stl->storage->gradient_f, 1); - DRW_shgroup_uniform_vec2(grp, "gradient_s", stl->storage->gradient_s, 1); - - /* viewport x-ray */ - stl->shgroups[id].is_xray = ((ob) && (ob->dt == OB_WIRE)) ? 1 : stl->storage->is_xray; - DRW_shgroup_uniform_int(grp, "viewport_xray", (const int *)&stl->shgroups[id].is_xray, 1); - DRW_shgroup_uniform_int(grp, "shading_type", (const int *)&stl->storage->shade_render, 2); - } - - if ((gpd) && (id > -1)) { - stl->shgroups[id].xray_mode = (ob->dtx & OB_DRAWXRAY) ? GP_XRAY_FRONT : GP_XRAY_3DSPACE; - DRW_shgroup_uniform_int(grp, "xraymode", (const int *)&stl->shgroups[id].xray_mode, 1); - - /* lock rotation of dots and boxes */ - stl->shgroups[id].use_follow_path = (gp_style->flag & GP_STYLE_COLOR_LOCK_DOTS) ? 0 : 1; - DRW_shgroup_uniform_int(grp, "use_follow_path", &stl->shgroups[id].use_follow_path, 1); - } - else { - /* for drawing always on predefined z-depth */ - DRW_shgroup_uniform_int(grp, "xraymode", &stl->storage->xray, 1); - - /* lock rotation of dots and boxes */ - DRW_shgroup_uniform_int(grp, "use_follow_path", &stl->storage->use_follow_path, 1); - } - - - - /* image texture */ - if ((gp_style) && (gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE) && (!onion)) { - ImBuf *ibuf; - Image *image = gp_style->sima; - ImageUser iuser = { NULL }; - void *lock; - - iuser.ok = true; - - ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock); - - if (ibuf == NULL || ibuf->rect == NULL) { - BKE_image_release_ibuf(image, ibuf, NULL); - } - else { - GPUTexture *texture = GPU_texture_from_blender(gp_style->sima, &iuser, GL_TEXTURE_2D, true); - DRW_shgroup_uniform_texture(grp, "myTexture", texture); - - BKE_image_release_ibuf(image, ibuf, NULL); - } - } - else { - /* if no texture defined, need a blank texture to avoid errors in draw manager */ - DRW_shgroup_uniform_texture(grp, "myTexture", e_data->gpencil_blank_texture); - } - - return grp; + GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; + const float *viewport_size = DRW_viewport_size_get(); + const DRWContextState *draw_ctx = DRW_context_state_get(); + View3D *v3d = draw_ctx->v3d; + + /* e_data.gpencil_stroke_sh */ + DRWShadingGroup *grp = DRW_shgroup_create(shader, pass); + + DRW_shgroup_uniform_vec2(grp, "Viewport", viewport_size, 1); + DRW_shgroup_uniform_float(grp, "pixsize", stl->storage->pixsize, 1); + + /* avoid wrong values */ + if ((gpd) && (gpd->pixfactor == 0.0f)) { + gpd->pixfactor = GP_DEFAULT_PIX_FACTOR; + } + + /* object scale and depth */ + if ((ob) && (id > -1)) { + stl->shgroups[id].obj_scale = scale; + DRW_shgroup_uniform_float(grp, "objscale", &stl->shgroups[id].obj_scale, 1); + stl->shgroups[id].keep_size = (int)((gpd) && (gpd->flag & GP_DATA_STROKE_KEEPTHICKNESS)); + DRW_shgroup_uniform_int(grp, "keep_size", &stl->shgroups[id].keep_size, 1); + + stl->shgroups[id].mode = gp_style->mode; + stl->shgroups[id].stroke_style = gp_style->stroke_style; + stl->shgroups[id].color_type = GPENCIL_COLOR_SOLID; + if ((gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE) && (!onion)) { + stl->shgroups[id].color_type = GPENCIL_COLOR_TEXTURE; + if (gp_style->flag & GP_STYLE_STROKE_PATTERN) { + stl->shgroups[id].color_type = GPENCIL_COLOR_PATTERN; + } + } + DRW_shgroup_uniform_int(grp, "color_type", &stl->shgroups[id].color_type, 1); + DRW_shgroup_uniform_int(grp, "mode", &stl->shgroups[id].mode, 1); + DRW_shgroup_uniform_float(grp, "pixfactor", &gpd->pixfactor, 1); + + stl->shgroups[id].gradient_f = gps->gradient_f; + copy_v2_v2(stl->shgroups[id].gradient_s, gps->gradient_s); + DRW_shgroup_uniform_float(grp, "gradient_f", &stl->shgroups[id].gradient_f, 1); + DRW_shgroup_uniform_vec2(grp, "gradient_s", stl->shgroups[id].gradient_s, 1); + + /* viewport x-ray */ + stl->shgroups[id].is_xray = (ob->dt == OB_WIRE) ? 1 : stl->storage->is_xray; + DRW_shgroup_uniform_int(grp, "viewport_xray", (const int *)&stl->shgroups[id].is_xray, 1); + + stl->shgroups[id].shading_type[0] = (GPENCIL_USE_SOLID(stl) || onion) ? (int)OB_RENDER : + shading_type[0]; + if (v3d) { + stl->shgroups[id].shading_type[1] = ((stl->shgroups[id].shading_type[0] == OB_WIRE) ? + v3d->shading.wire_color_type : + v3d->shading.color_type); + } + DRW_shgroup_uniform_int(grp, "shading_type", &stl->shgroups[id].shading_type[0], 2); + + /* wire color */ + set_wireframe_color(ob, gpl, v3d, stl, gp_style, id, false); + DRW_shgroup_uniform_vec4(grp, "wire_color", stl->shgroups[id].wire_color, 1); + } + else { + stl->storage->obj_scale = 1.0f; + stl->storage->keep_size = 0; + stl->storage->pixfactor = GP_DEFAULT_PIX_FACTOR; + stl->storage->mode = gp_style->mode; + DRW_shgroup_uniform_float(grp, "objscale", &stl->storage->obj_scale, 1); + DRW_shgroup_uniform_int(grp, "keep_size", &stl->storage->keep_size, 1); + DRW_shgroup_uniform_int(grp, "color_type", &stl->storage->color_type, 1); + DRW_shgroup_uniform_int(grp, "mode", &stl->storage->mode, 1); + if (gpd) { + DRW_shgroup_uniform_float(grp, "pixfactor", &gpd->pixfactor, 1); + } + else { + DRW_shgroup_uniform_float(grp, "pixfactor", &stl->storage->pixfactor, 1); + } + + DRW_shgroup_uniform_float(grp, "gradient_f", &stl->storage->gradient_f, 1); + DRW_shgroup_uniform_vec2(grp, "gradient_s", stl->storage->gradient_s, 1); + + /* viewport x-ray */ + stl->shgroups[id].is_xray = ((ob) && (ob->dt == OB_WIRE)) ? 1 : stl->storage->is_xray; + DRW_shgroup_uniform_int(grp, "viewport_xray", (const int *)&stl->shgroups[id].is_xray, 1); + DRW_shgroup_uniform_int(grp, "shading_type", (const int *)&stl->storage->shade_render, 2); + } + + if ((gpd) && (id > -1)) { + stl->shgroups[id].xray_mode = (ob->dtx & OB_DRAWXRAY) ? GP_XRAY_FRONT : GP_XRAY_3DSPACE; + DRW_shgroup_uniform_int(grp, "xraymode", (const int *)&stl->shgroups[id].xray_mode, 1); + + /* lock rotation of dots and boxes */ + stl->shgroups[id].use_follow_path = (gp_style->flag & GP_STYLE_COLOR_LOCK_DOTS) ? 0 : 1; + DRW_shgroup_uniform_int(grp, "use_follow_path", &stl->shgroups[id].use_follow_path, 1); + } + else { + /* for drawing always on predefined z-depth */ + DRW_shgroup_uniform_int(grp, "xraymode", &stl->storage->xray, 1); + + /* lock rotation of dots and boxes */ + DRW_shgroup_uniform_int(grp, "use_follow_path", &stl->storage->use_follow_path, 1); + } + + /* image texture */ + if ((gp_style) && (gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE) && (!onion)) { + ImBuf *ibuf; + Image *image = gp_style->sima; + ImageUser iuser = {NULL}; + void *lock; + + iuser.ok = true; + + ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock); + + if (ibuf == NULL || ibuf->rect == NULL) { + BKE_image_release_ibuf(image, ibuf, NULL); + } + else { + GPUTexture *texture = GPU_texture_from_blender(gp_style->sima, &iuser, GL_TEXTURE_2D, true); + DRW_shgroup_uniform_texture(grp, "myTexture", texture); + + BKE_image_release_ibuf(image, ibuf, NULL); + } + } + else { + /* if no texture defined, need a blank texture to avoid errors in draw manager */ + DRW_shgroup_uniform_texture(grp, "myTexture", e_data->gpencil_blank_texture); + } + + return grp; } /* add fill vertex info */ -static void gpencil_add_fill_vertexdata( - GpencilBatchCache *cache, - Object *ob, bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *gps, - float opacity, const float tintcolor[4], const bool onion, const bool custonion) +static void gpencil_add_fill_vertexdata(GpencilBatchCache *cache, + Object *ob, + bGPDlayer *gpl, + bGPDframe *gpf, + bGPDstroke *gps, + float opacity, + const float tintcolor[4], + const bool onion, + const bool custonion) { - MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1); - if (gps->totpoints >= 3) { - float tfill[4]; - /* set color using material, tint color and opacity */ - interp_v3_v3v3(tfill, gps->runtime.tmp_fill_rgba, tintcolor, tintcolor[3]); - tfill[3] = gps->runtime.tmp_fill_rgba[3] * opacity; - if ((tfill[3] > GPENCIL_ALPHA_OPACITY_THRESH) || - (gp_style->fill_style > 0) || - (gpl->blend_mode != eGplBlendMode_Normal)) - { - if (cache->is_dirty) { - const float *color; - if (!onion) { - color = tfill; - } - else { - if (custonion) { - color = tintcolor; - } - else { - ARRAY_SET_ITEMS(tfill, UNPACK3(gps->runtime.tmp_fill_rgba), tintcolor[3]); - color = tfill; - } - } - /* create vertex data */ - const int old_len = cache->b_fill.vbo_len; - DRW_gpencil_get_fill_geom(&cache->b_fill, ob, gps, color); - - /* add to list of groups */ - if (old_len < cache->b_fill.vbo_len) { - cache->grp_cache = gpencil_group_cache_add( - cache->grp_cache, gpl, gpf, gps, - eGpencilBatchGroupType_Fill, onion, - cache->b_fill.vbo_len, - &cache->grp_size, &cache->grp_used); - } - } - } - } + MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1); + if (gps->totpoints >= 3) { + float tfill[4]; + /* set color using material, tint color and opacity */ + interp_v3_v3v3(tfill, gps->runtime.tmp_fill_rgba, tintcolor, tintcolor[3]); + tfill[3] = gps->runtime.tmp_fill_rgba[3] * opacity; + if ((tfill[3] > GPENCIL_ALPHA_OPACITY_THRESH) || (gp_style->fill_style > 0) || + (gpl->blend_mode != eGplBlendMode_Normal)) { + if (cache->is_dirty) { + const float *color; + if (!onion) { + color = tfill; + } + else { + if (custonion) { + color = tintcolor; + } + else { + ARRAY_SET_ITEMS(tfill, UNPACK3(gps->runtime.tmp_fill_rgba), tintcolor[3]); + color = tfill; + } + } + /* create vertex data */ + const int old_len = cache->b_fill.vbo_len; + DRW_gpencil_get_fill_geom(&cache->b_fill, ob, gps, color); + + /* add to list of groups */ + if (old_len < cache->b_fill.vbo_len) { + cache->grp_cache = gpencil_group_cache_add(cache->grp_cache, + gpl, + gpf, + gps, + eGpencilBatchGroupType_Fill, + onion, + cache->b_fill.vbo_len, + &cache->grp_size, + &cache->grp_used); + } + } + } + } } /* add stroke vertex info */ -static void gpencil_add_stroke_vertexdata( - GpencilBatchCache *cache, - Object *ob, bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *gps, - const float opacity, const float tintcolor[4], const bool onion, - const bool custonion) +static void gpencil_add_stroke_vertexdata(GpencilBatchCache *cache, + Object *ob, + bGPDlayer *gpl, + bGPDframe *gpf, + bGPDstroke *gps, + const float opacity, + const float tintcolor[4], + const bool onion, + const bool custonion) { - float tcolor[4]; - float ink[4]; - short sthickness; - MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1); - - /* set color using base color, tint color and opacity */ - if (cache->is_dirty) { - if (!onion) { - /* if special stroke, use fill color as stroke color */ - if (gps->flag & GP_STROKE_NOFILL) { - interp_v3_v3v3(tcolor, gps->runtime.tmp_fill_rgba, tintcolor, tintcolor[3]); - tcolor[3] = gps->runtime.tmp_fill_rgba[3] * opacity; - } - else { - interp_v3_v3v3(tcolor, gps->runtime.tmp_stroke_rgba, tintcolor, tintcolor[3]); - tcolor[3] = gps->runtime.tmp_stroke_rgba[3] * opacity; - } - copy_v4_v4(ink, tcolor); - } - else { - if (custonion) { - copy_v4_v4(ink, tintcolor); - } - else { - ARRAY_SET_ITEMS(tcolor, UNPACK3(gps->runtime.tmp_stroke_rgba), opacity); - copy_v4_v4(ink, tcolor); - } - } - - sthickness = gps->thickness + gpl->line_change; - CLAMP_MIN(sthickness, 1); - - if ((gps->totpoints > 1) && (gp_style->mode == GP_STYLE_MODE_LINE)) { - /* create vertex data */ - const int old_len = cache->b_stroke.vbo_len; - DRW_gpencil_get_stroke_geom(&cache->b_stroke, gps, sthickness, ink); - - /* add to list of groups */ - if (old_len < cache->b_stroke.vbo_len) { - cache->grp_cache = gpencil_group_cache_add( - cache->grp_cache, gpl, gpf, gps, - eGpencilBatchGroupType_Stroke, onion, - cache->b_stroke.vbo_len, - &cache->grp_size, &cache->grp_used); - } - } - else { - /* create vertex data */ - const int old_len = cache->b_point.vbo_len; - DRW_gpencil_get_point_geom(&cache->b_point, gps, sthickness, ink); - - /* add to list of groups */ - if (old_len < cache->b_point.vbo_len) { - cache->grp_cache = gpencil_group_cache_add( - cache->grp_cache, gpl, gpf, gps, eGpencilBatchGroupType_Point, onion, - cache->b_point.vbo_len, - &cache->grp_size, &cache->grp_used); - } - } - } + float tcolor[4]; + float ink[4]; + short sthickness; + MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1); + + /* set color using base color, tint color and opacity */ + if (cache->is_dirty) { + if (!onion) { + /* if special stroke, use fill color as stroke color */ + if (gps->flag & GP_STROKE_NOFILL) { + interp_v3_v3v3(tcolor, gps->runtime.tmp_fill_rgba, tintcolor, tintcolor[3]); + tcolor[3] = gps->runtime.tmp_fill_rgba[3] * opacity; + } + else { + interp_v3_v3v3(tcolor, gps->runtime.tmp_stroke_rgba, tintcolor, tintcolor[3]); + tcolor[3] = gps->runtime.tmp_stroke_rgba[3] * opacity; + } + copy_v4_v4(ink, tcolor); + } + else { + if (custonion) { + copy_v4_v4(ink, tintcolor); + } + else { + ARRAY_SET_ITEMS(tcolor, UNPACK3(gps->runtime.tmp_stroke_rgba), opacity); + copy_v4_v4(ink, tcolor); + } + } + + sthickness = gps->thickness + gpl->line_change; + CLAMP_MIN(sthickness, 1); + + if ((gps->totpoints > 1) && (gp_style->mode == GP_STYLE_MODE_LINE)) { + /* create vertex data */ + const int old_len = cache->b_stroke.vbo_len; + DRW_gpencil_get_stroke_geom(&cache->b_stroke, gps, sthickness, ink); + + /* add to list of groups */ + if (old_len < cache->b_stroke.vbo_len) { + cache->grp_cache = gpencil_group_cache_add(cache->grp_cache, + gpl, + gpf, + gps, + eGpencilBatchGroupType_Stroke, + onion, + cache->b_stroke.vbo_len, + &cache->grp_size, + &cache->grp_used); + } + } + else { + /* create vertex data */ + const int old_len = cache->b_point.vbo_len; + DRW_gpencil_get_point_geom(&cache->b_point, gps, sthickness, ink); + + /* add to list of groups */ + if (old_len < cache->b_point.vbo_len) { + cache->grp_cache = gpencil_group_cache_add(cache->grp_cache, + gpl, + gpf, + gps, + eGpencilBatchGroupType_Point, + onion, + cache->b_point.vbo_len, + &cache->grp_size, + &cache->grp_used); + } + } + } } /* add edit points vertex info */ -static void gpencil_add_editpoints_vertexdata( - GpencilBatchCache *cache, Object *ob, - bGPdata *gpd, bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *gps) +static void gpencil_add_editpoints_vertexdata(GpencilBatchCache *cache, + Object *ob, + bGPdata *gpd, + bGPDlayer *gpl, + bGPDframe *gpf, + bGPDstroke *gps) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - View3D *v3d = draw_ctx->v3d; - MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1); - - /* alpha factor for edit points/line to make them more subtle */ - float edit_alpha = v3d->vertex_opacity; - - if (GPENCIL_ANY_EDIT_MODE(gpd)) { - Object *obact = DRW_context_state_get()->obact; - if ((!obact) || (obact->type != OB_GPENCIL)) { - return; - } - const bool is_weight_paint = (gpd) && (gpd->flag & GP_DATA_STROKE_WEIGHTMODE); - - if (cache->is_dirty) { - if ((obact == ob) && - ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) && - (v3d->gp_flag & V3D_GP_SHOW_EDIT_LINES)) - { - /* line of the original stroke */ - DRW_gpencil_get_edlin_geom(&cache->b_edlin, gps, edit_alpha, gpd->flag); - - /* add to list of groups */ - cache->grp_cache = gpencil_group_cache_add( - cache->grp_cache, gpl, gpf, gps, - eGpencilBatchGroupType_Edlin, false, - cache->b_edlin.vbo_len, - &cache->grp_size, &cache->grp_used); - } - /* edit points */ - if ((gps->flag & GP_STROKE_SELECT) || (is_weight_paint)) { - if ((gpl->flag & GP_LAYER_UNLOCK_COLOR) || ((gp_style->flag & GP_STYLE_COLOR_LOCKED) == 0)) { - if (obact == ob) { - DRW_gpencil_get_edit_geom(&cache->b_edit, gps, edit_alpha, gpd->flag); - - /* add to list of groups */ - cache->grp_cache = gpencil_group_cache_add( - cache->grp_cache, gpl, gpf, gps, - eGpencilBatchGroupType_Edit, false, - cache->b_edit.vbo_len, - &cache->grp_size, &cache->grp_used); - } - } - } - } - } + const DRWContextState *draw_ctx = DRW_context_state_get(); + View3D *v3d = draw_ctx->v3d; + MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1); + + /* alpha factor for edit points/line to make them more subtle */ + float edit_alpha = v3d->vertex_opacity; + + if (GPENCIL_ANY_EDIT_MODE(gpd)) { + Object *obact = DRW_context_state_get()->obact; + if ((!obact) || (obact->type != OB_GPENCIL)) { + return; + } + const bool is_weight_paint = (gpd) && (gpd->flag & GP_DATA_STROKE_WEIGHTMODE); + + if (cache->is_dirty) { + if ((obact == ob) && ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) && + (v3d->gp_flag & V3D_GP_SHOW_EDIT_LINES)) { + /* line of the original stroke */ + DRW_gpencil_get_edlin_geom(&cache->b_edlin, gps, edit_alpha, gpd->flag); + + /* add to list of groups */ + cache->grp_cache = gpencil_group_cache_add(cache->grp_cache, + gpl, + gpf, + gps, + eGpencilBatchGroupType_Edlin, + false, + cache->b_edlin.vbo_len, + &cache->grp_size, + &cache->grp_used); + } + /* edit points */ + if ((gps->flag & GP_STROKE_SELECT) || (is_weight_paint)) { + if ((gpl->flag & GP_LAYER_UNLOCK_COLOR) || + ((gp_style->flag & GP_STYLE_COLOR_LOCKED) == 0)) { + if (obact == ob) { + DRW_gpencil_get_edit_geom(&cache->b_edit, gps, edit_alpha, gpd->flag); + + /* add to list of groups */ + cache->grp_cache = gpencil_group_cache_add(cache->grp_cache, + gpl, + gpf, + gps, + eGpencilBatchGroupType_Edit, + false, + cache->b_edit.vbo_len, + &cache->grp_size, + &cache->grp_used); + } + } + } + } + } } /* main function to draw strokes */ -static void gpencil_draw_strokes( - GpencilBatchCache *cache, GPENCIL_e_data *e_data, void *vedata, Object *ob, - bGPdata *gpd, bGPDlayer *gpl, bGPDframe *src_gpf, bGPDframe *derived_gpf, - const float opacity, const float tintcolor[4], - const bool custonion, tGPencilObjectCache *cache_ob) +static void gpencil_draw_strokes(GpencilBatchCache *cache, + GPENCIL_e_data *e_data, + void *vedata, + Object *ob, + bGPdata *gpd, + bGPDlayer *gpl, + bGPDframe *src_gpf, + bGPDframe *derived_gpf, + const float opacity, + const float tintcolor[4], + const bool custonion, + tGPencilObjectCache *cache_ob) { - GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; - GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; - const DRWContextState *draw_ctx = DRW_context_state_get(); - Scene *scene = draw_ctx->scene; - View3D *v3d = draw_ctx->v3d; - bGPDstroke *gps, *src_gps; - float viewmatrix[4][4]; - const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); - const bool playing = stl->storage->is_playing; - const bool is_render = (bool)stl->storage->is_render; - const bool is_mat_preview = (bool)stl->storage->is_mat_preview; - const bool overlay_multiedit = v3d != NULL ? (v3d->gp_flag & V3D_GP_SHOW_MULTIEDIT_LINES) : true; - - /* Get evaluation context */ - /* NOTE: We must check if C is valid, otherwise we get crashes when trying to save files - * (i.e. the thumbnail offscreen rendering fails) - */ - Depsgraph *depsgraph = DRW_context_state_get()->depsgraph; - - /* get parent matrix and save as static data */ - ED_gpencil_parent_location(depsgraph, ob, gpd, gpl, viewmatrix); - copy_m4_m4(derived_gpf->runtime.viewmatrix, viewmatrix); - - if ((cache_ob != NULL) && (cache_ob->is_dup_ob)) { - copy_m4_m4(derived_gpf->runtime.viewmatrix, cache_ob->obmat); - } - - /* apply geometry modifiers */ - if ((cache->is_dirty) && (ob->greasepencil_modifiers.first) && (!is_multiedit)) { - if (!stl->storage->simplify_modif) { - if (BKE_gpencil_has_geometry_modifiers(ob)) { - BKE_gpencil_geometry_modifiers(depsgraph, ob, gpl, derived_gpf, stl->storage->is_render); - } - } - } - - if (src_gpf) { - src_gps = src_gpf->strokes.first; - } - else { - src_gps = NULL; - } - - for (gps = derived_gpf->strokes.first; gps; gps = gps->next) { - MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1); - - /* check if stroke can be drawn */ - if (gpencil_can_draw_stroke(gp_style, gps, false, is_mat_preview) == false) { - GP_SET_SRC_GPS(src_gps); - continue; - } - - /* be sure recalc all cache in source stroke to avoid recalculation when frame change - * and improve fps */ - if (src_gps) { - DRW_gpencil_recalc_geometry_caches(ob, gpl, gp_style, src_gps); - } - - /* if the fill has any value, it's considered a fill and is not drawn if simplify fill is enabled */ - if ((stl->storage->simplify_fill) && - (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_REMOVE_FILL_LINE)) - { - if ((gp_style->fill_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH) || - (gp_style->fill_style > GP_STYLE_FILL_STYLE_SOLID) || - (gpl->blend_mode != eGplBlendMode_Normal)) - { - GP_SET_SRC_GPS(src_gps); - continue; - } - } - - if ((gpl->actframe->framenum == derived_gpf->framenum) || - (!is_multiedit) || (overlay_multiedit)) - { - /* copy color to temp fields to apply temporal changes in the stroke */ - copy_v4_v4(gps->runtime.tmp_stroke_rgba, gp_style->stroke_rgba); - copy_v4_v4(gps->runtime.tmp_fill_rgba, gp_style->fill_rgba); - - /* apply modifiers (only modify geometry, but not create ) */ - if ((cache->is_dirty) && (ob->greasepencil_modifiers.first) && (!is_multiedit)) { - if (!stl->storage->simplify_modif) { - BKE_gpencil_stroke_modifiers(depsgraph, ob, gpl, derived_gpf, gps, stl->storage->is_render); - } - } - - /* hide any blend layer */ - if ((!stl->storage->simplify_blend) || - (gpl->blend_mode == eGplBlendMode_Normal)) - { - /* fill */ - if ((gp_style->flag & GP_STYLE_FILL_SHOW) && - (!stl->storage->simplify_fill) && - ((gps->flag & GP_STROKE_NOFILL) == 0)) - { - gpencil_add_fill_vertexdata( - cache, ob, gpl, derived_gpf, gps, - opacity, tintcolor, false, custonion); - } - /* stroke */ - /* No fill strokes, must show stroke always */ - if (((gp_style->flag & GP_STYLE_STROKE_SHOW) || - (gps->flag & GP_STROKE_NOFILL)) && - ((gp_style->stroke_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH) || - (gpl->blend_mode == eGplBlendMode_Normal))) - { - /* recalc strokes uv (geometry can be changed by modifiers) */ - if (gps->flag & GP_STROKE_RECALC_GEOMETRY) { - ED_gpencil_calc_stroke_uv(ob, gps); - } - - gpencil_add_stroke_vertexdata( - cache, ob, gpl, derived_gpf, gps, - opacity, tintcolor, false, custonion); - } - } - } - - /* edit points (only in edit mode and not play animation not render) */ - if ((draw_ctx->obact == ob) && (src_gps) && - (!playing) && (!is_render) && (!cache_ob->is_dup_ob)) - { - if ((gpl->flag & GP_LAYER_LOCKED) == 0) { - if (!stl->g_data->shgrps_edit_line) { - stl->g_data->shgrps_edit_line = DRW_shgroup_create(e_data->gpencil_line_sh, psl->edit_pass); - } - if (!stl->g_data->shgrps_edit_point) { - stl->g_data->shgrps_edit_point = DRW_shgroup_create(e_data->gpencil_edit_point_sh, psl->edit_pass); - const float *viewport_size = DRW_viewport_size_get(); - DRW_shgroup_uniform_vec2(stl->g_data->shgrps_edit_point, "Viewport", viewport_size, 1); - } - - gpencil_add_editpoints_vertexdata(cache, ob, gpd, gpl, derived_gpf, src_gps); - } - } - - GP_SET_SRC_GPS(src_gps); - } + GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; + GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene = draw_ctx->scene; + View3D *v3d = draw_ctx->v3d; + bGPDstroke *gps, *src_gps; + float viewmatrix[4][4]; + const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); + const bool playing = stl->storage->is_playing; + const bool is_render = (bool)stl->storage->is_render; + const bool is_mat_preview = (bool)stl->storage->is_mat_preview; + const bool overlay_multiedit = v3d != NULL ? (v3d->gp_flag & V3D_GP_SHOW_MULTIEDIT_LINES) : true; + + /* Get evaluation context */ + /* NOTE: We must check if C is valid, otherwise we get crashes when trying to save files + * (i.e. the thumbnail offscreen rendering fails) + */ + Depsgraph *depsgraph = DRW_context_state_get()->depsgraph; + + /* get parent matrix and save as static data */ + ED_gpencil_parent_location(depsgraph, ob, gpd, gpl, viewmatrix); + copy_m4_m4(derived_gpf->runtime.viewmatrix, viewmatrix); + + if ((cache_ob != NULL) && (cache_ob->is_dup_ob)) { + copy_m4_m4(derived_gpf->runtime.viewmatrix, cache_ob->obmat); + } + + /* apply geometry modifiers */ + if ((cache->is_dirty) && (ob->greasepencil_modifiers.first) && (!is_multiedit)) { + if (!stl->storage->simplify_modif) { + if (BKE_gpencil_has_geometry_modifiers(ob)) { + BKE_gpencil_geometry_modifiers(depsgraph, ob, gpl, derived_gpf, stl->storage->is_render); + } + } + } + + if (src_gpf) { + src_gps = src_gpf->strokes.first; + } + else { + src_gps = NULL; + } + + for (gps = derived_gpf->strokes.first; gps; gps = gps->next) { + MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1); + + /* check if stroke can be drawn */ + if (gpencil_can_draw_stroke(gp_style, gps, false, is_mat_preview) == false) { + GP_SET_SRC_GPS(src_gps); + continue; + } + + /* be sure recalc all cache in source stroke to avoid recalculation when frame change + * and improve fps */ + if (src_gps) { + DRW_gpencil_recalc_geometry_caches(ob, gpl, gp_style, src_gps); + } + + /* if the fill has any value, it's considered a fill and is not drawn if simplify fill is enabled */ + if ((stl->storage->simplify_fill) && + (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_REMOVE_FILL_LINE)) { + if ((gp_style->fill_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH) || + (gp_style->fill_style > GP_STYLE_FILL_STYLE_SOLID) || + (gpl->blend_mode != eGplBlendMode_Normal)) { + GP_SET_SRC_GPS(src_gps); + continue; + } + } + + if ((gpl->actframe->framenum == derived_gpf->framenum) || (!is_multiedit) || + (overlay_multiedit)) { + /* copy color to temp fields to apply temporal changes in the stroke */ + copy_v4_v4(gps->runtime.tmp_stroke_rgba, gp_style->stroke_rgba); + copy_v4_v4(gps->runtime.tmp_fill_rgba, gp_style->fill_rgba); + + /* apply modifiers (only modify geometry, but not create ) */ + if ((cache->is_dirty) && (ob->greasepencil_modifiers.first) && (!is_multiedit)) { + if (!stl->storage->simplify_modif) { + BKE_gpencil_stroke_modifiers( + depsgraph, ob, gpl, derived_gpf, gps, stl->storage->is_render); + } + } + + /* hide any blend layer */ + if ((!stl->storage->simplify_blend) || (gpl->blend_mode == eGplBlendMode_Normal)) { + /* fill */ + if ((gp_style->flag & GP_STYLE_FILL_SHOW) && (!stl->storage->simplify_fill) && + ((gps->flag & GP_STROKE_NOFILL) == 0)) { + gpencil_add_fill_vertexdata( + cache, ob, gpl, derived_gpf, gps, opacity, tintcolor, false, custonion); + } + /* stroke */ + /* No fill strokes, must show stroke always */ + if (((gp_style->flag & GP_STYLE_STROKE_SHOW) || (gps->flag & GP_STROKE_NOFILL)) && + ((gp_style->stroke_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH) || + (gpl->blend_mode == eGplBlendMode_Normal))) { + /* recalc strokes uv (geometry can be changed by modifiers) */ + if (gps->flag & GP_STROKE_RECALC_GEOMETRY) { + ED_gpencil_calc_stroke_uv(ob, gps); + } + + gpencil_add_stroke_vertexdata( + cache, ob, gpl, derived_gpf, gps, opacity, tintcolor, false, custonion); + } + } + } + + /* edit points (only in edit mode and not play animation not render) */ + if ((draw_ctx->obact == ob) && (src_gps) && (!playing) && (!is_render) && + (!cache_ob->is_dup_ob)) { + if ((gpl->flag & GP_LAYER_LOCKED) == 0) { + if (!stl->g_data->shgrps_edit_line) { + stl->g_data->shgrps_edit_line = DRW_shgroup_create(e_data->gpencil_line_sh, + psl->edit_pass); + } + if (!stl->g_data->shgrps_edit_point) { + stl->g_data->shgrps_edit_point = DRW_shgroup_create(e_data->gpencil_edit_point_sh, + psl->edit_pass); + const float *viewport_size = DRW_viewport_size_get(); + DRW_shgroup_uniform_vec2(stl->g_data->shgrps_edit_point, "Viewport", viewport_size, 1); + } + + gpencil_add_editpoints_vertexdata(cache, ob, gpd, gpl, derived_gpf, src_gps); + } + } + + GP_SET_SRC_GPS(src_gps); + } } /* get alpha factor for onion strokes */ @@ -1072,847 +1122,919 @@ static void gpencil_get_onion_alpha(float color[4], bGPdata *gpd) { #define MIN_ALPHA_VALUE 0.01f - /* if fade is disabled, opacity is equal in all frames */ - if ((gpd->onion_flag & GP_ONION_FADE) == 0) { - color[3] = gpd->onion_factor; - } - else { - /* add override opacity factor */ - color[3] += gpd->onion_factor - 0.5f; - } + /* if fade is disabled, opacity is equal in all frames */ + if ((gpd->onion_flag & GP_ONION_FADE) == 0) { + color[3] = gpd->onion_factor; + } + else { + /* add override opacity factor */ + color[3] += gpd->onion_factor - 0.5f; + } - CLAMP(color[3], MIN_ALPHA_VALUE, 1.0f); + CLAMP(color[3], MIN_ALPHA_VALUE, 1.0f); } /* function to draw strokes for onion only */ -static void gpencil_draw_onion_strokes( - GpencilBatchCache *cache, void *vedata, Object *ob, - bGPdata *gpd, bGPDlayer *gpl, bGPDframe *gpf, - const float opacity, const float tintcolor[4], const bool custonion) +static void gpencil_draw_onion_strokes(GpencilBatchCache *cache, + void *vedata, + Object *ob, + bGPdata *gpd, + bGPDlayer *gpl, + bGPDframe *gpf, + const float opacity, + const float tintcolor[4], + const bool custonion) { - GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; - Depsgraph *depsgraph = DRW_context_state_get()->depsgraph; - - float viewmatrix[4][4]; - - /* get parent matrix and save as static data */ - ED_gpencil_parent_location(depsgraph, ob, gpd, gpl, viewmatrix); - copy_m4_m4(gpf->runtime.viewmatrix, viewmatrix); - - for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { - MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1); - if (gp_style == NULL) { - continue; - } - copy_v4_v4(gps->runtime.tmp_stroke_rgba, gp_style->stroke_rgba); - copy_v4_v4(gps->runtime.tmp_fill_rgba, gp_style->fill_rgba); - - int id = stl->storage->shgroup_id; - /* check if stroke can be drawn */ - if (gpencil_can_draw_stroke(gp_style, gps, true, false) == false) { - continue; - } - /* limit the number of shading groups */ - if (id >= GPENCIL_MAX_SHGROUPS) { - continue; - } - - /* stroke */ - gpencil_add_stroke_vertexdata( - cache, ob, gpl, gpf, gps, opacity, tintcolor, - true, custonion); - - stl->storage->shgroup_id++; - } + GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; + Depsgraph *depsgraph = DRW_context_state_get()->depsgraph; + + float viewmatrix[4][4]; + + /* get parent matrix and save as static data */ + ED_gpencil_parent_location(depsgraph, ob, gpd, gpl, viewmatrix); + copy_m4_m4(gpf->runtime.viewmatrix, viewmatrix); + + for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { + MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1); + if (gp_style == NULL) { + continue; + } + copy_v4_v4(gps->runtime.tmp_stroke_rgba, gp_style->stroke_rgba); + copy_v4_v4(gps->runtime.tmp_fill_rgba, gp_style->fill_rgba); + + int id = stl->storage->shgroup_id; + /* check if stroke can be drawn */ + if (gpencil_can_draw_stroke(gp_style, gps, true, false) == false) { + continue; + } + /* limit the number of shading groups */ + if (id >= GPENCIL_MAX_SHGROUPS) { + continue; + } + + /* stroke */ + gpencil_add_stroke_vertexdata(cache, ob, gpl, gpf, gps, opacity, tintcolor, true, custonion); + + stl->storage->shgroup_id++; + } } /* draw onion-skinning for a layer */ -static void gpencil_draw_onionskins( - GpencilBatchCache *cache, void *vedata, - Object *ob, bGPdata *gpd, bGPDlayer *gpl, bGPDframe *gpf) +static void gpencil_draw_onionskins(GpencilBatchCache *cache, + void *vedata, + Object *ob, + bGPdata *gpd, + bGPDlayer *gpl, + bGPDframe *gpf) { - const float default_color[3] = { UNPACK3(U.gpencil_new_layer_col) }; - const float alpha = 1.0f; - float color[4]; - int idx; - float fac = 1.0f; - int step = 0; - int mode = 0; - bool colflag = false; - bGPDframe *gpf_loop = NULL; - int last = gpf->framenum; - - colflag = (bool)gpd->onion_flag & GP_ONION_GHOST_PREVCOL; - - /* ------------------------------- - * 1) Draw Previous Frames First - * ------------------------------- */ - step = gpd->gstep; - mode = gpd->onion_mode; - - if (gpd->onion_flag & GP_ONION_GHOST_PREVCOL) { - copy_v3_v3(color, gpd->gcolor_prev); - } - else { - copy_v3_v3(color, default_color); - } - - idx = 0; - for (bGPDframe *gf = gpf->prev; gf; gf = gf->prev) { - /* only selected frames */ - if ((mode == GP_ONION_MODE_SELECTED) && ((gf->flag & GP_FRAME_SELECT) == 0)) { - continue; - } - /* absolute range */ - if (mode == GP_ONION_MODE_ABSOLUTE) { - if ((gpf->framenum - gf->framenum) > step) { - break; - } - } - /* relative range */ - if (mode == GP_ONION_MODE_RELATIVE) { - idx++; - if (idx > step) { - break; - } - - } - /* alpha decreases with distance from curframe index */ - if (mode != GP_ONION_MODE_SELECTED) { - if (mode == GP_ONION_MODE_ABSOLUTE) { - fac = 1.0f - ((float)(gpf->framenum - gf->framenum) / (float)(step + 1)); - } - else { - fac = 1.0f - ((float)idx / (float)(step + 1)); - } - color[3] = alpha * fac * 0.66f; - } - else { - idx++; - fac = alpha - ((1.1f - (1.0f / (float)idx)) * 0.66f); - color[3] = fac; - } - - /* if loop option, save the frame to use later */ - if ((mode != GP_ONION_MODE_ABSOLUTE) && (gpd->onion_flag & GP_ONION_LOOP)) { - gpf_loop = gf; - } - - gpencil_get_onion_alpha(color, gpd); - gpencil_draw_onion_strokes(cache, vedata, ob, gpd, gpl, gf, color[3], color, colflag); - } - /* ------------------------------- - * 2) Now draw next frames - * ------------------------------- */ - step = gpd->gstep_next; - mode = gpd->onion_mode; - - if (gpd->onion_flag & GP_ONION_GHOST_NEXTCOL) { - copy_v3_v3(color, gpd->gcolor_next); - } - else { - copy_v3_v3(color, default_color); - } - - idx = 0; - for (bGPDframe *gf = gpf->next; gf; gf = gf->next) { - /* only selected frames */ - if ((mode == GP_ONION_MODE_SELECTED) && ((gf->flag & GP_FRAME_SELECT) == 0)) { - continue; - } - /* absolute range */ - if (mode == GP_ONION_MODE_ABSOLUTE) { - if ((gf->framenum - gpf->framenum) > step) { - break; - } - } - /* relative range */ - if (mode == GP_ONION_MODE_RELATIVE) { - idx++; - if (idx > step) { - break; - } - - } - /* alpha decreases with distance from curframe index */ - if (mode != GP_ONION_MODE_SELECTED) { - if (mode == GP_ONION_MODE_ABSOLUTE) { - fac = 1.0f - ((float)(gf->framenum - gpf->framenum) / (float)(step + 1)); - } - else { - fac = 1.0f - ((float)idx / (float)(step + 1)); - } - color[3] = alpha * fac * 0.66f; - } - else { - idx++; - fac = alpha - ((1.1f - (1.0f / (float)idx)) * 0.66f); - color[3] = fac; - } - - gpencil_get_onion_alpha(color, gpd); - gpencil_draw_onion_strokes(cache, vedata, ob, gpd, gpl, gf, color[3], color, colflag); - if (last < gf->framenum) { - last = gf->framenum; - } - } - - /* Draw first frame in blue for loop mode */ - if ((gpd->onion_flag & GP_ONION_LOOP) && (gpf_loop != NULL)) { - if ((last == gpf->framenum) || (gpf->next == NULL)) { - gpencil_get_onion_alpha(color, gpd); - gpencil_draw_onion_strokes( - cache, vedata, ob, gpd, gpl, - gpf_loop, color[3], color, colflag); - } - } + const float default_color[3] = {UNPACK3(U.gpencil_new_layer_col)}; + const float alpha = 1.0f; + float color[4]; + int idx; + float fac = 1.0f; + int step = 0; + int mode = 0; + bool colflag = false; + bGPDframe *gpf_loop = NULL; + int last = gpf->framenum; + + colflag = (bool)gpd->onion_flag & GP_ONION_GHOST_PREVCOL; + + /* ------------------------------- + * 1) Draw Previous Frames First + * ------------------------------- */ + step = gpd->gstep; + mode = gpd->onion_mode; + + if (gpd->onion_flag & GP_ONION_GHOST_PREVCOL) { + copy_v3_v3(color, gpd->gcolor_prev); + } + else { + copy_v3_v3(color, default_color); + } + + idx = 0; + for (bGPDframe *gf = gpf->prev; gf; gf = gf->prev) { + /* only selected frames */ + if ((mode == GP_ONION_MODE_SELECTED) && ((gf->flag & GP_FRAME_SELECT) == 0)) { + continue; + } + /* absolute range */ + if (mode == GP_ONION_MODE_ABSOLUTE) { + if ((gpf->framenum - gf->framenum) > step) { + break; + } + } + /* relative range */ + if (mode == GP_ONION_MODE_RELATIVE) { + idx++; + if (idx > step) { + break; + } + } + /* alpha decreases with distance from curframe index */ + if (mode != GP_ONION_MODE_SELECTED) { + if (mode == GP_ONION_MODE_ABSOLUTE) { + fac = 1.0f - ((float)(gpf->framenum - gf->framenum) / (float)(step + 1)); + } + else { + fac = 1.0f - ((float)idx / (float)(step + 1)); + } + color[3] = alpha * fac * 0.66f; + } + else { + idx++; + fac = alpha - ((1.1f - (1.0f / (float)idx)) * 0.66f); + color[3] = fac; + } + + /* if loop option, save the frame to use later */ + if ((mode != GP_ONION_MODE_ABSOLUTE) && (gpd->onion_flag & GP_ONION_LOOP)) { + gpf_loop = gf; + } + + gpencil_get_onion_alpha(color, gpd); + gpencil_draw_onion_strokes(cache, vedata, ob, gpd, gpl, gf, color[3], color, colflag); + } + /* ------------------------------- + * 2) Now draw next frames + * ------------------------------- */ + step = gpd->gstep_next; + mode = gpd->onion_mode; + + if (gpd->onion_flag & GP_ONION_GHOST_NEXTCOL) { + copy_v3_v3(color, gpd->gcolor_next); + } + else { + copy_v3_v3(color, default_color); + } + + idx = 0; + for (bGPDframe *gf = gpf->next; gf; gf = gf->next) { + /* only selected frames */ + if ((mode == GP_ONION_MODE_SELECTED) && ((gf->flag & GP_FRAME_SELECT) == 0)) { + continue; + } + /* absolute range */ + if (mode == GP_ONION_MODE_ABSOLUTE) { + if ((gf->framenum - gpf->framenum) > step) { + break; + } + } + /* relative range */ + if (mode == GP_ONION_MODE_RELATIVE) { + idx++; + if (idx > step) { + break; + } + } + /* alpha decreases with distance from curframe index */ + if (mode != GP_ONION_MODE_SELECTED) { + if (mode == GP_ONION_MODE_ABSOLUTE) { + fac = 1.0f - ((float)(gf->framenum - gpf->framenum) / (float)(step + 1)); + } + else { + fac = 1.0f - ((float)idx / (float)(step + 1)); + } + color[3] = alpha * fac * 0.66f; + } + else { + idx++; + fac = alpha - ((1.1f - (1.0f / (float)idx)) * 0.66f); + color[3] = fac; + } + + gpencil_get_onion_alpha(color, gpd); + gpencil_draw_onion_strokes(cache, vedata, ob, gpd, gpl, gf, color[3], color, colflag); + if (last < gf->framenum) { + last = gf->framenum; + } + } + + /* Draw first frame in blue for loop mode */ + if ((gpd->onion_flag & GP_ONION_LOOP) && (gpf_loop != NULL)) { + if ((last == gpf->framenum) || (gpf->next == NULL)) { + gpencil_get_onion_alpha(color, gpd); + gpencil_draw_onion_strokes(cache, vedata, ob, gpd, gpl, gpf_loop, color[3], color, colflag); + } + } } static void gpencil_copy_frame(bGPDframe *gpf, bGPDframe *derived_gpf) { - derived_gpf->prev = gpf->prev; - derived_gpf->next = gpf->next; - derived_gpf->framenum = gpf->framenum; - derived_gpf->flag = gpf->flag; - derived_gpf->key_type = gpf->key_type; - derived_gpf->runtime = gpf->runtime; - copy_m4_m4(derived_gpf->runtime.viewmatrix, gpf->runtime.viewmatrix); - - /* copy strokes */ - BLI_listbase_clear(&derived_gpf->strokes); - for (bGPDstroke *gps_src = gpf->strokes.first; gps_src; gps_src = gps_src->next) { - /* make copy of source stroke */ - bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps_src); - BLI_addtail(&derived_gpf->strokes, gps_dst); - } + derived_gpf->prev = gpf->prev; + derived_gpf->next = gpf->next; + derived_gpf->framenum = gpf->framenum; + derived_gpf->flag = gpf->flag; + derived_gpf->key_type = gpf->key_type; + derived_gpf->runtime = gpf->runtime; + copy_m4_m4(derived_gpf->runtime.viewmatrix, gpf->runtime.viewmatrix); + + /* copy strokes */ + BLI_listbase_clear(&derived_gpf->strokes); + for (bGPDstroke *gps_src = gpf->strokes.first; gps_src; gps_src = gps_src->next) { + /* make copy of source stroke */ + bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps_src); + BLI_addtail(&derived_gpf->strokes, gps_dst); + } } /* Triangulate stroke for high quality fill (this is done only if cache is null or stroke was modified) */ void DRW_gpencil_triangulate_stroke_fill(Object *ob, bGPDstroke *gps) { - BLI_assert(gps->totpoints >= 3); - - bGPdata *gpd = (bGPdata *)ob->data; - - /* allocate memory for temporary areas */ - gps->tot_triangles = gps->totpoints - 2; - uint(*tmp_triangles)[3] = MEM_mallocN(sizeof(*tmp_triangles) * gps->tot_triangles, "GP Stroke temp triangulation"); - float(*points2d)[2] = MEM_mallocN(sizeof(*points2d) * gps->totpoints, "GP Stroke temp 2d points"); - float(*uv)[2] = MEM_mallocN(sizeof(*uv) * gps->totpoints, "GP Stroke temp 2d uv data"); - - int direction = 0; - - /* convert to 2d and triangulate */ - BKE_gpencil_stroke_2d_flat(gps->points, gps->totpoints, points2d, &direction); - BLI_polyfill_calc(points2d, (uint)gps->totpoints, direction, tmp_triangles); - - /* calc texture coordinates automatically */ - float minv[2]; - float maxv[2]; - /* first needs bounding box data */ - if (gpd->flag & GP_DATA_UV_ADAPTIVE) { - gpencil_calc_2d_bounding_box(points2d, gps->totpoints, minv, maxv); - } - else { - ARRAY_SET_ITEMS(minv, -1.0f, -1.0f); - ARRAY_SET_ITEMS(maxv, 1.0f, 1.0f); - } - - /* calc uv data */ - gpencil_calc_stroke_fill_uv(points2d, gps->totpoints, minv, maxv, uv); - - /* Number of triangles */ - gps->tot_triangles = gps->totpoints - 2; - /* save triangulation data in stroke cache */ - if (gps->tot_triangles > 0) { - if (gps->triangles == NULL) { - gps->triangles = MEM_callocN(sizeof(*gps->triangles) * gps->tot_triangles, "GP Stroke triangulation"); - } - else { - gps->triangles = MEM_recallocN(gps->triangles, sizeof(*gps->triangles) * gps->tot_triangles); - } - - for (int i = 0; i < gps->tot_triangles; i++) { - bGPDtriangle *stroke_triangle = &gps->triangles[i]; - memcpy(gps->triangles[i].verts, tmp_triangles[i], sizeof(uint[3])); - /* copy texture coordinates */ - copy_v2_v2(stroke_triangle->uv[0], uv[tmp_triangles[i][0]]); - copy_v2_v2(stroke_triangle->uv[1], uv[tmp_triangles[i][1]]); - copy_v2_v2(stroke_triangle->uv[2], uv[tmp_triangles[i][2]]); - } - } - else { - /* No triangles needed - Free anything allocated previously */ - if (gps->triangles) { - MEM_freeN(gps->triangles); - } - - gps->triangles = NULL; - } - - /* disable recalculation flag */ - if (gps->flag & GP_STROKE_RECALC_GEOMETRY) { - gps->flag &= ~GP_STROKE_RECALC_GEOMETRY; - } - - /* clear memory */ - MEM_SAFE_FREE(tmp_triangles); - MEM_SAFE_FREE(points2d); - MEM_SAFE_FREE(uv); + BLI_assert(gps->totpoints >= 3); + + bGPdata *gpd = (bGPdata *)ob->data; + + /* allocate memory for temporary areas */ + gps->tot_triangles = gps->totpoints - 2; + uint(*tmp_triangles)[3] = MEM_mallocN(sizeof(*tmp_triangles) * gps->tot_triangles, + "GP Stroke temp triangulation"); + float(*points2d)[2] = MEM_mallocN(sizeof(*points2d) * gps->totpoints, + "GP Stroke temp 2d points"); + float(*uv)[2] = MEM_mallocN(sizeof(*uv) * gps->totpoints, "GP Stroke temp 2d uv data"); + + int direction = 0; + + /* convert to 2d and triangulate */ + BKE_gpencil_stroke_2d_flat(gps->points, gps->totpoints, points2d, &direction); + BLI_polyfill_calc(points2d, (uint)gps->totpoints, direction, tmp_triangles); + + /* calc texture coordinates automatically */ + float minv[2]; + float maxv[2]; + /* first needs bounding box data */ + if (gpd->flag & GP_DATA_UV_ADAPTIVE) { + gpencil_calc_2d_bounding_box(points2d, gps->totpoints, minv, maxv); + } + else { + ARRAY_SET_ITEMS(minv, -1.0f, -1.0f); + ARRAY_SET_ITEMS(maxv, 1.0f, 1.0f); + } + + /* calc uv data */ + gpencil_calc_stroke_fill_uv(points2d, gps->totpoints, minv, maxv, uv); + + /* Number of triangles */ + gps->tot_triangles = gps->totpoints - 2; + /* save triangulation data in stroke cache */ + if (gps->tot_triangles > 0) { + if (gps->triangles == NULL) { + gps->triangles = MEM_callocN(sizeof(*gps->triangles) * gps->tot_triangles, + "GP Stroke triangulation"); + } + else { + gps->triangles = MEM_recallocN(gps->triangles, sizeof(*gps->triangles) * gps->tot_triangles); + } + + for (int i = 0; i < gps->tot_triangles; i++) { + bGPDtriangle *stroke_triangle = &gps->triangles[i]; + memcpy(gps->triangles[i].verts, tmp_triangles[i], sizeof(uint[3])); + /* copy texture coordinates */ + copy_v2_v2(stroke_triangle->uv[0], uv[tmp_triangles[i][0]]); + copy_v2_v2(stroke_triangle->uv[1], uv[tmp_triangles[i][1]]); + copy_v2_v2(stroke_triangle->uv[2], uv[tmp_triangles[i][2]]); + } + } + else { + /* No triangles needed - Free anything allocated previously */ + if (gps->triangles) { + MEM_freeN(gps->triangles); + } + + gps->triangles = NULL; + } + + /* disable recalculation flag */ + if (gps->flag & GP_STROKE_RECALC_GEOMETRY) { + gps->flag &= ~GP_STROKE_RECALC_GEOMETRY; + } + + /* clear memory */ + MEM_SAFE_FREE(tmp_triangles); + MEM_SAFE_FREE(points2d); + MEM_SAFE_FREE(uv); } /* draw stroke in drawing buffer */ -void DRW_gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data, void *vedata, ToolSettings *ts, Object *ob) +void DRW_gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data, + void *vedata, + ToolSettings *ts, + Object *ob) { - GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; - GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; - const DRWContextState *draw_ctx = DRW_context_state_get(); - View3D *v3d = draw_ctx->v3d; - const bool overlay = v3d != NULL ? (bool)((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) : true; - Brush *brush = BKE_paint_brush(&ts->gp_paint->paint); - bGPdata *gpd_eval = ob->data; - /* need the original to avoid cow overhead while drawing */ - bGPdata *gpd = (bGPdata *)DEG_get_original_id(&gpd_eval->id); - - MaterialGPencilStyle *gp_style = NULL; - float obscale = mat4_to_scale(ob->obmat); - - /* use the brush material */ - Material *ma = BKE_gpencil_object_material_get_from_brush(ob, brush); - if (ma != NULL) { - gp_style = ma->gp_style; - } - /* this is not common, but avoid any special situations when brush could be without material */ - if (gp_style == NULL) { - gp_style = BKE_material_gpencil_settings_get(ob, ob->actcol); - } - - /* drawing strokes */ - /* Check if may need to draw the active stroke cache, only if this layer is the active layer - * that is being edited. (Stroke buffer is currently stored in gp-data) - */ - if (gpd->runtime.sbuffer_size > 0) { - if ((gpd->runtime.sbuffer_sflag & GP_STROKE_ERASER) == 0) { - /* It should also be noted that sbuffer contains temporary point types - * i.e. tGPspoints NOT bGPDspoints - */ - short lthick = brush->size * obscale; - - /* save gradient info */ - stl->storage->gradient_f = brush->gpencil_settings->gradient_f; - copy_v2_v2(stl->storage->gradient_s, brush->gpencil_settings->gradient_s); - stl->storage->use_follow_path = (gp_style->flag & GP_STYLE_COLOR_LOCK_DOTS) ? 0 : 1; - - /* if only one point, don't need to draw buffer because the user has no time to see it */ - if (gpd->runtime.sbuffer_size > 1) { - if ((gp_style) && (gp_style->mode == GP_STYLE_MODE_LINE)) { - stl->g_data->shgrps_drawing_stroke = DRW_gpencil_shgroup_stroke_create( - e_data, vedata, psl->drawing_pass, e_data->gpencil_stroke_sh, NULL, - gpd, NULL, NULL, gp_style, -1, - false, 1.0f, (const int *)stl->storage->shade_render); - } - else { - stl->g_data->shgrps_drawing_stroke = DRW_gpencil_shgroup_point_create( - e_data, vedata, psl->drawing_pass, e_data->gpencil_point_sh, NULL, - gpd, NULL, NULL, gp_style, -1, - false, 1.0f, (const int *)stl->storage->shade_render); - } - - /* clean previous version of the batch */ - if (stl->storage->buffer_stroke) { - GPU_BATCH_DISCARD_SAFE(e_data->batch_buffer_stroke); - MEM_SAFE_FREE(e_data->batch_buffer_stroke); - stl->storage->buffer_stroke = false; - } - - /* use unit matrix because the buffer is in screen space and does not need conversion */ - if (gpd->runtime.mode == GP_STYLE_MODE_LINE) { - e_data->batch_buffer_stroke = DRW_gpencil_get_buffer_stroke_geom( - gpd, lthick); - } - else { - e_data->batch_buffer_stroke = DRW_gpencil_get_buffer_point_geom( - gpd, lthick); - } - - /* buffer strokes, must show stroke always */ - DRW_shgroup_call_add( - stl->g_data->shgrps_drawing_stroke, - e_data->batch_buffer_stroke, - stl->storage->unit_matrix); - - if ((gpd->runtime.sbuffer_size >= 3) && - (gpd->runtime.sfill[3] > GPENCIL_ALPHA_OPACITY_THRESH) && - ((gpd->runtime.sbuffer_sflag & GP_STROKE_NOFILL) == 0) && - ((brush->gpencil_settings->flag & GP_BRUSH_DISSABLE_LASSO) == 0) && - (gp_style->flag & GP_STYLE_FILL_SHOW)) - { - /* if not solid, fill is simulated with solid color */ - if (gpd->runtime.bfill_style > 0) { - gpd->runtime.sfill[3] = 0.5f; - } - stl->g_data->shgrps_drawing_fill = DRW_shgroup_create( - e_data->gpencil_drawing_fill_sh, psl->drawing_pass); - - /* clean previous version of the batch */ - if (stl->storage->buffer_fill) { - GPU_BATCH_DISCARD_SAFE(e_data->batch_buffer_fill); - MEM_SAFE_FREE(e_data->batch_buffer_fill); - stl->storage->buffer_fill = false; - } - - e_data->batch_buffer_fill = DRW_gpencil_get_buffer_fill_geom(gpd); - DRW_shgroup_call_add( - stl->g_data->shgrps_drawing_fill, - e_data->batch_buffer_fill, - stl->storage->unit_matrix); - stl->storage->buffer_fill = true; - } - stl->storage->buffer_stroke = true; - } - } - } - - /* control points for primitives and speed guide */ - const bool is_cppoint = (gpd->runtime.tot_cp_points > 0); - const bool is_speed_guide = (ts->gp_sculpt.guide.use_guide && (draw_ctx->object_mode == OB_MODE_PAINT_GPENCIL)); - const bool is_show_gizmo = (((v3d->gizmo_flag & V3D_GIZMO_HIDE) == 0) && ((v3d->gizmo_flag & V3D_GIZMO_HIDE_TOOL) == 0)); - - if ((overlay) && (is_cppoint || is_speed_guide) && (is_show_gizmo) && - ((gpd->runtime.sbuffer_sflag & GP_STROKE_ERASER) == 0)) - { - DRWShadingGroup *shgrp = DRW_shgroup_create( - e_data->gpencil_edit_point_sh, psl->drawing_pass); - const float *viewport_size = DRW_viewport_size_get(); - DRW_shgroup_uniform_vec2(shgrp, "Viewport", viewport_size, 1); - - /* clean previous version of the batch */ - if (stl->storage->buffer_ctrlpoint) { - GPU_BATCH_DISCARD_SAFE(e_data->batch_buffer_ctrlpoint); - MEM_SAFE_FREE(e_data->batch_buffer_ctrlpoint); - stl->storage->buffer_ctrlpoint = false; - } - - e_data->batch_buffer_ctrlpoint = DRW_gpencil_get_buffer_ctrlpoint_geom(gpd); - - DRW_shgroup_call_add( - shgrp, - e_data->batch_buffer_ctrlpoint, - stl->storage->unit_matrix); - - stl->storage->buffer_ctrlpoint = true; - } + GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; + GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + View3D *v3d = draw_ctx->v3d; + const bool overlay = v3d != NULL ? (bool)((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) : true; + Brush *brush = BKE_paint_brush(&ts->gp_paint->paint); + bGPdata *gpd_eval = ob->data; + /* need the original to avoid cow overhead while drawing */ + bGPdata *gpd = (bGPdata *)DEG_get_original_id(&gpd_eval->id); + + MaterialGPencilStyle *gp_style = NULL; + float obscale = mat4_to_scale(ob->obmat); + + /* use the brush material */ + Material *ma = BKE_gpencil_object_material_get_from_brush(ob, brush); + if (ma != NULL) { + gp_style = ma->gp_style; + } + /* this is not common, but avoid any special situations when brush could be without material */ + if (gp_style == NULL) { + gp_style = BKE_material_gpencil_settings_get(ob, ob->actcol); + } + + /* drawing strokes */ + /* Check if may need to draw the active stroke cache, only if this layer is the active layer + * that is being edited. (Stroke buffer is currently stored in gp-data) + */ + if (gpd->runtime.sbuffer_size > 0) { + if ((gpd->runtime.sbuffer_sflag & GP_STROKE_ERASER) == 0) { + /* It should also be noted that sbuffer contains temporary point types + * i.e. tGPspoints NOT bGPDspoints + */ + short lthick = brush->size * obscale; + + /* save gradient info */ + stl->storage->gradient_f = brush->gpencil_settings->gradient_f; + copy_v2_v2(stl->storage->gradient_s, brush->gpencil_settings->gradient_s); + stl->storage->use_follow_path = (gp_style->flag & GP_STYLE_COLOR_LOCK_DOTS) ? 0 : 1; + + /* if only one point, don't need to draw buffer because the user has no time to see it */ + if (gpd->runtime.sbuffer_size > 1) { + if ((gp_style) && (gp_style->mode == GP_STYLE_MODE_LINE)) { + stl->g_data->shgrps_drawing_stroke = DRW_gpencil_shgroup_stroke_create( + e_data, + vedata, + psl->drawing_pass, + e_data->gpencil_stroke_sh, + NULL, + gpd, + NULL, + NULL, + gp_style, + -1, + false, + 1.0f, + (const int *)stl->storage->shade_render); + } + else { + stl->g_data->shgrps_drawing_stroke = DRW_gpencil_shgroup_point_create( + e_data, + vedata, + psl->drawing_pass, + e_data->gpencil_point_sh, + NULL, + gpd, + NULL, + NULL, + gp_style, + -1, + false, + 1.0f, + (const int *)stl->storage->shade_render); + } + + /* clean previous version of the batch */ + if (stl->storage->buffer_stroke) { + GPU_BATCH_DISCARD_SAFE(e_data->batch_buffer_stroke); + MEM_SAFE_FREE(e_data->batch_buffer_stroke); + stl->storage->buffer_stroke = false; + } + + /* use unit matrix because the buffer is in screen space and does not need conversion */ + if (gpd->runtime.mode == GP_STYLE_MODE_LINE) { + e_data->batch_buffer_stroke = DRW_gpencil_get_buffer_stroke_geom(gpd, lthick); + } + else { + e_data->batch_buffer_stroke = DRW_gpencil_get_buffer_point_geom(gpd, lthick); + } + + /* buffer strokes, must show stroke always */ + DRW_shgroup_call_add(stl->g_data->shgrps_drawing_stroke, + e_data->batch_buffer_stroke, + stl->storage->unit_matrix); + + if ((gpd->runtime.sbuffer_size >= 3) && + (gpd->runtime.sfill[3] > GPENCIL_ALPHA_OPACITY_THRESH) && + ((gpd->runtime.sbuffer_sflag & GP_STROKE_NOFILL) == 0) && + ((brush->gpencil_settings->flag & GP_BRUSH_DISSABLE_LASSO) == 0) && + (gp_style->flag & GP_STYLE_FILL_SHOW)) { + /* if not solid, fill is simulated with solid color */ + if (gpd->runtime.bfill_style > 0) { + gpd->runtime.sfill[3] = 0.5f; + } + stl->g_data->shgrps_drawing_fill = DRW_shgroup_create(e_data->gpencil_drawing_fill_sh, + psl->drawing_pass); + + /* clean previous version of the batch */ + if (stl->storage->buffer_fill) { + GPU_BATCH_DISCARD_SAFE(e_data->batch_buffer_fill); + MEM_SAFE_FREE(e_data->batch_buffer_fill); + stl->storage->buffer_fill = false; + } + + e_data->batch_buffer_fill = DRW_gpencil_get_buffer_fill_geom(gpd); + DRW_shgroup_call_add(stl->g_data->shgrps_drawing_fill, + e_data->batch_buffer_fill, + stl->storage->unit_matrix); + stl->storage->buffer_fill = true; + } + stl->storage->buffer_stroke = true; + } + } + } + + /* control points for primitives and speed guide */ + const bool is_cppoint = (gpd->runtime.tot_cp_points > 0); + const bool is_speed_guide = (ts->gp_sculpt.guide.use_guide && + (draw_ctx->object_mode == OB_MODE_PAINT_GPENCIL)); + const bool is_show_gizmo = (((v3d->gizmo_flag & V3D_GIZMO_HIDE) == 0) && + ((v3d->gizmo_flag & V3D_GIZMO_HIDE_TOOL) == 0)); + + if ((overlay) && (is_cppoint || is_speed_guide) && (is_show_gizmo) && + ((gpd->runtime.sbuffer_sflag & GP_STROKE_ERASER) == 0)) { + DRWShadingGroup *shgrp = DRW_shgroup_create(e_data->gpencil_edit_point_sh, psl->drawing_pass); + const float *viewport_size = DRW_viewport_size_get(); + DRW_shgroup_uniform_vec2(shgrp, "Viewport", viewport_size, 1); + + /* clean previous version of the batch */ + if (stl->storage->buffer_ctrlpoint) { + GPU_BATCH_DISCARD_SAFE(e_data->batch_buffer_ctrlpoint); + MEM_SAFE_FREE(e_data->batch_buffer_ctrlpoint); + stl->storage->buffer_ctrlpoint = false; + } + + e_data->batch_buffer_ctrlpoint = DRW_gpencil_get_buffer_ctrlpoint_geom(gpd); + + DRW_shgroup_call_add(shgrp, e_data->batch_buffer_ctrlpoint, stl->storage->unit_matrix); + + stl->storage->buffer_ctrlpoint = true; + } } /* create all missing batches */ static void DRW_gpencil_create_batches(GpencilBatchCache *cache) { - if ((cache->b_point.vbo) && (cache->b_point.batch == NULL)) { - cache->b_point.batch = GPU_batch_create_ex(GPU_PRIM_POINTS, cache->b_point.vbo, NULL, GPU_BATCH_OWNS_VBO); - } - if ((cache->b_stroke.vbo) && (cache->b_stroke.batch == NULL)) { - cache->b_stroke.batch = GPU_batch_create_ex(GPU_PRIM_LINE_STRIP_ADJ, cache->b_stroke.vbo, NULL, GPU_BATCH_OWNS_VBO); - } - if ((cache->b_fill.vbo) && (cache->b_fill.batch == NULL)) { - cache->b_fill.batch = GPU_batch_create_ex(GPU_PRIM_TRIS, cache->b_fill.vbo, NULL, GPU_BATCH_OWNS_VBO); - } - if ((cache->b_edit.vbo) && (cache->b_edit.batch == NULL)) { - cache->b_edit.batch = GPU_batch_create_ex(GPU_PRIM_POINTS, cache->b_edit.vbo, NULL, GPU_BATCH_OWNS_VBO); - } - if ((cache->b_edlin.vbo) && (cache->b_edlin.batch == NULL)) { - cache->b_edlin.batch = GPU_batch_create_ex(GPU_PRIM_LINE_STRIP, cache->b_edlin.vbo, NULL, GPU_BATCH_OWNS_VBO); - } + if ((cache->b_point.vbo) && (cache->b_point.batch == NULL)) { + cache->b_point.batch = GPU_batch_create_ex( + GPU_PRIM_POINTS, cache->b_point.vbo, NULL, GPU_BATCH_OWNS_VBO); + } + if ((cache->b_stroke.vbo) && (cache->b_stroke.batch == NULL)) { + cache->b_stroke.batch = GPU_batch_create_ex( + GPU_PRIM_LINE_STRIP_ADJ, cache->b_stroke.vbo, NULL, GPU_BATCH_OWNS_VBO); + } + if ((cache->b_fill.vbo) && (cache->b_fill.batch == NULL)) { + cache->b_fill.batch = GPU_batch_create_ex( + GPU_PRIM_TRIS, cache->b_fill.vbo, NULL, GPU_BATCH_OWNS_VBO); + } + if ((cache->b_edit.vbo) && (cache->b_edit.batch == NULL)) { + cache->b_edit.batch = GPU_batch_create_ex( + GPU_PRIM_POINTS, cache->b_edit.vbo, NULL, GPU_BATCH_OWNS_VBO); + } + if ((cache->b_edlin.vbo) && (cache->b_edlin.batch == NULL)) { + cache->b_edlin.batch = GPU_batch_create_ex( + GPU_PRIM_LINE_STRIP, cache->b_edlin.vbo, NULL, GPU_BATCH_OWNS_VBO); + } } /* create all shading groups */ -static void DRW_gpencil_shgroups_create( - GPENCIL_e_data *e_data, void *vedata, - Object *ob, - GpencilBatchCache *cache, tGPencilObjectCache *cache_ob) +static void DRW_gpencil_shgroups_create(GPENCIL_e_data *e_data, + void *vedata, + Object *ob, + GpencilBatchCache *cache, + tGPencilObjectCache *cache_ob) { - GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; - GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; - bGPdata *gpd = (bGPdata *)ob->data; - DRWPass *stroke_pass = GPENCIL_3D_DRAWMODE(ob, gpd) ? psl->stroke_pass_3d : psl->stroke_pass_2d; - - GpencilBatchGroup *elm = NULL; - DRWShadingGroup *shgrp = NULL; - tGPencilObjectCache_shgrp *array_elm = NULL; - - bGPDlayer *gpl = NULL; - bGPDlayer *gpl_prev = NULL; - int idx = 0; - bool tag_first = false; - - int start_stroke = 0; - int start_point = 0; - int start_fill = 0; - int start_edit = 0; - int start_edlin = 0; - - for (int i = 0; i < cache->grp_used; i++) { - elm = &cache->grp_cache[i]; - array_elm = &cache_ob->shgrp_array[idx]; - const float scale = cache_ob->scale; - - /* save last group when change */ - if (gpl_prev == NULL) { - gpl_prev = elm->gpl; - tag_first = true; - } - else { - if (elm->gpl != gpl_prev) { - /* first layer is always blend Normal */ - array_elm->mode = idx == 0 ? eGplBlendMode_Normal: gpl->blend_mode; - array_elm->end_shgrp = shgrp; - gpl_prev = elm->gpl; - tag_first = true; - idx++; - } - } - - gpl = elm->gpl; - bGPDframe *gpf = elm->gpf; - bGPDstroke *gps = elm->gps; - MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1); - /* if the user switch used material from data to object, - * the material could not be available */ - if (gp_style == NULL) { - break; - } - - /* limit the number of shading groups */ - if (i >= GPENCIL_MAX_SHGROUPS) { - break; - } - - switch (elm->type) { - case eGpencilBatchGroupType_Stroke: - { - const int len = elm->vertex_idx - start_stroke; - - shgrp = DRW_gpencil_shgroup_stroke_create( - e_data, vedata, stroke_pass, e_data->gpencil_stroke_sh, - ob, gpd, gpl, gps, gp_style, stl->storage->shgroup_id, elm->onion, - scale, cache_ob->shading_type); - - DRW_shgroup_call_range_add( - shgrp, cache->b_stroke.batch, - (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix : cache_ob->obmat, - start_stroke, len); - - stl->storage->shgroup_id++; - start_stroke = elm->vertex_idx; - break; - } - case eGpencilBatchGroupType_Point: - { - const int len = elm->vertex_idx - start_point; - - shgrp = DRW_gpencil_shgroup_point_create( - e_data, vedata, stroke_pass, e_data->gpencil_point_sh, - ob, gpd, gpl, gps, gp_style, stl->storage->shgroup_id, elm->onion, - scale, cache_ob->shading_type); - - DRW_shgroup_call_range_add( - shgrp, cache->b_point.batch, - (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix : cache_ob->obmat, - start_point, len); - - stl->storage->shgroup_id++; - start_point = elm->vertex_idx; - break; - } - case eGpencilBatchGroupType_Fill: - { - const int len = elm->vertex_idx - start_fill; - - shgrp = DRW_gpencil_shgroup_fill_create( - e_data, vedata, stroke_pass, e_data->gpencil_fill_sh, - ob, gpd, gpl, gp_style, stl->storage->shgroup_id, - cache_ob->shading_type); - - DRW_shgroup_call_range_add( - shgrp, cache->b_fill.batch, - (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix : cache_ob->obmat, - start_fill, len); - - stl->storage->shgroup_id++; - start_fill = elm->vertex_idx; - break; - } - case eGpencilBatchGroupType_Edit: - { - if (stl->g_data->shgrps_edit_point) { - const int len = elm->vertex_idx - start_edit; - /* use always the same group */ - DRW_shgroup_call_range_add( - stl->g_data->shgrps_edit_point, - cache->b_edit.batch, - (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix : cache_ob->obmat, - start_edit, len); - - start_edit = elm->vertex_idx; - } - break; - } - case eGpencilBatchGroupType_Edlin: - { - if (stl->g_data->shgrps_edit_line) { - const int len = elm->vertex_idx - start_edlin; - /* use always the same group */ - DRW_shgroup_call_range_add( - stl->g_data->shgrps_edit_line, - cache->b_edlin.batch, - (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix : cache_ob->obmat, - start_edlin, len); - - start_edlin = elm->vertex_idx; - } - break; - } - default: - { - break; - } - } - /* save first group */ - if ((shgrp != NULL) && (tag_first)) { - array_elm = &cache_ob->shgrp_array[idx]; - array_elm->mode = idx == 0 ? eGplBlendMode_Normal: gpl->blend_mode; - array_elm->clamp_layer = gpl->flag & GP_LAYER_USE_MASK; - array_elm->blend_opacity = gpl->opacity; - array_elm->init_shgrp = shgrp; - cache_ob->tot_layers++; - - tag_first = false; - } - } - - /* save last group */ - if (shgrp != NULL) { - array_elm->mode = idx == 0 ? eGplBlendMode_Normal : gpl->blend_mode; - array_elm->end_shgrp = shgrp; - } + GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; + GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; + bGPdata *gpd = (bGPdata *)ob->data; + DRWPass *stroke_pass = GPENCIL_3D_DRAWMODE(ob, gpd) ? psl->stroke_pass_3d : psl->stroke_pass_2d; + + GpencilBatchGroup *elm = NULL; + DRWShadingGroup *shgrp = NULL; + tGPencilObjectCache_shgrp *array_elm = NULL; + + bGPDlayer *gpl = NULL; + bGPDlayer *gpl_prev = NULL; + int idx = 0; + bool tag_first = false; + + int start_stroke = 0; + int start_point = 0; + int start_fill = 0; + int start_edit = 0; + int start_edlin = 0; + + for (int i = 0; i < cache->grp_used; i++) { + elm = &cache->grp_cache[i]; + array_elm = &cache_ob->shgrp_array[idx]; + const float scale = cache_ob->scale; + + /* save last group when change */ + if (gpl_prev == NULL) { + gpl_prev = elm->gpl; + tag_first = true; + } + else { + if (elm->gpl != gpl_prev) { + /* first layer is always blend Normal */ + array_elm->mode = idx == 0 ? eGplBlendMode_Normal : gpl->blend_mode; + array_elm->end_shgrp = shgrp; + gpl_prev = elm->gpl; + tag_first = true; + idx++; + } + } + + gpl = elm->gpl; + bGPDframe *gpf = elm->gpf; + bGPDstroke *gps = elm->gps; + MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1); + /* if the user switch used material from data to object, + * the material could not be available */ + if (gp_style == NULL) { + break; + } + + /* limit the number of shading groups */ + if (i >= GPENCIL_MAX_SHGROUPS) { + break; + } + + switch (elm->type) { + case eGpencilBatchGroupType_Stroke: { + const int len = elm->vertex_idx - start_stroke; + + shgrp = DRW_gpencil_shgroup_stroke_create(e_data, + vedata, + stroke_pass, + e_data->gpencil_stroke_sh, + ob, + gpd, + gpl, + gps, + gp_style, + stl->storage->shgroup_id, + elm->onion, + scale, + cache_ob->shading_type); + + DRW_shgroup_call_range_add(shgrp, + cache->b_stroke.batch, + (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix : + cache_ob->obmat, + start_stroke, + len); + + stl->storage->shgroup_id++; + start_stroke = elm->vertex_idx; + break; + } + case eGpencilBatchGroupType_Point: { + const int len = elm->vertex_idx - start_point; + + shgrp = DRW_gpencil_shgroup_point_create(e_data, + vedata, + stroke_pass, + e_data->gpencil_point_sh, + ob, + gpd, + gpl, + gps, + gp_style, + stl->storage->shgroup_id, + elm->onion, + scale, + cache_ob->shading_type); + + DRW_shgroup_call_range_add(shgrp, + cache->b_point.batch, + (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix : + cache_ob->obmat, + start_point, + len); + + stl->storage->shgroup_id++; + start_point = elm->vertex_idx; + break; + } + case eGpencilBatchGroupType_Fill: { + const int len = elm->vertex_idx - start_fill; + + shgrp = DRW_gpencil_shgroup_fill_create(e_data, + vedata, + stroke_pass, + e_data->gpencil_fill_sh, + ob, + gpd, + gpl, + gp_style, + stl->storage->shgroup_id, + cache_ob->shading_type); + + DRW_shgroup_call_range_add(shgrp, + cache->b_fill.batch, + (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix : + cache_ob->obmat, + start_fill, + len); + + stl->storage->shgroup_id++; + start_fill = elm->vertex_idx; + break; + } + case eGpencilBatchGroupType_Edit: { + if (stl->g_data->shgrps_edit_point) { + const int len = elm->vertex_idx - start_edit; + /* use always the same group */ + DRW_shgroup_call_range_add(stl->g_data->shgrps_edit_point, + cache->b_edit.batch, + (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix : + cache_ob->obmat, + start_edit, + len); + + start_edit = elm->vertex_idx; + } + break; + } + case eGpencilBatchGroupType_Edlin: { + if (stl->g_data->shgrps_edit_line) { + const int len = elm->vertex_idx - start_edlin; + /* use always the same group */ + DRW_shgroup_call_range_add(stl->g_data->shgrps_edit_line, + cache->b_edlin.batch, + (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix : + cache_ob->obmat, + start_edlin, + len); + + start_edlin = elm->vertex_idx; + } + break; + } + default: { + break; + } + } + /* save first group */ + if ((shgrp != NULL) && (tag_first)) { + array_elm = &cache_ob->shgrp_array[idx]; + array_elm->mode = idx == 0 ? eGplBlendMode_Normal : gpl->blend_mode; + array_elm->clamp_layer = gpl->flag & GP_LAYER_USE_MASK; + array_elm->blend_opacity = gpl->opacity; + array_elm->init_shgrp = shgrp; + cache_ob->tot_layers++; + + tag_first = false; + } + } + + /* save last group */ + if (shgrp != NULL) { + array_elm->mode = idx == 0 ? eGplBlendMode_Normal : gpl->blend_mode; + array_elm->end_shgrp = shgrp; + } } /* populate a datablock for multiedit (no onions, no modifiers) */ -void DRW_gpencil_populate_multiedit( - GPENCIL_e_data *e_data, void *vedata, Object *ob, - tGPencilObjectCache *cache_ob) +void DRW_gpencil_populate_multiedit(GPENCIL_e_data *e_data, + void *vedata, + Object *ob, + tGPencilObjectCache *cache_ob) { - bGPdata *gpd = (bGPdata *)ob->data; - bGPDframe *gpf = NULL; - - GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; - const DRWContextState *draw_ctx = DRW_context_state_get(); - int cfra_eval = (int)DEG_get_ctime(draw_ctx->depsgraph); - GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra_eval); - - /* check if playing animation */ - const bool playing = stl->storage->is_playing; - - /* calc max size of VBOs */ - gpencil_calc_vertex(stl, cache_ob, cache, gpd, cfra_eval); - - /* draw strokes */ - for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { - /* don't draw layer if hidden */ - if (gpl->flag & GP_LAYER_HIDE) { - continue; - } - - /* list of frames to draw */ - if (!playing) { - for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { - if ((gpf == gpl->actframe) || (gpf->flag & GP_FRAME_SELECT)) { - gpencil_draw_strokes( - cache, e_data, vedata, ob, gpd, gpl, gpf, gpf, - gpl->opacity, gpl->tintcolor, false, cache_ob); - } - } - } - else { - gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, GP_GETFRAME_USE_PREV); - if (gpf) { - gpencil_draw_strokes( - cache, e_data, vedata, ob, gpd, gpl, gpf, gpf, - gpl->opacity, gpl->tintcolor, false, cache_ob); - } - } - - } - - /* create batchs and shading groups */ - DRW_gpencil_create_batches(cache); - DRW_gpencil_shgroups_create(e_data, vedata, ob, cache, cache_ob); - - cache->is_dirty = false; + bGPdata *gpd = (bGPdata *)ob->data; + bGPDframe *gpf = NULL; + + GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + int cfra_eval = (int)DEG_get_ctime(draw_ctx->depsgraph); + GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra_eval); + + /* check if playing animation */ + const bool playing = stl->storage->is_playing; + + /* calc max size of VBOs */ + gpencil_calc_vertex(stl, cache_ob, cache, gpd, cfra_eval); + + /* draw strokes */ + for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { + /* don't draw layer if hidden */ + if (gpl->flag & GP_LAYER_HIDE) { + continue; + } + + /* list of frames to draw */ + if (!playing) { + for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { + if ((gpf == gpl->actframe) || (gpf->flag & GP_FRAME_SELECT)) { + gpencil_draw_strokes(cache, + e_data, + vedata, + ob, + gpd, + gpl, + gpf, + gpf, + gpl->opacity, + gpl->tintcolor, + false, + cache_ob); + } + } + } + else { + gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, GP_GETFRAME_USE_PREV); + if (gpf) { + gpencil_draw_strokes(cache, + e_data, + vedata, + ob, + gpd, + gpl, + gpf, + gpf, + gpl->opacity, + gpl->tintcolor, + false, + cache_ob); + } + } + } + + /* create batchs and shading groups */ + DRW_gpencil_create_batches(cache); + DRW_gpencil_shgroups_create(e_data, vedata, ob, cache, cache_ob); + + cache->is_dirty = false; } /* helper for populate a complete grease pencil datablock */ -void DRW_gpencil_populate_datablock( - GPENCIL_e_data *e_data, void *vedata, - Object *ob, - tGPencilObjectCache *cache_ob) +void DRW_gpencil_populate_datablock(GPENCIL_e_data *e_data, + void *vedata, + Object *ob, + tGPencilObjectCache *cache_ob) { - GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; - const DRWContextState *draw_ctx = DRW_context_state_get(); - const ViewLayer *view_layer = DEG_get_evaluated_view_layer(draw_ctx->depsgraph); - Scene *scene = draw_ctx->scene; - - bGPdata *gpd = (bGPdata *)ob->data; - - View3D *v3d = draw_ctx->v3d; - int cfra_eval = (int)DEG_get_ctime(draw_ctx->depsgraph); - - bGPDframe *derived_gpf = NULL; - const bool main_onion = v3d != NULL ? (v3d->gp_flag & V3D_GP_SHOW_ONION_SKIN) : true; - const bool do_onion = (bool)((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0) && - main_onion && DRW_gpencil_onion_active(gpd); - const bool overlay = v3d != NULL ? (bool)((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) : true; - const bool time_remap = BKE_gpencil_has_time_modifiers(ob); - - float opacity; - bGPDframe *gpf = NULL; - bGPDlayer *gpl_active = BKE_gpencil_layer_getactive(gpd); - - /* check if playing animation */ - const bool playing = stl->storage->is_playing; - - GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra_eval); - - /* if object is duplicate, only create shading groups */ - if (cache_ob->is_dup_ob) { - DRW_gpencil_shgroups_create(e_data, vedata, ob, cache, cache_ob); - return; - } - - /* calc max size of VBOs */ - gpencil_calc_vertex(stl, cache_ob, cache, gpd, cfra_eval); - - /* init general modifiers data */ - if (!stl->storage->simplify_modif) { - if ((cache->is_dirty) && (ob->greasepencil_modifiers.first)) { - BKE_gpencil_lattice_init(ob); - } - } - /* draw normal strokes */ - for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { - /* don't draw layer if hidden */ - if (gpl->flag & GP_LAYER_HIDE) { - continue; - } - - const bool is_solomode = GPENCIL_PAINT_MODE(gpd) && - (!playing) && (!stl->storage->is_render) && - (gpl->flag & GP_LAYER_SOLO_MODE); - - /* filter view layer to gp layers in the same view layer (for compo) */ - if ((stl->storage->is_render) && (gpl->viewlayername[0] != '\0')) { - if (!STREQ(view_layer->name, gpl->viewlayername)) { - continue; - } - } - - /* remap time */ - int remap_cfra = cfra_eval; - if ((time_remap) && (!stl->storage->simplify_modif)) { - remap_cfra = BKE_gpencil_time_modifier( - draw_ctx->depsgraph, scene, ob, gpl, cfra_eval, - stl->storage->is_render); - } - - gpf = BKE_gpencil_layer_getframe(gpl, remap_cfra, GP_GETFRAME_USE_PREV); - if (gpf == NULL) { - continue; - } - - /* if solo mode, display only frames with keyframe in the current frame */ - if ((is_solomode) && (gpf->framenum != remap_cfra)) { - continue; - } - - opacity = gpl->opacity; - /* if pose mode, maybe the overlay to fade geometry is enabled */ - if ((draw_ctx->obact) && (draw_ctx->object_mode == OB_MODE_POSE) && - (v3d->overlay.flag & V3D_OVERLAY_BONE_SELECT)) - { - opacity = opacity * v3d->overlay.xray_alpha_bone; - } - /* fade no active layers */ - if ((overlay) && (draw_ctx->object_mode == OB_MODE_PAINT_GPENCIL) && - (v3d->gp_flag & V3D_GP_FADE_NOACTIVE_LAYERS) && - (draw_ctx->obact) && (draw_ctx->obact == ob) && - (gpl != gpl_active)) - { - opacity = opacity * v3d->overlay.gpencil_fade_layer; - } - - /* create derived frames array data or expand */ - int derived_idx = BLI_findindex(&gpd->layers, gpl); - derived_gpf = &cache->derived_array[derived_idx]; - - /* if no derived frame or dirty cache, create a new one */ - if ((derived_gpf == NULL) || (cache->is_dirty)) { - if (derived_gpf != NULL) { - /* first clear temp data */ - BKE_gpencil_free_frame_runtime_data(derived_gpf); - } - /* create new data (do not assign new memory)*/ - gpencil_copy_frame(gpf, derived_gpf); - } - - /* draw onion skins */ - if (!ID_IS_LINKED(&gpd->id)) { - if ((do_onion) && (gpl->onion_flag & GP_LAYER_ONIONSKIN) && - ((!playing) || (gpd->onion_flag & GP_ONION_GHOST_ALWAYS)) && - (!cache_ob->is_dup_ob) && (gpd->id.us <= 1)) - { - if (((!stl->storage->is_render) && (overlay)) || - ((stl->storage->is_render) && (gpd->onion_flag & GP_ONION_GHOST_ALWAYS))) - { - gpencil_draw_onionskins(cache, vedata, ob, gpd, gpl, gpf); - } - } - } - /* draw normal strokes */ - gpencil_draw_strokes( - cache, e_data, vedata, ob, gpd, gpl, gpf, derived_gpf, - opacity, gpl->tintcolor, false, cache_ob); - } - - /* clear any lattice data */ - if ((cache->is_dirty) && (ob->greasepencil_modifiers.first)) { - BKE_gpencil_lattice_clear(ob); - } - - /* create batchs and shading groups */ - DRW_gpencil_create_batches(cache); - DRW_gpencil_shgroups_create(e_data, vedata, ob, cache, cache_ob); - - cache->is_dirty = false; + GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + const ViewLayer *view_layer = DEG_get_evaluated_view_layer(draw_ctx->depsgraph); + Scene *scene = draw_ctx->scene; + + bGPdata *gpd = (bGPdata *)ob->data; + + View3D *v3d = draw_ctx->v3d; + int cfra_eval = (int)DEG_get_ctime(draw_ctx->depsgraph); + + bGPDframe *derived_gpf = NULL; + const bool main_onion = v3d != NULL ? (v3d->gp_flag & V3D_GP_SHOW_ONION_SKIN) : true; + const bool do_onion = (bool)((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0) && main_onion && + DRW_gpencil_onion_active(gpd); + const bool overlay = v3d != NULL ? (bool)((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) : true; + const bool time_remap = BKE_gpencil_has_time_modifiers(ob); + + float opacity; + bGPDframe *gpf = NULL; + bGPDlayer *gpl_active = BKE_gpencil_layer_getactive(gpd); + + /* check if playing animation */ + const bool playing = stl->storage->is_playing; + + GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra_eval); + + /* if object is duplicate, only create shading groups */ + if (cache_ob->is_dup_ob) { + DRW_gpencil_shgroups_create(e_data, vedata, ob, cache, cache_ob); + return; + } + + /* calc max size of VBOs */ + gpencil_calc_vertex(stl, cache_ob, cache, gpd, cfra_eval); + + /* init general modifiers data */ + if (!stl->storage->simplify_modif) { + if ((cache->is_dirty) && (ob->greasepencil_modifiers.first)) { + BKE_gpencil_lattice_init(ob); + } + } + /* draw normal strokes */ + for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { + /* don't draw layer if hidden */ + if (gpl->flag & GP_LAYER_HIDE) { + continue; + } + + const bool is_solomode = GPENCIL_PAINT_MODE(gpd) && (!playing) && (!stl->storage->is_render) && + (gpl->flag & GP_LAYER_SOLO_MODE); + + /* filter view layer to gp layers in the same view layer (for compo) */ + if ((stl->storage->is_render) && (gpl->viewlayername[0] != '\0')) { + if (!STREQ(view_layer->name, gpl->viewlayername)) { + continue; + } + } + + /* remap time */ + int remap_cfra = cfra_eval; + if ((time_remap) && (!stl->storage->simplify_modif)) { + remap_cfra = BKE_gpencil_time_modifier( + draw_ctx->depsgraph, scene, ob, gpl, cfra_eval, stl->storage->is_render); + } + + gpf = BKE_gpencil_layer_getframe(gpl, remap_cfra, GP_GETFRAME_USE_PREV); + if (gpf == NULL) { + continue; + } + + /* if solo mode, display only frames with keyframe in the current frame */ + if ((is_solomode) && (gpf->framenum != remap_cfra)) { + continue; + } + + opacity = gpl->opacity; + /* if pose mode, maybe the overlay to fade geometry is enabled */ + if ((draw_ctx->obact) && (draw_ctx->object_mode == OB_MODE_POSE) && + (v3d->overlay.flag & V3D_OVERLAY_BONE_SELECT)) { + opacity = opacity * v3d->overlay.xray_alpha_bone; + } + /* fade no active layers */ + if ((overlay) && (draw_ctx->object_mode == OB_MODE_PAINT_GPENCIL) && + (v3d->gp_flag & V3D_GP_FADE_NOACTIVE_LAYERS) && (draw_ctx->obact) && + (draw_ctx->obact == ob) && (gpl != gpl_active)) { + opacity = opacity * v3d->overlay.gpencil_fade_layer; + } + + /* create derived frames array data or expand */ + int derived_idx = BLI_findindex(&gpd->layers, gpl); + derived_gpf = &cache->derived_array[derived_idx]; + + /* if no derived frame or dirty cache, create a new one */ + if ((derived_gpf == NULL) || (cache->is_dirty)) { + if (derived_gpf != NULL) { + /* first clear temp data */ + BKE_gpencil_free_frame_runtime_data(derived_gpf); + } + /* create new data (do not assign new memory)*/ + gpencil_copy_frame(gpf, derived_gpf); + } + + /* draw onion skins */ + if (!ID_IS_LINKED(&gpd->id)) { + if ((do_onion) && (gpl->onion_flag & GP_LAYER_ONIONSKIN) && + ((!playing) || (gpd->onion_flag & GP_ONION_GHOST_ALWAYS)) && (!cache_ob->is_dup_ob) && + (gpd->id.us <= 1)) { + if (((!stl->storage->is_render) && (overlay)) || + ((stl->storage->is_render) && (gpd->onion_flag & GP_ONION_GHOST_ALWAYS))) { + gpencil_draw_onionskins(cache, vedata, ob, gpd, gpl, gpf); + } + } + } + /* draw normal strokes */ + gpencil_draw_strokes(cache, + e_data, + vedata, + ob, + gpd, + gpl, + gpf, + derived_gpf, + opacity, + gpl->tintcolor, + false, + cache_ob); + } + + /* clear any lattice data */ + if ((cache->is_dirty) && (ob->greasepencil_modifiers.first)) { + BKE_gpencil_lattice_clear(ob); + } + + /* create batchs and shading groups */ + DRW_gpencil_create_batches(cache); + DRW_gpencil_shgroups_create(e_data, vedata, ob, cache, cache_ob); + + cache->is_dirty = false; } void DRW_gpencil_populate_particles(GPENCIL_e_data *e_data, GHash *gh_objects, void *vedata) { - GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; - - /* add particles */ - for (int i = 0; i < stl->g_data->gp_cache_used; i++) { - tGPencilObjectCache *cache_ob = &stl->g_data->gp_object_cache[i]; - if (cache_ob->is_dup_ob) { - /* reasign duplicate objects because memory for particles is not available - * and need to use the original datablock and runtime data */ - Object *ob = (Object *)BLI_ghash_lookup(gh_objects, cache_ob->name); - if (ob) { - cache_ob->ob = ob; - cache_ob->gpd = (bGPdata *)ob->data; - GpencilBatchCache *cache = ob->runtime.gpencil_cache; - if (cache != NULL) { - DRW_gpencil_shgroups_create(e_data, vedata, ob, cache, cache_ob); - } - } - } - } + GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; + + /* add particles */ + for (int i = 0; i < stl->g_data->gp_cache_used; i++) { + tGPencilObjectCache *cache_ob = &stl->g_data->gp_object_cache[i]; + if (cache_ob->is_dup_ob) { + /* reasign duplicate objects because memory for particles is not available + * and need to use the original datablock and runtime data */ + Object *ob = (Object *)BLI_ghash_lookup(gh_objects, cache_ob->name); + if (ob) { + cache_ob->ob = ob; + cache_ob->gpd = (bGPdata *)ob->data; + GpencilBatchCache *cache = ob->runtime.gpencil_cache; + if (cache != NULL) { + DRW_gpencil_shgroups_create(e_data, vedata, ob, cache, cache_ob); + } + } + } + } } diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c index d1a8f40a428..6fa07245396 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.c +++ b/source/blender/draw/engines/gpencil/gpencil_engine.c @@ -44,7 +44,6 @@ #include "UI_resources.h" - extern char datatoc_gpencil_fill_vert_glsl[]; extern char datatoc_gpencil_fill_frag_glsl[]; extern char datatoc_gpencil_stroke_vert_glsl[]; @@ -70,1054 +69,1023 @@ static GPENCIL_e_data e_data = {NULL}; /* Engine data */ /* create a multisample buffer if not present */ void DRW_gpencil_multisample_ensure(GPENCIL_Data *vedata, int rect_w, int rect_h) { - GPENCIL_FramebufferList *fbl = vedata->fbl; - GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; - GPENCIL_TextureList *txl = ((GPENCIL_Data *)vedata)->txl; - - short samples = stl->storage->multisamples; - - if (samples > 0) { - if (!fbl->multisample_fb) { - fbl->multisample_fb = GPU_framebuffer_create(); - if (fbl->multisample_fb) { - if (txl->multisample_color == NULL) { - txl->multisample_color = GPU_texture_create_2d_multisample( - rect_w, rect_h, GPU_RGBA16F, NULL, samples, NULL); - } - if (txl->multisample_depth == NULL) { - txl->multisample_depth = GPU_texture_create_2d_multisample( - rect_w, rect_h, GPU_DEPTH_COMPONENT24, NULL, samples, NULL); - } - GPU_framebuffer_ensure_config( - &fbl->multisample_fb, { - GPU_ATTACHMENT_TEXTURE(txl->multisample_depth), - GPU_ATTACHMENT_TEXTURE(txl->multisample_color) - }); - } - } - } + GPENCIL_FramebufferList *fbl = vedata->fbl; + GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; + GPENCIL_TextureList *txl = ((GPENCIL_Data *)vedata)->txl; + + short samples = stl->storage->multisamples; + + if (samples > 0) { + if (!fbl->multisample_fb) { + fbl->multisample_fb = GPU_framebuffer_create(); + if (fbl->multisample_fb) { + if (txl->multisample_color == NULL) { + txl->multisample_color = GPU_texture_create_2d_multisample( + rect_w, rect_h, GPU_RGBA16F, NULL, samples, NULL); + } + if (txl->multisample_depth == NULL) { + txl->multisample_depth = GPU_texture_create_2d_multisample( + rect_w, rect_h, GPU_DEPTH_COMPONENT24, NULL, samples, NULL); + } + GPU_framebuffer_ensure_config(&fbl->multisample_fb, + {GPU_ATTACHMENT_TEXTURE(txl->multisample_depth), + GPU_ATTACHMENT_TEXTURE(txl->multisample_color)}); + } + } + } } static void GPENCIL_create_framebuffers(void *vedata) { - GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl; - GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; - - /* Go full 32bits for rendering */ - eGPUTextureFormat fb_format = DRW_state_is_image_render() ? GPU_RGBA32F : GPU_RGBA16F; - - if (DRW_state_is_fbo()) { - const float *viewport_size = DRW_viewport_size_get(); - const int size[2] = { (int)viewport_size[0], (int)viewport_size[1] }; - - /* create multiframe framebuffer for AA */ - if ((stl->storage->framebuffer_flag & GP_FRAMEBUFFER_MULTISAMPLE) && - (stl->storage->multisamples > 0)) - { - DRW_gpencil_multisample_ensure(vedata, size[0], size[1]); - } - - /* Framebufers for basic object drawing */ - if (stl->storage->framebuffer_flag & GP_FRAMEBUFFER_BASIC) { - /* temp textures for ping-pong buffers */ - e_data.temp_depth_tx_a = DRW_texture_pool_query_2d( - size[0], size[1], GPU_DEPTH_COMPONENT24, - &draw_engine_gpencil_type); - e_data.temp_color_tx_a = DRW_texture_pool_query_2d( - size[0], size[1], fb_format, - &draw_engine_gpencil_type); - GPU_framebuffer_ensure_config( - &fbl->temp_fb_a, { - GPU_ATTACHMENT_TEXTURE(e_data.temp_depth_tx_a), - GPU_ATTACHMENT_TEXTURE(e_data.temp_color_tx_a), - }); - - e_data.temp_depth_tx_b = DRW_texture_pool_query_2d( - size[0], size[1], GPU_DEPTH_COMPONENT24, - &draw_engine_gpencil_type); - e_data.temp_color_tx_b = DRW_texture_pool_query_2d( - size[0], size[1], fb_format, - &draw_engine_gpencil_type); - GPU_framebuffer_ensure_config( - &fbl->temp_fb_b, { - GPU_ATTACHMENT_TEXTURE(e_data.temp_depth_tx_b), - GPU_ATTACHMENT_TEXTURE(e_data.temp_color_tx_b), - }); - - /* used for FX effects and Layer blending */ - e_data.temp_depth_tx_fx = DRW_texture_pool_query_2d( - size[0], size[1], GPU_DEPTH_COMPONENT24, - &draw_engine_gpencil_type); - e_data.temp_color_tx_fx = DRW_texture_pool_query_2d( - size[0], size[1], fb_format, - &draw_engine_gpencil_type); - GPU_framebuffer_ensure_config( - &fbl->temp_fb_fx, { - GPU_ATTACHMENT_TEXTURE(e_data.temp_depth_tx_fx), - GPU_ATTACHMENT_TEXTURE(e_data.temp_color_tx_fx), - }); - } - - /* background framebuffer to speed up drawing process (always 16 bits) */ - if (stl->storage->framebuffer_flag & GP_FRAMEBUFFER_DRAW) { - e_data.background_depth_tx = DRW_texture_pool_query_2d( - size[0], size[1], GPU_DEPTH_COMPONENT24, - &draw_engine_gpencil_type); - e_data.background_color_tx = DRW_texture_pool_query_2d( - size[0], size[1], GPU_RGBA32F, - &draw_engine_gpencil_type); - GPU_framebuffer_ensure_config( - &fbl->background_fb, { - GPU_ATTACHMENT_TEXTURE(e_data.background_depth_tx), - GPU_ATTACHMENT_TEXTURE(e_data.background_color_tx), - }); - } - } + GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl; + GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; + + /* Go full 32bits for rendering */ + eGPUTextureFormat fb_format = DRW_state_is_image_render() ? GPU_RGBA32F : GPU_RGBA16F; + + if (DRW_state_is_fbo()) { + const float *viewport_size = DRW_viewport_size_get(); + const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]}; + + /* create multiframe framebuffer for AA */ + if ((stl->storage->framebuffer_flag & GP_FRAMEBUFFER_MULTISAMPLE) && + (stl->storage->multisamples > 0)) { + DRW_gpencil_multisample_ensure(vedata, size[0], size[1]); + } + + /* Framebufers for basic object drawing */ + if (stl->storage->framebuffer_flag & GP_FRAMEBUFFER_BASIC) { + /* temp textures for ping-pong buffers */ + e_data.temp_depth_tx_a = DRW_texture_pool_query_2d( + size[0], size[1], GPU_DEPTH_COMPONENT24, &draw_engine_gpencil_type); + e_data.temp_color_tx_a = DRW_texture_pool_query_2d( + size[0], size[1], fb_format, &draw_engine_gpencil_type); + GPU_framebuffer_ensure_config(&fbl->temp_fb_a, + { + GPU_ATTACHMENT_TEXTURE(e_data.temp_depth_tx_a), + GPU_ATTACHMENT_TEXTURE(e_data.temp_color_tx_a), + }); + + e_data.temp_depth_tx_b = DRW_texture_pool_query_2d( + size[0], size[1], GPU_DEPTH_COMPONENT24, &draw_engine_gpencil_type); + e_data.temp_color_tx_b = DRW_texture_pool_query_2d( + size[0], size[1], fb_format, &draw_engine_gpencil_type); + GPU_framebuffer_ensure_config(&fbl->temp_fb_b, + { + GPU_ATTACHMENT_TEXTURE(e_data.temp_depth_tx_b), + GPU_ATTACHMENT_TEXTURE(e_data.temp_color_tx_b), + }); + + /* used for FX effects and Layer blending */ + e_data.temp_depth_tx_fx = DRW_texture_pool_query_2d( + size[0], size[1], GPU_DEPTH_COMPONENT24, &draw_engine_gpencil_type); + e_data.temp_color_tx_fx = DRW_texture_pool_query_2d( + size[0], size[1], fb_format, &draw_engine_gpencil_type); + GPU_framebuffer_ensure_config(&fbl->temp_fb_fx, + { + GPU_ATTACHMENT_TEXTURE(e_data.temp_depth_tx_fx), + GPU_ATTACHMENT_TEXTURE(e_data.temp_color_tx_fx), + }); + } + + /* background framebuffer to speed up drawing process (always 16 bits) */ + if (stl->storage->framebuffer_flag & GP_FRAMEBUFFER_DRAW) { + e_data.background_depth_tx = DRW_texture_pool_query_2d( + size[0], size[1], GPU_DEPTH_COMPONENT24, &draw_engine_gpencil_type); + e_data.background_color_tx = DRW_texture_pool_query_2d( + size[0], size[1], GPU_RGBA32F, &draw_engine_gpencil_type); + GPU_framebuffer_ensure_config(&fbl->background_fb, + { + GPU_ATTACHMENT_TEXTURE(e_data.background_depth_tx), + GPU_ATTACHMENT_TEXTURE(e_data.background_color_tx), + }); + } + } } static void GPENCIL_create_shaders(void) { - /* normal fill shader */ - if (!e_data.gpencil_fill_sh) { - e_data.gpencil_fill_sh = DRW_shader_create( - datatoc_gpencil_fill_vert_glsl, NULL, - datatoc_gpencil_fill_frag_glsl, NULL); - } - - /* normal stroke shader using geometry to display lines (line mode) */ - if (!e_data.gpencil_stroke_sh) { - e_data.gpencil_stroke_sh = DRW_shader_create( - datatoc_gpencil_stroke_vert_glsl, - datatoc_gpencil_stroke_geom_glsl, - datatoc_gpencil_stroke_frag_glsl, - NULL); - } - - /* dot/rectangle mode for normal strokes using geometry */ - if (!e_data.gpencil_point_sh) { - e_data.gpencil_point_sh = DRW_shader_create( - datatoc_gpencil_point_vert_glsl, - datatoc_gpencil_point_geom_glsl, - datatoc_gpencil_point_frag_glsl, - NULL); - } - /* used for edit points or strokes with one point only */ - if (!e_data.gpencil_edit_point_sh) { - e_data.gpencil_edit_point_sh = DRW_shader_create( - datatoc_gpencil_edit_point_vert_glsl, - datatoc_gpencil_edit_point_geom_glsl, - datatoc_gpencil_edit_point_frag_glsl, NULL); - } - - /* used for edit lines for edit modes */ - if (!e_data.gpencil_line_sh) { - e_data.gpencil_line_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_FLAT_COLOR); - } - - /* used to filling during drawing */ - if (!e_data.gpencil_drawing_fill_sh) { - e_data.gpencil_drawing_fill_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_SMOOTH_COLOR); - } - - /* full screen for mix zdepth*/ - if (!e_data.gpencil_fullscreen_sh) { - e_data.gpencil_fullscreen_sh = DRW_shader_create_fullscreen(datatoc_gpencil_zdepth_mix_frag_glsl, NULL); - } - if (!e_data.gpencil_simple_fullscreen_sh) { - e_data.gpencil_simple_fullscreen_sh = DRW_shader_create_fullscreen(datatoc_gpencil_simple_mix_frag_glsl, NULL); - } - - /* blend */ - if (!e_data.gpencil_blend_fullscreen_sh) { - e_data.gpencil_blend_fullscreen_sh = DRW_shader_create_fullscreen(datatoc_gpencil_blend_frag_glsl, NULL); - } - - /* shaders for use when drawing */ - if (!e_data.gpencil_background_sh) { - e_data.gpencil_background_sh = DRW_shader_create_fullscreen(datatoc_gpencil_background_frag_glsl, NULL); - } - if (!e_data.gpencil_paper_sh) { - e_data.gpencil_paper_sh = DRW_shader_create_fullscreen(datatoc_gpencil_paper_frag_glsl, NULL); - } + /* normal fill shader */ + if (!e_data.gpencil_fill_sh) { + e_data.gpencil_fill_sh = DRW_shader_create( + datatoc_gpencil_fill_vert_glsl, NULL, datatoc_gpencil_fill_frag_glsl, NULL); + } + + /* normal stroke shader using geometry to display lines (line mode) */ + if (!e_data.gpencil_stroke_sh) { + e_data.gpencil_stroke_sh = DRW_shader_create(datatoc_gpencil_stroke_vert_glsl, + datatoc_gpencil_stroke_geom_glsl, + datatoc_gpencil_stroke_frag_glsl, + NULL); + } + + /* dot/rectangle mode for normal strokes using geometry */ + if (!e_data.gpencil_point_sh) { + e_data.gpencil_point_sh = DRW_shader_create(datatoc_gpencil_point_vert_glsl, + datatoc_gpencil_point_geom_glsl, + datatoc_gpencil_point_frag_glsl, + NULL); + } + /* used for edit points or strokes with one point only */ + if (!e_data.gpencil_edit_point_sh) { + e_data.gpencil_edit_point_sh = DRW_shader_create(datatoc_gpencil_edit_point_vert_glsl, + datatoc_gpencil_edit_point_geom_glsl, + datatoc_gpencil_edit_point_frag_glsl, + NULL); + } + + /* used for edit lines for edit modes */ + if (!e_data.gpencil_line_sh) { + e_data.gpencil_line_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_FLAT_COLOR); + } + + /* used to filling during drawing */ + if (!e_data.gpencil_drawing_fill_sh) { + e_data.gpencil_drawing_fill_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_SMOOTH_COLOR); + } + + /* full screen for mix zdepth*/ + if (!e_data.gpencil_fullscreen_sh) { + e_data.gpencil_fullscreen_sh = DRW_shader_create_fullscreen( + datatoc_gpencil_zdepth_mix_frag_glsl, NULL); + } + if (!e_data.gpencil_simple_fullscreen_sh) { + e_data.gpencil_simple_fullscreen_sh = DRW_shader_create_fullscreen( + datatoc_gpencil_simple_mix_frag_glsl, NULL); + } + + /* blend */ + if (!e_data.gpencil_blend_fullscreen_sh) { + e_data.gpencil_blend_fullscreen_sh = DRW_shader_create_fullscreen( + datatoc_gpencil_blend_frag_glsl, NULL); + } + + /* shaders for use when drawing */ + if (!e_data.gpencil_background_sh) { + e_data.gpencil_background_sh = DRW_shader_create_fullscreen( + datatoc_gpencil_background_frag_glsl, NULL); + } + if (!e_data.gpencil_paper_sh) { + e_data.gpencil_paper_sh = DRW_shader_create_fullscreen(datatoc_gpencil_paper_frag_glsl, NULL); + } } void GPENCIL_engine_init(void *vedata) { - GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; - /* init storage */ - if (!stl->storage) { - stl->storage = MEM_callocN(sizeof(GPENCIL_Storage), "GPENCIL_Storage"); - - /* unit matrix */ - unit_m4(stl->storage->unit_matrix); - stl->storage->shade_render[0] = OB_RENDER; - stl->storage->shade_render[1] = 0; - } - - stl->storage->multisamples = U.gpencil_multisamples; - - /* create shaders */ - GPENCIL_create_shaders(); - GPENCIL_create_fx_shaders(&e_data); - - /* blank texture used if no texture defined for fill shader */ - if (!e_data.gpencil_blank_texture) { - float rect[16][16][4] = {{{0.0f}}}; - e_data.gpencil_blank_texture = DRW_texture_create_2d(16, 16, GPU_RGBA8, DRW_TEX_FILTER, (float *)rect); - } + GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; + /* init storage */ + if (!stl->storage) { + stl->storage = MEM_callocN(sizeof(GPENCIL_Storage), "GPENCIL_Storage"); + + /* unit matrix */ + unit_m4(stl->storage->unit_matrix); + stl->storage->shade_render[0] = OB_RENDER; + stl->storage->shade_render[1] = 0; + } + + stl->storage->multisamples = U.gpencil_multisamples; + + /* create shaders */ + GPENCIL_create_shaders(); + GPENCIL_create_fx_shaders(&e_data); + + /* blank texture used if no texture defined for fill shader */ + if (!e_data.gpencil_blank_texture) { + float rect[16][16][4] = {{{0.0f}}}; + e_data.gpencil_blank_texture = DRW_texture_create_2d( + 16, 16, GPU_RGBA8, DRW_TEX_FILTER, (float *)rect); + } } static void GPENCIL_engine_free(void) { - /* only free custom shaders, builtin shaders are freed in blender close */ - DRW_SHADER_FREE_SAFE(e_data.gpencil_fill_sh); - DRW_SHADER_FREE_SAFE(e_data.gpencil_stroke_sh); - DRW_SHADER_FREE_SAFE(e_data.gpencil_point_sh); - DRW_SHADER_FREE_SAFE(e_data.gpencil_edit_point_sh); - DRW_SHADER_FREE_SAFE(e_data.gpencil_fullscreen_sh); - DRW_SHADER_FREE_SAFE(e_data.gpencil_simple_fullscreen_sh); - DRW_SHADER_FREE_SAFE(e_data.gpencil_blend_fullscreen_sh); - DRW_SHADER_FREE_SAFE(e_data.gpencil_background_sh); - DRW_SHADER_FREE_SAFE(e_data.gpencil_paper_sh); + /* only free custom shaders, builtin shaders are freed in blender close */ + DRW_SHADER_FREE_SAFE(e_data.gpencil_fill_sh); + DRW_SHADER_FREE_SAFE(e_data.gpencil_stroke_sh); + DRW_SHADER_FREE_SAFE(e_data.gpencil_point_sh); + DRW_SHADER_FREE_SAFE(e_data.gpencil_edit_point_sh); + DRW_SHADER_FREE_SAFE(e_data.gpencil_fullscreen_sh); + DRW_SHADER_FREE_SAFE(e_data.gpencil_simple_fullscreen_sh); + DRW_SHADER_FREE_SAFE(e_data.gpencil_blend_fullscreen_sh); + DRW_SHADER_FREE_SAFE(e_data.gpencil_background_sh); + DRW_SHADER_FREE_SAFE(e_data.gpencil_paper_sh); - DRW_TEXTURE_FREE_SAFE(e_data.gpencil_blank_texture); + DRW_TEXTURE_FREE_SAFE(e_data.gpencil_blank_texture); - GPU_BATCH_DISCARD_SAFE(e_data.batch_buffer_stroke); - MEM_SAFE_FREE(e_data.batch_buffer_stroke); + GPU_BATCH_DISCARD_SAFE(e_data.batch_buffer_stroke); + MEM_SAFE_FREE(e_data.batch_buffer_stroke); - GPU_BATCH_DISCARD_SAFE(e_data.batch_buffer_fill); - MEM_SAFE_FREE(e_data.batch_buffer_fill); + GPU_BATCH_DISCARD_SAFE(e_data.batch_buffer_fill); + MEM_SAFE_FREE(e_data.batch_buffer_fill); - GPU_BATCH_DISCARD_SAFE(e_data.batch_buffer_ctrlpoint); - MEM_SAFE_FREE(e_data.batch_buffer_ctrlpoint); + GPU_BATCH_DISCARD_SAFE(e_data.batch_buffer_ctrlpoint); + MEM_SAFE_FREE(e_data.batch_buffer_ctrlpoint); - GPU_BATCH_DISCARD_SAFE(e_data.batch_grid); - MEM_SAFE_FREE(e_data.batch_grid); + GPU_BATCH_DISCARD_SAFE(e_data.batch_grid); + MEM_SAFE_FREE(e_data.batch_grid); - /* effects */ - GPENCIL_delete_fx_shaders(&e_data); + /* effects */ + GPENCIL_delete_fx_shaders(&e_data); } void GPENCIL_cache_init(void *vedata) { - GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; - GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; - const DRWContextState *draw_ctx = DRW_context_state_get(); - Scene *scene = draw_ctx->scene; - ToolSettings *ts = scene->toolsettings; - View3D *v3d = draw_ctx->v3d; - Brush *brush = BKE_paint_brush(&ts->gp_paint->paint); - - /* Special handling for when active object is GP object (e.g. for draw mode) */ - Object *obact = draw_ctx->obact; - bGPdata *obact_gpd = NULL; - MaterialGPencilStyle *gp_style = NULL; - - if (obact && (obact->type == OB_GPENCIL) && (obact->data)) { - obact_gpd = (bGPdata *)obact->data; - /* use the brush material */ - Material *ma = BKE_gpencil_object_material_get_from_brush(obact, brush); - if (ma != NULL) { - gp_style = ma->gp_style; - } - /* this is not common, but avoid any special situations when brush could be without material */ - if (gp_style == NULL) { - gp_style = BKE_material_gpencil_settings_get(obact, obact->actcol); - } - } - - if (!stl->g_data) { - /* Alloc transient pointers */ - stl->g_data = MEM_mallocN(sizeof(g_data), "g_data"); - stl->storage->xray = GP_XRAY_FRONT; /* used for drawing */ - stl->storage->stroke_style = GP_STYLE_STROKE_STYLE_SOLID; /* used for drawing */ - } - stl->storage->tonemapping = 0; - - stl->g_data->shgrps_edit_line = NULL; - stl->g_data->shgrps_edit_point = NULL; - - if (!stl->shgroups) { - /* Alloc maximum size because count strokes is very slow and can be very complex due onion skinning. - */ - stl->shgroups = MEM_mallocN(sizeof(GPENCIL_shgroup) * GPENCIL_MAX_SHGROUPS, "GPENCIL_shgroup"); - } - - /* init gp objects cache */ - stl->g_data->gp_cache_used = 0; - stl->g_data->gp_cache_size = 0; - stl->g_data->gp_object_cache = NULL; - stl->g_data->do_instances = false; - - { - /* Stroke pass 2D */ - psl->stroke_pass_2d = DRW_pass_create( - "GPencil Stroke Pass", - DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS | DRW_STATE_BLEND); - stl->storage->shgroup_id = 0; - /* Stroke pass 3D */ - psl->stroke_pass_3d = DRW_pass_create( - "GPencil Stroke Pass", - DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND); - stl->storage->shgroup_id = 0; - - /* edit pass */ - psl->edit_pass = DRW_pass_create( - "GPencil Edit Pass", - DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND); - - /* detect if playing animation */ - if (draw_ctx->evil_C) { - - bool playing = ED_screen_animation_playing(CTX_wm_manager(draw_ctx->evil_C)) != NULL; - if (playing != stl->storage->is_playing) { - stl->storage->reset_cache = true; - } - stl->storage->is_playing = playing; - } - else { - stl->storage->is_playing = false; - stl->storage->reset_cache = false; - } - /* save render state */ - stl->storage->is_render = DRW_state_is_image_render(); - stl->storage->is_mat_preview = (bool)stl->storage->is_render && STREQ(scene->id.name + 2, "preview"); - - if (obact_gpd) { - /* for some reason, when press play there is a delay in the animation flag check - * and this produces errors. To be sure, we set cache as dirty because the frame - * is changing. - */ - if (stl->storage->is_playing == true) { - obact_gpd->flag |= GP_DATA_CACHE_IS_DIRTY; - } - /* if render, set as dirty to update all data */ - else if (stl->storage->is_render == true) { - obact_gpd->flag |= GP_DATA_CACHE_IS_DIRTY; - } - } - - /* save simplify flags (can change while drawing, so it's better to save) */ - stl->storage->simplify_fill = GP_SIMPLIFY_FILL(scene, stl->storage->is_playing); - stl->storage->simplify_modif = GP_SIMPLIFY_MODIF(scene, stl->storage->is_playing); - stl->storage->simplify_fx = GP_SIMPLIFY_FX(scene, stl->storage->is_playing); - stl->storage->simplify_blend = GP_SIMPLIFY_BLEND(scene, stl->storage->is_playing); - - /* xray mode */ - if (v3d) { - stl->storage->is_xray = XRAY_ACTIVE(v3d); - } - else { - stl->storage->is_xray = 0; - } - - /* save pixsize */ - stl->storage->pixsize = DRW_viewport_pixelsize_get(); - if ((!DRW_state_is_opengl_render()) && (stl->storage->is_render)) { - stl->storage->pixsize = &stl->storage->render_pixsize; - } - - /* detect if painting session */ - if ((obact_gpd) && - (obact_gpd->flag & GP_DATA_STROKE_PAINTMODE) && - (stl->storage->is_playing == false)) - { - /* need the original to avoid cow overhead while drawing */ - bGPdata *gpd_orig = (bGPdata *)DEG_get_original_id(&obact_gpd->id); - if (((gpd_orig->runtime.sbuffer_sflag & GP_STROKE_ERASER) == 0) && - (gpd_orig->runtime.sbuffer_size > 0) && - ((gpd_orig->flag & GP_DATA_STROKE_POLYGON) == 0) && - !DRW_state_is_depth()) - { - stl->g_data->session_flag |= GP_DRW_PAINT_PAINTING; - } - else { - stl->g_data->session_flag = GP_DRW_PAINT_IDLE; - } - } - else { - /* if not drawing mode */ - stl->g_data->session_flag = GP_DRW_PAINT_HOLD; - } - - if (gp_style) { - stl->storage->stroke_style = gp_style->stroke_style; - stl->storage->color_type = GPENCIL_COLOR_SOLID; - if (gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE) { - stl->storage->color_type = GPENCIL_COLOR_TEXTURE; - if (gp_style->flag & GP_STYLE_STROKE_PATTERN) { - stl->storage->color_type = GPENCIL_COLOR_PATTERN; - } - } - } - else { - stl->storage->stroke_style = GP_STYLE_STROKE_STYLE_SOLID; - stl->storage->color_type = GPENCIL_COLOR_SOLID; - } - - /* drawing buffer pass for drawing the stroke that is being drawing by the user. The data - * is stored in sbuffer - */ - psl->drawing_pass = DRW_pass_create( - "GPencil Drawing Pass", - DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS); - - /* full screen pass to combine the result with default framebuffer */ - struct GPUBatch *quad = DRW_cache_fullscreen_quad_get(); - psl->mix_pass = DRW_pass_create( - "GPencil Mix Pass", - DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS); - DRWShadingGroup *mix_shgrp = DRW_shgroup_create(e_data.gpencil_fullscreen_sh, psl->mix_pass); - DRW_shgroup_call_add(mix_shgrp, quad, NULL); - DRW_shgroup_uniform_texture_ref(mix_shgrp, "strokeColor", &e_data.input_color_tx); - DRW_shgroup_uniform_texture_ref(mix_shgrp, "strokeDepth", &e_data.input_depth_tx); - DRW_shgroup_uniform_int(mix_shgrp, "tonemapping", &stl->storage->tonemapping, 1); - DRW_shgroup_uniform_int(mix_shgrp, "do_select", &stl->storage->do_select_outline, 1); - DRW_shgroup_uniform_vec4(mix_shgrp, "select_color", stl->storage->select_color, 1); - - /* mix pass no blend used to copy between passes. A separated pass is required - * because if mix_pass is used, the acumulation of blend degrade the colors. - * - * This pass is used too to take the snapshot used for background_pass. This image - * will be used as the background while the user is drawing. - */ - psl->mix_pass_noblend = DRW_pass_create( - "GPencil Mix Pass no blend", - DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS); - DRWShadingGroup *mix_shgrp_noblend = DRW_shgroup_create(e_data.gpencil_fullscreen_sh, psl->mix_pass_noblend); - DRW_shgroup_call_add(mix_shgrp_noblend, quad, NULL); - DRW_shgroup_uniform_texture_ref(mix_shgrp_noblend, "strokeColor", &e_data.input_color_tx); - DRW_shgroup_uniform_texture_ref(mix_shgrp_noblend, "strokeDepth", &e_data.input_depth_tx); - DRW_shgroup_uniform_int(mix_shgrp_noblend, "tonemapping", &stl->storage->tonemapping, 1); - DRW_shgroup_uniform_int(mix_shgrp_noblend, "do_select", &stl->storage->do_select_outline, 1); - DRW_shgroup_uniform_vec4(mix_shgrp_noblend, "select_color", stl->storage->select_color, 1); - - /* Painting session pass (used only to speedup while the user is drawing ) - * This pass is used to show the snapshot of the current grease pencil strokes captured - * when the user starts to draw (see comments above). - * In this way, the previous strokes don't need to be redraw and the drawing process - * is far to agile. - */ - psl->background_pass = DRW_pass_create( - "GPencil Background Painting Session Pass", - DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS); - DRWShadingGroup *background_shgrp = DRW_shgroup_create(e_data.gpencil_background_sh, psl->background_pass); - DRW_shgroup_call_add(background_shgrp, quad, NULL); - DRW_shgroup_uniform_texture_ref(background_shgrp, "strokeColor", &e_data.background_color_tx); - DRW_shgroup_uniform_texture_ref(background_shgrp, "strokeDepth", &e_data.background_depth_tx); - - /* pass for drawing paper (only if viewport) - * In render, the v3d is null so the paper is disabled - * The paper is way to isolate the drawing in complex scene and to have a cleaner - * drawing area. - */ - if (v3d) { - psl->paper_pass = DRW_pass_create( - "GPencil Paper Pass", - DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND); - DRWShadingGroup *paper_shgrp = DRW_shgroup_create(e_data.gpencil_paper_sh, psl->paper_pass); - DRW_shgroup_call_add(paper_shgrp, quad, NULL); - DRW_shgroup_uniform_vec3(paper_shgrp, "color", v3d->shading.background_color, 1); - DRW_shgroup_uniform_float(paper_shgrp, "opacity", &v3d->overlay.gpencil_paper_opacity, 1); - } - - /* grid pass */ - if (v3d) { - psl->grid_pass = DRW_pass_create( - "GPencil Grid Pass", - DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS); - stl->g_data->shgrps_grid = DRW_shgroup_create(e_data.gpencil_line_sh, psl->grid_pass); - } - - /* blend layers pass */ - psl->blend_pass = DRW_pass_create( - "GPencil Blend Layers Pass", - DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS); - DRWShadingGroup *blend_shgrp = DRW_shgroup_create(e_data.gpencil_blend_fullscreen_sh, psl->blend_pass); - DRW_shgroup_call_add(blend_shgrp, quad, NULL); - DRW_shgroup_uniform_texture_ref(blend_shgrp, "strokeColor", &e_data.temp_color_tx_a); - DRW_shgroup_uniform_texture_ref(blend_shgrp, "strokeDepth", &e_data.temp_depth_tx_a); - DRW_shgroup_uniform_texture_ref(blend_shgrp, "blendColor", &e_data.temp_color_tx_fx); - DRW_shgroup_uniform_texture_ref(blend_shgrp, "blendDepth", &e_data.temp_depth_tx_fx); - DRW_shgroup_uniform_int(blend_shgrp, "mode", &stl->storage->blend_mode, 1); - DRW_shgroup_uniform_int(blend_shgrp, "clamp_layer", &stl->storage->clamp_layer, 1); - DRW_shgroup_uniform_float(blend_shgrp, "blend_opacity", &stl->storage->blend_opacity, 1); - DRW_shgroup_uniform_int(mix_shgrp, "tonemapping", &stl->storage->tonemapping, 1); - - /* create effects passes */ - if (!stl->storage->simplify_fx) { - GPENCIL_create_fx_passes(psl); - } - } + GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; + GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene = draw_ctx->scene; + ToolSettings *ts = scene->toolsettings; + View3D *v3d = draw_ctx->v3d; + Brush *brush = BKE_paint_brush(&ts->gp_paint->paint); + + /* Special handling for when active object is GP object (e.g. for draw mode) */ + Object *obact = draw_ctx->obact; + bGPdata *obact_gpd = NULL; + MaterialGPencilStyle *gp_style = NULL; + + if (obact && (obact->type == OB_GPENCIL) && (obact->data)) { + obact_gpd = (bGPdata *)obact->data; + /* use the brush material */ + Material *ma = BKE_gpencil_object_material_get_from_brush(obact, brush); + if (ma != NULL) { + gp_style = ma->gp_style; + } + /* this is not common, but avoid any special situations when brush could be without material */ + if (gp_style == NULL) { + gp_style = BKE_material_gpencil_settings_get(obact, obact->actcol); + } + } + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_mallocN(sizeof(g_data), "g_data"); + stl->storage->xray = GP_XRAY_FRONT; /* used for drawing */ + stl->storage->stroke_style = GP_STYLE_STROKE_STYLE_SOLID; /* used for drawing */ + } + stl->storage->tonemapping = 0; + + stl->g_data->shgrps_edit_line = NULL; + stl->g_data->shgrps_edit_point = NULL; + + if (!stl->shgroups) { + /* Alloc maximum size because count strokes is very slow and can be very complex due onion skinning. + */ + stl->shgroups = MEM_mallocN(sizeof(GPENCIL_shgroup) * GPENCIL_MAX_SHGROUPS, "GPENCIL_shgroup"); + } + + /* init gp objects cache */ + stl->g_data->gp_cache_used = 0; + stl->g_data->gp_cache_size = 0; + stl->g_data->gp_object_cache = NULL; + stl->g_data->do_instances = false; + + { + /* Stroke pass 2D */ + psl->stroke_pass_2d = DRW_pass_create("GPencil Stroke Pass", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | + DRW_STATE_DEPTH_ALWAYS | DRW_STATE_BLEND); + stl->storage->shgroup_id = 0; + /* Stroke pass 3D */ + psl->stroke_pass_3d = DRW_pass_create("GPencil Stroke Pass", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | + DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND); + stl->storage->shgroup_id = 0; + + /* edit pass */ + psl->edit_pass = DRW_pass_create("GPencil Edit Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND); + + /* detect if playing animation */ + if (draw_ctx->evil_C) { + + bool playing = ED_screen_animation_playing(CTX_wm_manager(draw_ctx->evil_C)) != NULL; + if (playing != stl->storage->is_playing) { + stl->storage->reset_cache = true; + } + stl->storage->is_playing = playing; + } + else { + stl->storage->is_playing = false; + stl->storage->reset_cache = false; + } + /* save render state */ + stl->storage->is_render = DRW_state_is_image_render(); + stl->storage->is_mat_preview = (bool)stl->storage->is_render && + STREQ(scene->id.name + 2, "preview"); + + if (obact_gpd) { + /* for some reason, when press play there is a delay in the animation flag check + * and this produces errors. To be sure, we set cache as dirty because the frame + * is changing. + */ + if (stl->storage->is_playing == true) { + obact_gpd->flag |= GP_DATA_CACHE_IS_DIRTY; + } + /* if render, set as dirty to update all data */ + else if (stl->storage->is_render == true) { + obact_gpd->flag |= GP_DATA_CACHE_IS_DIRTY; + } + } + + /* save simplify flags (can change while drawing, so it's better to save) */ + stl->storage->simplify_fill = GP_SIMPLIFY_FILL(scene, stl->storage->is_playing); + stl->storage->simplify_modif = GP_SIMPLIFY_MODIF(scene, stl->storage->is_playing); + stl->storage->simplify_fx = GP_SIMPLIFY_FX(scene, stl->storage->is_playing); + stl->storage->simplify_blend = GP_SIMPLIFY_BLEND(scene, stl->storage->is_playing); + + /* xray mode */ + if (v3d) { + stl->storage->is_xray = XRAY_ACTIVE(v3d); + } + else { + stl->storage->is_xray = 0; + } + + /* save pixsize */ + stl->storage->pixsize = DRW_viewport_pixelsize_get(); + if ((!DRW_state_is_opengl_render()) && (stl->storage->is_render)) { + stl->storage->pixsize = &stl->storage->render_pixsize; + } + + /* detect if painting session */ + if ((obact_gpd) && (obact_gpd->flag & GP_DATA_STROKE_PAINTMODE) && + (stl->storage->is_playing == false)) { + /* need the original to avoid cow overhead while drawing */ + bGPdata *gpd_orig = (bGPdata *)DEG_get_original_id(&obact_gpd->id); + if (((gpd_orig->runtime.sbuffer_sflag & GP_STROKE_ERASER) == 0) && + (gpd_orig->runtime.sbuffer_size > 0) && + ((gpd_orig->flag & GP_DATA_STROKE_POLYGON) == 0) && !DRW_state_is_depth()) { + stl->g_data->session_flag |= GP_DRW_PAINT_PAINTING; + } + else { + stl->g_data->session_flag = GP_DRW_PAINT_IDLE; + } + } + else { + /* if not drawing mode */ + stl->g_data->session_flag = GP_DRW_PAINT_HOLD; + } + + if (gp_style) { + stl->storage->stroke_style = gp_style->stroke_style; + stl->storage->color_type = GPENCIL_COLOR_SOLID; + if (gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE) { + stl->storage->color_type = GPENCIL_COLOR_TEXTURE; + if (gp_style->flag & GP_STYLE_STROKE_PATTERN) { + stl->storage->color_type = GPENCIL_COLOR_PATTERN; + } + } + } + else { + stl->storage->stroke_style = GP_STYLE_STROKE_STYLE_SOLID; + stl->storage->color_type = GPENCIL_COLOR_SOLID; + } + + /* drawing buffer pass for drawing the stroke that is being drawing by the user. The data + * is stored in sbuffer + */ + psl->drawing_pass = DRW_pass_create("GPencil Drawing Pass", + DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND | + DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS); + + /* full screen pass to combine the result with default framebuffer */ + struct GPUBatch *quad = DRW_cache_fullscreen_quad_get(); + psl->mix_pass = DRW_pass_create("GPencil Mix Pass", + DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND | + DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS); + DRWShadingGroup *mix_shgrp = DRW_shgroup_create(e_data.gpencil_fullscreen_sh, psl->mix_pass); + DRW_shgroup_call_add(mix_shgrp, quad, NULL); + DRW_shgroup_uniform_texture_ref(mix_shgrp, "strokeColor", &e_data.input_color_tx); + DRW_shgroup_uniform_texture_ref(mix_shgrp, "strokeDepth", &e_data.input_depth_tx); + DRW_shgroup_uniform_int(mix_shgrp, "tonemapping", &stl->storage->tonemapping, 1); + DRW_shgroup_uniform_int(mix_shgrp, "do_select", &stl->storage->do_select_outline, 1); + DRW_shgroup_uniform_vec4(mix_shgrp, "select_color", stl->storage->select_color, 1); + + /* mix pass no blend used to copy between passes. A separated pass is required + * because if mix_pass is used, the acumulation of blend degrade the colors. + * + * This pass is used too to take the snapshot used for background_pass. This image + * will be used as the background while the user is drawing. + */ + psl->mix_pass_noblend = DRW_pass_create("GPencil Mix Pass no blend", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | + DRW_STATE_DEPTH_LESS); + DRWShadingGroup *mix_shgrp_noblend = DRW_shgroup_create(e_data.gpencil_fullscreen_sh, + psl->mix_pass_noblend); + DRW_shgroup_call_add(mix_shgrp_noblend, quad, NULL); + DRW_shgroup_uniform_texture_ref(mix_shgrp_noblend, "strokeColor", &e_data.input_color_tx); + DRW_shgroup_uniform_texture_ref(mix_shgrp_noblend, "strokeDepth", &e_data.input_depth_tx); + DRW_shgroup_uniform_int(mix_shgrp_noblend, "tonemapping", &stl->storage->tonemapping, 1); + DRW_shgroup_uniform_int(mix_shgrp_noblend, "do_select", &stl->storage->do_select_outline, 1); + DRW_shgroup_uniform_vec4(mix_shgrp_noblend, "select_color", stl->storage->select_color, 1); + + /* Painting session pass (used only to speedup while the user is drawing ) + * This pass is used to show the snapshot of the current grease pencil strokes captured + * when the user starts to draw (see comments above). + * In this way, the previous strokes don't need to be redraw and the drawing process + * is far to agile. + */ + psl->background_pass = DRW_pass_create("GPencil Background Painting Session Pass", + DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND | + DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS); + DRWShadingGroup *background_shgrp = DRW_shgroup_create(e_data.gpencil_background_sh, + psl->background_pass); + DRW_shgroup_call_add(background_shgrp, quad, NULL); + DRW_shgroup_uniform_texture_ref(background_shgrp, "strokeColor", &e_data.background_color_tx); + DRW_shgroup_uniform_texture_ref(background_shgrp, "strokeDepth", &e_data.background_depth_tx); + + /* pass for drawing paper (only if viewport) + * In render, the v3d is null so the paper is disabled + * The paper is way to isolate the drawing in complex scene and to have a cleaner + * drawing area. + */ + if (v3d) { + psl->paper_pass = DRW_pass_create("GPencil Paper Pass", + DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND); + DRWShadingGroup *paper_shgrp = DRW_shgroup_create(e_data.gpencil_paper_sh, psl->paper_pass); + DRW_shgroup_call_add(paper_shgrp, quad, NULL); + DRW_shgroup_uniform_vec3(paper_shgrp, "color", v3d->shading.background_color, 1); + DRW_shgroup_uniform_float(paper_shgrp, "opacity", &v3d->overlay.gpencil_paper_opacity, 1); + } + + /* grid pass */ + if (v3d) { + psl->grid_pass = DRW_pass_create("GPencil Grid Pass", + DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND | + DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS); + stl->g_data->shgrps_grid = DRW_shgroup_create(e_data.gpencil_line_sh, psl->grid_pass); + } + + /* blend layers pass */ + psl->blend_pass = DRW_pass_create("GPencil Blend Layers Pass", + DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND | + DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS); + DRWShadingGroup *blend_shgrp = DRW_shgroup_create(e_data.gpencil_blend_fullscreen_sh, + psl->blend_pass); + DRW_shgroup_call_add(blend_shgrp, quad, NULL); + DRW_shgroup_uniform_texture_ref(blend_shgrp, "strokeColor", &e_data.temp_color_tx_a); + DRW_shgroup_uniform_texture_ref(blend_shgrp, "strokeDepth", &e_data.temp_depth_tx_a); + DRW_shgroup_uniform_texture_ref(blend_shgrp, "blendColor", &e_data.temp_color_tx_fx); + DRW_shgroup_uniform_texture_ref(blend_shgrp, "blendDepth", &e_data.temp_depth_tx_fx); + DRW_shgroup_uniform_int(blend_shgrp, "mode", &stl->storage->blend_mode, 1); + DRW_shgroup_uniform_int(blend_shgrp, "clamp_layer", &stl->storage->clamp_layer, 1); + DRW_shgroup_uniform_float(blend_shgrp, "blend_opacity", &stl->storage->blend_opacity, 1); + DRW_shgroup_uniform_int(mix_shgrp, "tonemapping", &stl->storage->tonemapping, 1); + + /* create effects passes */ + if (!stl->storage->simplify_fx) { + GPENCIL_create_fx_passes(psl); + } + } } static void gpencil_add_draw_data(void *vedata, Object *ob) { - GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; - bGPdata *gpd = (bGPdata *)ob->data; - const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); - - int i = stl->g_data->gp_cache_used - 1; - tGPencilObjectCache *cache_ob = &stl->g_data->gp_object_cache[i]; - - if (!cache_ob->is_dup_ob) { - /* fill shading groups */ - if ((!is_multiedit) || (stl->storage->is_render)) { - DRW_gpencil_populate_datablock(&e_data, vedata, ob, cache_ob); - } - else { - DRW_gpencil_populate_multiedit(&e_data, vedata, ob, cache_ob); - } - } - - /* FX passses */ - cache_ob->has_fx = false; - if ((!stl->storage->simplify_fx) && - (!ELEM(cache_ob->shading_type[0], OB_WIRE, OB_SOLID)) && - (BKE_shaderfx_has_gpencil(ob))) - { - cache_ob->has_fx = true; - if ((!stl->storage->simplify_fx) && (!is_multiedit)) { - DRW_gpencil_fx_prepare(&e_data, vedata, cache_ob); - } - } + GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; + bGPdata *gpd = (bGPdata *)ob->data; + const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); + + int i = stl->g_data->gp_cache_used - 1; + tGPencilObjectCache *cache_ob = &stl->g_data->gp_object_cache[i]; + + if (!cache_ob->is_dup_ob) { + /* fill shading groups */ + if ((!is_multiedit) || (stl->storage->is_render)) { + DRW_gpencil_populate_datablock(&e_data, vedata, ob, cache_ob); + } + else { + DRW_gpencil_populate_multiedit(&e_data, vedata, ob, cache_ob); + } + } + + /* FX passses */ + cache_ob->has_fx = false; + if ((!stl->storage->simplify_fx) && (!ELEM(cache_ob->shading_type[0], OB_WIRE, OB_SOLID)) && + (BKE_shaderfx_has_gpencil(ob))) { + cache_ob->has_fx = true; + if ((!stl->storage->simplify_fx) && (!is_multiedit)) { + DRW_gpencil_fx_prepare(&e_data, vedata, cache_ob); + } + } } void GPENCIL_cache_populate(void *vedata, Object *ob) { - /* object must be visible */ - if (!(DRW_object_visibility_in_active_context(ob) & OB_VISIBLE_SELF)) { - return; - } - - GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; - const DRWContextState *draw_ctx = DRW_context_state_get(); - Scene *scene = draw_ctx->scene; - ToolSettings *ts = scene->toolsettings; - View3D *v3d = draw_ctx->v3d; - const View3DCursor *cursor = &scene->cursor; - - if (ob->type == OB_GPENCIL && ob->data) { - bGPdata *gpd = (bGPdata *)ob->data; - - /* enable multisample and basic framebuffer creation */ - stl->storage->framebuffer_flag |= GP_FRAMEBUFFER_MULTISAMPLE; - stl->storage->framebuffer_flag |= GP_FRAMEBUFFER_BASIC; - - /* when start/stop animation the cache must be set as dirty to reset all data */ - if (stl->storage->reset_cache) { - gpd->flag |= GP_DATA_CACHE_IS_DIRTY; - stl->storage->reset_cache = false; - } - - if ((stl->g_data->session_flag & GP_DRW_PAINT_READY) == 0) { - /* bound box object are not visible, only external box*/ - if (ob->dt != OB_BOUNDBOX) { - /* save gp objects for drawing later */ - stl->g_data->gp_object_cache = gpencil_object_cache_add( - stl->g_data->gp_object_cache, ob, - &stl->g_data->gp_cache_size, &stl->g_data->gp_cache_used); - - /* enable instance loop */ - if (!stl->g_data->do_instances) { - tGPencilObjectCache *cache_ob = &stl->g_data->gp_object_cache[stl->g_data->gp_cache_used - 1]; - stl->g_data->do_instances = cache_ob->is_dup_ob; - } - - /* load drawing data */ - gpencil_add_draw_data(vedata, ob); - } - } - - /* draw current painting strokes - * (only if region is equal to originated paint region) - * - * Need to use original data because to use the copy of data, the paint - * operator must update depsgraph and this makes that first events of the - * mouse are missed if the datablock is very big due the time required to - * copy the datablock. The search of the original data is faster than a - * full datablock copy. - * Using the original data doesn't require a copy and the feel when drawing - * is far better. - */ - - bGPdata *gpd_orig = (bGPdata *)DEG_get_original_id(&gpd->id); - if ((draw_ctx->obact == ob) && - ((gpd_orig->runtime.ar == NULL) || (gpd_orig->runtime.ar == draw_ctx->ar))) - { - DRW_gpencil_populate_buffer_strokes(&e_data, vedata, ts, ob); - } - - /* grid */ - if ((v3d) && - ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) && - (v3d->gp_flag & V3D_GP_SHOW_GRID) && - (ob->type == OB_GPENCIL) && (ob == draw_ctx->obact) && - ((ts->gpencil_v3d_align & GP_PROJECT_DEPTH_VIEW) == 0) && - ((ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) == 0)) - { - GPU_BATCH_DISCARD_SAFE(e_data.batch_grid); - MEM_SAFE_FREE(e_data.batch_grid); - - e_data.batch_grid = DRW_gpencil_get_grid(ob); - - /* define grid orientation */ - switch (ts->gp_sculpt.lock_axis) { - case GP_LOCKAXIS_VIEW: - { - /* align always to view */ - invert_m4_m4(stl->storage->grid_matrix, draw_ctx->rv3d->viewmat); - /* copy ob location */ - copy_v3_v3(stl->storage->grid_matrix[3], ob->obmat[3]); - break; - } - case GP_LOCKAXIS_CURSOR: - { - float scale[3] = { 1.0f, 1.0f, 1.0f }; - loc_eul_size_to_mat4( - stl->storage->grid_matrix, - cursor->location, - cursor->rotation_euler, - scale); - break; - } - default: - { - copy_m4_m4(stl->storage->grid_matrix, ob->obmat); - break; - } - } - - /* Move the origin to Object or Cursor */ - if (ts->gpencil_v3d_align & GP_PROJECT_CURSOR) { - copy_v3_v3(stl->storage->grid_matrix[3], cursor->location); - } - else { - copy_v3_v3(stl->storage->grid_matrix[3], ob->obmat[3]); - } - - DRW_shgroup_call_add( - stl->g_data->shgrps_grid, - e_data.batch_grid, - stl->storage->grid_matrix); - } - } + /* object must be visible */ + if (!(DRW_object_visibility_in_active_context(ob) & OB_VISIBLE_SELF)) { + return; + } + + GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene = draw_ctx->scene; + ToolSettings *ts = scene->toolsettings; + View3D *v3d = draw_ctx->v3d; + const View3DCursor *cursor = &scene->cursor; + + if (ob->type == OB_GPENCIL && ob->data) { + bGPdata *gpd = (bGPdata *)ob->data; + + /* enable multisample and basic framebuffer creation */ + stl->storage->framebuffer_flag |= GP_FRAMEBUFFER_MULTISAMPLE; + stl->storage->framebuffer_flag |= GP_FRAMEBUFFER_BASIC; + + /* when start/stop animation the cache must be set as dirty to reset all data */ + if (stl->storage->reset_cache) { + gpd->flag |= GP_DATA_CACHE_IS_DIRTY; + stl->storage->reset_cache = false; + } + + if ((stl->g_data->session_flag & GP_DRW_PAINT_READY) == 0) { + /* bound box object are not visible, only external box*/ + if (ob->dt != OB_BOUNDBOX) { + /* save gp objects for drawing later */ + stl->g_data->gp_object_cache = gpencil_object_cache_add(stl->g_data->gp_object_cache, + ob, + &stl->g_data->gp_cache_size, + &stl->g_data->gp_cache_used); + + /* enable instance loop */ + if (!stl->g_data->do_instances) { + tGPencilObjectCache *cache_ob = + &stl->g_data->gp_object_cache[stl->g_data->gp_cache_used - 1]; + stl->g_data->do_instances = cache_ob->is_dup_ob; + } + + /* load drawing data */ + gpencil_add_draw_data(vedata, ob); + } + } + + /* draw current painting strokes + * (only if region is equal to originated paint region) + * + * Need to use original data because to use the copy of data, the paint + * operator must update depsgraph and this makes that first events of the + * mouse are missed if the datablock is very big due the time required to + * copy the datablock. The search of the original data is faster than a + * full datablock copy. + * Using the original data doesn't require a copy and the feel when drawing + * is far better. + */ + + bGPdata *gpd_orig = (bGPdata *)DEG_get_original_id(&gpd->id); + if ((draw_ctx->obact == ob) && + ((gpd_orig->runtime.ar == NULL) || (gpd_orig->runtime.ar == draw_ctx->ar))) { + DRW_gpencil_populate_buffer_strokes(&e_data, vedata, ts, ob); + } + + /* grid */ + if ((v3d) && ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) && (v3d->gp_flag & V3D_GP_SHOW_GRID) && + (ob->type == OB_GPENCIL) && (ob == draw_ctx->obact) && + ((ts->gpencil_v3d_align & GP_PROJECT_DEPTH_VIEW) == 0) && + ((ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) == 0)) { + GPU_BATCH_DISCARD_SAFE(e_data.batch_grid); + MEM_SAFE_FREE(e_data.batch_grid); + + e_data.batch_grid = DRW_gpencil_get_grid(ob); + + /* define grid orientation */ + switch (ts->gp_sculpt.lock_axis) { + case GP_LOCKAXIS_VIEW: { + /* align always to view */ + invert_m4_m4(stl->storage->grid_matrix, draw_ctx->rv3d->viewmat); + /* copy ob location */ + copy_v3_v3(stl->storage->grid_matrix[3], ob->obmat[3]); + break; + } + case GP_LOCKAXIS_CURSOR: { + float scale[3] = {1.0f, 1.0f, 1.0f}; + loc_eul_size_to_mat4( + stl->storage->grid_matrix, cursor->location, cursor->rotation_euler, scale); + break; + } + default: { + copy_m4_m4(stl->storage->grid_matrix, ob->obmat); + break; + } + } + + /* Move the origin to Object or Cursor */ + if (ts->gpencil_v3d_align & GP_PROJECT_CURSOR) { + copy_v3_v3(stl->storage->grid_matrix[3], cursor->location); + } + else { + copy_v3_v3(stl->storage->grid_matrix[3], ob->obmat[3]); + } + + DRW_shgroup_call_add(stl->g_data->shgrps_grid, e_data.batch_grid, stl->storage->grid_matrix); + } + } } void GPENCIL_cache_finish(void *vedata) { - GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; - tGPencilObjectCache *cache_ob = NULL; - Object *ob = NULL; - - /* create data for instances */ - if (stl->g_data->do_instances) { - GHash *gh_objects = BLI_ghash_str_new(__func__); - /* create hash of real object (non duplicated) */ - for (int i = 0; i < stl->g_data->gp_cache_used; i++) { - cache_ob = &stl->g_data->gp_object_cache[i]; - if (!cache_ob->is_dup_ob) { - ob = cache_ob->ob; - char *name = BKE_id_to_unique_string_key(&ob->id); - BLI_ghash_insert(gh_objects, name, cache_ob->ob); - } - } - - /* draw particles */ - DRW_gpencil_populate_particles(&e_data, gh_objects, vedata); - - /* free hash */ - BLI_ghash_free(gh_objects, MEM_freeN, NULL); - } - - if (stl->g_data->session_flag & (GP_DRW_PAINT_IDLE | GP_DRW_PAINT_FILLING)) { - stl->storage->framebuffer_flag |= GP_FRAMEBUFFER_DRAW; - } - - /* create framebuffers (only for normal drawing) */ - if (!DRW_state_is_select() || !DRW_state_is_depth()) { - GPENCIL_create_framebuffers(vedata); - } + GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; + tGPencilObjectCache *cache_ob = NULL; + Object *ob = NULL; + + /* create data for instances */ + if (stl->g_data->do_instances) { + GHash *gh_objects = BLI_ghash_str_new(__func__); + /* create hash of real object (non duplicated) */ + for (int i = 0; i < stl->g_data->gp_cache_used; i++) { + cache_ob = &stl->g_data->gp_object_cache[i]; + if (!cache_ob->is_dup_ob) { + ob = cache_ob->ob; + char *name = BKE_id_to_unique_string_key(&ob->id); + BLI_ghash_insert(gh_objects, name, cache_ob->ob); + } + } + + /* draw particles */ + DRW_gpencil_populate_particles(&e_data, gh_objects, vedata); + + /* free hash */ + BLI_ghash_free(gh_objects, MEM_freeN, NULL); + } + + if (stl->g_data->session_flag & (GP_DRW_PAINT_IDLE | GP_DRW_PAINT_FILLING)) { + stl->storage->framebuffer_flag |= GP_FRAMEBUFFER_DRAW; + } + + /* create framebuffers (only for normal drawing) */ + if (!DRW_state_is_select() || !DRW_state_is_depth()) { + GPENCIL_create_framebuffers(vedata); + } } /* helper function to sort inverse gpencil objects using qsort */ static int gpencil_object_cache_compare_zdepth(const void *a1, const void *a2) { - const tGPencilObjectCache *ps1 = a1, *ps2 = a2; + const tGPencilObjectCache *ps1 = a1, *ps2 = a2; - if (ps1->zdepth < ps2->zdepth) { - return 1; - } - else if (ps1->zdepth > ps2->zdepth) { - return -1; - } + if (ps1->zdepth < ps2->zdepth) { + return 1; + } + else if (ps1->zdepth > ps2->zdepth) { + return -1; + } - return 0; + return 0; } /* prepare a texture with full viewport screenshot for fast drawing */ -static void gpencil_prepare_fast_drawing( - GPENCIL_StorageList *stl, DefaultFramebufferList *dfbl, - GPENCIL_FramebufferList *fbl, DRWPass *pass, - const float clearcol[4]) +static void gpencil_prepare_fast_drawing(GPENCIL_StorageList *stl, + DefaultFramebufferList *dfbl, + GPENCIL_FramebufferList *fbl, + DRWPass *pass, + const float clearcol[4]) { - if (stl->g_data->session_flag & (GP_DRW_PAINT_IDLE | GP_DRW_PAINT_FILLING)) { - GPU_framebuffer_bind(fbl->background_fb); - /* clean only in first loop cycle */ - if (stl->g_data->session_flag & GP_DRW_PAINT_IDLE) { - GPU_framebuffer_clear_color_depth(fbl->background_fb, clearcol, 1.0f); - stl->g_data->session_flag = GP_DRW_PAINT_FILLING; - } - /* repeat pass to fill temp texture */ - DRW_draw_pass(pass); - /* set default framebuffer again */ - GPU_framebuffer_bind(dfbl->default_fb); - } + if (stl->g_data->session_flag & (GP_DRW_PAINT_IDLE | GP_DRW_PAINT_FILLING)) { + GPU_framebuffer_bind(fbl->background_fb); + /* clean only in first loop cycle */ + if (stl->g_data->session_flag & GP_DRW_PAINT_IDLE) { + GPU_framebuffer_clear_color_depth(fbl->background_fb, clearcol, 1.0f); + stl->g_data->session_flag = GP_DRW_PAINT_FILLING; + } + /* repeat pass to fill temp texture */ + DRW_draw_pass(pass); + /* set default framebuffer again */ + GPU_framebuffer_bind(dfbl->default_fb); + } } static void gpencil_free_obj_runtime(GPENCIL_StorageList *stl) { - if (stl->g_data->gp_object_cache == NULL) { - return; - } - - /* reset all cache flags */ - for (int i = 0; i < stl->g_data->gp_cache_used; i++) { - tGPencilObjectCache *cache_ob = &stl->g_data->gp_object_cache[i]; - if (cache_ob) { - bGPdata *gpd = cache_ob->gpd; - gpd->flag &= ~GP_DATA_CACHE_IS_DIRTY; - - /* free shgrp array */ - cache_ob->tot_layers = 0; - MEM_SAFE_FREE(cache_ob->name); - MEM_SAFE_FREE(cache_ob->shgrp_array); - } - } - - /* free the cache itself */ - MEM_SAFE_FREE(stl->g_data->gp_object_cache); + if (stl->g_data->gp_object_cache == NULL) { + return; + } + + /* reset all cache flags */ + for (int i = 0; i < stl->g_data->gp_cache_used; i++) { + tGPencilObjectCache *cache_ob = &stl->g_data->gp_object_cache[i]; + if (cache_ob) { + bGPdata *gpd = cache_ob->gpd; + gpd->flag &= ~GP_DATA_CACHE_IS_DIRTY; + + /* free shgrp array */ + cache_ob->tot_layers = 0; + MEM_SAFE_FREE(cache_ob->name); + MEM_SAFE_FREE(cache_ob->shgrp_array); + } + } + + /* free the cache itself */ + MEM_SAFE_FREE(stl->g_data->gp_object_cache); } -static void gpencil_draw_pass_range( - GPENCIL_FramebufferList *fbl, GPENCIL_StorageList *stl, - GPENCIL_PassList *psl, GPENCIL_TextureList *txl, - GPUFrameBuffer *fb, Object *ob, bGPdata *gpd, - DRWShadingGroup *init_shgrp, DRWShadingGroup *end_shgrp, bool multi) +static void gpencil_draw_pass_range(GPENCIL_FramebufferList *fbl, + GPENCIL_StorageList *stl, + GPENCIL_PassList *psl, + GPENCIL_TextureList *txl, + GPUFrameBuffer *fb, + Object *ob, + bGPdata *gpd, + DRWShadingGroup *init_shgrp, + DRWShadingGroup *end_shgrp, + bool multi) { - if (init_shgrp == NULL) { - return; - } - - /* previews don't use AA */ - if ((!stl->storage->is_mat_preview) && (multi)) { - MULTISAMPLE_GP_SYNC_ENABLE(stl->storage->multisamples, fbl); - } - - DRW_draw_pass_subset( - GPENCIL_3D_DRAWMODE(ob, gpd) ? psl->stroke_pass_3d : psl->stroke_pass_2d, - init_shgrp, end_shgrp); - - if ((!stl->storage->is_mat_preview) && (multi)) { - MULTISAMPLE_GP_SYNC_DISABLE(stl->storage->multisamples, fbl, fb, txl); - } + if (init_shgrp == NULL) { + return; + } + + /* previews don't use AA */ + if ((!stl->storage->is_mat_preview) && (multi)) { + MULTISAMPLE_GP_SYNC_ENABLE(stl->storage->multisamples, fbl); + } + + DRW_draw_pass_subset(GPENCIL_3D_DRAWMODE(ob, gpd) ? psl->stroke_pass_3d : psl->stroke_pass_2d, + init_shgrp, + end_shgrp); + + if ((!stl->storage->is_mat_preview) && (multi)) { + MULTISAMPLE_GP_SYNC_DISABLE(stl->storage->multisamples, fbl, fb, txl); + } } /* draw strokes to use for selection */ static void drw_gpencil_select_render(GPENCIL_StorageList *stl, GPENCIL_PassList *psl) { - tGPencilObjectCache *cache_ob; - tGPencilObjectCache_shgrp *array_elm = NULL; - DRWShadingGroup *init_shgrp = NULL; - DRWShadingGroup *end_shgrp = NULL; - - /* Draw all pending objects */ - if ((stl->g_data->gp_cache_used > 0) && - (stl->g_data->gp_object_cache)) - { - /* sort by zdepth */ - qsort(stl->g_data->gp_object_cache, stl->g_data->gp_cache_used, - sizeof(tGPencilObjectCache), gpencil_object_cache_compare_zdepth); - - for (int i = 0; i < stl->g_data->gp_cache_used; i++) { - cache_ob = &stl->g_data->gp_object_cache[i]; - if (cache_ob) { - Object *ob = cache_ob->ob; - bGPdata *gpd = cache_ob->gpd; - init_shgrp = NULL; - if (cache_ob->tot_layers > 0) { - for (int e = 0; e < cache_ob->tot_layers; e++) { - array_elm = &cache_ob->shgrp_array[e]; - if (init_shgrp == NULL) { - init_shgrp = array_elm->init_shgrp; - } - end_shgrp = array_elm->end_shgrp; - } - /* draw group */ - DRW_draw_pass_subset( - GPENCIL_3D_DRAWMODE(ob, gpd) ? psl->stroke_pass_3d : psl->stroke_pass_2d, - init_shgrp, end_shgrp); - } - /* the cache must be dirty for next loop */ - gpd->flag |= GP_DATA_CACHE_IS_DIRTY; - } - } - } + tGPencilObjectCache *cache_ob; + tGPencilObjectCache_shgrp *array_elm = NULL; + DRWShadingGroup *init_shgrp = NULL; + DRWShadingGroup *end_shgrp = NULL; + + /* Draw all pending objects */ + if ((stl->g_data->gp_cache_used > 0) && (stl->g_data->gp_object_cache)) { + /* sort by zdepth */ + qsort(stl->g_data->gp_object_cache, + stl->g_data->gp_cache_used, + sizeof(tGPencilObjectCache), + gpencil_object_cache_compare_zdepth); + + for (int i = 0; i < stl->g_data->gp_cache_used; i++) { + cache_ob = &stl->g_data->gp_object_cache[i]; + if (cache_ob) { + Object *ob = cache_ob->ob; + bGPdata *gpd = cache_ob->gpd; + init_shgrp = NULL; + if (cache_ob->tot_layers > 0) { + for (int e = 0; e < cache_ob->tot_layers; e++) { + array_elm = &cache_ob->shgrp_array[e]; + if (init_shgrp == NULL) { + init_shgrp = array_elm->init_shgrp; + } + end_shgrp = array_elm->end_shgrp; + } + /* draw group */ + DRW_draw_pass_subset(GPENCIL_3D_DRAWMODE(ob, gpd) ? psl->stroke_pass_3d : + psl->stroke_pass_2d, + init_shgrp, + end_shgrp); + } + /* the cache must be dirty for next loop */ + gpd->flag |= GP_DATA_CACHE_IS_DIRTY; + } + } + } } /* draw scene */ void GPENCIL_draw_scene(void *ved) { - GPENCIL_Data *vedata = (GPENCIL_Data *)ved; - GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; - - GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; - GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl; - DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); - GPENCIL_TextureList *txl = ((GPENCIL_Data *)vedata)->txl; - - tGPencilObjectCache *cache_ob; - tGPencilObjectCache_shgrp *array_elm = NULL; - DRWShadingGroup *init_shgrp = NULL; - DRWShadingGroup *end_shgrp = NULL; - - const float clearcol[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; - - const DRWContextState *draw_ctx = DRW_context_state_get(); - View3D *v3d = draw_ctx->v3d; - Object *obact = draw_ctx->obact; - const bool playing = stl->storage->is_playing; - const bool is_render = stl->storage->is_render; - bGPdata *gpd_act = (obact) && (obact->type == OB_GPENCIL) ? (bGPdata *)obact->data : NULL; - const bool is_edit = GPENCIL_ANY_EDIT_MODE(gpd_act); - const bool overlay = v3d != NULL ? (bool)((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) : true; - - /* if the draw is for select, do a basic drawing and return */ - if (DRW_state_is_select() || DRW_state_is_depth()) { - drw_gpencil_select_render(stl, psl); - /* free memory */ - gpencil_free_obj_runtime(stl); - return; - } - - /* paper pass to display a comfortable area to draw over complex scenes with geometry */ - if ((!is_render) && (obact) && (obact->type == OB_GPENCIL)) { - if (((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) && - (v3d->gp_flag & V3D_GP_SHOW_PAPER)) - { - DRW_draw_pass(psl->paper_pass); - } - } - - /* if we have a painting session, we use fast viewport drawing method */ - if ((!is_render) && (stl->g_data->session_flag & GP_DRW_PAINT_PAINTING)) { - GPU_framebuffer_bind(dfbl->default_fb); - - MULTISAMPLE_GP_SYNC_ENABLE(stl->storage->multisamples, fbl); - if (obact->dt != OB_BOUNDBOX) { - DRW_draw_pass(psl->background_pass); - } - DRW_draw_pass(psl->drawing_pass); - - MULTISAMPLE_GP_SYNC_DISABLE(stl->storage->multisamples, fbl, dfbl->default_fb, txl); - - /* free memory */ - gpencil_free_obj_runtime(stl); - - /* grid pass */ - if ((!is_render) && (obact) && (obact->type == OB_GPENCIL)) { - if (((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) && - (v3d->gp_flag & V3D_GP_SHOW_GRID)) - { - DRW_draw_pass(psl->grid_pass); - } - } - return; - } - - if (DRW_state_is_fbo()) { - - /* Draw all pending objects */ - if (stl->g_data->gp_cache_used > 0) { - /* sort by zdepth */ - qsort(stl->g_data->gp_object_cache, stl->g_data->gp_cache_used, - sizeof(tGPencilObjectCache), gpencil_object_cache_compare_zdepth); - - for (int i = 0; i < stl->g_data->gp_cache_used; i++) { - cache_ob = &stl->g_data->gp_object_cache[i]; - Object *ob = cache_ob->ob; - bGPdata *gpd = cache_ob->gpd; - init_shgrp = NULL; - /* Render stroke in separated framebuffer */ - GPU_framebuffer_bind(fbl->temp_fb_a); - GPU_framebuffer_clear_color_depth(fbl->temp_fb_a, clearcol, 1.0f); - - /* Stroke Pass: - * draw only a subset that usually starts with a fill and ends with stroke - */ - bool use_blend = false; - if (cache_ob->tot_layers > 0) { - for (int e = 0; e < cache_ob->tot_layers; e++) { - bool is_last = e == cache_ob->tot_layers - 1 ? true : false; - array_elm = &cache_ob->shgrp_array[e]; - - if (((array_elm->mode == eGplBlendMode_Normal) && - (!use_blend) && (!array_elm->clamp_layer)) || - (e == 0)) - { - if (init_shgrp == NULL) { - init_shgrp = array_elm->init_shgrp; - } - end_shgrp = array_elm->end_shgrp; - } - else { - use_blend = true; - /* draw pending groups */ - gpencil_draw_pass_range( - fbl, stl, psl, txl, fbl->temp_fb_a, - ob, gpd, init_shgrp, end_shgrp, is_last); - - /* draw current group in separated texture */ - init_shgrp = array_elm->init_shgrp; - end_shgrp = array_elm->end_shgrp; - - GPU_framebuffer_bind(fbl->temp_fb_fx); - GPU_framebuffer_clear_color_depth(fbl->temp_fb_fx, clearcol, 1.0f); - gpencil_draw_pass_range( - fbl, stl, psl, txl, fbl->temp_fb_fx, - ob, gpd, init_shgrp, end_shgrp, - is_last); - - /* Blend A texture and FX texture */ - GPU_framebuffer_bind(fbl->temp_fb_b); - GPU_framebuffer_clear_color_depth(fbl->temp_fb_b, clearcol, 1.0f); - stl->storage->blend_mode = array_elm->mode; - stl->storage->clamp_layer = (int)array_elm->clamp_layer; - stl->storage->blend_opacity = array_elm->blend_opacity; - stl->storage->tonemapping = stl->storage->is_render ? 1 : 0; - DRW_draw_pass(psl->blend_pass); - stl->storage->tonemapping = 0; - - /* Copy B texture to A texture to follow loop */ - e_data.input_depth_tx = e_data.temp_depth_tx_b; - e_data.input_color_tx = e_data.temp_color_tx_b; - - GPU_framebuffer_bind(fbl->temp_fb_a); - GPU_framebuffer_clear_color_depth(fbl->temp_fb_a, clearcol, 1.0f); - DRW_draw_pass(psl->mix_pass_noblend); - - /* prepare next group */ - init_shgrp = NULL; - } - } - /* last group */ - gpencil_draw_pass_range( - fbl, stl, psl, txl, fbl->temp_fb_a, - ob, gpd, init_shgrp, end_shgrp, - true); - } - - /* Current buffer drawing */ - if ((!is_render) && (cache_ob->is_dup_ob == false)) { - DRW_draw_pass(psl->drawing_pass); - } - /* fx passes */ - if (cache_ob->has_fx == true) { - stl->storage->tonemapping = 0; - DRW_gpencil_fx_draw(&e_data, vedata, cache_ob); - } - - e_data.input_depth_tx = e_data.temp_depth_tx_a; - e_data.input_color_tx = e_data.temp_color_tx_a; - - /* Combine with scene buffer */ - if ((!is_render) || (fbl->main == NULL)) { - GPU_framebuffer_bind(dfbl->default_fb); - } - else { - GPU_framebuffer_bind(fbl->main); - } - /* tonemapping */ - stl->storage->tonemapping = stl->storage->is_render ? 1 : 0; - - /* active select flag and selection color */ - stl->storage->do_select_outline = ( - (overlay) && - (ob->base_flag & BASE_SELECTED) && - (ob->mode == OB_MODE_OBJECT) && - (!is_render) && (!playing) && - (v3d->flag & V3D_SELECT_OUTLINE)); - - /* if active object is not object mode, disable for all objects */ - if ((draw_ctx->obact) && (draw_ctx->obact->mode != OB_MODE_OBJECT)) { - stl->storage->do_select_outline = 0; - } - UI_GetThemeColorShadeAlpha4fv( - (ob == draw_ctx->obact) ? TH_ACTIVE : TH_SELECT, 0, -40, - stl->storage->select_color); - - /* draw mix pass */ - DRW_draw_pass(psl->mix_pass); - - /* disable select flag */ - stl->storage->do_select_outline = 0; - - /* prepare for fast drawing */ - if (!is_render) { - if (!playing) { - gpencil_prepare_fast_drawing(stl, dfbl, fbl, psl->mix_pass_noblend, clearcol); - } - } - else { - /* if render, the cache must be dirty for next loop */ - gpd->flag |= GP_DATA_CACHE_IS_DIRTY; - } - } - /* edit points */ - if ((!is_render) && (!playing) && (is_edit)) { - DRW_draw_pass(psl->edit_pass); - } - } - /* grid pass */ - if ((!is_render) && (obact) && (obact->type == OB_GPENCIL)) { - if (((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) && - (v3d->gp_flag & V3D_GP_SHOW_GRID)) - { - DRW_draw_pass(psl->grid_pass); - } - } - } - /* free memory */ - gpencil_free_obj_runtime(stl); - - /* reset */ - if (DRW_state_is_fbo()) { - /* attach again default framebuffer */ - if (!is_render) { - GPU_framebuffer_bind(dfbl->default_fb); - } - - /* the temp texture is ready. Now we can use fast screen drawing */ - if (stl->g_data->session_flag & GP_DRW_PAINT_FILLING) { - stl->g_data->session_flag = GP_DRW_PAINT_READY; - } - } + GPENCIL_Data *vedata = (GPENCIL_Data *)ved; + GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; + + GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; + GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl; + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + GPENCIL_TextureList *txl = ((GPENCIL_Data *)vedata)->txl; + + tGPencilObjectCache *cache_ob; + tGPencilObjectCache_shgrp *array_elm = NULL; + DRWShadingGroup *init_shgrp = NULL; + DRWShadingGroup *end_shgrp = NULL; + + const float clearcol[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + + const DRWContextState *draw_ctx = DRW_context_state_get(); + View3D *v3d = draw_ctx->v3d; + Object *obact = draw_ctx->obact; + const bool playing = stl->storage->is_playing; + const bool is_render = stl->storage->is_render; + bGPdata *gpd_act = (obact) && (obact->type == OB_GPENCIL) ? (bGPdata *)obact->data : NULL; + const bool is_edit = GPENCIL_ANY_EDIT_MODE(gpd_act); + const bool overlay = v3d != NULL ? (bool)((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) : true; + + /* if the draw is for select, do a basic drawing and return */ + if (DRW_state_is_select() || DRW_state_is_depth()) { + drw_gpencil_select_render(stl, psl); + /* free memory */ + gpencil_free_obj_runtime(stl); + return; + } + + /* paper pass to display a comfortable area to draw over complex scenes with geometry */ + if ((!is_render) && (obact) && (obact->type == OB_GPENCIL)) { + if (((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) && (v3d->gp_flag & V3D_GP_SHOW_PAPER)) { + DRW_draw_pass(psl->paper_pass); + } + } + + /* if we have a painting session, we use fast viewport drawing method */ + if ((!is_render) && (stl->g_data->session_flag & GP_DRW_PAINT_PAINTING)) { + GPU_framebuffer_bind(dfbl->default_fb); + + MULTISAMPLE_GP_SYNC_ENABLE(stl->storage->multisamples, fbl); + if (obact->dt != OB_BOUNDBOX) { + DRW_draw_pass(psl->background_pass); + } + DRW_draw_pass(psl->drawing_pass); + + MULTISAMPLE_GP_SYNC_DISABLE(stl->storage->multisamples, fbl, dfbl->default_fb, txl); + + /* free memory */ + gpencil_free_obj_runtime(stl); + + /* grid pass */ + if ((!is_render) && (obact) && (obact->type == OB_GPENCIL)) { + if (((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) && (v3d->gp_flag & V3D_GP_SHOW_GRID)) { + DRW_draw_pass(psl->grid_pass); + } + } + return; + } + + if (DRW_state_is_fbo()) { + + /* Draw all pending objects */ + if (stl->g_data->gp_cache_used > 0) { + /* sort by zdepth */ + qsort(stl->g_data->gp_object_cache, + stl->g_data->gp_cache_used, + sizeof(tGPencilObjectCache), + gpencil_object_cache_compare_zdepth); + + for (int i = 0; i < stl->g_data->gp_cache_used; i++) { + cache_ob = &stl->g_data->gp_object_cache[i]; + Object *ob = cache_ob->ob; + bGPdata *gpd = cache_ob->gpd; + init_shgrp = NULL; + /* Render stroke in separated framebuffer */ + GPU_framebuffer_bind(fbl->temp_fb_a); + GPU_framebuffer_clear_color_depth(fbl->temp_fb_a, clearcol, 1.0f); + + /* Stroke Pass: + * draw only a subset that usually starts with a fill and ends with stroke + */ + bool use_blend = false; + if (cache_ob->tot_layers > 0) { + for (int e = 0; e < cache_ob->tot_layers; e++) { + bool is_last = e == cache_ob->tot_layers - 1 ? true : false; + array_elm = &cache_ob->shgrp_array[e]; + + if (((array_elm->mode == eGplBlendMode_Normal) && (!use_blend) && + (!array_elm->clamp_layer)) || + (e == 0)) { + if (init_shgrp == NULL) { + init_shgrp = array_elm->init_shgrp; + } + end_shgrp = array_elm->end_shgrp; + } + else { + use_blend = true; + /* draw pending groups */ + gpencil_draw_pass_range( + fbl, stl, psl, txl, fbl->temp_fb_a, ob, gpd, init_shgrp, end_shgrp, is_last); + + /* draw current group in separated texture */ + init_shgrp = array_elm->init_shgrp; + end_shgrp = array_elm->end_shgrp; + + GPU_framebuffer_bind(fbl->temp_fb_fx); + GPU_framebuffer_clear_color_depth(fbl->temp_fb_fx, clearcol, 1.0f); + gpencil_draw_pass_range( + fbl, stl, psl, txl, fbl->temp_fb_fx, ob, gpd, init_shgrp, end_shgrp, is_last); + + /* Blend A texture and FX texture */ + GPU_framebuffer_bind(fbl->temp_fb_b); + GPU_framebuffer_clear_color_depth(fbl->temp_fb_b, clearcol, 1.0f); + stl->storage->blend_mode = array_elm->mode; + stl->storage->clamp_layer = (int)array_elm->clamp_layer; + stl->storage->blend_opacity = array_elm->blend_opacity; + stl->storage->tonemapping = stl->storage->is_render ? 1 : 0; + DRW_draw_pass(psl->blend_pass); + stl->storage->tonemapping = 0; + + /* Copy B texture to A texture to follow loop */ + e_data.input_depth_tx = e_data.temp_depth_tx_b; + e_data.input_color_tx = e_data.temp_color_tx_b; + + GPU_framebuffer_bind(fbl->temp_fb_a); + GPU_framebuffer_clear_color_depth(fbl->temp_fb_a, clearcol, 1.0f); + DRW_draw_pass(psl->mix_pass_noblend); + + /* prepare next group */ + init_shgrp = NULL; + } + } + /* last group */ + gpencil_draw_pass_range( + fbl, stl, psl, txl, fbl->temp_fb_a, ob, gpd, init_shgrp, end_shgrp, true); + } + + /* Current buffer drawing */ + if ((!is_render) && (cache_ob->is_dup_ob == false)) { + DRW_draw_pass(psl->drawing_pass); + } + /* fx passes */ + if (cache_ob->has_fx == true) { + stl->storage->tonemapping = 0; + DRW_gpencil_fx_draw(&e_data, vedata, cache_ob); + } + + e_data.input_depth_tx = e_data.temp_depth_tx_a; + e_data.input_color_tx = e_data.temp_color_tx_a; + + /* Combine with scene buffer */ + if ((!is_render) || (fbl->main == NULL)) { + GPU_framebuffer_bind(dfbl->default_fb); + } + else { + GPU_framebuffer_bind(fbl->main); + } + /* tonemapping */ + stl->storage->tonemapping = stl->storage->is_render ? 1 : 0; + + /* active select flag and selection color */ + stl->storage->do_select_outline = ((overlay) && (ob->base_flag & BASE_SELECTED) && + (ob->mode == OB_MODE_OBJECT) && (!is_render) && + (!playing) && (v3d->flag & V3D_SELECT_OUTLINE)); + + /* if active object is not object mode, disable for all objects */ + if ((draw_ctx->obact) && (draw_ctx->obact->mode != OB_MODE_OBJECT)) { + stl->storage->do_select_outline = 0; + } + UI_GetThemeColorShadeAlpha4fv( + (ob == draw_ctx->obact) ? TH_ACTIVE : TH_SELECT, 0, -40, stl->storage->select_color); + + /* draw mix pass */ + DRW_draw_pass(psl->mix_pass); + + /* disable select flag */ + stl->storage->do_select_outline = 0; + + /* prepare for fast drawing */ + if (!is_render) { + if (!playing) { + gpencil_prepare_fast_drawing(stl, dfbl, fbl, psl->mix_pass_noblend, clearcol); + } + } + else { + /* if render, the cache must be dirty for next loop */ + gpd->flag |= GP_DATA_CACHE_IS_DIRTY; + } + } + /* edit points */ + if ((!is_render) && (!playing) && (is_edit)) { + DRW_draw_pass(psl->edit_pass); + } + } + /* grid pass */ + if ((!is_render) && (obact) && (obact->type == OB_GPENCIL)) { + if (((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) && (v3d->gp_flag & V3D_GP_SHOW_GRID)) { + DRW_draw_pass(psl->grid_pass); + } + } + } + /* free memory */ + gpencil_free_obj_runtime(stl); + + /* reset */ + if (DRW_state_is_fbo()) { + /* attach again default framebuffer */ + if (!is_render) { + GPU_framebuffer_bind(dfbl->default_fb); + } + + /* the temp texture is ready. Now we can use fast screen drawing */ + if (stl->g_data->session_flag & GP_DRW_PAINT_FILLING) { + stl->g_data->session_flag = GP_DRW_PAINT_READY; + } + } } static const DrawEngineDataSize GPENCIL_data_size = DRW_VIEWPORT_DATA_SIZE(GPENCIL_Data); DrawEngineType draw_engine_gpencil_type = { - NULL, NULL, - N_("GpencilMode"), - &GPENCIL_data_size, - &GPENCIL_engine_init, - &GPENCIL_engine_free, - &GPENCIL_cache_init, - &GPENCIL_cache_populate, - &GPENCIL_cache_finish, - NULL, - &GPENCIL_draw_scene, - NULL, - NULL, - &GPENCIL_render_to_image, + NULL, + NULL, + N_("GpencilMode"), + &GPENCIL_data_size, + &GPENCIL_engine_init, + &GPENCIL_engine_free, + &GPENCIL_cache_init, + &GPENCIL_cache_populate, + &GPENCIL_cache_finish, + NULL, + &GPENCIL_draw_scene, + NULL, + NULL, + &GPENCIL_render_to_image, }; diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h index 5d0d2397f8d..3add2cb0f1b 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.h +++ b/source/blender/draw/engines/gpencil/gpencil_engine.h @@ -42,376 +42,414 @@ struct tGPspoint; /* used to expand VBOs. Size has a big impact in the speed */ #define GPENCIL_VBO_BLOCK_SIZE 128 -#define GPENCIL_COLOR_SOLID 0 +#define GPENCIL_COLOR_SOLID 0 #define GPENCIL_COLOR_TEXTURE 1 #define GPENCIL_COLOR_PATTERN 2 #define GP_SIMPLIFY(scene) ((scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ENABLE)) -#define GP_SIMPLIFY_ONPLAY(playing) (((playing == true) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ON_PLAY)) || ((scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ON_PLAY) == 0)) -#define GP_SIMPLIFY_FILL(scene, playing) ((GP_SIMPLIFY_ONPLAY(playing) && (GP_SIMPLIFY(scene)) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_FILL))) -#define GP_SIMPLIFY_MODIF(scene, playing) ((GP_SIMPLIFY_ONPLAY(playing) && (GP_SIMPLIFY(scene)) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_MODIFIER))) -#define GP_SIMPLIFY_FX(scene, playing) ((GP_SIMPLIFY_ONPLAY(playing) && (GP_SIMPLIFY(scene)) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_FX))) -#define GP_SIMPLIFY_BLEND(scene, playing) ((GP_SIMPLIFY_ONPLAY(playing) && (GP_SIMPLIFY(scene)) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_BLEND))) +#define GP_SIMPLIFY_ONPLAY(playing) \ + (((playing == true) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ON_PLAY)) || \ + ((scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ON_PLAY) == 0)) +#define GP_SIMPLIFY_FILL(scene, playing) \ + ((GP_SIMPLIFY_ONPLAY(playing) && (GP_SIMPLIFY(scene)) && \ + (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_FILL))) +#define GP_SIMPLIFY_MODIF(scene, playing) \ + ((GP_SIMPLIFY_ONPLAY(playing) && (GP_SIMPLIFY(scene)) && \ + (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_MODIFIER))) +#define GP_SIMPLIFY_FX(scene, playing) \ + ((GP_SIMPLIFY_ONPLAY(playing) && (GP_SIMPLIFY(scene)) && \ + (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_FX))) +#define GP_SIMPLIFY_BLEND(scene, playing) \ + ((GP_SIMPLIFY_ONPLAY(playing) && (GP_SIMPLIFY(scene)) && \ + (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_BLEND))) #define GP_IS_CAMERAVIEW ((rv3d != NULL) && (rv3d->persp == RV3D_CAMOB && v3d->camera)) - /* *********** OBJECTS CACHE *********** */ +/* *********** OBJECTS CACHE *********** */ typedef struct tGPencilObjectCache_shgrp { - int mode; - bool clamp_layer; - float blend_opacity; - DRWShadingGroup *init_shgrp; - DRWShadingGroup *end_shgrp; + int mode; + bool clamp_layer; + float blend_opacity; + DRWShadingGroup *init_shgrp; + DRWShadingGroup *end_shgrp; } tGPencilObjectCache_shgrp; - /* used to save gpencil object data for drawing */ +/* used to save gpencil object data for drawing */ typedef struct tGPencilObjectCache { - struct Object *ob; - struct bGPdata *gpd; - int idx; /*original index, can change after sort */ - char *name; - - /* effects */ - bool has_fx; - ListBase shader_fx; - float pixfactor; - DRWShadingGroup *fx_wave_sh; - DRWShadingGroup *fx_blur_sh; - DRWShadingGroup *fx_colorize_sh; - DRWShadingGroup *fx_pixel_sh; - DRWShadingGroup *fx_rim_sh; - DRWShadingGroup *fx_shadow_sh; - DRWShadingGroup *fx_glow_sh; - DRWShadingGroup *fx_swirl_sh; - DRWShadingGroup *fx_flip_sh; - DRWShadingGroup *fx_light_sh; - - float loc[3]; - float obmat[4][4]; - float zdepth; /* z-depth value to sort gp object */ - bool is_dup_ob; /* flag to tag duplicate objects */ - float scale; - - /* shading type */ - int shading_type[2]; - - /* GPU data size */ - int tot_vertex; - int tot_triangles; - - /* Save shader groups by layer */ - int tot_layers; - tGPencilObjectCache_shgrp *shgrp_array; + struct Object *ob; + struct bGPdata *gpd; + int idx; /*original index, can change after sort */ + char *name; + + /* effects */ + bool has_fx; + ListBase shader_fx; + float pixfactor; + DRWShadingGroup *fx_wave_sh; + DRWShadingGroup *fx_blur_sh; + DRWShadingGroup *fx_colorize_sh; + DRWShadingGroup *fx_pixel_sh; + DRWShadingGroup *fx_rim_sh; + DRWShadingGroup *fx_shadow_sh; + DRWShadingGroup *fx_glow_sh; + DRWShadingGroup *fx_swirl_sh; + DRWShadingGroup *fx_flip_sh; + DRWShadingGroup *fx_light_sh; + + float loc[3]; + float obmat[4][4]; + float zdepth; /* z-depth value to sort gp object */ + bool is_dup_ob; /* flag to tag duplicate objects */ + float scale; + + /* shading type */ + int shading_type[2]; + + /* GPU data size */ + int tot_vertex; + int tot_triangles; + + /* Save shader groups by layer */ + int tot_layers; + tGPencilObjectCache_shgrp *shgrp_array; } tGPencilObjectCache; - /* *********** LISTS *********** */ +/* *********** LISTS *********** */ typedef struct GPENCIL_shgroup { - int s_clamp; - int stroke_style; - int color_type; - int mode; - int texture_mix; - int texture_flip; - int texture_clamp; - int fill_style; - int keep_size; - int caps_mode[2]; - float obj_scale; - int xray_mode; - int use_follow_path; - - float gradient_f; - float gradient_s[2]; - - /* color of the wireframe */ - float wire_color[4]; - /* shading type and mode */ - int shading_type[2]; - int is_xray; + int s_clamp; + int stroke_style; + int color_type; + int mode; + int texture_mix; + int texture_flip; + int texture_clamp; + int fill_style; + int keep_size; + int caps_mode[2]; + float obj_scale; + int xray_mode; + int use_follow_path; + + float gradient_f; + float gradient_s[2]; + + /* color of the wireframe */ + float wire_color[4]; + /* shading type and mode */ + int shading_type[2]; + int is_xray; } GPENCIL_shgroup; typedef struct GPENCIL_Storage { - int shgroup_id; /* total elements */ - float unit_matrix[4][4]; - int stroke_style; - int color_type; - int mode; - int xray; - int keep_size; - float obj_scale; - float pixfactor; - bool is_playing; - bool is_render; - bool is_mat_preview; - int is_xray; - bool reset_cache; - bool buffer_stroke; - bool buffer_fill; - bool buffer_ctrlpoint; - const float *pixsize; - float render_pixsize; - int tonemapping; - int do_select_outline; - float select_color[4]; - short multisamples; - - short framebuffer_flag; /* flag what framebuffer need to create */ - - int blend_mode; - int clamp_layer; - float blend_opacity; - - /* simplify settings*/ - bool simplify_fill; - bool simplify_modif; - bool simplify_fx; - bool simplify_blend; - - float gradient_f; - float gradient_s[2]; - int use_follow_path; - - /* Render Matrices and data */ - float persmat[4][4], persinv[4][4]; - float viewmat[4][4], viewinv[4][4]; - float winmat[4][4], wininv[4][4]; - float view_vecs[2][4]; /* vec4[2] */ - - float grid_matrix[4][4]; - int shade_render[2]; - - Object *camera; /* camera pointer for render mode */ + int shgroup_id; /* total elements */ + float unit_matrix[4][4]; + int stroke_style; + int color_type; + int mode; + int xray; + int keep_size; + float obj_scale; + float pixfactor; + bool is_playing; + bool is_render; + bool is_mat_preview; + int is_xray; + bool reset_cache; + bool buffer_stroke; + bool buffer_fill; + bool buffer_ctrlpoint; + const float *pixsize; + float render_pixsize; + int tonemapping; + int do_select_outline; + float select_color[4]; + short multisamples; + + short framebuffer_flag; /* flag what framebuffer need to create */ + + int blend_mode; + int clamp_layer; + float blend_opacity; + + /* simplify settings*/ + bool simplify_fill; + bool simplify_modif; + bool simplify_fx; + bool simplify_blend; + + float gradient_f; + float gradient_s[2]; + int use_follow_path; + + /* Render Matrices and data */ + float persmat[4][4], persinv[4][4]; + float viewmat[4][4], viewinv[4][4]; + float winmat[4][4], wininv[4][4]; + float view_vecs[2][4]; /* vec4[2] */ + + float grid_matrix[4][4]; + int shade_render[2]; + + Object *camera; /* camera pointer for render mode */ } GPENCIL_Storage; typedef enum eGpencilFramebuffer_Flag { - GP_FRAMEBUFFER_MULTISAMPLE = (1 << 0), - GP_FRAMEBUFFER_BASIC = (1 << 1), - GP_FRAMEBUFFER_DRAW = (1 << 2), + GP_FRAMEBUFFER_MULTISAMPLE = (1 << 0), + GP_FRAMEBUFFER_BASIC = (1 << 1), + GP_FRAMEBUFFER_DRAW = (1 << 2), } eGpencilFramebuffer_Flag; typedef struct GPENCIL_StorageList { - struct GPENCIL_Storage *storage; - struct g_data *g_data; - struct GPENCIL_shgroup *shgroups; + struct GPENCIL_Storage *storage; + struct g_data *g_data; + struct GPENCIL_shgroup *shgroups; } GPENCIL_StorageList; typedef struct GPENCIL_PassList { - struct DRWPass *stroke_pass_2d; - struct DRWPass *stroke_pass_3d; - struct DRWPass *edit_pass; - struct DRWPass *drawing_pass; - struct DRWPass *mix_pass; - struct DRWPass *mix_pass_noblend; - struct DRWPass *background_pass; - struct DRWPass *paper_pass; - struct DRWPass *grid_pass; - struct DRWPass *blend_pass; - - /* effects */ - struct DRWPass *fx_shader_pass; - struct DRWPass *fx_shader_pass_blend; + struct DRWPass *stroke_pass_2d; + struct DRWPass *stroke_pass_3d; + struct DRWPass *edit_pass; + struct DRWPass *drawing_pass; + struct DRWPass *mix_pass; + struct DRWPass *mix_pass_noblend; + struct DRWPass *background_pass; + struct DRWPass *paper_pass; + struct DRWPass *grid_pass; + struct DRWPass *blend_pass; + + /* effects */ + struct DRWPass *fx_shader_pass; + struct DRWPass *fx_shader_pass_blend; } GPENCIL_PassList; typedef struct GPENCIL_FramebufferList { - struct GPUFrameBuffer *main; - struct GPUFrameBuffer *temp_fb_a; - struct GPUFrameBuffer *temp_fb_b; - struct GPUFrameBuffer *temp_fb_fx; - struct GPUFrameBuffer *background_fb; + struct GPUFrameBuffer *main; + struct GPUFrameBuffer *temp_fb_a; + struct GPUFrameBuffer *temp_fb_b; + struct GPUFrameBuffer *temp_fb_fx; + struct GPUFrameBuffer *background_fb; - struct GPUFrameBuffer *multisample_fb; + struct GPUFrameBuffer *multisample_fb; } GPENCIL_FramebufferList; typedef struct GPENCIL_TextureList { - struct GPUTexture *texture; + struct GPUTexture *texture; - /* multisample textures */ - struct GPUTexture *multisample_color; - struct GPUTexture *multisample_depth; + /* multisample textures */ + struct GPUTexture *multisample_color; + struct GPUTexture *multisample_depth; } GPENCIL_TextureList; typedef struct GPENCIL_Data { - void *engine_type; /* Required */ - struct GPENCIL_FramebufferList *fbl; - struct GPENCIL_TextureList *txl; - struct GPENCIL_PassList *psl; - struct GPENCIL_StorageList *stl; + void *engine_type; /* Required */ + struct GPENCIL_FramebufferList *fbl; + struct GPENCIL_TextureList *txl; + struct GPENCIL_PassList *psl; + struct GPENCIL_StorageList *stl; - /* render textures */ - struct GPUTexture *render_depth_tx; - struct GPUTexture *render_color_tx; + /* render textures */ + struct GPUTexture *render_depth_tx; + struct GPUTexture *render_color_tx; } GPENCIL_Data; /* *********** STATIC *********** */ typedef struct g_data { - struct DRWShadingGroup *shgrps_edit_point; - struct DRWShadingGroup *shgrps_edit_line; - struct DRWShadingGroup *shgrps_drawing_stroke; - struct DRWShadingGroup *shgrps_drawing_fill; - struct DRWShadingGroup *shgrps_grid; + struct DRWShadingGroup *shgrps_edit_point; + struct DRWShadingGroup *shgrps_edit_line; + struct DRWShadingGroup *shgrps_drawing_stroke; + struct DRWShadingGroup *shgrps_drawing_fill; + struct DRWShadingGroup *shgrps_grid; - int gp_cache_used; /* total objects in cache */ - int gp_cache_size; /* size of the cache */ - struct tGPencilObjectCache *gp_object_cache; + int gp_cache_used; /* total objects in cache */ + int gp_cache_size; /* size of the cache */ + struct tGPencilObjectCache *gp_object_cache; - int session_flag; - bool do_instances; + int session_flag; + bool do_instances; } g_data; /* Transient data */ /* flags for fast drawing support */ typedef enum eGPsession_Flag { - GP_DRW_PAINT_HOLD = (1 << 0), - GP_DRW_PAINT_IDLE = (1 << 1), - GP_DRW_PAINT_FILLING = (1 << 2), - GP_DRW_PAINT_READY = (1 << 3), - GP_DRW_PAINT_PAINTING = (1 << 4), + GP_DRW_PAINT_HOLD = (1 << 0), + GP_DRW_PAINT_IDLE = (1 << 1), + GP_DRW_PAINT_FILLING = (1 << 2), + GP_DRW_PAINT_READY = (1 << 3), + GP_DRW_PAINT_PAINTING = (1 << 4), } eGPsession_Flag; typedef struct GPENCIL_e_data { - /* general drawing shaders */ - struct GPUShader *gpencil_fill_sh; - struct GPUShader *gpencil_stroke_sh; - struct GPUShader *gpencil_point_sh; - struct GPUShader *gpencil_edit_point_sh; - struct GPUShader *gpencil_line_sh; - struct GPUShader *gpencil_drawing_fill_sh; - struct GPUShader *gpencil_fullscreen_sh; - struct GPUShader *gpencil_simple_fullscreen_sh; - struct GPUShader *gpencil_blend_fullscreen_sh; - struct GPUShader *gpencil_background_sh; - struct GPUShader *gpencil_paper_sh; - - /* effects */ - struct GPUShader *gpencil_fx_blur_sh; - struct GPUShader *gpencil_fx_colorize_sh; - struct GPUShader *gpencil_fx_flip_sh; - struct GPUShader *gpencil_fx_glow_prepare_sh; - struct GPUShader *gpencil_fx_glow_resolve_sh; - struct GPUShader *gpencil_fx_light_sh; - struct GPUShader *gpencil_fx_pixel_sh; - struct GPUShader *gpencil_fx_rim_prepare_sh; - struct GPUShader *gpencil_fx_rim_resolve_sh; - struct GPUShader *gpencil_fx_shadow_prepare_sh; - struct GPUShader *gpencil_fx_shadow_resolve_sh; - struct GPUShader *gpencil_fx_swirl_sh; - struct GPUShader *gpencil_fx_wave_sh; - - /* textures */ - struct GPUTexture *background_depth_tx; - struct GPUTexture *background_color_tx; - - struct GPUTexture *gpencil_blank_texture; - - /* runtime pointers texture */ - struct GPUTexture *input_depth_tx; - struct GPUTexture *input_color_tx; - - /* working textures */ - struct GPUTexture *temp_color_tx_a; - struct GPUTexture *temp_depth_tx_a; - - struct GPUTexture *temp_color_tx_b; - struct GPUTexture *temp_depth_tx_b; - - struct GPUTexture *temp_color_tx_fx; - struct GPUTexture *temp_depth_tx_fx; - - /* for buffer only one batch is nedeed because the drawing is only of one stroke */ - GPUBatch *batch_buffer_stroke; - GPUBatch *batch_buffer_fill; - GPUBatch *batch_buffer_ctrlpoint; - - /* grid geometry */ - GPUBatch *batch_grid; + /* general drawing shaders */ + struct GPUShader *gpencil_fill_sh; + struct GPUShader *gpencil_stroke_sh; + struct GPUShader *gpencil_point_sh; + struct GPUShader *gpencil_edit_point_sh; + struct GPUShader *gpencil_line_sh; + struct GPUShader *gpencil_drawing_fill_sh; + struct GPUShader *gpencil_fullscreen_sh; + struct GPUShader *gpencil_simple_fullscreen_sh; + struct GPUShader *gpencil_blend_fullscreen_sh; + struct GPUShader *gpencil_background_sh; + struct GPUShader *gpencil_paper_sh; + + /* effects */ + struct GPUShader *gpencil_fx_blur_sh; + struct GPUShader *gpencil_fx_colorize_sh; + struct GPUShader *gpencil_fx_flip_sh; + struct GPUShader *gpencil_fx_glow_prepare_sh; + struct GPUShader *gpencil_fx_glow_resolve_sh; + struct GPUShader *gpencil_fx_light_sh; + struct GPUShader *gpencil_fx_pixel_sh; + struct GPUShader *gpencil_fx_rim_prepare_sh; + struct GPUShader *gpencil_fx_rim_resolve_sh; + struct GPUShader *gpencil_fx_shadow_prepare_sh; + struct GPUShader *gpencil_fx_shadow_resolve_sh; + struct GPUShader *gpencil_fx_swirl_sh; + struct GPUShader *gpencil_fx_wave_sh; + + /* textures */ + struct GPUTexture *background_depth_tx; + struct GPUTexture *background_color_tx; + + struct GPUTexture *gpencil_blank_texture; + + /* runtime pointers texture */ + struct GPUTexture *input_depth_tx; + struct GPUTexture *input_color_tx; + + /* working textures */ + struct GPUTexture *temp_color_tx_a; + struct GPUTexture *temp_depth_tx_a; + + struct GPUTexture *temp_color_tx_b; + struct GPUTexture *temp_depth_tx_b; + + struct GPUTexture *temp_color_tx_fx; + struct GPUTexture *temp_depth_tx_fx; + + /* for buffer only one batch is nedeed because the drawing is only of one stroke */ + GPUBatch *batch_buffer_stroke; + GPUBatch *batch_buffer_fill; + GPUBatch *batch_buffer_ctrlpoint; + + /* grid geometry */ + GPUBatch *batch_grid; } GPENCIL_e_data; /* Engine data */ /* GPUBatch Cache */ typedef struct GpencilBatchCacheElem { - GPUBatch *batch; - GPUVertBuf *vbo; - int vbo_len; - /* attr ids */ - GPUVertFormat format; - uint pos_id; - uint color_id; - uint thickness_id; - uint uvdata_id; - uint prev_pos_id; - - /* size for VBO alloc */ - int tot_vertex; + GPUBatch *batch; + GPUVertBuf *vbo; + int vbo_len; + /* attr ids */ + GPUVertFormat format; + uint pos_id; + uint color_id; + uint thickness_id; + uint uvdata_id; + uint prev_pos_id; + + /* size for VBO alloc */ + int tot_vertex; } GpencilBatchCacheElem; typedef struct GpencilBatchGroup { - bGPDlayer *gpl; /* reference to original layer */ - bGPDframe *gpf; /* reference to original frame */ - bGPDstroke *gps; /* reference to original stroke */ - short type; /* type of element */ - bool onion; /* the group is part of onion skin */ - int vertex_idx; /* index of vertex data */ + bGPDlayer *gpl; /* reference to original layer */ + bGPDframe *gpf; /* reference to original frame */ + bGPDstroke *gps; /* reference to original stroke */ + short type; /* type of element */ + bool onion; /* the group is part of onion skin */ + int vertex_idx; /* index of vertex data */ } GpencilBatchGroup; typedef enum GpencilBatchGroup_Type { - eGpencilBatchGroupType_Stroke = 1, - eGpencilBatchGroupType_Point = 2, - eGpencilBatchGroupType_Fill = 3, - eGpencilBatchGroupType_Edit = 4, - eGpencilBatchGroupType_Edlin = 5, + eGpencilBatchGroupType_Stroke = 1, + eGpencilBatchGroupType_Point = 2, + eGpencilBatchGroupType_Fill = 3, + eGpencilBatchGroupType_Edit = 4, + eGpencilBatchGroupType_Edlin = 5, } GpencilBatchGroup_Type; typedef struct GpencilBatchCache { - GpencilBatchCacheElem b_stroke; - GpencilBatchCacheElem b_point; - GpencilBatchCacheElem b_fill; - GpencilBatchCacheElem b_edit; - GpencilBatchCacheElem b_edlin; - - /* settings to determine if cache is invalid */ - bool is_dirty; - bool is_editmode; - int cache_frame; - - /* data with the shading groups */ - int grp_used; /* total groups in arrays */ - int grp_size; /* max size of the array */ - struct GpencilBatchGroup *grp_cache; /* array of elements */ - - int tot_layers; - struct bGPDframe *derived_array; /* runtime data created by modifiers */ + GpencilBatchCacheElem b_stroke; + GpencilBatchCacheElem b_point; + GpencilBatchCacheElem b_fill; + GpencilBatchCacheElem b_edit; + GpencilBatchCacheElem b_edlin; + + /* settings to determine if cache is invalid */ + bool is_dirty; + bool is_editmode; + int cache_frame; + + /* data with the shading groups */ + int grp_used; /* total groups in arrays */ + int grp_size; /* max size of the array */ + struct GpencilBatchGroup *grp_cache; /* array of elements */ + + int tot_layers; + struct bGPDframe *derived_array; /* runtime data created by modifiers */ } GpencilBatchCache; /* general drawing functions */ -struct DRWShadingGroup *DRW_gpencil_shgroup_stroke_create( - struct GPENCIL_e_data *e_data, struct GPENCIL_Data *vedata, struct DRWPass *pass, struct GPUShader *shader, - struct Object *ob, struct bGPdata *gpd, - struct bGPDlayer *gpl, struct bGPDstroke *gps, - struct MaterialGPencilStyle *gp_style, int id, bool onion, - const float scale, const int shading_type[2]); -void DRW_gpencil_populate_datablock( - struct GPENCIL_e_data *e_data, void *vedata, - struct Object *ob, struct tGPencilObjectCache *cache_ob); -void DRW_gpencil_populate_buffer_strokes( - struct GPENCIL_e_data *e_data, void *vedata, struct ToolSettings *ts, struct Object *ob); -void DRW_gpencil_populate_multiedit( - struct GPENCIL_e_data *e_data, void *vedata, - struct Object *ob, struct tGPencilObjectCache *cache_ob); +struct DRWShadingGroup *DRW_gpencil_shgroup_stroke_create(struct GPENCIL_e_data *e_data, + struct GPENCIL_Data *vedata, + struct DRWPass *pass, + struct GPUShader *shader, + struct Object *ob, + struct bGPdata *gpd, + struct bGPDlayer *gpl, + struct bGPDstroke *gps, + struct MaterialGPencilStyle *gp_style, + int id, + bool onion, + const float scale, + const int shading_type[2]); +void DRW_gpencil_populate_datablock(struct GPENCIL_e_data *e_data, + void *vedata, + struct Object *ob, + struct tGPencilObjectCache *cache_ob); +void DRW_gpencil_populate_buffer_strokes(struct GPENCIL_e_data *e_data, + void *vedata, + struct ToolSettings *ts, + struct Object *ob); +void DRW_gpencil_populate_multiedit(struct GPENCIL_e_data *e_data, + void *vedata, + struct Object *ob, + struct tGPencilObjectCache *cache_ob); void DRW_gpencil_triangulate_stroke_fill(struct Object *ob, struct bGPDstroke *gps); -void DRW_gpencil_populate_particles(struct GPENCIL_e_data *e_data, struct GHash *gh_objects, void *vedata); +void DRW_gpencil_populate_particles(struct GPENCIL_e_data *e_data, + struct GHash *gh_objects, + void *vedata); void DRW_gpencil_multisample_ensure(struct GPENCIL_Data *vedata, int rect_w, int rect_h); /* create geometry functions */ -void DRW_gpencil_get_point_geom(struct GpencilBatchCacheElem *be, struct bGPDstroke *gps, short thickness, const float ink[4]); -void DRW_gpencil_get_stroke_geom(struct GpencilBatchCacheElem *be, struct bGPDstroke *gps, short thickness, const float ink[4]); -void DRW_gpencil_get_fill_geom(struct GpencilBatchCacheElem *be, struct Object *ob, struct bGPDstroke *gps, const float color[4]); -void DRW_gpencil_get_edit_geom(struct GpencilBatchCacheElem *be, struct bGPDstroke *gps, float alpha, short dflag); -void DRW_gpencil_get_edlin_geom(struct GpencilBatchCacheElem *be, struct bGPDstroke *gps, float alpha, short dflag); +void DRW_gpencil_get_point_geom(struct GpencilBatchCacheElem *be, + struct bGPDstroke *gps, + short thickness, + const float ink[4]); +void DRW_gpencil_get_stroke_geom(struct GpencilBatchCacheElem *be, + struct bGPDstroke *gps, + short thickness, + const float ink[4]); +void DRW_gpencil_get_fill_geom(struct GpencilBatchCacheElem *be, + struct Object *ob, + struct bGPDstroke *gps, + const float color[4]); +void DRW_gpencil_get_edit_geom(struct GpencilBatchCacheElem *be, + struct bGPDstroke *gps, + float alpha, + short dflag); +void DRW_gpencil_get_edlin_geom(struct GpencilBatchCacheElem *be, + struct bGPDstroke *gps, + float alpha, + short dflag); struct GPUBatch *DRW_gpencil_get_buffer_stroke_geom(struct bGPdata *gpd, short thickness); struct GPUBatch *DRW_gpencil_get_buffer_fill_geom(struct bGPdata *gpd); @@ -420,19 +458,23 @@ struct GPUBatch *DRW_gpencil_get_buffer_ctrlpoint_geom(struct bGPdata *gpd); struct GPUBatch *DRW_gpencil_get_grid(Object *ob); /* object cache functions */ -struct tGPencilObjectCache *gpencil_object_cache_add( - struct tGPencilObjectCache *cache_array, struct Object *ob, - int *gp_cache_size, int *gp_cache_used); +struct tGPencilObjectCache *gpencil_object_cache_add(struct tGPencilObjectCache *cache_array, + struct Object *ob, + int *gp_cache_size, + int *gp_cache_used); bool DRW_gpencil_onion_active(struct bGPdata *gpd); /* shading groups cache functions */ -struct GpencilBatchGroup *gpencil_group_cache_add( - struct GpencilBatchGroup *cache_array, - struct bGPDlayer *gpl, struct bGPDframe *gpf, struct bGPDstroke *gps, - const short type, const bool onion, - const int vertex_idx, - int *grp_size, int *grp_used); +struct GpencilBatchGroup *gpencil_group_cache_add(struct GpencilBatchGroup *cache_array, + struct bGPDlayer *gpl, + struct bGPDframe *gpf, + struct bGPDstroke *gps, + const short type, + const bool onion, + const int vertex_idx, + int *grp_size, + int *grp_used); /* geometry batch cache functions */ struct GpencilBatchCache *gpencil_batch_cache_get(struct Object *ob, int cfra); @@ -442,12 +484,12 @@ void GPENCIL_create_fx_shaders(struct GPENCIL_e_data *e_data); void GPENCIL_delete_fx_shaders(struct GPENCIL_e_data *e_data); void GPENCIL_create_fx_passes(struct GPENCIL_PassList *psl); -void DRW_gpencil_fx_prepare( - struct GPENCIL_e_data *e_data, struct GPENCIL_Data *vedata, - struct tGPencilObjectCache *cache_ob); -void DRW_gpencil_fx_draw( - struct GPENCIL_e_data *e_data, struct GPENCIL_Data *vedata, - struct tGPencilObjectCache *cache_ob); +void DRW_gpencil_fx_prepare(struct GPENCIL_e_data *e_data, + struct GPENCIL_Data *vedata, + struct tGPencilObjectCache *cache_ob); +void DRW_gpencil_fx_draw(struct GPENCIL_e_data *e_data, + struct GPENCIL_Data *vedata, + struct tGPencilObjectCache *cache_ob); /* main functions */ void GPENCIL_engine_init(void *vedata); @@ -457,33 +499,41 @@ void GPENCIL_cache_finish(void *vedata); void GPENCIL_draw_scene(void *vedata); /* render */ -void GPENCIL_render_init(struct GPENCIL_Data *ved, struct RenderEngine *engine, struct Depsgraph *depsgraph); -void GPENCIL_render_to_image(void *vedata, struct RenderEngine *engine, struct RenderLayer *render_layer, const rcti *rect); +void GPENCIL_render_init(struct GPENCIL_Data *ved, + struct RenderEngine *engine, + struct Depsgraph *depsgraph); +void GPENCIL_render_to_image(void *vedata, + struct RenderEngine *engine, + struct RenderLayer *render_layer, + const rcti *rect); /* Use of multisample framebuffers. */ -#define MULTISAMPLE_GP_SYNC_ENABLE(lvl, fbl) { \ - if ((lvl > 0) && (fbl->multisample_fb != NULL)) { \ - DRW_stats_query_start("GP Multisample Blit"); \ - GPU_framebuffer_bind(fbl->multisample_fb); \ - GPU_framebuffer_clear_color_depth(fbl->multisample_fb, (const float[4]){0.0f}, 1.0f); \ - DRW_stats_query_end(); \ - } \ -} ((void)0) - -#define MULTISAMPLE_GP_SYNC_DISABLE(lvl, fbl, fb, txl) { \ - if ((lvl > 0) && (fbl->multisample_fb != NULL)) { \ - DRW_stats_query_start("GP Multisample Resolve"); \ - GPU_framebuffer_bind(fb); \ - DRW_multisamples_resolve(txl->multisample_depth, txl->multisample_color, true); \ - DRW_stats_query_end(); \ - } \ -} ((void)0) +#define MULTISAMPLE_GP_SYNC_ENABLE(lvl, fbl) \ + { \ + if ((lvl > 0) && (fbl->multisample_fb != NULL)) { \ + DRW_stats_query_start("GP Multisample Blit"); \ + GPU_framebuffer_bind(fbl->multisample_fb); \ + GPU_framebuffer_clear_color_depth(fbl->multisample_fb, (const float[4]){0.0f}, 1.0f); \ + DRW_stats_query_end(); \ + } \ + } \ + ((void)0) + +#define MULTISAMPLE_GP_SYNC_DISABLE(lvl, fbl, fb, txl) \ + { \ + if ((lvl > 0) && (fbl->multisample_fb != NULL)) { \ + DRW_stats_query_start("GP Multisample Resolve"); \ + GPU_framebuffer_bind(fb); \ + DRW_multisamples_resolve(txl->multisample_depth, txl->multisample_color, true); \ + DRW_stats_query_end(); \ + } \ + } \ + ((void)0) #define GPENCIL_3D_DRAWMODE(ob, gpd) \ - ((gpd) && (gpd->draw_mode == GP_DRAWMODE_3D) && \ - ((ob->dtx & OB_DRAWXRAY) == 0)) + ((gpd) && (gpd->draw_mode == GP_DRAWMODE_3D) && ((ob->dtx & OB_DRAWXRAY) == 0)) #define GPENCIL_USE_SOLID(stl) \ - ((stl) && ((stl->storage->is_render) || (stl->storage->is_mat_preview))) + ((stl) && ((stl->storage->is_render) || (stl->storage->is_mat_preview))) #endif /* __GPENCIL_ENGINE_H__ */ diff --git a/source/blender/draw/engines/gpencil/gpencil_render.c b/source/blender/draw/engines/gpencil/gpencil_render.c index 45fef77cbac..282c4ca3a77 100644 --- a/source/blender/draw/engines/gpencil/gpencil_render.c +++ b/source/blender/draw/engines/gpencil/gpencil_render.c @@ -16,7 +16,7 @@ * Copyright 2017, Blender Foundation. */ - /** \file +/** \file * \ingroup draw */ #include "BLI_rect.h" @@ -35,322 +35,345 @@ #include "gpencil_engine.h" - /* Get pixel size for render +/* Get pixel size for render * This function uses the same calculation used for viewport, because if use * camera pixelsize, the result is not correct. */ static float get_render_pixelsize(float persmat[4][4], int winx, int winy) { - float v1[3], v2[3]; - float len_px, len_sc; + float v1[3], v2[3]; + float len_px, len_sc; - v1[0] = persmat[0][0]; - v1[1] = persmat[1][0]; - v1[2] = persmat[2][0]; + v1[0] = persmat[0][0]; + v1[1] = persmat[1][0]; + v1[2] = persmat[2][0]; - v2[0] = persmat[0][1]; - v2[1] = persmat[1][1]; - v2[2] = persmat[2][1]; + v2[0] = persmat[0][1]; + v2[1] = persmat[1][1]; + v2[2] = persmat[2][1]; - len_px = 2.0f / sqrtf(min_ff(len_squared_v3(v1), len_squared_v3(v2))); - len_sc = (float)MAX2(winx, winy); + len_px = 2.0f / sqrtf(min_ff(len_squared_v3(v1), len_squared_v3(v2))); + len_sc = (float)MAX2(winx, winy); - return len_px / len_sc; + return len_px / len_sc; } /* init render data */ void GPENCIL_render_init(GPENCIL_Data *ved, RenderEngine *engine, struct Depsgraph *depsgraph) { - GPENCIL_Data *vedata = (GPENCIL_Data *)ved; - GPENCIL_StorageList *stl = vedata->stl; - GPENCIL_FramebufferList *fbl = vedata->fbl; - - Scene *scene = DEG_get_evaluated_scene(depsgraph); - const float *viewport_size = DRW_viewport_size_get(); - const int size[2] = { (int)viewport_size[0], (int)viewport_size[1] }; - - /* In render mode the default framebuffer is not generated - * because there is no viewport. So we need to manually create one - * NOTE : use 32 bit format for precision in render mode. - */ - /* create multiframe framebuffer for AA */ - if (U.gpencil_multisamples > 0) { - int rect_w = (int)viewport_size[0]; - int rect_h = (int)viewport_size[1]; - DRW_gpencil_multisample_ensure(vedata, rect_w, rect_h); - } - - vedata->render_depth_tx = DRW_texture_pool_query_2d( - size[0], size[1], GPU_DEPTH_COMPONENT24, - &draw_engine_gpencil_type); - vedata->render_color_tx = DRW_texture_pool_query_2d( - size[0], size[1], GPU_RGBA32F, - &draw_engine_gpencil_type); - GPU_framebuffer_ensure_config( - &fbl->main, { - GPU_ATTACHMENT_TEXTURE(vedata->render_depth_tx), - GPU_ATTACHMENT_TEXTURE(vedata->render_color_tx) - }); - - /* Alloc transient data. */ - if (!stl->g_data) { - stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__); - } - - /* Set the pers & view matrix. */ - struct Object *camera = DEG_get_evaluated_object(depsgraph, RE_GetCamera(engine->re)); - float frame = BKE_scene_frame_get(scene); - RE_GetCameraWindow(engine->re, camera, frame, stl->storage->winmat); - RE_GetCameraModelMatrix(engine->re, camera, stl->storage->viewinv); - - invert_m4_m4(stl->storage->viewmat, stl->storage->viewinv); - mul_m4_m4m4(stl->storage->persmat, stl->storage->winmat, stl->storage->viewmat); - invert_m4_m4(stl->storage->persinv, stl->storage->persmat); - invert_m4_m4(stl->storage->wininv, stl->storage->winmat); - - DRW_viewport_matrix_override_set(stl->storage->persmat, DRW_MAT_PERS); - DRW_viewport_matrix_override_set(stl->storage->persinv, DRW_MAT_PERSINV); - DRW_viewport_matrix_override_set(stl->storage->winmat, DRW_MAT_WIN); - DRW_viewport_matrix_override_set(stl->storage->wininv, DRW_MAT_WININV); - DRW_viewport_matrix_override_set(stl->storage->viewmat, DRW_MAT_VIEW); - DRW_viewport_matrix_override_set(stl->storage->viewinv, DRW_MAT_VIEWINV); - - /* calculate pixel size for render */ - stl->storage->render_pixsize = get_render_pixelsize(stl->storage->persmat, viewport_size[0], viewport_size[1]); - /* INIT CACHE */ - GPENCIL_cache_init(vedata); + GPENCIL_Data *vedata = (GPENCIL_Data *)ved; + GPENCIL_StorageList *stl = vedata->stl; + GPENCIL_FramebufferList *fbl = vedata->fbl; + + Scene *scene = DEG_get_evaluated_scene(depsgraph); + const float *viewport_size = DRW_viewport_size_get(); + const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]}; + + /* In render mode the default framebuffer is not generated + * because there is no viewport. So we need to manually create one + * NOTE : use 32 bit format for precision in render mode. + */ + /* create multiframe framebuffer for AA */ + if (U.gpencil_multisamples > 0) { + int rect_w = (int)viewport_size[0]; + int rect_h = (int)viewport_size[1]; + DRW_gpencil_multisample_ensure(vedata, rect_w, rect_h); + } + + vedata->render_depth_tx = DRW_texture_pool_query_2d( + size[0], size[1], GPU_DEPTH_COMPONENT24, &draw_engine_gpencil_type); + vedata->render_color_tx = DRW_texture_pool_query_2d( + size[0], size[1], GPU_RGBA32F, &draw_engine_gpencil_type); + GPU_framebuffer_ensure_config(&fbl->main, + {GPU_ATTACHMENT_TEXTURE(vedata->render_depth_tx), + GPU_ATTACHMENT_TEXTURE(vedata->render_color_tx)}); + + /* Alloc transient data. */ + if (!stl->g_data) { + stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__); + } + + /* Set the pers & view matrix. */ + struct Object *camera = DEG_get_evaluated_object(depsgraph, RE_GetCamera(engine->re)); + float frame = BKE_scene_frame_get(scene); + RE_GetCameraWindow(engine->re, camera, frame, stl->storage->winmat); + RE_GetCameraModelMatrix(engine->re, camera, stl->storage->viewinv); + + invert_m4_m4(stl->storage->viewmat, stl->storage->viewinv); + mul_m4_m4m4(stl->storage->persmat, stl->storage->winmat, stl->storage->viewmat); + invert_m4_m4(stl->storage->persinv, stl->storage->persmat); + invert_m4_m4(stl->storage->wininv, stl->storage->winmat); + + DRW_viewport_matrix_override_set(stl->storage->persmat, DRW_MAT_PERS); + DRW_viewport_matrix_override_set(stl->storage->persinv, DRW_MAT_PERSINV); + DRW_viewport_matrix_override_set(stl->storage->winmat, DRW_MAT_WIN); + DRW_viewport_matrix_override_set(stl->storage->wininv, DRW_MAT_WININV); + DRW_viewport_matrix_override_set(stl->storage->viewmat, DRW_MAT_VIEW); + DRW_viewport_matrix_override_set(stl->storage->viewinv, DRW_MAT_VIEWINV); + + /* calculate pixel size for render */ + stl->storage->render_pixsize = get_render_pixelsize( + stl->storage->persmat, viewport_size[0], viewport_size[1]); + /* INIT CACHE */ + GPENCIL_cache_init(vedata); } /* render all objects and select only grease pencil */ -static void GPENCIL_render_cache( - void *vedata, struct Object *ob, - struct RenderEngine *UNUSED(engine), struct Depsgraph *UNUSED(depsgraph)) +static void GPENCIL_render_cache(void *vedata, + struct Object *ob, + struct RenderEngine *UNUSED(engine), + struct Depsgraph *UNUSED(depsgraph)) { - if (ob && ob->type == OB_GPENCIL) { - if (DRW_object_visibility_in_active_context(ob) & OB_VISIBLE_SELF) { - GPENCIL_cache_populate(vedata, ob); - } - } + if (ob && ob->type == OB_GPENCIL) { + if (DRW_object_visibility_in_active_context(ob) & OB_VISIBLE_SELF) { + GPENCIL_cache_populate(vedata, ob); + } + } } /* TODO: Reuse Eevee code in shared module instead to duplicate here */ -static void GPENCIL_render_update_viewvecs(float invproj[4][4], float winmat[4][4], float(*r_viewvecs)[4]) +static void GPENCIL_render_update_viewvecs(float invproj[4][4], + float winmat[4][4], + float (*r_viewvecs)[4]) { - /* view vectors for the corners of the view frustum. - * Can be used to recreate the world space position easily */ - float view_vecs[4][4] = { - {-1.0f, -1.0f, -1.0f, 1.0f}, - {1.0f, -1.0f, -1.0f, 1.0f}, - {-1.0f, 1.0f, -1.0f, 1.0f}, - {-1.0f, -1.0f, 1.0f, 1.0f} - }; - - /* convert the view vectors to view space */ - const bool is_persp = (winmat[3][3] == 0.0f); - for (int i = 0; i < 4; i++) { - mul_project_m4_v3(invproj, view_vecs[i]); - /* normalized trick see: - * http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */ - if (is_persp) { - /* Divide XY by Z. */ - mul_v2_fl(view_vecs[i], 1.0f / view_vecs[i][2]); - } - } - - /** - * If ortho : view_vecs[0] is the near-bottom-left corner of the frustum and - * view_vecs[1] is the vector going from the near-bottom-left corner to - * the far-top-right corner. - * If Persp : view_vecs[0].xy and view_vecs[1].xy are respectively the bottom-left corner - * when Z = 1, and top-left corner if Z = 1. - * view_vecs[0].z the near clip distance and view_vecs[1].z is the (signed) - * distance from the near plane to the far clip plane. - */ - copy_v4_v4(r_viewvecs[0], view_vecs[0]); - - /* we need to store the differences */ - r_viewvecs[1][0] = view_vecs[1][0] - view_vecs[0][0]; - r_viewvecs[1][1] = view_vecs[2][1] - view_vecs[0][1]; - r_viewvecs[1][2] = view_vecs[3][2] - view_vecs[0][2]; + /* view vectors for the corners of the view frustum. + * Can be used to recreate the world space position easily */ + float view_vecs[4][4] = {{-1.0f, -1.0f, -1.0f, 1.0f}, + {1.0f, -1.0f, -1.0f, 1.0f}, + {-1.0f, 1.0f, -1.0f, 1.0f}, + {-1.0f, -1.0f, 1.0f, 1.0f}}; + + /* convert the view vectors to view space */ + const bool is_persp = (winmat[3][3] == 0.0f); + for (int i = 0; i < 4; i++) { + mul_project_m4_v3(invproj, view_vecs[i]); + /* normalized trick see: + * http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */ + if (is_persp) { + /* Divide XY by Z. */ + mul_v2_fl(view_vecs[i], 1.0f / view_vecs[i][2]); + } + } + + /** + * If ortho : view_vecs[0] is the near-bottom-left corner of the frustum and + * view_vecs[1] is the vector going from the near-bottom-left corner to + * the far-top-right corner. + * If Persp : view_vecs[0].xy and view_vecs[1].xy are respectively the bottom-left corner + * when Z = 1, and top-left corner if Z = 1. + * view_vecs[0].z the near clip distance and view_vecs[1].z is the (signed) + * distance from the near plane to the far clip plane. + */ + copy_v4_v4(r_viewvecs[0], view_vecs[0]); + + /* we need to store the differences */ + r_viewvecs[1][0] = view_vecs[1][0] - view_vecs[0][0]; + r_viewvecs[1][1] = view_vecs[2][1] - view_vecs[0][1]; + r_viewvecs[1][2] = view_vecs[3][2] - view_vecs[0][2]; } /* Update view_vecs */ static void GPENCIL_render_update_vecs(GPENCIL_Data *vedata) { - GPENCIL_StorageList *stl = vedata->stl; + GPENCIL_StorageList *stl = vedata->stl; - float invproj[4][4], winmat[4][4]; - DRW_viewport_matrix_get(winmat, DRW_MAT_WIN); - DRW_viewport_matrix_get(invproj, DRW_MAT_WININV); + float invproj[4][4], winmat[4][4]; + DRW_viewport_matrix_get(winmat, DRW_MAT_WIN); + DRW_viewport_matrix_get(invproj, DRW_MAT_WININV); - /* this is separated to keep function equal to Eevee for future reuse of same code */ - GPENCIL_render_update_viewvecs(invproj, winmat, stl->storage->view_vecs); + /* this is separated to keep function equal to Eevee for future reuse of same code */ + GPENCIL_render_update_viewvecs(invproj, winmat, stl->storage->view_vecs); } /* read z-depth render result */ -static void GPENCIL_render_result_z(struct RenderLayer *rl, const char *viewname, GPENCIL_Data *vedata, const rcti *rect) +static void GPENCIL_render_result_z(struct RenderLayer *rl, + const char *viewname, + GPENCIL_Data *vedata, + const rcti *rect) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - ViewLayer *view_layer = draw_ctx->view_layer; - GPENCIL_StorageList *stl = vedata->stl; - - if ((view_layer->passflag & SCE_PASS_Z) != 0) { - RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_Z, viewname); - - GPU_framebuffer_read_depth(vedata->fbl->main, rect->xmin, rect->ymin, BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), rp->rect); - - bool is_persp = DRW_viewport_is_persp_get(); - - GPENCIL_render_update_vecs(vedata); - - /* Convert ogl depth [0..1] to view Z [near..far] */ - for (int i = 0; i < BLI_rcti_size_x(rect) * BLI_rcti_size_y(rect); i++) { - if (rp->rect[i] == 1.0f) { - rp->rect[i] = 1e10f; /* Background */ - } - else { - if (is_persp) { - rp->rect[i] = rp->rect[i] * 2.0f - 1.0f; - rp->rect[i] = stl->storage->winmat[3][2] / (rp->rect[i] + stl->storage->winmat[2][2]); - } - else { - rp->rect[i] = -stl->storage->view_vecs[0][2] + rp->rect[i] * -stl->storage->view_vecs[1][2]; - } - } - } - } + const DRWContextState *draw_ctx = DRW_context_state_get(); + ViewLayer *view_layer = draw_ctx->view_layer; + GPENCIL_StorageList *stl = vedata->stl; + + if ((view_layer->passflag & SCE_PASS_Z) != 0) { + RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_Z, viewname); + + GPU_framebuffer_read_depth(vedata->fbl->main, + rect->xmin, + rect->ymin, + BLI_rcti_size_x(rect), + BLI_rcti_size_y(rect), + rp->rect); + + bool is_persp = DRW_viewport_is_persp_get(); + + GPENCIL_render_update_vecs(vedata); + + /* Convert ogl depth [0..1] to view Z [near..far] */ + for (int i = 0; i < BLI_rcti_size_x(rect) * BLI_rcti_size_y(rect); i++) { + if (rp->rect[i] == 1.0f) { + rp->rect[i] = 1e10f; /* Background */ + } + else { + if (is_persp) { + rp->rect[i] = rp->rect[i] * 2.0f - 1.0f; + rp->rect[i] = stl->storage->winmat[3][2] / (rp->rect[i] + stl->storage->winmat[2][2]); + } + else { + rp->rect[i] = -stl->storage->view_vecs[0][2] + + rp->rect[i] * -stl->storage->view_vecs[1][2]; + } + } + } + } } /* read combined render result */ -static void GPENCIL_render_result_combined(struct RenderLayer *rl, const char *viewname, GPENCIL_Data *vedata, const rcti *rect) +static void GPENCIL_render_result_combined(struct RenderLayer *rl, + const char *viewname, + GPENCIL_Data *vedata, + const rcti *rect) { - RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_COMBINED, viewname); - GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl; - - GPU_framebuffer_bind(fbl->main); - GPU_framebuffer_read_color(vedata->fbl->main, rect->xmin, rect->ymin, BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), 4, 0, rp->rect); + RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_COMBINED, viewname); + GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl; + + GPU_framebuffer_bind(fbl->main); + GPU_framebuffer_read_color(vedata->fbl->main, + rect->xmin, + rect->ymin, + BLI_rcti_size_x(rect), + BLI_rcti_size_y(rect), + 4, + 0, + rp->rect); } /* helper to blend pixels */ static void blend_pixel(float top_color[4], float bottom_color[4], float dst_color[4]) { - float alpha = top_color[3]; + float alpha = top_color[3]; - /* use blend: GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA */ - dst_color[0] = (top_color[0] * alpha) + (bottom_color[0] * (1.0f - alpha)); - dst_color[1] = (top_color[1] * alpha) + (bottom_color[1] * (1.0f - alpha)); - dst_color[2] = (top_color[2] * alpha) + (bottom_color[2] * (1.0f - alpha)); + /* use blend: GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA */ + dst_color[0] = (top_color[0] * alpha) + (bottom_color[0] * (1.0f - alpha)); + dst_color[1] = (top_color[1] * alpha) + (bottom_color[1] * (1.0f - alpha)); + dst_color[2] = (top_color[2] * alpha) + (bottom_color[2] * (1.0f - alpha)); } /* render grease pencil to image */ -void GPENCIL_render_to_image(void *vedata, RenderEngine *engine, struct RenderLayer *render_layer, const rcti *rect) +void GPENCIL_render_to_image(void *vedata, + RenderEngine *engine, + struct RenderLayer *render_layer, + const rcti *rect) { - const char *viewname = RE_GetActiveRenderView(engine->re); - const DRWContextState *draw_ctx = DRW_context_state_get(); - int imgsize = BLI_rcti_size_x(rect) * BLI_rcti_size_y(rect); - - /* save previous render data */ - RenderPass *rpass_color_src = RE_pass_find_by_name(render_layer, RE_PASSNAME_COMBINED, viewname); - RenderPass *rpass_depth_src = RE_pass_find_by_name(render_layer, RE_PASSNAME_Z, viewname); - float *src_rect_color_data = NULL; - float *src_rect_depth_data = NULL; - if ((rpass_color_src) && (rpass_depth_src) && (rpass_color_src->rect) && (rpass_depth_src->rect)) { - src_rect_color_data = MEM_dupallocN(rpass_color_src->rect); - src_rect_depth_data = MEM_dupallocN(rpass_depth_src->rect); - } - else { - /* TODO: put this message in a better place */ - printf("Warning: To render grease pencil, enable Combined and Z passes.\n"); - } - - GPENCIL_engine_init(vedata); - GPENCIL_render_init(vedata, engine, draw_ctx->depsgraph); - - GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; - Object *camera = DEG_get_evaluated_object(draw_ctx->depsgraph, RE_GetCamera(engine->re)); - stl->storage->camera = camera; /* save current camera */ - - GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl; - if (fbl->main) { - GPU_framebuffer_texture_attach(fbl->main, ((GPENCIL_Data *)vedata)->render_depth_tx, 0, 0); - GPU_framebuffer_texture_attach(fbl->main, ((GPENCIL_Data *)vedata)->render_color_tx, 0, 0); - /* clean first time the buffer */ - float clearcol[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; - GPU_framebuffer_bind(fbl->main); - GPU_framebuffer_clear_color_depth(fbl->main, clearcol, 1.0f); - } - - /* loop all objects and draw */ - DRW_render_object_iter(vedata, engine, draw_ctx->depsgraph, GPENCIL_render_cache); - - GPENCIL_cache_finish(vedata); - GPENCIL_draw_scene(vedata); - - /* combined data */ - GPENCIL_render_result_combined(render_layer, viewname, vedata, rect); - /* z-depth data */ - GPENCIL_render_result_z(render_layer, viewname, vedata, rect); - - /* detach textures */ - if (fbl->main) { - GPU_framebuffer_texture_detach(fbl->main, ((GPENCIL_Data *)vedata)->render_depth_tx); - GPU_framebuffer_texture_detach(fbl->main, ((GPENCIL_Data *)vedata)->render_color_tx); - } - - /* merge previous render image with new GP image */ - if (src_rect_color_data) { - RenderPass *rpass_color_gp = RE_pass_find_by_name(render_layer, RE_PASSNAME_COMBINED, viewname); - RenderPass *rpass_depth_gp = RE_pass_find_by_name(render_layer, RE_PASSNAME_Z, viewname); - float *gp_rect_color_data = rpass_color_gp->rect; - float *gp_rect_depth_data = rpass_depth_gp->rect; - float *gp_pixel_rgba; - float *gp_pixel_depth; - float *src_pixel_rgba; - float *src_pixel_depth; - - for (int i = 0; i < imgsize; i++) { - gp_pixel_rgba = &gp_rect_color_data[i * 4]; - gp_pixel_depth = &gp_rect_depth_data[i]; - - src_pixel_rgba = &src_rect_color_data[i * 4]; - src_pixel_depth = &src_rect_depth_data[i]; - - /* check grease pencil render transparency */ - if (gp_pixel_rgba[3] > 0.0f) { - if (src_pixel_rgba[3] > 0.0f) { - /* check z-depth */ - if (gp_pixel_depth[0] > src_pixel_depth[0]) { - /* copy source z-depth */ - gp_pixel_depth[0] = src_pixel_depth[0]; - /* blend object on top */ - if (src_pixel_rgba[3] < 1.0f) { - blend_pixel(src_pixel_rgba, gp_pixel_rgba, gp_pixel_rgba); - } - else { - copy_v4_v4(gp_pixel_rgba, src_pixel_rgba); - } - } - else { - /* blend gp render */ - if (gp_pixel_rgba[3] < 1.0f) { - /* premult alpha factor to remove double blend effects */ - mul_v3_fl(gp_pixel_rgba, 1.0f / gp_pixel_rgba[3]); - - blend_pixel(gp_pixel_rgba, src_pixel_rgba, gp_pixel_rgba); - - gp_pixel_rgba[3] = gp_pixel_rgba[3] > src_pixel_rgba[3] ? gp_pixel_rgba[3] : src_pixel_rgba[3]; - } - } - } - } - else { - copy_v4_v4(gp_pixel_rgba, src_pixel_rgba); - gp_pixel_depth[0] = src_pixel_depth[0]; - } - } - - /* free memory */ - MEM_SAFE_FREE(src_rect_color_data); - MEM_SAFE_FREE(src_rect_depth_data); - } + const char *viewname = RE_GetActiveRenderView(engine->re); + const DRWContextState *draw_ctx = DRW_context_state_get(); + int imgsize = BLI_rcti_size_x(rect) * BLI_rcti_size_y(rect); + + /* save previous render data */ + RenderPass *rpass_color_src = RE_pass_find_by_name(render_layer, RE_PASSNAME_COMBINED, viewname); + RenderPass *rpass_depth_src = RE_pass_find_by_name(render_layer, RE_PASSNAME_Z, viewname); + float *src_rect_color_data = NULL; + float *src_rect_depth_data = NULL; + if ((rpass_color_src) && (rpass_depth_src) && (rpass_color_src->rect) && + (rpass_depth_src->rect)) { + src_rect_color_data = MEM_dupallocN(rpass_color_src->rect); + src_rect_depth_data = MEM_dupallocN(rpass_depth_src->rect); + } + else { + /* TODO: put this message in a better place */ + printf("Warning: To render grease pencil, enable Combined and Z passes.\n"); + } + + GPENCIL_engine_init(vedata); + GPENCIL_render_init(vedata, engine, draw_ctx->depsgraph); + + GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; + Object *camera = DEG_get_evaluated_object(draw_ctx->depsgraph, RE_GetCamera(engine->re)); + stl->storage->camera = camera; /* save current camera */ + + GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl; + if (fbl->main) { + GPU_framebuffer_texture_attach(fbl->main, ((GPENCIL_Data *)vedata)->render_depth_tx, 0, 0); + GPU_framebuffer_texture_attach(fbl->main, ((GPENCIL_Data *)vedata)->render_color_tx, 0, 0); + /* clean first time the buffer */ + float clearcol[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + GPU_framebuffer_bind(fbl->main); + GPU_framebuffer_clear_color_depth(fbl->main, clearcol, 1.0f); + } + + /* loop all objects and draw */ + DRW_render_object_iter(vedata, engine, draw_ctx->depsgraph, GPENCIL_render_cache); + + GPENCIL_cache_finish(vedata); + GPENCIL_draw_scene(vedata); + + /* combined data */ + GPENCIL_render_result_combined(render_layer, viewname, vedata, rect); + /* z-depth data */ + GPENCIL_render_result_z(render_layer, viewname, vedata, rect); + + /* detach textures */ + if (fbl->main) { + GPU_framebuffer_texture_detach(fbl->main, ((GPENCIL_Data *)vedata)->render_depth_tx); + GPU_framebuffer_texture_detach(fbl->main, ((GPENCIL_Data *)vedata)->render_color_tx); + } + + /* merge previous render image with new GP image */ + if (src_rect_color_data) { + RenderPass *rpass_color_gp = RE_pass_find_by_name( + render_layer, RE_PASSNAME_COMBINED, viewname); + RenderPass *rpass_depth_gp = RE_pass_find_by_name(render_layer, RE_PASSNAME_Z, viewname); + float *gp_rect_color_data = rpass_color_gp->rect; + float *gp_rect_depth_data = rpass_depth_gp->rect; + float *gp_pixel_rgba; + float *gp_pixel_depth; + float *src_pixel_rgba; + float *src_pixel_depth; + + for (int i = 0; i < imgsize; i++) { + gp_pixel_rgba = &gp_rect_color_data[i * 4]; + gp_pixel_depth = &gp_rect_depth_data[i]; + + src_pixel_rgba = &src_rect_color_data[i * 4]; + src_pixel_depth = &src_rect_depth_data[i]; + + /* check grease pencil render transparency */ + if (gp_pixel_rgba[3] > 0.0f) { + if (src_pixel_rgba[3] > 0.0f) { + /* check z-depth */ + if (gp_pixel_depth[0] > src_pixel_depth[0]) { + /* copy source z-depth */ + gp_pixel_depth[0] = src_pixel_depth[0]; + /* blend object on top */ + if (src_pixel_rgba[3] < 1.0f) { + blend_pixel(src_pixel_rgba, gp_pixel_rgba, gp_pixel_rgba); + } + else { + copy_v4_v4(gp_pixel_rgba, src_pixel_rgba); + } + } + else { + /* blend gp render */ + if (gp_pixel_rgba[3] < 1.0f) { + /* premult alpha factor to remove double blend effects */ + mul_v3_fl(gp_pixel_rgba, 1.0f / gp_pixel_rgba[3]); + + blend_pixel(gp_pixel_rgba, src_pixel_rgba, gp_pixel_rgba); + + gp_pixel_rgba[3] = gp_pixel_rgba[3] > src_pixel_rgba[3] ? gp_pixel_rgba[3] : + src_pixel_rgba[3]; + } + } + } + } + else { + copy_v4_v4(gp_pixel_rgba, src_pixel_rgba); + gp_pixel_depth[0] = src_pixel_depth[0]; + } + } + + /* free memory */ + MEM_SAFE_FREE(src_rect_color_data); + MEM_SAFE_FREE(src_rect_depth_data); + } } diff --git a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c index a2632c47e7e..b133d9310b0 100644 --- a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c +++ b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c @@ -49,28 +49,25 @@ extern char datatoc_gpencil_fx_wave_frag_glsl[]; /* verify if this fx is active */ static bool effect_is_active(bGPdata *gpd, ShaderFxData *fx, bool is_render) { - if (fx == NULL) { - return false; - } - - if (gpd == NULL) { - return false; - } - - bool is_edit = GPENCIL_ANY_EDIT_MODE(gpd); - if (((fx->mode & eShaderFxMode_Editmode) == 0) && - (is_edit) && (!is_render)) - { - return false; - } - - if (((fx->mode & eShaderFxMode_Realtime) && (is_render == false)) || - ((fx->mode & eShaderFxMode_Render) && (is_render == true))) - { - return true; - } - - return false; + if (fx == NULL) { + return false; + } + + if (gpd == NULL) { + return false; + } + + bool is_edit = GPENCIL_ANY_EDIT_MODE(gpd); + if (((fx->mode & eShaderFxMode_Editmode) == 0) && (is_edit) && (!is_render)) { + return false; + } + + if (((fx->mode & eShaderFxMode_Realtime) && (is_render == false)) || + ((fx->mode & eShaderFxMode_Render) && (is_render == true))) { + return true; + } + + return false; } /** @@ -81,60 +78,60 @@ static bool effect_is_active(bGPdata *gpd, ShaderFxData *fx, bool is_render) */ static bool get_normal_vector(bGPdata *gpd, float r_point[3], float r_normal[3]) { - for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { - if (gpl->flag & GP_LAYER_HIDE) { - continue; - } - - /* get frame */ - bGPDframe *gpf = gpl->actframe; - if (gpf == NULL) { - continue; - } - for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { - if (gps->totpoints >= 3) { - bGPDspoint *pt = &gps->points[0]; - BKE_gpencil_stroke_normal(gps, r_normal); - /* in some weird situations, the normal cannot be calculated, so try next stroke */ - if ((r_normal[0] != 0.0f) || (r_normal[1] != 0.0f) || (r_normal[2] != 0.0f)) { - copy_v3_v3(r_point, &pt->x); - return true; - } - } - } - } - - return false; + for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { + if (gpl->flag & GP_LAYER_HIDE) { + continue; + } + + /* get frame */ + bGPDframe *gpf = gpl->actframe; + if (gpf == NULL) { + continue; + } + for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { + if (gps->totpoints >= 3) { + bGPDspoint *pt = &gps->points[0]; + BKE_gpencil_stroke_normal(gps, r_normal); + /* in some weird situations, the normal cannot be calculated, so try next stroke */ + if ((r_normal[0] != 0.0f) || (r_normal[1] != 0.0f) || (r_normal[2] != 0.0f)) { + copy_v3_v3(r_point, &pt->x); + return true; + } + } + } + } + + return false; } /* helper to get near and far depth of field values */ static void GPENCIL_dof_nearfar(Object *camera, float coc, float nearfar[2]) { - if (camera == NULL) { - return; - } - - const DRWContextState *draw_ctx = DRW_context_state_get(); - Scene *scene = draw_ctx->scene; - Camera *cam = (Camera *)camera->data; - - float fstop = cam->gpu_dof.fstop; - float focus_dist = BKE_camera_object_dof_distance(camera); - float focal_len = cam->lens; - - /* this is factor that converts to the scene scale. focal length and sensor are expressed in mm - * unit.scale_length is how many meters per blender unit we have. We want to convert to blender units though - * because the shader reads coordinates in world space, which is in blender units. - * Note however that focus_distance is already in blender units and shall not be scaled here (see T48157). */ - float scale = (scene->unit.system) ? scene->unit.scale_length : 1.0f; - float scale_camera = 0.001f / scale; - /* we want radius here for the aperture number */ - float aperture_scaled = 0.5f * scale_camera * focal_len / fstop; - float focal_len_scaled = scale_camera * focal_len; - - float hyperfocal = (focal_len_scaled * focal_len_scaled) / (aperture_scaled * coc); - nearfar[0] = (hyperfocal * focus_dist) / (hyperfocal + focal_len); - nearfar[1] = (hyperfocal * focus_dist) / (hyperfocal - focal_len); + if (camera == NULL) { + return; + } + + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene = draw_ctx->scene; + Camera *cam = (Camera *)camera->data; + + float fstop = cam->gpu_dof.fstop; + float focus_dist = BKE_camera_object_dof_distance(camera); + float focal_len = cam->lens; + + /* this is factor that converts to the scene scale. focal length and sensor are expressed in mm + * unit.scale_length is how many meters per blender unit we have. We want to convert to blender units though + * because the shader reads coordinates in world space, which is in blender units. + * Note however that focus_distance is already in blender units and shall not be scaled here (see T48157). */ + float scale = (scene->unit.system) ? scene->unit.scale_length : 1.0f; + float scale_camera = 0.001f / scale; + /* we want radius here for the aperture number */ + float aperture_scaled = 0.5f * scale_camera * focal_len / fstop; + float focal_len_scaled = scale_camera * focal_len; + + float hyperfocal = (focal_len_scaled * focal_len_scaled) / (aperture_scaled * coc); + nearfar[0] = (hyperfocal * focus_dist) / (hyperfocal + focal_len); + nearfar[1] = (hyperfocal * focus_dist) / (hyperfocal - focal_len); } /* **************** Shader Effects ***************************** */ @@ -143,514 +140,499 @@ static void GPENCIL_dof_nearfar(Object *camera, float coc, float nearfar[2]) * The effect is done using two shading groups because is faster to apply horizontal * and vertical in different operations. */ -static void DRW_gpencil_fx_blur( - ShaderFxData *fx, int ob_idx, GPENCIL_e_data *e_data, - GPENCIL_Data *vedata, tGPencilObjectCache *cache) +static void DRW_gpencil_fx_blur(ShaderFxData *fx, + int ob_idx, + GPENCIL_e_data *e_data, + GPENCIL_Data *vedata, + tGPencilObjectCache *cache) { - if (fx == NULL) { - return; - } - - BlurShaderFxData *fxd = (BlurShaderFxData *)fx; - - GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; - GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; - const DRWContextState *draw_ctx = DRW_context_state_get(); - View3D *v3d = draw_ctx->v3d; - RegionView3D *rv3d = draw_ctx->rv3d; - DRWShadingGroup *fx_shgrp; - bGPdata *gpd = cache->gpd; - copy_v3_v3(fxd->runtime.loc, cache->loc); - - fxd->blur[0] = fxd->radius[0]; - fxd->blur[1] = fxd->radius[1]; - - /* init weight */ - if (fxd->flag & FX_BLUR_DOF_MODE) { - /* viewport and opengl render */ - Object *camera = NULL; - if (rv3d) { - if (rv3d->persp == RV3D_CAMOB) { - camera = v3d->camera; - } - } - else { - camera = stl->storage->camera; - } - - if (camera) { - float nearfar[2]; - GPENCIL_dof_nearfar(camera, fxd->coc, nearfar); - float zdepth = stl->g_data->gp_object_cache[ob_idx].zdepth; - /* the object is on focus area */ - if ((zdepth >= nearfar[0]) && (zdepth <= nearfar[1])) { - fxd->blur[0] = 0; - fxd->blur[1] = 0; - } - else { - float f; - if (zdepth < nearfar[0]) { - f = nearfar[0] - zdepth; - } - else { - f = zdepth - nearfar[1]; - } - fxd->blur[0] = f; - fxd->blur[1] = f; - CLAMP2(&fxd->blur[0], 0, fxd->radius[0]); - } - } - else { - /* if not camera view, the blur is disabled */ - fxd->blur[0] = 0; - fxd->blur[1] = 0; - } - } - - GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); - - fx_shgrp = DRW_shgroup_create( - e_data->gpencil_fx_blur_sh, - psl->fx_shader_pass_blend); - DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); - DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); - DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); - DRW_shgroup_uniform_vec2(fx_shgrp, "Viewport", DRW_viewport_size_get(), 1); - DRW_shgroup_uniform_int(fx_shgrp, "blur", &fxd->blur[0], 2); - - DRW_shgroup_uniform_vec3(fx_shgrp, "loc", fxd->runtime.loc, 1); - DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1); - DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &gpd->pixfactor, 1); - - fxd->runtime.fx_sh = fx_shgrp; + if (fx == NULL) { + return; + } + + BlurShaderFxData *fxd = (BlurShaderFxData *)fx; + + GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; + GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + View3D *v3d = draw_ctx->v3d; + RegionView3D *rv3d = draw_ctx->rv3d; + DRWShadingGroup *fx_shgrp; + bGPdata *gpd = cache->gpd; + copy_v3_v3(fxd->runtime.loc, cache->loc); + + fxd->blur[0] = fxd->radius[0]; + fxd->blur[1] = fxd->radius[1]; + + /* init weight */ + if (fxd->flag & FX_BLUR_DOF_MODE) { + /* viewport and opengl render */ + Object *camera = NULL; + if (rv3d) { + if (rv3d->persp == RV3D_CAMOB) { + camera = v3d->camera; + } + } + else { + camera = stl->storage->camera; + } + + if (camera) { + float nearfar[2]; + GPENCIL_dof_nearfar(camera, fxd->coc, nearfar); + float zdepth = stl->g_data->gp_object_cache[ob_idx].zdepth; + /* the object is on focus area */ + if ((zdepth >= nearfar[0]) && (zdepth <= nearfar[1])) { + fxd->blur[0] = 0; + fxd->blur[1] = 0; + } + else { + float f; + if (zdepth < nearfar[0]) { + f = nearfar[0] - zdepth; + } + else { + f = zdepth - nearfar[1]; + } + fxd->blur[0] = f; + fxd->blur[1] = f; + CLAMP2(&fxd->blur[0], 0, fxd->radius[0]); + } + } + else { + /* if not camera view, the blur is disabled */ + fxd->blur[0] = 0; + fxd->blur[1] = 0; + } + } + + GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); + + fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_blur_sh, psl->fx_shader_pass_blend); + DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); + DRW_shgroup_uniform_vec2(fx_shgrp, "Viewport", DRW_viewport_size_get(), 1); + DRW_shgroup_uniform_int(fx_shgrp, "blur", &fxd->blur[0], 2); + + DRW_shgroup_uniform_vec3(fx_shgrp, "loc", fxd->runtime.loc, 1); + DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1); + DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &gpd->pixfactor, 1); + + fxd->runtime.fx_sh = fx_shgrp; } /* Colorize FX */ -static void DRW_gpencil_fx_colorize( - ShaderFxData *fx, GPENCIL_e_data *e_data, GPENCIL_Data *vedata) +static void DRW_gpencil_fx_colorize(ShaderFxData *fx, GPENCIL_e_data *e_data, GPENCIL_Data *vedata) { - if (fx == NULL) { - return; - } - ColorizeShaderFxData *fxd = (ColorizeShaderFxData *)fx; - GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; - DRWShadingGroup *fx_shgrp; - - GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); - fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_colorize_sh, psl->fx_shader_pass); - DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); - DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); - DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); - DRW_shgroup_uniform_vec4(fx_shgrp, "low_color", &fxd->low_color[0], 1); - DRW_shgroup_uniform_vec4(fx_shgrp, "high_color", &fxd->high_color[0], 1); - DRW_shgroup_uniform_int(fx_shgrp, "mode", &fxd->mode, 1); - DRW_shgroup_uniform_float(fx_shgrp, "factor", &fxd->factor, 1); - - fxd->runtime.fx_sh = fx_shgrp; + if (fx == NULL) { + return; + } + ColorizeShaderFxData *fxd = (ColorizeShaderFxData *)fx; + GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; + DRWShadingGroup *fx_shgrp; + + GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); + fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_colorize_sh, psl->fx_shader_pass); + DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); + DRW_shgroup_uniform_vec4(fx_shgrp, "low_color", &fxd->low_color[0], 1); + DRW_shgroup_uniform_vec4(fx_shgrp, "high_color", &fxd->high_color[0], 1); + DRW_shgroup_uniform_int(fx_shgrp, "mode", &fxd->mode, 1); + DRW_shgroup_uniform_float(fx_shgrp, "factor", &fxd->factor, 1); + + fxd->runtime.fx_sh = fx_shgrp; } /* Flip FX */ -static void DRW_gpencil_fx_flip( - ShaderFxData *fx, GPENCIL_e_data *e_data, GPENCIL_Data *vedata) +static void DRW_gpencil_fx_flip(ShaderFxData *fx, GPENCIL_e_data *e_data, GPENCIL_Data *vedata) { - if (fx == NULL) { - return; - } - FlipShaderFxData *fxd = (FlipShaderFxData *)fx; - GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; - DRWShadingGroup *fx_shgrp; - - fxd->flipmode = 100; - /* the number works as bit flag */ - if (fxd->flag & FX_FLIP_HORIZONTAL) { - fxd->flipmode += 10; - } - if (fxd->flag & FX_FLIP_VERTICAL) { - fxd->flipmode += 1; - } - - GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); - fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_flip_sh, psl->fx_shader_pass); - DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); - DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); - DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); - DRW_shgroup_uniform_int(fx_shgrp, "flipmode", &fxd->flipmode, 1); - - DRW_shgroup_uniform_vec2(fx_shgrp, "wsize", DRW_viewport_size_get(), 1); - - fxd->runtime.fx_sh = fx_shgrp; + if (fx == NULL) { + return; + } + FlipShaderFxData *fxd = (FlipShaderFxData *)fx; + GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; + DRWShadingGroup *fx_shgrp; + + fxd->flipmode = 100; + /* the number works as bit flag */ + if (fxd->flag & FX_FLIP_HORIZONTAL) { + fxd->flipmode += 10; + } + if (fxd->flag & FX_FLIP_VERTICAL) { + fxd->flipmode += 1; + } + + GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); + fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_flip_sh, psl->fx_shader_pass); + DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); + DRW_shgroup_uniform_int(fx_shgrp, "flipmode", &fxd->flipmode, 1); + + DRW_shgroup_uniform_vec2(fx_shgrp, "wsize", DRW_viewport_size_get(), 1); + + fxd->runtime.fx_sh = fx_shgrp; } /* Light FX */ -static void DRW_gpencil_fx_light( - ShaderFxData *fx, GPENCIL_e_data *e_data, GPENCIL_Data *vedata, - tGPencilObjectCache *cache) +static void DRW_gpencil_fx_light(ShaderFxData *fx, + GPENCIL_e_data *e_data, + GPENCIL_Data *vedata, + tGPencilObjectCache *cache) { - if (fx == NULL) { - return; - } - LightShaderFxData *fxd = (LightShaderFxData *)fx; - - if (fxd->object == NULL) { - return; - } - GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; - GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; - DRWShadingGroup *fx_shgrp; - - GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); - fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_light_sh, psl->fx_shader_pass); - DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); - DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); - DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); - - DRW_shgroup_uniform_vec2(fx_shgrp, "Viewport", DRW_viewport_size_get(), 1); - - /* location of the light using obj location as origin */ - copy_v3_v3(fxd->loc, fxd->object->obmat[3]); - - /* Calc distance to strokes plane - * The w component of location is used to transfer the distance to drawing plane - */ - float r_point[3], r_normal[3]; - float r_plane[4]; - bGPdata *gpd = cache->gpd; - if (!get_normal_vector(gpd, r_point, r_normal)) { - return; - } - mul_mat3_m4_v3(cache->obmat, r_normal); /* only rotation component */ - plane_from_point_normal_v3(r_plane, r_point, r_normal); - float dt = dist_to_plane_v3(fxd->object->obmat[3], r_plane); - fxd->loc[3] = dt; /* use last element to save it */ - - DRW_shgroup_uniform_vec4(fx_shgrp, "loc", &fxd->loc[0], 1); - - DRW_shgroup_uniform_float(fx_shgrp, "energy", &fxd->energy, 1); - DRW_shgroup_uniform_float(fx_shgrp, "ambient", &fxd->ambient, 1); - - DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1); - DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &gpd->pixfactor, 1); - - fxd->runtime.fx_sh = fx_shgrp; + if (fx == NULL) { + return; + } + LightShaderFxData *fxd = (LightShaderFxData *)fx; + + if (fxd->object == NULL) { + return; + } + GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; + GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; + DRWShadingGroup *fx_shgrp; + + GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); + fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_light_sh, psl->fx_shader_pass); + DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); + + DRW_shgroup_uniform_vec2(fx_shgrp, "Viewport", DRW_viewport_size_get(), 1); + + /* location of the light using obj location as origin */ + copy_v3_v3(fxd->loc, fxd->object->obmat[3]); + + /* Calc distance to strokes plane + * The w component of location is used to transfer the distance to drawing plane + */ + float r_point[3], r_normal[3]; + float r_plane[4]; + bGPdata *gpd = cache->gpd; + if (!get_normal_vector(gpd, r_point, r_normal)) { + return; + } + mul_mat3_m4_v3(cache->obmat, r_normal); /* only rotation component */ + plane_from_point_normal_v3(r_plane, r_point, r_normal); + float dt = dist_to_plane_v3(fxd->object->obmat[3], r_plane); + fxd->loc[3] = dt; /* use last element to save it */ + + DRW_shgroup_uniform_vec4(fx_shgrp, "loc", &fxd->loc[0], 1); + + DRW_shgroup_uniform_float(fx_shgrp, "energy", &fxd->energy, 1); + DRW_shgroup_uniform_float(fx_shgrp, "ambient", &fxd->ambient, 1); + + DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1); + DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &gpd->pixfactor, 1); + + fxd->runtime.fx_sh = fx_shgrp; } /* Pixelate FX */ -static void DRW_gpencil_fx_pixel( - ShaderFxData *fx, GPENCIL_e_data *e_data, GPENCIL_Data *vedata, - tGPencilObjectCache *cache) +static void DRW_gpencil_fx_pixel(ShaderFxData *fx, + GPENCIL_e_data *e_data, + GPENCIL_Data *vedata, + tGPencilObjectCache *cache) { - if (fx == NULL) { - return; - } - PixelShaderFxData *fxd = (PixelShaderFxData *)fx; - - GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; - GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; - DRWShadingGroup *fx_shgrp; - bGPdata *gpd = cache->gpd; - copy_v3_v3(fxd->runtime.loc, cache->loc); - - fxd->size[2] = (int)fxd->flag & FX_PIXEL_USE_LINES; - - GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); - fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_pixel_sh, psl->fx_shader_pass); - DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); - DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); - DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); - DRW_shgroup_uniform_int(fx_shgrp, "size", &fxd->size[0], 3); - DRW_shgroup_uniform_vec4(fx_shgrp, "color", &fxd->rgba[0], 1); - - DRW_shgroup_uniform_vec3(fx_shgrp, "loc", fxd->runtime.loc, 1); - DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1); - DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &gpd->pixfactor, 1); - - fxd->runtime.fx_sh = fx_shgrp; + if (fx == NULL) { + return; + } + PixelShaderFxData *fxd = (PixelShaderFxData *)fx; + + GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; + GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; + DRWShadingGroup *fx_shgrp; + bGPdata *gpd = cache->gpd; + copy_v3_v3(fxd->runtime.loc, cache->loc); + + fxd->size[2] = (int)fxd->flag & FX_PIXEL_USE_LINES; + + GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); + fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_pixel_sh, psl->fx_shader_pass); + DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); + DRW_shgroup_uniform_int(fx_shgrp, "size", &fxd->size[0], 3); + DRW_shgroup_uniform_vec4(fx_shgrp, "color", &fxd->rgba[0], 1); + + DRW_shgroup_uniform_vec3(fx_shgrp, "loc", fxd->runtime.loc, 1); + DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1); + DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &gpd->pixfactor, 1); + + fxd->runtime.fx_sh = fx_shgrp; } /* Rim FX */ -static void DRW_gpencil_fx_rim( - ShaderFxData *fx, GPENCIL_e_data *e_data, GPENCIL_Data *vedata, - tGPencilObjectCache *cache) +static void DRW_gpencil_fx_rim(ShaderFxData *fx, + GPENCIL_e_data *e_data, + GPENCIL_Data *vedata, + tGPencilObjectCache *cache) { - if (fx == NULL) { - return; - } - RimShaderFxData *fxd = (RimShaderFxData *)fx; - bGPdata *gpd = cache->gpd; - - GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; - GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; - DRWShadingGroup *fx_shgrp; - - GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); - copy_v3_v3(fxd->runtime.loc, cache->loc); - - /* prepare pass */ - fx_shgrp = DRW_shgroup_create( - e_data->gpencil_fx_rim_prepare_sh, - psl->fx_shader_pass_blend); - DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); - DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); - DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); - DRW_shgroup_uniform_vec2(fx_shgrp, "Viewport", DRW_viewport_size_get(), 1); - - DRW_shgroup_uniform_int(fx_shgrp, "offset", &fxd->offset[0], 2); - DRW_shgroup_uniform_vec3(fx_shgrp, "rim_color", &fxd->rim_rgb[0], 1); - DRW_shgroup_uniform_vec3(fx_shgrp, "mask_color", &fxd->mask_rgb[0], 1); - - DRW_shgroup_uniform_vec3(fx_shgrp, "loc", fxd->runtime.loc, 1); - DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1); - DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &gpd->pixfactor, 1); - - fxd->runtime.fx_sh = fx_shgrp; - - /* blur pass */ - fx_shgrp = DRW_shgroup_create( - e_data->gpencil_fx_blur_sh, - psl->fx_shader_pass_blend); - DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); - DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_fx); - DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_fx); - DRW_shgroup_uniform_vec2(fx_shgrp, "Viewport", DRW_viewport_size_get(), 1); - DRW_shgroup_uniform_int(fx_shgrp, "blur", &fxd->blur[0], 2); - - DRW_shgroup_uniform_vec3(fx_shgrp, "loc", fxd->runtime.loc, 1); - DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1); - DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &gpd->pixfactor, 1); - - fxd->runtime.fx_sh_b = fx_shgrp; - - /* resolve pass */ - fx_shgrp = DRW_shgroup_create( - e_data->gpencil_fx_rim_resolve_sh, - psl->fx_shader_pass_blend); - DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); - DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); - DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); - DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeRim", &e_data->temp_color_tx_fx); - DRW_shgroup_uniform_vec3(fx_shgrp, "mask_color", &fxd->mask_rgb[0], 1); - DRW_shgroup_uniform_int(fx_shgrp, "mode", &fxd->mode, 1); - - fxd->runtime.fx_sh_c = fx_shgrp; + if (fx == NULL) { + return; + } + RimShaderFxData *fxd = (RimShaderFxData *)fx; + bGPdata *gpd = cache->gpd; + + GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; + GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; + DRWShadingGroup *fx_shgrp; + + GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); + copy_v3_v3(fxd->runtime.loc, cache->loc); + + /* prepare pass */ + fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_rim_prepare_sh, psl->fx_shader_pass_blend); + DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); + DRW_shgroup_uniform_vec2(fx_shgrp, "Viewport", DRW_viewport_size_get(), 1); + + DRW_shgroup_uniform_int(fx_shgrp, "offset", &fxd->offset[0], 2); + DRW_shgroup_uniform_vec3(fx_shgrp, "rim_color", &fxd->rim_rgb[0], 1); + DRW_shgroup_uniform_vec3(fx_shgrp, "mask_color", &fxd->mask_rgb[0], 1); + + DRW_shgroup_uniform_vec3(fx_shgrp, "loc", fxd->runtime.loc, 1); + DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1); + DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &gpd->pixfactor, 1); + + fxd->runtime.fx_sh = fx_shgrp; + + /* blur pass */ + fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_blur_sh, psl->fx_shader_pass_blend); + DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_fx); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_fx); + DRW_shgroup_uniform_vec2(fx_shgrp, "Viewport", DRW_viewport_size_get(), 1); + DRW_shgroup_uniform_int(fx_shgrp, "blur", &fxd->blur[0], 2); + + DRW_shgroup_uniform_vec3(fx_shgrp, "loc", fxd->runtime.loc, 1); + DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1); + DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &gpd->pixfactor, 1); + + fxd->runtime.fx_sh_b = fx_shgrp; + + /* resolve pass */ + fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_rim_resolve_sh, psl->fx_shader_pass_blend); + DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeRim", &e_data->temp_color_tx_fx); + DRW_shgroup_uniform_vec3(fx_shgrp, "mask_color", &fxd->mask_rgb[0], 1); + DRW_shgroup_uniform_int(fx_shgrp, "mode", &fxd->mode, 1); + + fxd->runtime.fx_sh_c = fx_shgrp; } /* Shadow FX */ -static void DRW_gpencil_fx_shadow( - ShaderFxData *fx, GPENCIL_e_data *e_data, GPENCIL_Data *vedata, - tGPencilObjectCache *cache) +static void DRW_gpencil_fx_shadow(ShaderFxData *fx, + GPENCIL_e_data *e_data, + GPENCIL_Data *vedata, + tGPencilObjectCache *cache) { - if (fx == NULL) { - return; - } - ShadowShaderFxData *fxd = (ShadowShaderFxData *)fx; - if ((!fxd->object) && (fxd->flag & FX_SHADOW_USE_OBJECT)) { - fxd->runtime.fx_sh = NULL; - fxd->runtime.fx_sh_b = NULL; - fxd->runtime.fx_sh_c = NULL; - return; - } - - GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; - GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; - DRWShadingGroup *fx_shgrp; - bGPdata *gpd = cache->gpd; - copy_v3_v3(fxd->runtime.loc, cache->loc); - - GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); - /* prepare pass */ - fx_shgrp = DRW_shgroup_create( - e_data->gpencil_fx_shadow_prepare_sh, - psl->fx_shader_pass_blend); - DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); - DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); - DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); - DRW_shgroup_uniform_vec2(fx_shgrp, "Viewport", DRW_viewport_size_get(), 1); - - DRW_shgroup_uniform_int(fx_shgrp, "offset", &fxd->offset[0], 2); - DRW_shgroup_uniform_float(fx_shgrp, "scale", &fxd->scale[0], 2); - DRW_shgroup_uniform_float(fx_shgrp, "rotation", &fxd->rotation, 1); - DRW_shgroup_uniform_vec4(fx_shgrp, "shadow_color", &fxd->shadow_rgba[0], 1); - - if ((fxd->object) && (fxd->flag & FX_SHADOW_USE_OBJECT)) { - DRW_shgroup_uniform_vec3(fx_shgrp, "loc", fxd->object->obmat[3], 1); - } - else { - DRW_shgroup_uniform_vec3(fx_shgrp, "loc", fxd->runtime.loc, 1); - } - - const int nowave = -1; - if (fxd->flag & FX_SHADOW_USE_WAVE) { - DRW_shgroup_uniform_int(fx_shgrp, "orientation", &fxd->orientation, 1); - } - else { - DRW_shgroup_uniform_int(fx_shgrp, "orientation", &nowave, 1); - } - DRW_shgroup_uniform_float(fx_shgrp, "amplitude", &fxd->amplitude, 1); - DRW_shgroup_uniform_float(fx_shgrp, "period", &fxd->period, 1); - DRW_shgroup_uniform_float(fx_shgrp, "phase", &fxd->phase, 1); - - DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1); - DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &gpd->pixfactor, 1); - - fxd->runtime.fx_sh = fx_shgrp; - - /* blur pass */ - fx_shgrp = DRW_shgroup_create( - e_data->gpencil_fx_blur_sh, - psl->fx_shader_pass_blend); - DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); - DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_fx); - DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_fx); - DRW_shgroup_uniform_vec2(fx_shgrp, "Viewport", DRW_viewport_size_get(), 1); - DRW_shgroup_uniform_int(fx_shgrp, "blur", &fxd->blur[0], 2); - - DRW_shgroup_uniform_vec3(fx_shgrp, "loc", fxd->runtime.loc, 1); - DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1); - DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &gpd->pixfactor, 1); - - fxd->runtime.fx_sh_b = fx_shgrp; - - /* resolve pass */ - fx_shgrp = DRW_shgroup_create( - e_data->gpencil_fx_shadow_resolve_sh, - psl->fx_shader_pass_blend); - DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); - DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); - DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); - DRW_shgroup_uniform_texture_ref(fx_shgrp, "shadowColor", &e_data->temp_color_tx_fx); - DRW_shgroup_uniform_texture_ref(fx_shgrp, "shadowDepth", &e_data->temp_depth_tx_fx); - - fxd->runtime.fx_sh_c = fx_shgrp; + if (fx == NULL) { + return; + } + ShadowShaderFxData *fxd = (ShadowShaderFxData *)fx; + if ((!fxd->object) && (fxd->flag & FX_SHADOW_USE_OBJECT)) { + fxd->runtime.fx_sh = NULL; + fxd->runtime.fx_sh_b = NULL; + fxd->runtime.fx_sh_c = NULL; + return; + } + + GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; + GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; + DRWShadingGroup *fx_shgrp; + bGPdata *gpd = cache->gpd; + copy_v3_v3(fxd->runtime.loc, cache->loc); + + GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); + /* prepare pass */ + fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_shadow_prepare_sh, psl->fx_shader_pass_blend); + DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); + DRW_shgroup_uniform_vec2(fx_shgrp, "Viewport", DRW_viewport_size_get(), 1); + + DRW_shgroup_uniform_int(fx_shgrp, "offset", &fxd->offset[0], 2); + DRW_shgroup_uniform_float(fx_shgrp, "scale", &fxd->scale[0], 2); + DRW_shgroup_uniform_float(fx_shgrp, "rotation", &fxd->rotation, 1); + DRW_shgroup_uniform_vec4(fx_shgrp, "shadow_color", &fxd->shadow_rgba[0], 1); + + if ((fxd->object) && (fxd->flag & FX_SHADOW_USE_OBJECT)) { + DRW_shgroup_uniform_vec3(fx_shgrp, "loc", fxd->object->obmat[3], 1); + } + else { + DRW_shgroup_uniform_vec3(fx_shgrp, "loc", fxd->runtime.loc, 1); + } + + const int nowave = -1; + if (fxd->flag & FX_SHADOW_USE_WAVE) { + DRW_shgroup_uniform_int(fx_shgrp, "orientation", &fxd->orientation, 1); + } + else { + DRW_shgroup_uniform_int(fx_shgrp, "orientation", &nowave, 1); + } + DRW_shgroup_uniform_float(fx_shgrp, "amplitude", &fxd->amplitude, 1); + DRW_shgroup_uniform_float(fx_shgrp, "period", &fxd->period, 1); + DRW_shgroup_uniform_float(fx_shgrp, "phase", &fxd->phase, 1); + + DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1); + DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &gpd->pixfactor, 1); + + fxd->runtime.fx_sh = fx_shgrp; + + /* blur pass */ + fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_blur_sh, psl->fx_shader_pass_blend); + DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_fx); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_fx); + DRW_shgroup_uniform_vec2(fx_shgrp, "Viewport", DRW_viewport_size_get(), 1); + DRW_shgroup_uniform_int(fx_shgrp, "blur", &fxd->blur[0], 2); + + DRW_shgroup_uniform_vec3(fx_shgrp, "loc", fxd->runtime.loc, 1); + DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1); + DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &gpd->pixfactor, 1); + + fxd->runtime.fx_sh_b = fx_shgrp; + + /* resolve pass */ + fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_shadow_resolve_sh, psl->fx_shader_pass_blend); + DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "shadowColor", &e_data->temp_color_tx_fx); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "shadowDepth", &e_data->temp_depth_tx_fx); + + fxd->runtime.fx_sh_c = fx_shgrp; } /* Glow FX */ -static void DRW_gpencil_fx_glow( - ShaderFxData *fx, GPENCIL_e_data *e_data, GPENCIL_Data *vedata, - tGPencilObjectCache *cache) +static void DRW_gpencil_fx_glow(ShaderFxData *fx, + GPENCIL_e_data *e_data, + GPENCIL_Data *vedata, + tGPencilObjectCache *cache) { - if (fx == NULL) { - return; - } - GlowShaderFxData *fxd = (GlowShaderFxData *)fx; - bGPdata *gpd = cache->gpd; - copy_v3_v3(fxd->runtime.loc, cache->loc); - - GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; - GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; - DRWShadingGroup *fx_shgrp; - - GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); - /* prepare pass */ - fx_shgrp = DRW_shgroup_create( - e_data->gpencil_fx_glow_prepare_sh, - psl->fx_shader_pass_blend); - DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); - DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); - DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); - - DRW_shgroup_uniform_vec3(fx_shgrp, "glow_color", &fxd->glow_color[0], 1); - DRW_shgroup_uniform_vec3(fx_shgrp, "select_color", &fxd->select_color[0], 1); - DRW_shgroup_uniform_int(fx_shgrp, "mode", &fxd->mode, 1); - DRW_shgroup_uniform_float(fx_shgrp, "threshold", &fxd->threshold, 1); - - fxd->runtime.fx_sh = fx_shgrp; - - /* blur pass */ - fx_shgrp = DRW_shgroup_create( - e_data->gpencil_fx_blur_sh, - psl->fx_shader_pass_blend); - DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); - DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_fx); - DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_fx); - DRW_shgroup_uniform_vec2(fx_shgrp, "Viewport", DRW_viewport_size_get(), 1); - DRW_shgroup_uniform_int(fx_shgrp, "blur", &fxd->blur[0], 2); - - DRW_shgroup_uniform_vec3(fx_shgrp, "loc", fxd->runtime.loc, 1); - DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1); - DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &gpd->pixfactor, 1); - - fxd->runtime.fx_sh_b = fx_shgrp; - - /* resolve pass */ - fx_shgrp = DRW_shgroup_create( - e_data->gpencil_fx_glow_resolve_sh, - psl->fx_shader_pass_blend); - DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); - DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); - DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); - DRW_shgroup_uniform_texture_ref(fx_shgrp, "glowColor", &e_data->temp_color_tx_fx); - DRW_shgroup_uniform_texture_ref(fx_shgrp, "glowDepth", &e_data->temp_depth_tx_fx); - - /* reuse field */ - DRW_shgroup_uniform_int(fx_shgrp, "alpha_mode", &fxd->blur[1], 1); - - fxd->runtime.fx_sh_c = fx_shgrp; + if (fx == NULL) { + return; + } + GlowShaderFxData *fxd = (GlowShaderFxData *)fx; + bGPdata *gpd = cache->gpd; + copy_v3_v3(fxd->runtime.loc, cache->loc); + + GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; + GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; + DRWShadingGroup *fx_shgrp; + + GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); + /* prepare pass */ + fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_glow_prepare_sh, psl->fx_shader_pass_blend); + DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); + + DRW_shgroup_uniform_vec3(fx_shgrp, "glow_color", &fxd->glow_color[0], 1); + DRW_shgroup_uniform_vec3(fx_shgrp, "select_color", &fxd->select_color[0], 1); + DRW_shgroup_uniform_int(fx_shgrp, "mode", &fxd->mode, 1); + DRW_shgroup_uniform_float(fx_shgrp, "threshold", &fxd->threshold, 1); + + fxd->runtime.fx_sh = fx_shgrp; + + /* blur pass */ + fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_blur_sh, psl->fx_shader_pass_blend); + DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_fx); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_fx); + DRW_shgroup_uniform_vec2(fx_shgrp, "Viewport", DRW_viewport_size_get(), 1); + DRW_shgroup_uniform_int(fx_shgrp, "blur", &fxd->blur[0], 2); + + DRW_shgroup_uniform_vec3(fx_shgrp, "loc", fxd->runtime.loc, 1); + DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1); + DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &gpd->pixfactor, 1); + + fxd->runtime.fx_sh_b = fx_shgrp; + + /* resolve pass */ + fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_glow_resolve_sh, psl->fx_shader_pass_blend); + DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "glowColor", &e_data->temp_color_tx_fx); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "glowDepth", &e_data->temp_depth_tx_fx); + + /* reuse field */ + DRW_shgroup_uniform_int(fx_shgrp, "alpha_mode", &fxd->blur[1], 1); + + fxd->runtime.fx_sh_c = fx_shgrp; } /* Swirl FX */ -static void DRW_gpencil_fx_swirl( - ShaderFxData *fx, GPENCIL_e_data *e_data, GPENCIL_Data *vedata, - tGPencilObjectCache *cache) +static void DRW_gpencil_fx_swirl(ShaderFxData *fx, + GPENCIL_e_data *e_data, + GPENCIL_Data *vedata, + tGPencilObjectCache *cache) { - if (fx == NULL) { - return; - } - SwirlShaderFxData *fxd = (SwirlShaderFxData *)fx; - if (fxd->object == NULL) { - return; - } + if (fx == NULL) { + return; + } + SwirlShaderFxData *fxd = (SwirlShaderFxData *)fx; + if (fxd->object == NULL) { + return; + } - GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; - GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; - DRWShadingGroup *fx_shgrp; - bGPdata *gpd = cache->gpd; + GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; + GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; + DRWShadingGroup *fx_shgrp; + bGPdata *gpd = cache->gpd; - fxd->transparent = (int)fxd->flag & FX_SWIRL_MAKE_TRANSPARENT; + fxd->transparent = (int)fxd->flag & FX_SWIRL_MAKE_TRANSPARENT; - GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); - fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_swirl_sh, psl->fx_shader_pass); - DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); - DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); - DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); + GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); + fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_swirl_sh, psl->fx_shader_pass); + DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); - DRW_shgroup_uniform_vec2(fx_shgrp, "Viewport", DRW_viewport_size_get(), 1); + DRW_shgroup_uniform_vec2(fx_shgrp, "Viewport", DRW_viewport_size_get(), 1); - DRW_shgroup_uniform_vec3(fx_shgrp, "loc", fxd->object->obmat[3], 1); + DRW_shgroup_uniform_vec3(fx_shgrp, "loc", fxd->object->obmat[3], 1); - DRW_shgroup_uniform_int(fx_shgrp, "radius", &fxd->radius, 1); - DRW_shgroup_uniform_float(fx_shgrp, "angle", &fxd->angle, 1); - DRW_shgroup_uniform_int(fx_shgrp, "transparent", &fxd->transparent, 1); + DRW_shgroup_uniform_int(fx_shgrp, "radius", &fxd->radius, 1); + DRW_shgroup_uniform_float(fx_shgrp, "angle", &fxd->angle, 1); + DRW_shgroup_uniform_int(fx_shgrp, "transparent", &fxd->transparent, 1); - DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1); - DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &gpd->pixfactor, 1); + DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1); + DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &gpd->pixfactor, 1); - fxd->runtime.fx_sh = fx_shgrp; + fxd->runtime.fx_sh = fx_shgrp; } /* Wave Distorsion FX */ -static void DRW_gpencil_fx_wave( - ShaderFxData *fx, GPENCIL_e_data *e_data, GPENCIL_Data *vedata) +static void DRW_gpencil_fx_wave(ShaderFxData *fx, GPENCIL_e_data *e_data, GPENCIL_Data *vedata) { - if (fx == NULL) { - return; - } - - WaveShaderFxData *fxd = (WaveShaderFxData *)fx; - - GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; - GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); - - DRWShadingGroup *fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_wave_sh, psl->fx_shader_pass); - DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); - DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); - DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); - DRW_shgroup_uniform_float(fx_shgrp, "amplitude", &fxd->amplitude, 1); - DRW_shgroup_uniform_float(fx_shgrp, "period", &fxd->period, 1); - DRW_shgroup_uniform_float(fx_shgrp, "phase", &fxd->phase, 1); - DRW_shgroup_uniform_int(fx_shgrp, "orientation", &fxd->orientation, 1); - DRW_shgroup_uniform_vec2(fx_shgrp, "wsize", DRW_viewport_size_get(), 1); - - fxd->runtime.fx_sh = fx_shgrp; + if (fx == NULL) { + return; + } + + WaveShaderFxData *fxd = (WaveShaderFxData *)fx; + + GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; + GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); + + DRWShadingGroup *fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_wave_sh, psl->fx_shader_pass); + DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); + DRW_shgroup_uniform_float(fx_shgrp, "amplitude", &fxd->amplitude, 1); + DRW_shgroup_uniform_float(fx_shgrp, "period", &fxd->period, 1); + DRW_shgroup_uniform_float(fx_shgrp, "phase", &fxd->phase, 1); + DRW_shgroup_uniform_int(fx_shgrp, "orientation", &fxd->orientation, 1); + DRW_shgroup_uniform_vec2(fx_shgrp, "wsize", DRW_viewport_size_get(), 1); + + fxd->runtime.fx_sh = fx_shgrp; } /* ************************************************************** */ @@ -658,484 +640,443 @@ static void DRW_gpencil_fx_wave( /* create all FX shaders */ void GPENCIL_create_fx_shaders(GPENCIL_e_data *e_data) { - /* fx shaders (all in screen space) */ - if (!e_data->gpencil_fx_blur_sh) { - e_data->gpencil_fx_blur_sh = DRW_shader_create_fullscreen( - datatoc_gpencil_fx_blur_frag_glsl, NULL); - } - if (!e_data->gpencil_fx_colorize_sh) { - e_data->gpencil_fx_colorize_sh = DRW_shader_create_fullscreen( - datatoc_gpencil_fx_colorize_frag_glsl, NULL); - } - if (!e_data->gpencil_fx_flip_sh) { - e_data->gpencil_fx_flip_sh = DRW_shader_create_fullscreen( - datatoc_gpencil_fx_flip_frag_glsl, NULL); - } - if (!e_data->gpencil_fx_light_sh) { - e_data->gpencil_fx_light_sh = DRW_shader_create_fullscreen( - datatoc_gpencil_fx_light_frag_glsl, NULL); - } - if (!e_data->gpencil_fx_pixel_sh) { - e_data->gpencil_fx_pixel_sh = DRW_shader_create_fullscreen( - datatoc_gpencil_fx_pixel_frag_glsl, NULL); - } - if (!e_data->gpencil_fx_rim_prepare_sh) { - e_data->gpencil_fx_rim_prepare_sh = DRW_shader_create_fullscreen( - datatoc_gpencil_fx_rim_prepare_frag_glsl, NULL); - - e_data->gpencil_fx_rim_resolve_sh = DRW_shader_create_fullscreen( - datatoc_gpencil_fx_rim_resolve_frag_glsl, NULL); - } - if (!e_data->gpencil_fx_shadow_prepare_sh) { - e_data->gpencil_fx_shadow_prepare_sh = DRW_shader_create_fullscreen( - datatoc_gpencil_fx_shadow_prepare_frag_glsl, NULL); - - e_data->gpencil_fx_shadow_resolve_sh = DRW_shader_create_fullscreen( - datatoc_gpencil_fx_shadow_resolve_frag_glsl, NULL); - } - if (!e_data->gpencil_fx_glow_prepare_sh) { - e_data->gpencil_fx_glow_prepare_sh = DRW_shader_create_fullscreen( - datatoc_gpencil_fx_glow_prepare_frag_glsl, NULL); - - e_data->gpencil_fx_glow_resolve_sh = DRW_shader_create_fullscreen( - datatoc_gpencil_fx_glow_resolve_frag_glsl, NULL); - } - if (!e_data->gpencil_fx_swirl_sh) { - e_data->gpencil_fx_swirl_sh = DRW_shader_create_fullscreen( - datatoc_gpencil_fx_swirl_frag_glsl, NULL); - } - if (!e_data->gpencil_fx_wave_sh) { - e_data->gpencil_fx_wave_sh = DRW_shader_create_fullscreen( - datatoc_gpencil_fx_wave_frag_glsl, NULL); - } + /* fx shaders (all in screen space) */ + if (!e_data->gpencil_fx_blur_sh) { + e_data->gpencil_fx_blur_sh = DRW_shader_create_fullscreen(datatoc_gpencil_fx_blur_frag_glsl, + NULL); + } + if (!e_data->gpencil_fx_colorize_sh) { + e_data->gpencil_fx_colorize_sh = DRW_shader_create_fullscreen( + datatoc_gpencil_fx_colorize_frag_glsl, NULL); + } + if (!e_data->gpencil_fx_flip_sh) { + e_data->gpencil_fx_flip_sh = DRW_shader_create_fullscreen(datatoc_gpencil_fx_flip_frag_glsl, + NULL); + } + if (!e_data->gpencil_fx_light_sh) { + e_data->gpencil_fx_light_sh = DRW_shader_create_fullscreen(datatoc_gpencil_fx_light_frag_glsl, + NULL); + } + if (!e_data->gpencil_fx_pixel_sh) { + e_data->gpencil_fx_pixel_sh = DRW_shader_create_fullscreen(datatoc_gpencil_fx_pixel_frag_glsl, + NULL); + } + if (!e_data->gpencil_fx_rim_prepare_sh) { + e_data->gpencil_fx_rim_prepare_sh = DRW_shader_create_fullscreen( + datatoc_gpencil_fx_rim_prepare_frag_glsl, NULL); + + e_data->gpencil_fx_rim_resolve_sh = DRW_shader_create_fullscreen( + datatoc_gpencil_fx_rim_resolve_frag_glsl, NULL); + } + if (!e_data->gpencil_fx_shadow_prepare_sh) { + e_data->gpencil_fx_shadow_prepare_sh = DRW_shader_create_fullscreen( + datatoc_gpencil_fx_shadow_prepare_frag_glsl, NULL); + + e_data->gpencil_fx_shadow_resolve_sh = DRW_shader_create_fullscreen( + datatoc_gpencil_fx_shadow_resolve_frag_glsl, NULL); + } + if (!e_data->gpencil_fx_glow_prepare_sh) { + e_data->gpencil_fx_glow_prepare_sh = DRW_shader_create_fullscreen( + datatoc_gpencil_fx_glow_prepare_frag_glsl, NULL); + + e_data->gpencil_fx_glow_resolve_sh = DRW_shader_create_fullscreen( + datatoc_gpencil_fx_glow_resolve_frag_glsl, NULL); + } + if (!e_data->gpencil_fx_swirl_sh) { + e_data->gpencil_fx_swirl_sh = DRW_shader_create_fullscreen(datatoc_gpencil_fx_swirl_frag_glsl, + NULL); + } + if (!e_data->gpencil_fx_wave_sh) { + e_data->gpencil_fx_wave_sh = DRW_shader_create_fullscreen(datatoc_gpencil_fx_wave_frag_glsl, + NULL); + } } /* free FX shaders */ void GPENCIL_delete_fx_shaders(GPENCIL_e_data *e_data) { - DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_blur_sh); - DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_colorize_sh); - DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_flip_sh); - DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_light_sh); - DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_pixel_sh); - DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_rim_prepare_sh); - DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_rim_resolve_sh); - DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_shadow_prepare_sh); - DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_shadow_resolve_sh); - DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_glow_prepare_sh); - DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_glow_resolve_sh); - DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_swirl_sh); - DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_wave_sh); + DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_blur_sh); + DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_colorize_sh); + DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_flip_sh); + DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_light_sh); + DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_pixel_sh); + DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_rim_prepare_sh); + DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_rim_resolve_sh); + DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_shadow_prepare_sh); + DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_shadow_resolve_sh); + DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_glow_prepare_sh); + DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_glow_resolve_sh); + DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_swirl_sh); + DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_wave_sh); } /* create all passes used by FX */ void GPENCIL_create_fx_passes(GPENCIL_PassList *psl) { - psl->fx_shader_pass = DRW_pass_create( - "GPencil Shader FX Pass", - DRW_STATE_WRITE_COLOR | - DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS); - psl->fx_shader_pass_blend = DRW_pass_create( - "GPencil Shader FX Pass", - DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND | - DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS); + psl->fx_shader_pass = DRW_pass_create("GPencil Shader FX Pass", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | + DRW_STATE_DEPTH_LESS); + psl->fx_shader_pass_blend = DRW_pass_create("GPencil Shader FX Pass", + DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND | + DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS); } - /* prepare fx shading groups */ -void DRW_gpencil_fx_prepare( - GPENCIL_e_data *e_data, GPENCIL_Data *vedata, - tGPencilObjectCache *cache_ob) +void DRW_gpencil_fx_prepare(GPENCIL_e_data *e_data, + GPENCIL_Data *vedata, + tGPencilObjectCache *cache_ob) { - GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; - const bool wiremode = (bool)(cache_ob->shading_type[0] == OB_WIRE); - - int ob_idx = cache_ob->idx; - - if ((wiremode) || (cache_ob->shader_fx.first == NULL)) { - return; - } - /* loop FX */ - for (ShaderFxData *fx = cache_ob->shader_fx.first; fx; fx = fx->next) { - if (effect_is_active(cache_ob->gpd, fx, stl->storage->is_render)) { - switch (fx->type) { - case eShaderFxType_Blur: - DRW_gpencil_fx_blur(fx, ob_idx, e_data, vedata, cache_ob); - break; - case eShaderFxType_Colorize: - DRW_gpencil_fx_colorize(fx, e_data, vedata); - break; - case eShaderFxType_Flip: - DRW_gpencil_fx_flip(fx, e_data, vedata); - break; - case eShaderFxType_Light: - DRW_gpencil_fx_light(fx, e_data, vedata, cache_ob); - break; - case eShaderFxType_Pixel: - DRW_gpencil_fx_pixel(fx, e_data, vedata, cache_ob); - break; - case eShaderFxType_Rim: - DRW_gpencil_fx_rim(fx, e_data, vedata, cache_ob); - break; - case eShaderFxType_Shadow: - DRW_gpencil_fx_shadow(fx, e_data, vedata, cache_ob); - break; - case eShaderFxType_Glow: - DRW_gpencil_fx_glow(fx, e_data, vedata, cache_ob); - break; - case eShaderFxType_Swirl: - DRW_gpencil_fx_swirl(fx, e_data, vedata, cache_ob); - break; - case eShaderFxType_Wave: - DRW_gpencil_fx_wave(fx, e_data, vedata); - break; - default: - break; - } - } - } - + GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; + const bool wiremode = (bool)(cache_ob->shading_type[0] == OB_WIRE); + + int ob_idx = cache_ob->idx; + + if ((wiremode) || (cache_ob->shader_fx.first == NULL)) { + return; + } + /* loop FX */ + for (ShaderFxData *fx = cache_ob->shader_fx.first; fx; fx = fx->next) { + if (effect_is_active(cache_ob->gpd, fx, stl->storage->is_render)) { + switch (fx->type) { + case eShaderFxType_Blur: + DRW_gpencil_fx_blur(fx, ob_idx, e_data, vedata, cache_ob); + break; + case eShaderFxType_Colorize: + DRW_gpencil_fx_colorize(fx, e_data, vedata); + break; + case eShaderFxType_Flip: + DRW_gpencil_fx_flip(fx, e_data, vedata); + break; + case eShaderFxType_Light: + DRW_gpencil_fx_light(fx, e_data, vedata, cache_ob); + break; + case eShaderFxType_Pixel: + DRW_gpencil_fx_pixel(fx, e_data, vedata, cache_ob); + break; + case eShaderFxType_Rim: + DRW_gpencil_fx_rim(fx, e_data, vedata, cache_ob); + break; + case eShaderFxType_Shadow: + DRW_gpencil_fx_shadow(fx, e_data, vedata, cache_ob); + break; + case eShaderFxType_Glow: + DRW_gpencil_fx_glow(fx, e_data, vedata, cache_ob); + break; + case eShaderFxType_Swirl: + DRW_gpencil_fx_swirl(fx, e_data, vedata, cache_ob); + break; + case eShaderFxType_Wave: + DRW_gpencil_fx_wave(fx, e_data, vedata); + break; + default: + break; + } + } + } } /* helper to draw one FX pass and do ping-pong copy */ -static void gpencil_draw_fx_pass( - GPENCIL_e_data *e_data, - GPENCIL_PassList *psl, - GPENCIL_FramebufferList *fbl, - DRWShadingGroup *shgrp, bool blend) +static void gpencil_draw_fx_pass(GPENCIL_e_data *e_data, + GPENCIL_PassList *psl, + GPENCIL_FramebufferList *fbl, + DRWShadingGroup *shgrp, + bool blend) { - if (shgrp == NULL) { - return; - } - - const float clearcol[4] = {0.0f}; - GPU_framebuffer_bind(fbl->temp_fb_b); - GPU_framebuffer_clear_color_depth(fbl->temp_fb_b, clearcol, 1.0f); - - /* draw effect pass in temp texture (B) using as source the previous image - * existing in the other temp texture (A) */ - if (!blend) { - DRW_draw_pass_subset(psl->fx_shader_pass, shgrp, shgrp); - } - else { - DRW_draw_pass_subset(psl->fx_shader_pass_blend, shgrp, shgrp); - } - - /* copy pass from b to a for ping-pong frame buffers */ - e_data->input_depth_tx = e_data->temp_depth_tx_b; - e_data->input_color_tx = e_data->temp_color_tx_b; - - GPU_framebuffer_bind(fbl->temp_fb_a); - GPU_framebuffer_clear_color_depth(fbl->temp_fb_a, clearcol, 1.0f); - DRW_draw_pass(psl->mix_pass_noblend); + if (shgrp == NULL) { + return; + } + + const float clearcol[4] = {0.0f}; + GPU_framebuffer_bind(fbl->temp_fb_b); + GPU_framebuffer_clear_color_depth(fbl->temp_fb_b, clearcol, 1.0f); + + /* draw effect pass in temp texture (B) using as source the previous image + * existing in the other temp texture (A) */ + if (!blend) { + DRW_draw_pass_subset(psl->fx_shader_pass, shgrp, shgrp); + } + else { + DRW_draw_pass_subset(psl->fx_shader_pass_blend, shgrp, shgrp); + } + + /* copy pass from b to a for ping-pong frame buffers */ + e_data->input_depth_tx = e_data->temp_depth_tx_b; + e_data->input_color_tx = e_data->temp_color_tx_b; + + GPU_framebuffer_bind(fbl->temp_fb_a); + GPU_framebuffer_clear_color_depth(fbl->temp_fb_a, clearcol, 1.0f); + DRW_draw_pass(psl->mix_pass_noblend); } /* helper to manage gaussian blur passes */ -static void draw_gpencil_blur_passes( - GPENCIL_e_data *e_data, - GPENCIL_Data *vedata, - BlurShaderFxData *fxd) +static void draw_gpencil_blur_passes(GPENCIL_e_data *e_data, + GPENCIL_Data *vedata, + BlurShaderFxData *fxd) { - if (fxd->runtime.fx_sh == NULL) { - return; - } - - GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; - GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl; - DRWShadingGroup *shgrp = fxd->runtime.fx_sh; - int samples = fxd->samples; - - float bx = fxd->blur[0]; - float by = fxd->blur[1]; - - /* the blur is done in two steps (Hor/Ver) because is faster and - * gets better result - * - * samples could be 0 and disable de blur effects because sometimes - * is easier animate the number of samples only, instead to animate the - * hide/unhide and the number of samples to make some effects. - */ - for (int b = 0; b < samples; b++) { - /* horizontal */ - if (bx > 0) { - fxd->blur[0] = bx; - fxd->blur[1] = 0; - gpencil_draw_fx_pass(e_data, psl, fbl, shgrp, true); - } - /* vertical */ - if (by > 0) { - fxd->blur[0] = 0; - fxd->blur[1] = by; - gpencil_draw_fx_pass(e_data, psl, fbl, shgrp, true); - } - } + if (fxd->runtime.fx_sh == NULL) { + return; + } + + GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; + GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl; + DRWShadingGroup *shgrp = fxd->runtime.fx_sh; + int samples = fxd->samples; + + float bx = fxd->blur[0]; + float by = fxd->blur[1]; + + /* the blur is done in two steps (Hor/Ver) because is faster and + * gets better result + * + * samples could be 0 and disable de blur effects because sometimes + * is easier animate the number of samples only, instead to animate the + * hide/unhide and the number of samples to make some effects. + */ + for (int b = 0; b < samples; b++) { + /* horizontal */ + if (bx > 0) { + fxd->blur[0] = bx; + fxd->blur[1] = 0; + gpencil_draw_fx_pass(e_data, psl, fbl, shgrp, true); + } + /* vertical */ + if (by > 0) { + fxd->blur[0] = 0; + fxd->blur[1] = by; + gpencil_draw_fx_pass(e_data, psl, fbl, shgrp, true); + } + } } /* blur intermediate pass */ -static void draw_gpencil_midpass_blur( - GPENCIL_Data *vedata, - ShaderFxData_Runtime *runtime) +static void draw_gpencil_midpass_blur(GPENCIL_Data *vedata, ShaderFxData_Runtime *runtime) { - GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; - GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl; - const float clearcol[4] = {0.0f}; - - GPU_framebuffer_bind(fbl->temp_fb_b); - GPU_framebuffer_clear_color_depth(fbl->temp_fb_b, clearcol, 1.0f); - DRW_draw_pass_subset( - psl->fx_shader_pass_blend, - runtime->fx_sh_b, runtime->fx_sh_b); - - /* copy pass from b for ping-pong frame buffers */ - GPU_framebuffer_bind(fbl->temp_fb_fx); - GPU_framebuffer_clear_color_depth(fbl->temp_fb_fx, clearcol, 1.0f); - DRW_draw_pass(psl->mix_pass_noblend); + GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; + GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl; + const float clearcol[4] = {0.0f}; + + GPU_framebuffer_bind(fbl->temp_fb_b); + GPU_framebuffer_clear_color_depth(fbl->temp_fb_b, clearcol, 1.0f); + DRW_draw_pass_subset(psl->fx_shader_pass_blend, runtime->fx_sh_b, runtime->fx_sh_b); + + /* copy pass from b for ping-pong frame buffers */ + GPU_framebuffer_bind(fbl->temp_fb_fx); + GPU_framebuffer_clear_color_depth(fbl->temp_fb_fx, clearcol, 1.0f); + DRW_draw_pass(psl->mix_pass_noblend); } /* do blur of mid passes */ -static void draw_gpencil_do_blur( - GPENCIL_e_data *e_data, - GPENCIL_Data *vedata, - ShaderFxData_Runtime *runtime, - int samples, int bx, int by, int blur[2]) +static void draw_gpencil_do_blur(GPENCIL_e_data *e_data, + GPENCIL_Data *vedata, + ShaderFxData_Runtime *runtime, + int samples, + int bx, + int by, + int blur[2]) { - e_data->input_depth_tx = e_data->temp_depth_tx_b; - e_data->input_color_tx = e_data->temp_color_tx_b; - - if ((samples > 0) && ((bx > 0) || (by > 0))) { - for (int x = 0; x < samples; x++) { - - /* horizontal */ - blur[0] = bx; - blur[1] = 0; - draw_gpencil_midpass_blur(vedata, runtime); - - /* Vertical */ - blur[0] = 0; - blur[1] = by; - draw_gpencil_midpass_blur(vedata, runtime); - - blur[0] = bx; - blur[1] = by; - } - } + e_data->input_depth_tx = e_data->temp_depth_tx_b; + e_data->input_color_tx = e_data->temp_color_tx_b; + + if ((samples > 0) && ((bx > 0) || (by > 0))) { + for (int x = 0; x < samples; x++) { + + /* horizontal */ + blur[0] = bx; + blur[1] = 0; + draw_gpencil_midpass_blur(vedata, runtime); + + /* Vertical */ + blur[0] = 0; + blur[1] = by; + draw_gpencil_midpass_blur(vedata, runtime); + + blur[0] = bx; + blur[1] = by; + } + } } /* helper to draw RIM passes */ -static void draw_gpencil_rim_passes( - GPENCIL_e_data *e_data, - GPENCIL_Data *vedata, - RimShaderFxData *fxd) +static void draw_gpencil_rim_passes(GPENCIL_e_data *e_data, + GPENCIL_Data *vedata, + RimShaderFxData *fxd) { - if (fxd->runtime.fx_sh_b == NULL) { - return; - } - - GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; - GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl; - - const float clearcol[4] = {0.0f}; - - /* prepare mask */ - GPU_framebuffer_bind(fbl->temp_fb_fx); - GPU_framebuffer_clear_color_depth(fbl->temp_fb_fx, clearcol, 1.0f); - DRW_draw_pass_subset( - psl->fx_shader_pass_blend, - fxd->runtime.fx_sh, fxd->runtime.fx_sh); - - /* blur rim */ - draw_gpencil_do_blur( - e_data, vedata, &fxd->runtime, - fxd->samples, - fxd->blur[0], fxd->blur[1], - &fxd->blur[0]); - - /* resolve */ - GPU_framebuffer_bind(fbl->temp_fb_b); - GPU_framebuffer_clear_color_depth(fbl->temp_fb_b, clearcol, 1.0f); - DRW_draw_pass_subset( - psl->fx_shader_pass_blend, - fxd->runtime.fx_sh_c, fxd->runtime.fx_sh_c); - - /* copy pass from b to a for ping-pong frame buffers */ - e_data->input_depth_tx = e_data->temp_depth_tx_b; - e_data->input_color_tx = e_data->temp_color_tx_b; - - GPU_framebuffer_bind(fbl->temp_fb_a); - GPU_framebuffer_clear_color_depth(fbl->temp_fb_a, clearcol, 1.0f); - DRW_draw_pass(psl->mix_pass_noblend); + if (fxd->runtime.fx_sh_b == NULL) { + return; + } + + GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; + GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl; + + const float clearcol[4] = {0.0f}; + + /* prepare mask */ + GPU_framebuffer_bind(fbl->temp_fb_fx); + GPU_framebuffer_clear_color_depth(fbl->temp_fb_fx, clearcol, 1.0f); + DRW_draw_pass_subset(psl->fx_shader_pass_blend, fxd->runtime.fx_sh, fxd->runtime.fx_sh); + + /* blur rim */ + draw_gpencil_do_blur( + e_data, vedata, &fxd->runtime, fxd->samples, fxd->blur[0], fxd->blur[1], &fxd->blur[0]); + + /* resolve */ + GPU_framebuffer_bind(fbl->temp_fb_b); + GPU_framebuffer_clear_color_depth(fbl->temp_fb_b, clearcol, 1.0f); + DRW_draw_pass_subset(psl->fx_shader_pass_blend, fxd->runtime.fx_sh_c, fxd->runtime.fx_sh_c); + + /* copy pass from b to a for ping-pong frame buffers */ + e_data->input_depth_tx = e_data->temp_depth_tx_b; + e_data->input_color_tx = e_data->temp_color_tx_b; + + GPU_framebuffer_bind(fbl->temp_fb_a); + GPU_framebuffer_clear_color_depth(fbl->temp_fb_a, clearcol, 1.0f); + DRW_draw_pass(psl->mix_pass_noblend); } /* helper to draw SHADOW passes */ -static void draw_gpencil_shadow_passes( - GPENCIL_e_data *e_data, - GPENCIL_Data *vedata, - ShadowShaderFxData *fxd) +static void draw_gpencil_shadow_passes(GPENCIL_e_data *e_data, + GPENCIL_Data *vedata, + ShadowShaderFxData *fxd) { - if (fxd->runtime.fx_sh_b == NULL) { - return; - } - - GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; - GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl; - const float clearcol[4] = {0.0f}; - - /* prepare shadow */ - GPU_framebuffer_bind(fbl->temp_fb_fx); - GPU_framebuffer_clear_color_depth(fbl->temp_fb_fx, clearcol, 1.0f); - DRW_draw_pass_subset( - psl->fx_shader_pass_blend, - fxd->runtime.fx_sh, fxd->runtime.fx_sh); - - /* blur shadow */ - draw_gpencil_do_blur( - e_data, vedata, &fxd->runtime, - fxd->samples, - fxd->blur[0], fxd->blur[1], - &fxd->blur[0]); - - /* resolve */ - GPU_framebuffer_bind(fbl->temp_fb_b); - GPU_framebuffer_clear_color_depth(fbl->temp_fb_b, clearcol, 1.0f); - DRW_draw_pass_subset( - psl->fx_shader_pass_blend, - fxd->runtime.fx_sh_c, fxd->runtime.fx_sh_c); - - /* copy pass from b to a for ping-pong frame buffers */ - e_data->input_depth_tx = e_data->temp_depth_tx_b; - e_data->input_color_tx = e_data->temp_color_tx_b; - - GPU_framebuffer_bind(fbl->temp_fb_a); - GPU_framebuffer_clear_color_depth(fbl->temp_fb_a, clearcol, 1.0f); - DRW_draw_pass(psl->mix_pass_noblend); + if (fxd->runtime.fx_sh_b == NULL) { + return; + } + + GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; + GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl; + const float clearcol[4] = {0.0f}; + + /* prepare shadow */ + GPU_framebuffer_bind(fbl->temp_fb_fx); + GPU_framebuffer_clear_color_depth(fbl->temp_fb_fx, clearcol, 1.0f); + DRW_draw_pass_subset(psl->fx_shader_pass_blend, fxd->runtime.fx_sh, fxd->runtime.fx_sh); + + /* blur shadow */ + draw_gpencil_do_blur( + e_data, vedata, &fxd->runtime, fxd->samples, fxd->blur[0], fxd->blur[1], &fxd->blur[0]); + + /* resolve */ + GPU_framebuffer_bind(fbl->temp_fb_b); + GPU_framebuffer_clear_color_depth(fbl->temp_fb_b, clearcol, 1.0f); + DRW_draw_pass_subset(psl->fx_shader_pass_blend, fxd->runtime.fx_sh_c, fxd->runtime.fx_sh_c); + + /* copy pass from b to a for ping-pong frame buffers */ + e_data->input_depth_tx = e_data->temp_depth_tx_b; + e_data->input_color_tx = e_data->temp_color_tx_b; + + GPU_framebuffer_bind(fbl->temp_fb_a); + GPU_framebuffer_clear_color_depth(fbl->temp_fb_a, clearcol, 1.0f); + DRW_draw_pass(psl->mix_pass_noblend); } /* helper to draw GLOW passes */ -static void draw_gpencil_glow_passes( - GPENCIL_e_data *e_data, - GPENCIL_Data *vedata, - GlowShaderFxData *fxd) +static void draw_gpencil_glow_passes(GPENCIL_e_data *e_data, + GPENCIL_Data *vedata, + GlowShaderFxData *fxd) { - if (fxd->runtime.fx_sh_b == NULL) { - return; - } - - GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; - GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl; - - const float clearcol[4] = {0.0f}; - - /* prepare glow */ - GPU_framebuffer_bind(fbl->temp_fb_fx); - GPU_framebuffer_clear_color_depth(fbl->temp_fb_fx, clearcol, 1.0f); - DRW_draw_pass_subset( - psl->fx_shader_pass_blend, - fxd->runtime.fx_sh, fxd->runtime.fx_sh); - - /* blur glow */ - draw_gpencil_do_blur( - e_data, vedata, &fxd->runtime, - fxd->samples, - fxd->blur[0], fxd->blur[0], - &fxd->blur[0]); - - /* resolve */ - GPU_framebuffer_bind(fbl->temp_fb_b); - GPU_framebuffer_clear_color_depth(fbl->temp_fb_b, clearcol, 1.0f); - - /* reuses blur field to keep alpha mode */ - fxd->blur[1] = (fxd->flag & FX_GLOW_USE_ALPHA) ? 1 : 0; - - DRW_draw_pass_subset( - psl->fx_shader_pass_blend, - fxd->runtime.fx_sh_c, fxd->runtime.fx_sh_c); - - /* copy pass from b to a for ping-pong frame buffers */ - e_data->input_depth_tx = e_data->temp_depth_tx_b; - e_data->input_color_tx = e_data->temp_color_tx_b; - - GPU_framebuffer_bind(fbl->temp_fb_a); - GPU_framebuffer_clear_color_depth(fbl->temp_fb_a, clearcol, 1.0f); - DRW_draw_pass(psl->mix_pass_noblend); + if (fxd->runtime.fx_sh_b == NULL) { + return; + } + + GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; + GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl; + + const float clearcol[4] = {0.0f}; + + /* prepare glow */ + GPU_framebuffer_bind(fbl->temp_fb_fx); + GPU_framebuffer_clear_color_depth(fbl->temp_fb_fx, clearcol, 1.0f); + DRW_draw_pass_subset(psl->fx_shader_pass_blend, fxd->runtime.fx_sh, fxd->runtime.fx_sh); + + /* blur glow */ + draw_gpencil_do_blur( + e_data, vedata, &fxd->runtime, fxd->samples, fxd->blur[0], fxd->blur[0], &fxd->blur[0]); + + /* resolve */ + GPU_framebuffer_bind(fbl->temp_fb_b); + GPU_framebuffer_clear_color_depth(fbl->temp_fb_b, clearcol, 1.0f); + + /* reuses blur field to keep alpha mode */ + fxd->blur[1] = (fxd->flag & FX_GLOW_USE_ALPHA) ? 1 : 0; + + DRW_draw_pass_subset(psl->fx_shader_pass_blend, fxd->runtime.fx_sh_c, fxd->runtime.fx_sh_c); + + /* copy pass from b to a for ping-pong frame buffers */ + e_data->input_depth_tx = e_data->temp_depth_tx_b; + e_data->input_color_tx = e_data->temp_color_tx_b; + + GPU_framebuffer_bind(fbl->temp_fb_a); + GPU_framebuffer_clear_color_depth(fbl->temp_fb_a, clearcol, 1.0f); + DRW_draw_pass(psl->mix_pass_noblend); } /* apply all object fx effects */ -void DRW_gpencil_fx_draw( - GPENCIL_e_data *e_data, - GPENCIL_Data *vedata, tGPencilObjectCache *cache_ob) +void DRW_gpencil_fx_draw(GPENCIL_e_data *e_data, + GPENCIL_Data *vedata, + tGPencilObjectCache *cache_ob) { - GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; - GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; - GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl; - - /* loop FX modifiers */ - for (ShaderFxData *fx = cache_ob->shader_fx.first; fx; fx = fx->next) { - if (effect_is_active(cache_ob->gpd, fx, stl->storage->is_render)) { - switch (fx->type) { - - case eShaderFxType_Blur: - { - BlurShaderFxData *fxd = (BlurShaderFxData *)fx; - draw_gpencil_blur_passes(e_data, vedata, fxd); - break; - } - case eShaderFxType_Colorize: - { - ColorizeShaderFxData *fxd = (ColorizeShaderFxData *)fx; - gpencil_draw_fx_pass(e_data, psl, fbl, fxd->runtime.fx_sh, false); - break; - } - case eShaderFxType_Flip: - { - FlipShaderFxData *fxd = (FlipShaderFxData *)fx; - gpencil_draw_fx_pass(e_data, psl, fbl, fxd->runtime.fx_sh, false); - break; - } - case eShaderFxType_Light: - { - LightShaderFxData *fxd = (LightShaderFxData *)fx; - gpencil_draw_fx_pass(e_data, psl, fbl, fxd->runtime.fx_sh, false); - break; - } - case eShaderFxType_Pixel: - { - PixelShaderFxData *fxd = (PixelShaderFxData *)fx; - gpencil_draw_fx_pass(e_data, psl, fbl, fxd->runtime.fx_sh, false); - break; - } - case eShaderFxType_Rim: - { - RimShaderFxData *fxd = (RimShaderFxData *)fx; - draw_gpencil_rim_passes(e_data, vedata, fxd); - break; - } - case eShaderFxType_Shadow: - { - ShadowShaderFxData *fxd = (ShadowShaderFxData *)fx; - draw_gpencil_shadow_passes(e_data, vedata, fxd); - break; - } - case eShaderFxType_Glow: - { - GlowShaderFxData *fxd = (GlowShaderFxData *)fx; - draw_gpencil_glow_passes(e_data, vedata, fxd); - break; - } - case eShaderFxType_Swirl: - { - SwirlShaderFxData *fxd = (SwirlShaderFxData *)fx; - gpencil_draw_fx_pass(e_data, psl, fbl, fxd->runtime.fx_sh, false); - break; - } - case eShaderFxType_Wave: - { - WaveShaderFxData *fxd = (WaveShaderFxData *)fx; - gpencil_draw_fx_pass(e_data, psl, fbl, fxd->runtime.fx_sh, false); - break; - } - default: - break; - } - } - } + GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; + GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; + GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl; + + /* loop FX modifiers */ + for (ShaderFxData *fx = cache_ob->shader_fx.first; fx; fx = fx->next) { + if (effect_is_active(cache_ob->gpd, fx, stl->storage->is_render)) { + switch (fx->type) { + + case eShaderFxType_Blur: { + BlurShaderFxData *fxd = (BlurShaderFxData *)fx; + draw_gpencil_blur_passes(e_data, vedata, fxd); + break; + } + case eShaderFxType_Colorize: { + ColorizeShaderFxData *fxd = (ColorizeShaderFxData *)fx; + gpencil_draw_fx_pass(e_data, psl, fbl, fxd->runtime.fx_sh, false); + break; + } + case eShaderFxType_Flip: { + FlipShaderFxData *fxd = (FlipShaderFxData *)fx; + gpencil_draw_fx_pass(e_data, psl, fbl, fxd->runtime.fx_sh, false); + break; + } + case eShaderFxType_Light: { + LightShaderFxData *fxd = (LightShaderFxData *)fx; + gpencil_draw_fx_pass(e_data, psl, fbl, fxd->runtime.fx_sh, false); + break; + } + case eShaderFxType_Pixel: { + PixelShaderFxData *fxd = (PixelShaderFxData *)fx; + gpencil_draw_fx_pass(e_data, psl, fbl, fxd->runtime.fx_sh, false); + break; + } + case eShaderFxType_Rim: { + RimShaderFxData *fxd = (RimShaderFxData *)fx; + draw_gpencil_rim_passes(e_data, vedata, fxd); + break; + } + case eShaderFxType_Shadow: { + ShadowShaderFxData *fxd = (ShadowShaderFxData *)fx; + draw_gpencil_shadow_passes(e_data, vedata, fxd); + break; + } + case eShaderFxType_Glow: { + GlowShaderFxData *fxd = (GlowShaderFxData *)fx; + draw_gpencil_glow_passes(e_data, vedata, fxd); + break; + } + case eShaderFxType_Swirl: { + SwirlShaderFxData *fxd = (SwirlShaderFxData *)fx; + gpencil_draw_fx_pass(e_data, psl, fbl, fxd->runtime.fx_sh, false); + break; + } + case eShaderFxType_Wave: { + WaveShaderFxData *fxd = (WaveShaderFxData *)fx; + gpencil_draw_fx_pass(e_data, psl, fbl, fxd->runtime.fx_sh, false); + break; + } + default: + break; + } + } + } } diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_blur_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_blur_frag.glsl index cd348a477a1..0f64f54c67b 100644 --- a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_blur_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_blur_frag.glsl @@ -8,7 +8,7 @@ uniform vec2 Viewport; uniform int blur[2]; uniform vec3 loc; -uniform float pixsize; /* rv3d->pixsize */ +uniform float pixsize; /* rv3d->pixsize */ uniform float pixfactor; float defaultpixsize = pixsize * (1000.0 / pixfactor); @@ -18,66 +18,68 @@ out vec4 FragColor; float get_zdepth(ivec2 poxy) { - /* if outside viewport set as infinite depth */ - if ((poxy.x < 0) || (poxy.x > Viewport.x)) { - return 1.0f; - } - if ((poxy.y < 0) || (poxy.y > Viewport.y)) { - return 1.0f; - } - - float zdepth = texelFetch(strokeDepth, poxy, 0).r; - return zdepth; + /* if outside viewport set as infinite depth */ + if ((poxy.x < 0) || (poxy.x > Viewport.x)) { + return 1.0f; + } + if ((poxy.y < 0) || (poxy.y > Viewport.y)) { + return 1.0f; + } + + float zdepth = texelFetch(strokeDepth, poxy, 0).r; + return zdepth; } void main() { - ivec2 uv = ivec2(gl_FragCoord.xy); - - vec4 nloc = ProjectionMatrix * ViewMatrix * vec4(loc.xyz, 1.0); - - float dx = (ProjectionMatrix[3][3] == 0.0) ? (noffset[0] / (nloc.z * defaultpixsize)) : (noffset[0] / defaultpixsize); - float dy = (ProjectionMatrix[3][3] == 0.0) ? (noffset[1] / (nloc.z * defaultpixsize)) : (noffset[1] / defaultpixsize); - - /* round to avoid shift when add more samples */ - dx = floor(dx) + 1.0; - dy = floor(dy) + 1.0; - - /* apply blurring, using a 9-tap filter with predefined gaussian weights */ - /* depth (get the value of the surrounding pixels) */ - float outdepth = get_zdepth(ivec2(uv.x, uv.y)); - for (int x = -1; x < 2; x++) { - for (int y = -1; y < 2; y++) { - float depth = get_zdepth(ivec2(uv.x + x * dx, uv.y + y * dy)); - if (depth < outdepth) { - outdepth = depth; - break; - } - } - } - gl_FragDepth = outdepth; - - /* color */ - vec4 outcolor = vec4(0.0); - outcolor += texelFetch(strokeColor, ivec2(uv.x - 1.0 * dx, uv.y + 1.0 * dy), 0) * 0.0947416; - outcolor += texelFetch(strokeColor, ivec2(uv.x - 0.0 * dx, uv.y + 1.0 * dy), 0) * 0.118318; - outcolor += texelFetch(strokeColor, ivec2(uv.x + 1.0 * dx, uv.y + 1.0 * dy), 0) * 0.0947416; - outcolor += texelFetch(strokeColor, ivec2(uv.x - 1.0 * dx, uv.y + 0.0 * dy), 0) * 0.118318; - - outcolor += texelFetch(strokeColor, ivec2(uv.x, uv.y), 0) * 0.147761; - - outcolor += texelFetch(strokeColor, ivec2(uv.x + 1.0 * dx, uv.y + 0.0 * dy), 0) * 0.118318; - outcolor += texelFetch(strokeColor, ivec2(uv.x - 1.0 * dx, uv.y - 1.0 * dy), 0) * 0.0947416; - outcolor += texelFetch(strokeColor, ivec2(uv.x + 0.0 * dx, uv.y - 1.0 * dy), 0) * 0.118318; - outcolor += texelFetch(strokeColor, ivec2(uv.x + 1.0 * dx, uv.y - 1.0 * dy), 0) * 0.0947416; - - FragColor = clamp(outcolor, 0, 1.0); - - /* discar extreme values */ - if (outcolor.a < 0.02f) { - discard; - } - if ((outdepth <= 0.000001) || (outdepth >= 0.999999)){ - discard; - } + ivec2 uv = ivec2(gl_FragCoord.xy); + + vec4 nloc = ProjectionMatrix * ViewMatrix * vec4(loc.xyz, 1.0); + + float dx = (ProjectionMatrix[3][3] == 0.0) ? (noffset[0] / (nloc.z * defaultpixsize)) : + (noffset[0] / defaultpixsize); + float dy = (ProjectionMatrix[3][3] == 0.0) ? (noffset[1] / (nloc.z * defaultpixsize)) : + (noffset[1] / defaultpixsize); + + /* round to avoid shift when add more samples */ + dx = floor(dx) + 1.0; + dy = floor(dy) + 1.0; + + /* apply blurring, using a 9-tap filter with predefined gaussian weights */ + /* depth (get the value of the surrounding pixels) */ + float outdepth = get_zdepth(ivec2(uv.x, uv.y)); + for (int x = -1; x < 2; x++) { + for (int y = -1; y < 2; y++) { + float depth = get_zdepth(ivec2(uv.x + x * dx, uv.y + y * dy)); + if (depth < outdepth) { + outdepth = depth; + break; + } + } + } + gl_FragDepth = outdepth; + + /* color */ + vec4 outcolor = vec4(0.0); + outcolor += texelFetch(strokeColor, ivec2(uv.x - 1.0 * dx, uv.y + 1.0 * dy), 0) * 0.0947416; + outcolor += texelFetch(strokeColor, ivec2(uv.x - 0.0 * dx, uv.y + 1.0 * dy), 0) * 0.118318; + outcolor += texelFetch(strokeColor, ivec2(uv.x + 1.0 * dx, uv.y + 1.0 * dy), 0) * 0.0947416; + outcolor += texelFetch(strokeColor, ivec2(uv.x - 1.0 * dx, uv.y + 0.0 * dy), 0) * 0.118318; + + outcolor += texelFetch(strokeColor, ivec2(uv.x, uv.y), 0) * 0.147761; + + outcolor += texelFetch(strokeColor, ivec2(uv.x + 1.0 * dx, uv.y + 0.0 * dy), 0) * 0.118318; + outcolor += texelFetch(strokeColor, ivec2(uv.x - 1.0 * dx, uv.y - 1.0 * dy), 0) * 0.0947416; + outcolor += texelFetch(strokeColor, ivec2(uv.x + 0.0 * dx, uv.y - 1.0 * dy), 0) * 0.118318; + outcolor += texelFetch(strokeColor, ivec2(uv.x + 1.0 * dx, uv.y - 1.0 * dy), 0) * 0.0947416; + + FragColor = clamp(outcolor, 0, 1.0); + + /* discar extreme values */ + if (outcolor.a < 0.02f) { + discard; + } + if ((outdepth <= 0.000001) || (outdepth >= 0.999999)) { + discard; + } } diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_colorize_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_colorize_frag.glsl index fb44b18cc86..52f42d30d06 100644 --- a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_colorize_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_colorize_frag.glsl @@ -8,79 +8,75 @@ uniform float factor; out vec4 FragColor; -#define MODE_GRAYSCALE 0 -#define MODE_SEPIA 1 -#define MODE_DUOTONE 2 -#define MODE_CUSTOM 3 +#define MODE_GRAYSCALE 0 +#define MODE_SEPIA 1 +#define MODE_DUOTONE 2 +#define MODE_CUSTOM 3 #define MODE_TRANSPARENT 4 float get_luminance(vec4 color) { - float lum = (color.r * 0.2126) + (color.g * 0.7152) + (color.b * 0.723); - return lum; + float lum = (color.r * 0.2126) + (color.g * 0.7152) + (color.b * 0.723); + return lum; } void main() { - ivec2 uv = ivec2(gl_FragCoord.xy); + ivec2 uv = ivec2(gl_FragCoord.xy); - float stroke_depth = texelFetch(strokeDepth, uv.xy, 0).r; - vec4 src_pixel= texelFetch(strokeColor, uv.xy, 0); - float luminance = get_luminance(src_pixel); - vec4 outcolor; + float stroke_depth = texelFetch(strokeDepth, uv.xy, 0).r; + vec4 src_pixel = texelFetch(strokeColor, uv.xy, 0); + float luminance = get_luminance(src_pixel); + vec4 outcolor; - /* is transparent */ - if (src_pixel.a == 0.0f) { - discard; - } + /* is transparent */ + if (src_pixel.a == 0.0f) { + discard; + } - switch(mode) { - case MODE_GRAYSCALE: - { - outcolor = vec4(luminance, luminance, luminance, src_pixel.a); - break; - } - case MODE_SEPIA: - { - float Red = (src_pixel.r * 0.393) + (src_pixel.g * 0.769) + (src_pixel.b * 0.189); - float Green = (src_pixel.r * 0.349) + (src_pixel.g * 0.686) + (src_pixel.b * 0.168); - float Blue = (src_pixel.r * 0.272) + (src_pixel.g * 0.534) + (src_pixel.b * 0.131); - outcolor = vec4(Red, Green, Blue, src_pixel.a); - break; - } - case MODE_DUOTONE: - { - if (luminance <= factor) { - outcolor = low_color; - } - else { - outcolor = high_color; - } - break; - } - case MODE_CUSTOM: - { - /* if below umbral, force custom color */ - if (luminance <= factor) { - outcolor = low_color; - } - else { - outcolor = vec4(luminance * low_color.r, luminance * low_color.b, luminance * low_color.b, src_pixel.a); - } - break; - } - case MODE_TRANSPARENT: - { - outcolor = vec4(src_pixel.rgb, src_pixel.a * factor); - break; - } - default: - { - outcolor = src_pixel; - } + switch (mode) { + case MODE_GRAYSCALE: { + outcolor = vec4(luminance, luminance, luminance, src_pixel.a); + break; + } + case MODE_SEPIA: { + float Red = (src_pixel.r * 0.393) + (src_pixel.g * 0.769) + (src_pixel.b * 0.189); + float Green = (src_pixel.r * 0.349) + (src_pixel.g * 0.686) + (src_pixel.b * 0.168); + float Blue = (src_pixel.r * 0.272) + (src_pixel.g * 0.534) + (src_pixel.b * 0.131); + outcolor = vec4(Red, Green, Blue, src_pixel.a); + break; + } + case MODE_DUOTONE: { + if (luminance <= factor) { + outcolor = low_color; + } + else { + outcolor = high_color; + } + break; + } + case MODE_CUSTOM: { + /* if below umbral, force custom color */ + if (luminance <= factor) { + outcolor = low_color; + } + else { + outcolor = vec4(luminance * low_color.r, + luminance * low_color.b, + luminance * low_color.b, + src_pixel.a); + } + break; + } + case MODE_TRANSPARENT: { + outcolor = vec4(src_pixel.rgb, src_pixel.a * factor); + break; + } + default: { + outcolor = src_pixel; + } + } - } - - gl_FragDepth = stroke_depth; - FragColor = outcolor; + gl_FragDepth = stroke_depth; + FragColor = outcolor; } diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_flip_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_flip_frag.glsl index 43589461cd1..2cd77007b36 100644 --- a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_flip_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_flip_frag.glsl @@ -7,31 +7,31 @@ uniform int flipmode; void main() { - vec2 mode = vec2(0,0); - /* horz. */ - if (flipmode >= 110) { - mode[0] = 1; - } - /* vert. */ - if ((flipmode == 101) || (flipmode == 111)) { - mode[1] = 1; - } + vec2 mode = vec2(0, 0); + /* horz. */ + if (flipmode >= 110) { + mode[0] = 1; + } + /* vert. */ + if ((flipmode == 101) || (flipmode == 111)) { + mode[1] = 1; + } - vec2 uv = vec2(gl_FragCoord.xy); - float stroke_depth; - vec4 outcolor; + vec2 uv = vec2(gl_FragCoord.xy); + float stroke_depth; + vec4 outcolor; - if (mode[0] > 0) { - uv.x = wsize.x - uv.x; - } - if (mode[1] > 0) { - uv.y = wsize.y - uv.y; - } + if (mode[0] > 0) { + uv.x = wsize.x - uv.x; + } + if (mode[1] > 0) { + uv.y = wsize.y - uv.y; + } - ivec2 iuv = ivec2(uv.x, uv.y); - stroke_depth = texelFetch(strokeDepth, iuv, 0).r; - outcolor = texelFetch(strokeColor, iuv, 0); + ivec2 iuv = ivec2(uv.x, uv.y); + stroke_depth = texelFetch(strokeDepth, iuv, 0).r; + outcolor = texelFetch(strokeColor, iuv, 0); - gl_FragDepth = stroke_depth; - FragColor = outcolor; + gl_FragDepth = stroke_depth; + FragColor = outcolor; } diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_glow_prepare_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_glow_prepare_frag.glsl index 9cdcad3e486..676b9b05db9 100644 --- a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_glow_prepare_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_glow_prepare_frag.glsl @@ -14,55 +14,55 @@ uniform int mode; out vec4 FragColor; -#define MODE_LUMINANCE 0 -#define MODE_COLOR 1 +#define MODE_LUMINANCE 0 +#define MODE_COLOR 1 /* calc luminance */ -float luma( vec3 color ) { - /* the color is linear, so do not apply tonemapping */ - return (color.r + color.g + color.b) / 3.0; +float luma(vec3 color) +{ + /* the color is linear, so do not apply tonemapping */ + return (color.r + color.g + color.b) / 3.0; } bool check_color(vec3 color_a, vec3 color_b) { - /* need round the number to avoid precision errors */ - if ((floor(color_a.r * 100) == floor(color_b.r * 100)) && - (floor(color_a.g * 100) == floor(color_b.g * 100)) && - (floor(color_a.b * 100) == floor(color_b.b * 100))) - { - return true; - } + /* need round the number to avoid precision errors */ + if ((floor(color_a.r * 100) == floor(color_b.r * 100)) && + (floor(color_a.g * 100) == floor(color_b.g * 100)) && + (floor(color_a.b * 100) == floor(color_b.b * 100))) { + return true; + } - return false; + return false; } void main() { - vec2 uv = vec2(gl_FragCoord.xy); + vec2 uv = vec2(gl_FragCoord.xy); - float stroke_depth = texelFetch(strokeDepth, ivec2(uv.xy), 0).r; - vec4 src_pixel= texelFetch(strokeColor, ivec2(uv.xy), 0); - vec4 outcolor; + float stroke_depth = texelFetch(strokeDepth, ivec2(uv.xy), 0).r; + vec4 src_pixel = texelFetch(strokeColor, ivec2(uv.xy), 0); + vec4 outcolor; - /* is transparent */ - if (src_pixel.a == 0.0f) { - discard; - } + /* is transparent */ + if (src_pixel.a == 0.0f) { + discard; + } - if (mode == MODE_LUMINANCE) { - if (luma(src_pixel.rgb) < threshold) { - discard; - } - } - else if (mode == MODE_COLOR) { - if (!check_color(src_pixel.rgb, select_color.rgb)) { - discard; - } - } - else { - discard; - } + if (mode == MODE_LUMINANCE) { + if (luma(src_pixel.rgb) < threshold) { + discard; + } + } + else if (mode == MODE_COLOR) { + if (!check_color(src_pixel.rgb, select_color.rgb)) { + discard; + } + } + else { + discard; + } - gl_FragDepth = stroke_depth; - FragColor = vec4(glow_color.rgb, 1.0); + gl_FragDepth = stroke_depth; + FragColor = vec4(glow_color.rgb, 1.0); } diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_glow_resolve_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_glow_resolve_frag.glsl index 5bff7a20523..e2aceb9eefe 100644 --- a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_glow_resolve_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_glow_resolve_frag.glsl @@ -11,36 +11,36 @@ out vec4 FragColor; void main() { - vec4 outcolor; - ivec2 uv = ivec2(gl_FragCoord.xy); + vec4 outcolor; + ivec2 uv = ivec2(gl_FragCoord.xy); - float stroke_depth = texelFetch(strokeDepth, uv.xy, 0).r; - vec4 src_pixel= texelFetch(strokeColor, uv.xy, 0); - vec4 glow_pixel= texelFetch(glowColor, uv.xy, 0); - float glow_depth = texelFetch(glowDepth, uv.xy, 0).r; + float stroke_depth = texelFetch(strokeDepth, uv.xy, 0).r; + vec4 src_pixel = texelFetch(strokeColor, uv.xy, 0); + vec4 glow_pixel = texelFetch(glowColor, uv.xy, 0); + float glow_depth = texelFetch(glowDepth, uv.xy, 0).r; - if (alpha_mode == 0) { - outcolor = src_pixel + glow_pixel; - } - else { - if ((src_pixel.a < 0.1) || (glow_pixel.a < 0.1)) { - outcolor = src_pixel + glow_pixel; - } - else { - outcolor = src_pixel; - } - } + if (alpha_mode == 0) { + outcolor = src_pixel + glow_pixel; + } + else { + if ((src_pixel.a < 0.1) || (glow_pixel.a < 0.1)) { + outcolor = src_pixel + glow_pixel; + } + else { + outcolor = src_pixel; + } + } - if (src_pixel.a < glow_pixel.a) { - gl_FragDepth = glow_depth; - } - else { - gl_FragDepth = stroke_depth; - } + if (src_pixel.a < glow_pixel.a) { + gl_FragDepth = glow_depth; + } + else { + gl_FragDepth = stroke_depth; + } - if (outcolor.a < 0.001) { - discard; - } + if (outcolor.a < 0.001) { + discard; + } - FragColor = outcolor; + FragColor = outcolor; } diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_light_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_light_frag.glsl index c12dd223ebe..a5c321c20c1 100644 --- a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_light_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_light_frag.glsl @@ -8,62 +8,63 @@ uniform vec4 loc; uniform float energy; uniform float ambient; -uniform float pixsize; /* rv3d->pixsize */ +uniform float pixsize; /* rv3d->pixsize */ uniform float pixfactor; out vec4 FragColor; float defaultpixsize = pixsize * (1000.0 / pixfactor); -#define height loc.w +#define height loc.w /* project 3d point to 2d on screen space */ vec2 toScreenSpace(vec4 vertex) { - /* need to calculate ndc because this is not done by vertex shader */ - vec3 ndc = vec3(vertex).xyz / vertex.w; + /* need to calculate ndc because this is not done by vertex shader */ + vec3 ndc = vec3(vertex).xyz / vertex.w; - vec2 sc; - sc.x = ((ndc.x + 1.0) / 2.0) * Viewport.x; - sc.y = ((ndc.y + 1.0) / 2.0) * Viewport.y; + vec2 sc; + sc.x = ((ndc.x + 1.0) / 2.0) * Viewport.x; + sc.y = ((ndc.y + 1.0) / 2.0) * Viewport.y; - return sc; + return sc; } void main() { - float stroke_depth; - vec4 objcolor; + float stroke_depth; + vec4 objcolor; - vec4 light_loc = ProjectionMatrix * ViewMatrix * vec4(loc.xyz, 1.0); - vec2 light2d = toScreenSpace(light_loc); + vec4 light_loc = ProjectionMatrix * ViewMatrix * vec4(loc.xyz, 1.0); + vec2 light2d = toScreenSpace(light_loc); - /* calc pixel scale */ - float pxscale = (ProjectionMatrix[3][3] == 0.0) ? (10.0 / (light_loc.z * defaultpixsize)) : (10.0 / defaultpixsize); - pxscale = max(pxscale, 0.000001); + /* calc pixel scale */ + float pxscale = (ProjectionMatrix[3][3] == 0.0) ? (10.0 / (light_loc.z * defaultpixsize)) : + (10.0 / defaultpixsize); + pxscale = max(pxscale, 0.000001); - /* the height over plane is received in the w component of the loc - * and needs a factor to adapt to pixels - */ - float peak = height * 10.0 * pxscale; - vec3 light3d = vec3(light2d.x, light2d.y, peak); + /* the height over plane is received in the w component of the loc + * and needs a factor to adapt to pixels + */ + float peak = height * 10.0 * pxscale; + vec3 light3d = vec3(light2d.x, light2d.y, peak); - vec2 uv = vec2(gl_FragCoord.xy); - vec3 frag_loc = vec3(uv.x, uv.y, 0); - vec3 norm = vec3(0, 0, 1.0); /* always z-up */ + vec2 uv = vec2(gl_FragCoord.xy); + vec3 frag_loc = vec3(uv.x, uv.y, 0); + vec3 norm = vec3(0, 0, 1.0); /* always z-up */ - ivec2 iuv = ivec2(uv.x, uv.y); - stroke_depth = texelFetch(strokeDepth, iuv, 0).r; - objcolor = texelFetch(strokeColor, iuv, 0); + ivec2 iuv = ivec2(uv.x, uv.y); + stroke_depth = texelFetch(strokeDepth, iuv, 0).r; + objcolor = texelFetch(strokeColor, iuv, 0); - /* diffuse light */ - vec3 lightdir = normalize(light3d - frag_loc); - float diff = max(dot(norm, lightdir), 0.0); - float dist = length(light3d - frag_loc) / pxscale; - float factor = diff * ((energy * 100.0) / (dist * dist)); + /* diffuse light */ + vec3 lightdir = normalize(light3d - frag_loc); + float diff = max(dot(norm, lightdir), 0.0); + float dist = length(light3d - frag_loc) / pxscale; + float factor = diff * ((energy * 100.0) / (dist * dist)); - vec3 result = factor * max(ambient, 0.1) * vec3(objcolor); + vec3 result = factor * max(ambient, 0.1) * vec3(objcolor); - gl_FragDepth = stroke_depth; - FragColor = vec4(result.r, result.g, result.b, objcolor.a); + gl_FragDepth = stroke_depth; + FragColor = vec4(result.r, result.g, result.b, objcolor.a); } diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_pixel_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_pixel_frag.glsl index eb5596c639a..46b3c4286b4 100644 --- a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_pixel_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_pixel_frag.glsl @@ -8,7 +8,7 @@ uniform int size[3]; uniform vec4 color; uniform vec3 loc; -uniform float pixsize; /* rv3d->pixsize */ +uniform float pixsize; /* rv3d->pixsize */ uniform float pixfactor; out vec4 FragColor; @@ -20,30 +20,32 @@ vec2 nsize = max(vec2(size[0], size[1]), 3.0); /* This pixelation shader is a modified version of original Geeks3d.com code */ void main() { - vec2 uv = vec2(gl_FragCoord.xy); - vec4 nloc = ProjectionMatrix * ViewMatrix * vec4(loc.xyz, 1.0); - - float dx = (ProjectionMatrix[3][3] == 0.0) ? (nsize[0] / (nloc.z * defaultpixsize)) : (nsize[0] / defaultpixsize); - float dy = (ProjectionMatrix[3][3] == 0.0) ? (nsize[1] / (nloc.z * defaultpixsize)) : (nsize[1] / defaultpixsize); - - dx = max(abs(dx), 3.0); - dy = max(abs(dy), 3.0); - - vec2 coord = vec2(dx * floor(uv.x / dx), dy * floor(uv.y / dy)); - - float stroke_depth = texelFetch(strokeDepth, ivec2(coord), 0).r; - vec4 outcolor = texelFetch(strokeColor, ivec2(coord), 0); - - if (uselines == 1) { - float difx = uv.x - (floor(uv.x / nsize[0]) * nsize[0]); - if ((difx == 0.5) && (outcolor.a > 0)) { - outcolor = color; - } - float dify = uv.y - (floor(uv.y / nsize[1]) * nsize[1]); - if ((dify == 0.5) && (outcolor.a > 0)) { - outcolor = color; - } - } - gl_FragDepth = stroke_depth; - FragColor = outcolor; + vec2 uv = vec2(gl_FragCoord.xy); + vec4 nloc = ProjectionMatrix * ViewMatrix * vec4(loc.xyz, 1.0); + + float dx = (ProjectionMatrix[3][3] == 0.0) ? (nsize[0] / (nloc.z * defaultpixsize)) : + (nsize[0] / defaultpixsize); + float dy = (ProjectionMatrix[3][3] == 0.0) ? (nsize[1] / (nloc.z * defaultpixsize)) : + (nsize[1] / defaultpixsize); + + dx = max(abs(dx), 3.0); + dy = max(abs(dy), 3.0); + + vec2 coord = vec2(dx * floor(uv.x / dx), dy * floor(uv.y / dy)); + + float stroke_depth = texelFetch(strokeDepth, ivec2(coord), 0).r; + vec4 outcolor = texelFetch(strokeColor, ivec2(coord), 0); + + if (uselines == 1) { + float difx = uv.x - (floor(uv.x / nsize[0]) * nsize[0]); + if ((difx == 0.5) && (outcolor.a > 0)) { + outcolor = color; + } + float dify = uv.y - (floor(uv.y / nsize[1]) * nsize[1]); + if ((dify == 0.5) && (outcolor.a > 0)) { + outcolor = color; + } + } + gl_FragDepth = stroke_depth; + FragColor = outcolor; } diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_rim_prepare_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_rim_prepare_frag.glsl index 2321429fbf1..2a17e573978 100644 --- a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_rim_prepare_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_rim_prepare_frag.glsl @@ -13,7 +13,7 @@ uniform vec3 rim_color; uniform vec3 mask_color; uniform vec3 loc; -uniform float pixsize; /* rv3d->pixsize */ +uniform float pixsize; /* rv3d->pixsize */ uniform float pixfactor; float defaultpixsize = pixsize * (1000.0 / pixfactor); @@ -23,41 +23,43 @@ out vec4 FragColor; void main() { - vec2 uv = vec2(gl_FragCoord.xy); - vec4 nloc = ProjectionMatrix * ViewMatrix * vec4(loc.xyz, 1.0); - - float dx = (ProjectionMatrix[3][3] == 0.0) ? (noffset[0] / (nloc.z * defaultpixsize)) : (noffset[0] / defaultpixsize); - float dy = (ProjectionMatrix[3][3] == 0.0) ? (noffset[1] / (nloc.z * defaultpixsize)) : (noffset[1] / defaultpixsize); - - float stroke_depth = texelFetch(strokeDepth, ivec2(uv.xy), 0).r; - vec4 src_pixel= texelFetch(strokeColor, ivec2(uv.xy), 0); - vec4 offset_pixel= texelFetch(strokeColor, ivec2(uv.x - dx, uv.y - dy), 0); - vec4 outcolor; - - /* is transparent */ - if (src_pixel.a == 0.0f) { - discard; - } - /* check inside viewport */ - else if ((uv.x - dx < 0) || (uv.x - dx > Viewport[0])) { - discard; - } - else if ((uv.y - dy < 0) || (uv.y - dy > Viewport[1])) { - discard; - } - /* pixel is equal to mask color, keep */ - else if (src_pixel.rgb == mask_color.rgb) { - discard; - } - else { - if ((src_pixel.a > 0) && (offset_pixel.a > 0)) { - discard; - } - else { - outcolor = vec4(rim_color, 1.0); - } - } - - gl_FragDepth = stroke_depth; - FragColor = outcolor; + vec2 uv = vec2(gl_FragCoord.xy); + vec4 nloc = ProjectionMatrix * ViewMatrix * vec4(loc.xyz, 1.0); + + float dx = (ProjectionMatrix[3][3] == 0.0) ? (noffset[0] / (nloc.z * defaultpixsize)) : + (noffset[0] / defaultpixsize); + float dy = (ProjectionMatrix[3][3] == 0.0) ? (noffset[1] / (nloc.z * defaultpixsize)) : + (noffset[1] / defaultpixsize); + + float stroke_depth = texelFetch(strokeDepth, ivec2(uv.xy), 0).r; + vec4 src_pixel = texelFetch(strokeColor, ivec2(uv.xy), 0); + vec4 offset_pixel = texelFetch(strokeColor, ivec2(uv.x - dx, uv.y - dy), 0); + vec4 outcolor; + + /* is transparent */ + if (src_pixel.a == 0.0f) { + discard; + } + /* check inside viewport */ + else if ((uv.x - dx < 0) || (uv.x - dx > Viewport[0])) { + discard; + } + else if ((uv.y - dy < 0) || (uv.y - dy > Viewport[1])) { + discard; + } + /* pixel is equal to mask color, keep */ + else if (src_pixel.rgb == mask_color.rgb) { + discard; + } + else { + if ((src_pixel.a > 0) && (offset_pixel.a > 0)) { + discard; + } + else { + outcolor = vec4(rim_color, 1.0); + } + } + + gl_FragDepth = stroke_depth; + FragColor = outcolor; } diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_rim_resolve_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_rim_resolve_frag.glsl index 0a7eb65d564..fa010baa32f 100644 --- a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_rim_resolve_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_rim_resolve_frag.glsl @@ -10,89 +10,89 @@ uniform int mode; out vec4 FragColor; -#define MODE_NORMAL 0 -#define MODE_OVERLAY 1 -#define MODE_ADD 2 -#define MODE_SUB 3 +#define MODE_NORMAL 0 +#define MODE_OVERLAY 1 +#define MODE_ADD 2 +#define MODE_SUB 3 #define MODE_MULTIPLY 4 -#define MODE_DIVIDE 5 +#define MODE_DIVIDE 5 float overlay_color(float a, float b) { - float rtn; - if (a < 0.5) { - rtn = 2.0 * a * b; - } - else { - rtn = 1.0 - 2.0 * (1.0 - a) * (1.0 - b); - } + float rtn; + if (a < 0.5) { + rtn = 2.0 * a * b; + } + else { + rtn = 1.0 - 2.0 * (1.0 - a) * (1.0 - b); + } - return rtn; + return rtn; } vec4 get_blend_color(int mode, vec4 src_color, vec4 mix_color) { - vec4 outcolor; - if (mode == MODE_NORMAL) { - outcolor = mix_color; - } - else if (mode == MODE_OVERLAY) { - outcolor.r = overlay_color(src_color.r, mix_color.r); - outcolor.g = overlay_color(src_color.g, mix_color.g); - outcolor.b = overlay_color(src_color.b, mix_color.b); - } - else if (mode == MODE_ADD){ - outcolor = src_color + mix_color; - } - else if (mode == MODE_SUB){ - outcolor = src_color - mix_color; - } - else if (mode == MODE_MULTIPLY) { - outcolor = src_color * mix_color; - } - else if (mode == MODE_DIVIDE) { - outcolor = src_color / mix_color; - } - else { - outcolor = mix_color; - } + vec4 outcolor; + if (mode == MODE_NORMAL) { + outcolor = mix_color; + } + else if (mode == MODE_OVERLAY) { + outcolor.r = overlay_color(src_color.r, mix_color.r); + outcolor.g = overlay_color(src_color.g, mix_color.g); + outcolor.b = overlay_color(src_color.b, mix_color.b); + } + else if (mode == MODE_ADD) { + outcolor = src_color + mix_color; + } + else if (mode == MODE_SUB) { + outcolor = src_color - mix_color; + } + else if (mode == MODE_MULTIPLY) { + outcolor = src_color * mix_color; + } + else if (mode == MODE_DIVIDE) { + outcolor = src_color / mix_color; + } + else { + outcolor = mix_color; + } - /* use always the alpha of source color */ + /* use always the alpha of source color */ - outcolor.a = src_color.a; - /* use alpha to calculate the weight of the mixed color */ - outcolor = mix(src_color, outcolor, mix_color.a); + outcolor.a = src_color.a; + /* use alpha to calculate the weight of the mixed color */ + outcolor = mix(src_color, outcolor, mix_color.a); - return outcolor; + return outcolor; } void main() { - ivec2 uv = ivec2(gl_FragCoord.xy); + ivec2 uv = ivec2(gl_FragCoord.xy); - float stroke_depth = texelFetch(strokeDepth, uv.xy, 0).r; - vec4 src_pixel= texelFetch(strokeColor, uv.xy, 0); - vec4 rim_pixel= texelFetch(strokeRim, uv.xy, 0); + float stroke_depth = texelFetch(strokeDepth, uv.xy, 0).r; + vec4 src_pixel = texelFetch(strokeColor, uv.xy, 0); + vec4 rim_pixel = texelFetch(strokeRim, uv.xy, 0); - vec4 outcolor = src_pixel; + vec4 outcolor = src_pixel; - /* is transparent */ - if (src_pixel.a == 0.0f) { - discard; - } - /* pixel is equal to mask color, keep */ - else if (src_pixel.rgb == mask_color.rgb) { - outcolor = src_pixel; - } - else { - if (rim_pixel.a == 0.0f) { - outcolor = src_pixel; - } - else { - outcolor = get_blend_color(mode, src_pixel, rim_pixel); - } - } + /* is transparent */ + if (src_pixel.a == 0.0f) { + discard; + } + /* pixel is equal to mask color, keep */ + else if (src_pixel.rgb == mask_color.rgb) { + outcolor = src_pixel; + } + else { + if (rim_pixel.a == 0.0f) { + outcolor = src_pixel; + } + else { + outcolor = get_blend_color(mode, src_pixel, rim_pixel); + } + } - gl_FragDepth = stroke_depth; - FragColor = outcolor; + gl_FragDepth = stroke_depth; + FragColor = outcolor; } diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_shadow_prepare_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_shadow_prepare_frag.glsl index 8bb92f69723..d2e20feae18 100644 --- a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_shadow_prepare_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_shadow_prepare_frag.glsl @@ -19,7 +19,7 @@ uniform float phase; uniform int orientation; uniform vec3 loc; -uniform float pixsize; /* rv3d->pixsize */ +uniform float pixsize; /* rv3d->pixsize */ uniform float pixfactor; #define M_PI 3.1415926535897932384626433832795 @@ -37,61 +37,62 @@ out vec4 FragColor; /* project 3d point to 2d on screen space */ vec2 toScreenSpace(vec4 vertex) { - /* need to calculate ndc because this is not done by vertex shader */ - vec3 ndc = vec3(vertex).xyz / vertex.w; + /* need to calculate ndc because this is not done by vertex shader */ + vec3 ndc = vec3(vertex).xyz / vertex.w; - vec2 sc; - sc.x = ((ndc.x + 1.0) / 2.0) * Viewport.x; - sc.y = ((ndc.y + 1.0) / 2.0) * Viewport.y; + vec2 sc; + sc.x = ((ndc.x + 1.0) / 2.0) * Viewport.x; + sc.y = ((ndc.y + 1.0) / 2.0) * Viewport.y; - return sc; + return sc; } void main() { - vec2 uv = vec2(gl_FragCoord.xy); - vec4 nloc = ProjectionMatrix * ViewMatrix * vec4(loc.xyz, 1.0); - vec2 loc2d = toScreenSpace(nloc); - - float dx = (ProjectionMatrix[3][3] == 0.0) ? (noffset[0] / (nloc.z * defaultpixsize)) : (noffset[0] / defaultpixsize); - float dy = (ProjectionMatrix[3][3] == 0.0) ? (noffset[1] / (nloc.z * defaultpixsize)) : (noffset[1] / defaultpixsize); - - - /* move point to new coords system */ - vec2 tpos = vec2(uv.x, uv.y) - loc2d; - - /* rotation */ - if (rotation != 0) { - vec2 rotpoint = vec2((tpos.x * cosv) - (tpos.y * sinv), (tpos.x * sinv) + (tpos.y * cosv)); - tpos = rotpoint; - } - - /* apply offset */ - tpos = vec2(tpos.x - dx, tpos.y - dy); - - /* apply scale */ - tpos.x *= 1.0 / scale[0]; - tpos.y *= 1.0 / scale[1]; - - /* back to original coords system */ - vec2 texpos = tpos + loc2d; - - /* wave */ - if (orientation == HORIZONTAL) { - float pval = (uv.x * M_PI) / Viewport[0]; - texpos.y += amplitude * sin((period * pval) + phase); - } - else if (orientation == VERTICAL){ - float pval = (uv.y * M_PI) / Viewport[1]; - texpos.x += amplitude * sin((period * pval) + phase); - } - - vec4 src_pixel = texelFetch(strokeColor, ivec2(texpos.x, texpos.y), 0); - /* is transparent */ - if (src_pixel.a == 0.0f) { - discard; - } - - gl_FragDepth = texelFetch(strokeDepth, ivec2(texpos.x, texpos.y), 0).r; - FragColor = shadow_color; + vec2 uv = vec2(gl_FragCoord.xy); + vec4 nloc = ProjectionMatrix * ViewMatrix * vec4(loc.xyz, 1.0); + vec2 loc2d = toScreenSpace(nloc); + + float dx = (ProjectionMatrix[3][3] == 0.0) ? (noffset[0] / (nloc.z * defaultpixsize)) : + (noffset[0] / defaultpixsize); + float dy = (ProjectionMatrix[3][3] == 0.0) ? (noffset[1] / (nloc.z * defaultpixsize)) : + (noffset[1] / defaultpixsize); + + /* move point to new coords system */ + vec2 tpos = vec2(uv.x, uv.y) - loc2d; + + /* rotation */ + if (rotation != 0) { + vec2 rotpoint = vec2((tpos.x * cosv) - (tpos.y * sinv), (tpos.x * sinv) + (tpos.y * cosv)); + tpos = rotpoint; + } + + /* apply offset */ + tpos = vec2(tpos.x - dx, tpos.y - dy); + + /* apply scale */ + tpos.x *= 1.0 / scale[0]; + tpos.y *= 1.0 / scale[1]; + + /* back to original coords system */ + vec2 texpos = tpos + loc2d; + + /* wave */ + if (orientation == HORIZONTAL) { + float pval = (uv.x * M_PI) / Viewport[0]; + texpos.y += amplitude * sin((period * pval) + phase); + } + else if (orientation == VERTICAL) { + float pval = (uv.y * M_PI) / Viewport[1]; + texpos.x += amplitude * sin((period * pval) + phase); + } + + vec4 src_pixel = texelFetch(strokeColor, ivec2(texpos.x, texpos.y), 0); + /* is transparent */ + if (src_pixel.a == 0.0f) { + discard; + } + + gl_FragDepth = texelFetch(strokeDepth, ivec2(texpos.x, texpos.y), 0).r; + FragColor = shadow_color; } diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_shadow_resolve_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_shadow_resolve_frag.glsl index 0343d0d42fc..3ef11008adf 100644 --- a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_shadow_resolve_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_shadow_resolve_frag.glsl @@ -10,23 +10,23 @@ out vec4 FragColor; void main() { - ivec2 uv = ivec2(gl_FragCoord.xy); + ivec2 uv = ivec2(gl_FragCoord.xy); - float stroke_depth = texelFetch(strokeDepth, uv.xy, 0).r; - float shadow_depth = texelFetch(shadowDepth, uv.xy, 0).r; - vec4 stroke_pixel= texelFetch(strokeColor, uv.xy, 0); - vec4 shadow_pixel= texelFetch(shadowColor, uv.xy, 0); + float stroke_depth = texelFetch(strokeDepth, uv.xy, 0).r; + float shadow_depth = texelFetch(shadowDepth, uv.xy, 0).r; + vec4 stroke_pixel = texelFetch(strokeColor, uv.xy, 0); + vec4 shadow_pixel = texelFetch(shadowColor, uv.xy, 0); - /* copy original pixel */ - vec4 outcolor = stroke_pixel; - float outdepth = stroke_depth; + /* copy original pixel */ + vec4 outcolor = stroke_pixel; + float outdepth = stroke_depth; - /* if stroke is not on top, copy shadow */ - if ((stroke_pixel.a <= 0.2) && (shadow_pixel.a > 0.0)) { - outcolor = shadow_pixel; - outdepth = shadow_depth; - } + /* if stroke is not on top, copy shadow */ + if ((stroke_pixel.a <= 0.2) && (shadow_pixel.a > 0.0)) { + outcolor = shadow_pixel; + outdepth = shadow_depth; + } - gl_FragDepth = outdepth; - FragColor = outcolor; + gl_FragDepth = outdepth; + FragColor = outcolor; } diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_swirl_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_swirl_frag.glsl index 92485987c93..b226d4f93bc 100644 --- a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_swirl_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_swirl_frag.glsl @@ -10,7 +10,7 @@ uniform int radius; uniform float angle; uniform int transparent; -uniform float pixsize; /* rv3d->pixsize */ +uniform float pixsize; /* rv3d->pixsize */ uniform float pixfactor; out vec4 FragColor; @@ -20,50 +20,51 @@ float defaultpixsize = pixsize * (1000.0 / pixfactor); /* project 3d point to 2d on screen space */ vec2 toScreenSpace(vec4 vertex) { - /* need to calculate ndc because this is not done by vertex shader */ - vec3 ndc = vec3(vertex).xyz / vertex.w; + /* need to calculate ndc because this is not done by vertex shader */ + vec3 ndc = vec3(vertex).xyz / vertex.w; - vec2 sc; - sc.x = ((ndc.x + 1.0) / 2.0) * Viewport.x; - sc.y = ((ndc.y + 1.0) / 2.0) * Viewport.y; + vec2 sc; + sc.x = ((ndc.x + 1.0) / 2.0) * Viewport.x; + sc.y = ((ndc.y + 1.0) / 2.0) * Viewport.y; - return sc; + return sc; } /* This swirl shader is a modified version of original Geeks3d.com code */ void main() { - vec2 uv = vec2(gl_FragCoord.xy); - float stroke_depth; - vec4 outcolor; + vec2 uv = vec2(gl_FragCoord.xy); + float stroke_depth; + vec4 outcolor; - vec4 center3d = ProjectionMatrix * ViewMatrix * vec4(loc.xyz, 1.0); - vec2 center = toScreenSpace(center3d); - vec2 tc = uv - center; + vec4 center3d = ProjectionMatrix * ViewMatrix * vec4(loc.xyz, 1.0); + vec2 center = toScreenSpace(center3d); + vec2 tc = uv - center; - float dist = length(tc); - float pxradius = (ProjectionMatrix[3][3] == 0.0) ? (radius / (loc.z * defaultpixsize)) : (radius / defaultpixsize); - pxradius = max(pxradius, 1); + float dist = length(tc); + float pxradius = (ProjectionMatrix[3][3] == 0.0) ? (radius / (loc.z * defaultpixsize)) : + (radius / defaultpixsize); + pxradius = max(pxradius, 1); - if (dist <= pxradius) { - float percent = (pxradius - dist) / pxradius; - float theta = percent * percent * angle * 8.0; - float s = sin(theta); - float c = cos(theta); - tc = vec2(dot(tc, vec2(c, -s)), dot(tc, vec2(s, c))); - tc += center; + if (dist <= pxradius) { + float percent = (pxradius - dist) / pxradius; + float theta = percent * percent * angle * 8.0; + float s = sin(theta); + float c = cos(theta); + tc = vec2(dot(tc, vec2(c, -s)), dot(tc, vec2(s, c))); + tc += center; - stroke_depth = texelFetch(strokeDepth, ivec2(tc), 0).r; - outcolor = texelFetch(strokeColor, ivec2(tc), 0); - } - else { - if (transparent == 1) { - discard; - } - stroke_depth = texelFetch(strokeDepth, ivec2(uv), 0).r; - outcolor = texelFetch(strokeColor, ivec2(uv), 0); - } + stroke_depth = texelFetch(strokeDepth, ivec2(tc), 0).r; + outcolor = texelFetch(strokeColor, ivec2(tc), 0); + } + else { + if (transparent == 1) { + discard; + } + stroke_depth = texelFetch(strokeDepth, ivec2(uv), 0).r; + outcolor = texelFetch(strokeColor, ivec2(uv), 0); + } - gl_FragDepth = stroke_depth; - FragColor = outcolor; + gl_FragDepth = stroke_depth; + FragColor = outcolor; } diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_wave_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_wave_frag.glsl index 04ab1557d07..0a5df9f6d77 100644 --- a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_wave_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_wave_frag.glsl @@ -17,28 +17,28 @@ uniform vec2 wsize; void main() { - vec4 outcolor; - ivec2 uv = ivec2(gl_FragCoord.xy); - float stroke_depth; - - float value; - if (orientation == HORIZONTAL) { - float pval = (uv.x * M_PI) / wsize[0]; - value = amplitude * sin((period * pval) + phase); - outcolor = texelFetch(strokeColor, ivec2(uv.x, uv.y + value), 0); - stroke_depth = texelFetch(strokeDepth, ivec2(uv.x, uv.y + value), 0).r; - } - else { - float pval = (uv.y * M_PI) / wsize[1]; - value = amplitude * sin((period * pval) + phase); - outcolor = texelFetch(strokeColor, ivec2(uv.x + value, uv.y), 0); - stroke_depth = texelFetch(strokeDepth, ivec2(uv.x + value, uv.y), 0).r; - } - - FragColor = outcolor; - gl_FragDepth = stroke_depth; - - if (outcolor.a < 0.02f) { - discard; - } + vec4 outcolor; + ivec2 uv = ivec2(gl_FragCoord.xy); + float stroke_depth; + + float value; + if (orientation == HORIZONTAL) { + float pval = (uv.x * M_PI) / wsize[0]; + value = amplitude * sin((period * pval) + phase); + outcolor = texelFetch(strokeColor, ivec2(uv.x, uv.y + value), 0); + stroke_depth = texelFetch(strokeDepth, ivec2(uv.x, uv.y + value), 0).r; + } + else { + float pval = (uv.y * M_PI) / wsize[1]; + value = amplitude * sin((period * pval) + phase); + outcolor = texelFetch(strokeColor, ivec2(uv.x + value, uv.y), 0); + stroke_depth = texelFetch(strokeDepth, ivec2(uv.x + value, uv.y), 0).r; + } + + FragColor = outcolor; + gl_FragDepth = stroke_depth; + + if (outcolor.a < 0.02f) { + discard; + } } diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_background_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_background_frag.glsl index cbd7a461dd3..18803bfa3fa 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_background_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_background_frag.glsl @@ -5,8 +5,8 @@ uniform sampler2D strokeDepth; void main() { - ivec2 uv = ivec2(gl_FragCoord.xy); + ivec2 uv = ivec2(gl_FragCoord.xy); - gl_FragDepth = texelFetch(strokeDepth, uv, 0).r; - FragColor = texelFetch(strokeColor, uv, 0); + gl_FragDepth = texelFetch(strokeDepth, uv, 0).r; + FragColor = texelFetch(strokeColor, uv, 0); } diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_blend_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_blend_frag.glsl index fdaad9890a0..0482ea50916 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_blend_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_blend_frag.glsl @@ -14,144 +14,145 @@ uniform int tonemapping; #define ON 1 #define OFF 0 -#define MODE_NORMAL 0 -#define MODE_OVERLAY 1 -#define MODE_ADD 2 -#define MODE_SUB 3 +#define MODE_NORMAL 0 +#define MODE_OVERLAY 1 +#define MODE_ADD 2 +#define MODE_SUB 3 #define MODE_MULTIPLY 4 -#define MODE_DIVIDE 5 +#define MODE_DIVIDE 5 float overlay_color(float a, float b) { - float rtn; - if (a < 0.5) { - rtn = 2.0 * a * b; - } - else { - rtn = 1.0 - 2.0 * (1.0 - a) * (1.0 - b); - } - - return rtn; + float rtn; + if (a < 0.5) { + rtn = 2.0 * a * b; + } + else { + rtn = 1.0 - 2.0 * (1.0 - a) * (1.0 - b); + } + + return rtn; } vec4 get_blend_color(int mode, vec4 src_color, vec4 blend_color) { - vec4 mix_color = blend_color; - vec4 outcolor; - - if (mix_color.a == 0) { - outcolor = src_color; - } - else if (mode == MODE_OVERLAY) { - mix_color.rgb = mix_color.rgb * mix_color.a * blend_opacity; - outcolor.r = overlay_color(src_color.r, mix_color.r); - outcolor.g = overlay_color(src_color.g, mix_color.g); - outcolor.b = overlay_color(src_color.b, mix_color.b); - outcolor.a = src_color.a; - } - else if (mode == MODE_ADD){ - mix_color.rgb = mix_color.rgb * mix_color.a * blend_opacity; - outcolor = src_color + mix_color; - outcolor.a = src_color.a; - } - else if (mode == MODE_SUB){ - outcolor = src_color - mix_color; - outcolor.a = clamp(src_color.a - (mix_color.a * blend_opacity), 0.0, 1.0); - } - else if (mode == MODE_MULTIPLY) { - /* interpolate between 1 and color using opacity */ - mix_color.rgb = mix(vec3(1,1,1), mix_color.rgb * mix_color.a, blend_opacity); - outcolor = src_color * mix_color; - outcolor.a = src_color.a; - } - else if (mode == MODE_DIVIDE) { - mix_color.rgb = mix_color.rgb * mix_color.a * blend_opacity; - outcolor = src_color / mix_color; - outcolor.a = src_color.a; - } - else { - outcolor = mix_color * blend_opacity;; - outcolor.a = src_color.a; - } - - return outcolor; + vec4 mix_color = blend_color; + vec4 outcolor; + + if (mix_color.a == 0) { + outcolor = src_color; + } + else if (mode == MODE_OVERLAY) { + mix_color.rgb = mix_color.rgb * mix_color.a * blend_opacity; + outcolor.r = overlay_color(src_color.r, mix_color.r); + outcolor.g = overlay_color(src_color.g, mix_color.g); + outcolor.b = overlay_color(src_color.b, mix_color.b); + outcolor.a = src_color.a; + } + else if (mode == MODE_ADD) { + mix_color.rgb = mix_color.rgb * mix_color.a * blend_opacity; + outcolor = src_color + mix_color; + outcolor.a = src_color.a; + } + else if (mode == MODE_SUB) { + outcolor = src_color - mix_color; + outcolor.a = clamp(src_color.a - (mix_color.a * blend_opacity), 0.0, 1.0); + } + else if (mode == MODE_MULTIPLY) { + /* interpolate between 1 and color using opacity */ + mix_color.rgb = mix(vec3(1, 1, 1), mix_color.rgb * mix_color.a, blend_opacity); + outcolor = src_color * mix_color; + outcolor.a = src_color.a; + } + else if (mode == MODE_DIVIDE) { + mix_color.rgb = mix_color.rgb * mix_color.a * blend_opacity; + outcolor = src_color / mix_color; + outcolor.a = src_color.a; + } + else { + outcolor = mix_color * blend_opacity; + ; + outcolor.a = src_color.a; + } + + return outcolor; } float linearrgb_to_srgb(float c) { - if (c < 0.0031308) { - return (c < 0.0) ? 0.0 : c * 12.92; - } - else { - return 1.055 * pow(c, 1.0 / 2.4) - 0.055; - } + if (c < 0.0031308) { + return (c < 0.0) ? 0.0 : c * 12.92; + } + else { + return 1.055 * pow(c, 1.0 / 2.4) - 0.055; + } } vec4 tone(vec4 stroke_color) { - if (tonemapping == 1) { - vec4 color = vec4(0, 0, 0, stroke_color.a); - color.r = linearrgb_to_srgb(stroke_color.r); - color.g = linearrgb_to_srgb(stroke_color.g); - color.b = linearrgb_to_srgb(stroke_color.b); - return color; - } - else { - return stroke_color; - } + if (tonemapping == 1) { + vec4 color = vec4(0, 0, 0, stroke_color.a); + color.r = linearrgb_to_srgb(stroke_color.r); + color.g = linearrgb_to_srgb(stroke_color.g); + color.b = linearrgb_to_srgb(stroke_color.b); + return color; + } + else { + return stroke_color; + } } void main() { - vec4 outcolor; - ivec2 uv = ivec2(gl_FragCoord.xy); - vec4 stroke_color = texelFetch(strokeColor, uv, 0).rgba; - float stroke_depth = texelFetch(strokeDepth, uv, 0).r; - - vec4 mix_color = texelFetch(blendColor, uv, 0).rgba; - float mix_depth = texelFetch(blendDepth, uv, 0).r; - - /* premult alpha factor to remove double blend effects */ - if (stroke_color.a > 0) { - stroke_color = vec4(vec3(stroke_color.rgb / stroke_color.a), stroke_color.a); - } - if (mix_color.a > 0) { - mix_color = vec4(vec3(mix_color.rgb / mix_color.a), mix_color.a); - } - - /* Normal mode */ - if (mode == MODE_NORMAL) { - if (stroke_color.a > 0) { - if (mix_color.a > 0) { - FragColor = vec4(mix(stroke_color.rgb, mix_color.rgb, mix_color.a), stroke_color.a); - gl_FragDepth = mix_depth; - } - else { - FragColor = stroke_color; - gl_FragDepth = stroke_depth; - } - } - else { - if (clamp_layer == ON) { - discard; - } - else { - FragColor = mix_color; - gl_FragDepth = mix_depth; - } - } - FragColor = tone(FragColor); - return; - } - - /* if not using mask, return mix color */ - if ((stroke_color.a == 0) && (clamp_layer == OFF)) { - FragColor = tone(mix_color); - gl_FragDepth = mix_depth; - return; - } - - /* apply blend mode */ - FragColor = tone(get_blend_color(mode, stroke_color, mix_color)); - gl_FragDepth = stroke_depth; + vec4 outcolor; + ivec2 uv = ivec2(gl_FragCoord.xy); + vec4 stroke_color = texelFetch(strokeColor, uv, 0).rgba; + float stroke_depth = texelFetch(strokeDepth, uv, 0).r; + + vec4 mix_color = texelFetch(blendColor, uv, 0).rgba; + float mix_depth = texelFetch(blendDepth, uv, 0).r; + + /* premult alpha factor to remove double blend effects */ + if (stroke_color.a > 0) { + stroke_color = vec4(vec3(stroke_color.rgb / stroke_color.a), stroke_color.a); + } + if (mix_color.a > 0) { + mix_color = vec4(vec3(mix_color.rgb / mix_color.a), mix_color.a); + } + + /* Normal mode */ + if (mode == MODE_NORMAL) { + if (stroke_color.a > 0) { + if (mix_color.a > 0) { + FragColor = vec4(mix(stroke_color.rgb, mix_color.rgb, mix_color.a), stroke_color.a); + gl_FragDepth = mix_depth; + } + else { + FragColor = stroke_color; + gl_FragDepth = stroke_depth; + } + } + else { + if (clamp_layer == ON) { + discard; + } + else { + FragColor = mix_color; + gl_FragDepth = mix_depth; + } + } + FragColor = tone(FragColor); + return; + } + + /* if not using mask, return mix color */ + if ((stroke_color.a == 0) && (clamp_layer == OFF)) { + FragColor = tone(mix_color); + gl_FragDepth = mix_depth; + return; + } + + /* apply blend mode */ + FragColor = tone(get_blend_color(mode, stroke_color, mix_color)); + gl_FragDepth = stroke_depth; } diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_frag.glsl index b3bd8e488f2..6a2a4f68dc9 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_frag.glsl @@ -4,14 +4,14 @@ out vec4 fragColor; void main() { - vec2 centered = mTexCoord - vec2(0.5); - float dist_squared = dot(centered, centered); - const float rad_squared = 0.25; + vec2 centered = mTexCoord - vec2(0.5); + float dist_squared = dot(centered, centered); + const float rad_squared = 0.25; - // round point with jaggy edges - if (dist_squared > rad_squared) { - discard; - } + // round point with jaggy edges + if (dist_squared > rad_squared) { + discard; + } - fragColor = mColor; + fragColor = mColor; } diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_geom.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_geom.glsl index 0d2da00db66..b5d0a5bce71 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_geom.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_geom.glsl @@ -13,36 +13,36 @@ out vec2 mTexCoord; /* project 3d point to 2d on screen space */ vec2 toScreenSpace(vec4 vertex) { - return vec2(vertex.xy / vertex.w) * Viewport; + return vec2(vertex.xy / vertex.w) * Viewport; } void main(void) { - vec4 P0 = gl_in[0].gl_Position; - vec2 sp0 = toScreenSpace(P0); + vec4 P0 = gl_in[0].gl_Position; + vec2 sp0 = toScreenSpace(P0); - float size = finalThickness[0]; + float size = finalThickness[0]; - /* generate the triangle strip */ - mTexCoord = vec2(0, 1); - mColor = finalColor[0]; - gl_Position = vec4(vec2(sp0.x - size, sp0.y + size) / Viewport, 0, 1.0); - EmitVertex(); + /* generate the triangle strip */ + mTexCoord = vec2(0, 1); + mColor = finalColor[0]; + gl_Position = vec4(vec2(sp0.x - size, sp0.y + size) / Viewport, 0, 1.0); + EmitVertex(); - mTexCoord = vec2(0, 0); - mColor = finalColor[0]; - gl_Position = vec4(vec2(sp0.x - size, sp0.y - size) / Viewport, 0, 1.0); - EmitVertex(); + mTexCoord = vec2(0, 0); + mColor = finalColor[0]; + gl_Position = vec4(vec2(sp0.x - size, sp0.y - size) / Viewport, 0, 1.0); + EmitVertex(); - mTexCoord = vec2(1, 1); - mColor = finalColor[0]; - gl_Position = vec4(vec2(sp0.x + size, sp0.y + size) / Viewport, 0, 1.0); - EmitVertex(); + mTexCoord = vec2(1, 1); + mColor = finalColor[0]; + gl_Position = vec4(vec2(sp0.x + size, sp0.y + size) / Viewport, 0, 1.0); + EmitVertex(); - mTexCoord = vec2(1, 0); - mColor = finalColor[0]; - gl_Position = vec4(vec2(sp0.x + size, sp0.y - size) / Viewport, 0, 1.0); - EmitVertex(); + mTexCoord = vec2(1, 0); + mColor = finalColor[0]; + gl_Position = vec4(vec2(sp0.x + size, sp0.y - size) / Viewport, 0, 1.0); + EmitVertex(); - EndPrimitive(); + EndPrimitive(); } diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_vert.glsl index 77fdf58bea0..eea28755ae6 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_vert.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_vert.glsl @@ -9,7 +9,7 @@ out float finalThickness; void main() { - gl_Position = ModelViewProjectionMatrix * vec4( pos, 1.0 ); - finalColor = color; - finalThickness = size; + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + finalColor = color; + finalThickness = size; } diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl index 7f3bbf17222..632c63a39aa 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl @@ -39,146 +39,172 @@ uniform vec4 wire_color; #define GP_DRAWMODE_2D 0 #define GP_DRAWMODE_3D 1 -#define OB_WIRE 2 +#define OB_WIRE 2 #define OB_SOLID 3 -#define V3D_SHADING_MATERIAL_COLOR 0 -#define V3D_SHADING_TEXTURE_COLOR 3 +#define V3D_SHADING_MATERIAL_COLOR 0 +#define V3D_SHADING_TEXTURE_COLOR 3 in vec4 finalColor; in vec2 texCoord_interp; out vec4 fragColor; #define texture2D texture -void set_color(in vec4 color, in vec4 color2, in vec4 tcolor, in float mixv, in float factor, - in int tmix, in int flip, out vec4 ocolor) +void set_color(in vec4 color, + in vec4 color2, + in vec4 tcolor, + in float mixv, + in float factor, + in int tmix, + in int flip, + out vec4 ocolor) { - /* full color A */ - if (mixv == 1.0) { - if (tmix == 1) { - ocolor = (flip == 0) ? color : tcolor; - } - else { - ocolor = (flip == 0) ? color : color2; - } - } - /* full color B */ - else if (mixv == 0.0) { - if (tmix == 1) { - ocolor = (flip == 0) ? tcolor : color; - } - else { - ocolor = (flip == 0) ? color2 : color; - } - } - /* mix of colors */ - else { - if (tmix == 1) { - ocolor = (flip == 0) ? mix(color, tcolor, factor) : mix(tcolor, color, factor); - } - else { - ocolor = (flip == 0) ? mix(color, color2, factor) : mix(color2, color, factor); - } - } - ocolor.a *= layer_opacity; + /* full color A */ + if (mixv == 1.0) { + if (tmix == 1) { + ocolor = (flip == 0) ? color : tcolor; + } + else { + ocolor = (flip == 0) ? color : color2; + } + } + /* full color B */ + else if (mixv == 0.0) { + if (tmix == 1) { + ocolor = (flip == 0) ? tcolor : color; + } + else { + ocolor = (flip == 0) ? color2 : color; + } + } + /* mix of colors */ + else { + if (tmix == 1) { + ocolor = (flip == 0) ? mix(color, tcolor, factor) : mix(tcolor, color, factor); + } + else { + ocolor = (flip == 0) ? mix(color, color2, factor) : mix(color2, color, factor); + } + } + ocolor.a *= layer_opacity; } void main() { - vec2 t_center = vec2(0.5, 0.5); - mat2 matrot_tex = mat2(cos(texture_angle), -sin(texture_angle), sin(texture_angle), cos(texture_angle)); - vec2 rot_tex = (matrot_tex * (texCoord_interp - t_center)) + t_center + texture_offset; - vec4 tmp_color; - tmp_color = (texture_clamp == 0) ? texture2D(myTexture, rot_tex * texture_scale) : texture2D(myTexture, clamp(rot_tex * texture_scale, 0.0, 1.0)); - vec4 text_color = vec4(tmp_color[0], tmp_color[1], tmp_color[2], tmp_color[3] * texture_opacity); - vec4 chesscolor; - - /* wireframe with x-ray discard */ - if ((viewport_xray == 1) && (shading_type[0] == OB_WIRE)) { - discard; - } - - /* solid fill */ - if (fill_type == SOLID) { - fragColor = finalColor; - } - else { - vec2 center = vec2(0.5, 0.5) + gradient_shift; - mat2 matrot = mat2(cos(gradient_angle), -sin(gradient_angle), sin(gradient_angle), cos(gradient_angle)); - vec2 rot = (((matrot * (texCoord_interp - center)) + center) * gradient_scale) + gradient_shift; - /* gradient */ - if (fill_type == GRADIENT) { - set_color(finalColor, color2, text_color, mix_factor, rot.x - mix_factor + 0.5, texture_mix, texture_flip, fragColor); - } - /* radial gradient */ - if (fill_type == RADIAL) { - float in_rad = gradient_radius * mix_factor; - float ex_rad = gradient_radius - in_rad; - float intensity = 0; - float distance = length((center - texCoord_interp) * gradient_scale); - if (distance > gradient_radius) { - discard; - } - if (distance > in_rad) { - intensity = clamp(((distance - in_rad) / ex_rad), 0.0, 1.0); - } - set_color(finalColor, color2, text_color, mix_factor, intensity, texture_mix, texture_flip, fragColor); - } - /* chessboard */ - if (fill_type == CHESS) { - vec2 pos = rot / pattern_gridsize; - if ((fract(pos.x) < 0.5 && fract(pos.y) < 0.5) || (fract(pos.x) > 0.5 && fract(pos.y) > 0.5)) { - chesscolor = (texture_flip == 0) ? finalColor : color2; - } - else { - chesscolor = (texture_flip == 0) ? color2 : finalColor; - } - /* mix with texture */ - fragColor = (texture_mix == 1) ? mix(chesscolor, text_color, mix_factor) : chesscolor; - fragColor.a *= layer_opacity; - } - /* texture */ - if (fill_type == TEXTURE) { - fragColor = (texture_mix == 1) ? mix(text_color, finalColor, mix_factor) : text_color; - fragColor.a *= layer_opacity; - } - /* pattern */ - if (fill_type == PATTERN) { - fragColor = finalColor; - fragColor.a = min(text_color.a, finalColor.a) * layer_opacity; - } - } - - /* set zdepth */ - if (xraymode == GP_XRAY_FRONT) { - gl_FragDepth = 0.000001; - } - else if (xraymode == GP_XRAY_3DSPACE) { - /* if 3D mode, move slightly the fill to avoid z-fighting between stroke and fill on same stroke */ - if (drawmode == GP_DRAWMODE_3D) { - gl_FragDepth = gl_FragCoord.z * 1.0001; - } - else { - gl_FragDepth = gl_FragCoord.z; - } - } - else { - gl_FragDepth = 0.000001; - } - - /* if wireframe override colors */ - if (shading_type[0] == OB_WIRE) { - fragColor = wire_color; - } - - /* for solid override color */ - if (shading_type[0] == OB_SOLID) { - if ((shading_type[1] != V3D_SHADING_MATERIAL_COLOR) && (shading_type[1] != V3D_SHADING_TEXTURE_COLOR)) { - fragColor = wire_color; - } - if (viewport_xray == 1) { - fragColor.a *= 0.5; - } - } - + vec2 t_center = vec2(0.5, 0.5); + mat2 matrot_tex = mat2( + cos(texture_angle), -sin(texture_angle), sin(texture_angle), cos(texture_angle)); + vec2 rot_tex = (matrot_tex * (texCoord_interp - t_center)) + t_center + texture_offset; + vec4 tmp_color; + tmp_color = (texture_clamp == 0) ? + texture2D(myTexture, rot_tex * texture_scale) : + texture2D(myTexture, clamp(rot_tex * texture_scale, 0.0, 1.0)); + vec4 text_color = vec4(tmp_color[0], tmp_color[1], tmp_color[2], tmp_color[3] * texture_opacity); + vec4 chesscolor; + + /* wireframe with x-ray discard */ + if ((viewport_xray == 1) && (shading_type[0] == OB_WIRE)) { + discard; + } + + /* solid fill */ + if (fill_type == SOLID) { + fragColor = finalColor; + } + else { + vec2 center = vec2(0.5, 0.5) + gradient_shift; + mat2 matrot = mat2( + cos(gradient_angle), -sin(gradient_angle), sin(gradient_angle), cos(gradient_angle)); + vec2 rot = (((matrot * (texCoord_interp - center)) + center) * gradient_scale) + + gradient_shift; + /* gradient */ + if (fill_type == GRADIENT) { + set_color(finalColor, + color2, + text_color, + mix_factor, + rot.x - mix_factor + 0.5, + texture_mix, + texture_flip, + fragColor); + } + /* radial gradient */ + if (fill_type == RADIAL) { + float in_rad = gradient_radius * mix_factor; + float ex_rad = gradient_radius - in_rad; + float intensity = 0; + float distance = length((center - texCoord_interp) * gradient_scale); + if (distance > gradient_radius) { + discard; + } + if (distance > in_rad) { + intensity = clamp(((distance - in_rad) / ex_rad), 0.0, 1.0); + } + set_color(finalColor, + color2, + text_color, + mix_factor, + intensity, + texture_mix, + texture_flip, + fragColor); + } + /* chessboard */ + if (fill_type == CHESS) { + vec2 pos = rot / pattern_gridsize; + if ((fract(pos.x) < 0.5 && fract(pos.y) < 0.5) || + (fract(pos.x) > 0.5 && fract(pos.y) > 0.5)) { + chesscolor = (texture_flip == 0) ? finalColor : color2; + } + else { + chesscolor = (texture_flip == 0) ? color2 : finalColor; + } + /* mix with texture */ + fragColor = (texture_mix == 1) ? mix(chesscolor, text_color, mix_factor) : chesscolor; + fragColor.a *= layer_opacity; + } + /* texture */ + if (fill_type == TEXTURE) { + fragColor = (texture_mix == 1) ? mix(text_color, finalColor, mix_factor) : text_color; + fragColor.a *= layer_opacity; + } + /* pattern */ + if (fill_type == PATTERN) { + fragColor = finalColor; + fragColor.a = min(text_color.a, finalColor.a) * layer_opacity; + } + } + + /* set zdepth */ + if (xraymode == GP_XRAY_FRONT) { + gl_FragDepth = 0.000001; + } + else if (xraymode == GP_XRAY_3DSPACE) { + /* if 3D mode, move slightly the fill to avoid z-fighting between stroke and fill on same stroke */ + if (drawmode == GP_DRAWMODE_3D) { + gl_FragDepth = gl_FragCoord.z * 1.0001; + } + else { + gl_FragDepth = gl_FragCoord.z; + } + } + else { + gl_FragDepth = 0.000001; + } + + /* if wireframe override colors */ + if (shading_type[0] == OB_WIRE) { + fragColor = wire_color; + } + + /* for solid override color */ + if (shading_type[0] == OB_SOLID) { + if ((shading_type[1] != V3D_SHADING_MATERIAL_COLOR) && + (shading_type[1] != V3D_SHADING_TEXTURE_COLOR)) { + fragColor = wire_color; + } + if (viewport_xray == 1) { + fragColor.a *= 0.5; + } + } } diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_fill_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_fill_vert.glsl index 52da354a562..d71f57eb98c 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_fill_vert.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_fill_vert.glsl @@ -8,7 +8,7 @@ out vec2 texCoord_interp; void main(void) { - gl_Position = ModelViewProjectionMatrix * vec4( pos, 1.0 ); - finalColor = color; - texCoord_interp = texCoord; + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + finalColor = color; + texCoord_interp = texCoord; } diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_paper_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_paper_frag.glsl index c2e3f787bec..3c1424f98ff 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_paper_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_paper_frag.glsl @@ -5,5 +5,5 @@ out vec4 FragColor; void main() { - FragColor = vec4(color, opacity); + FragColor = vec4(color, opacity); } diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_point_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_point_frag.glsl index ca8c888fe21..c8af822bc9e 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_point_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_point_frag.glsl @@ -11,62 +11,62 @@ out vec4 fragColor; #define texture2D texture -#define GPENCIL_MODE_LINE 0 -#define GPENCIL_MODE_DOTS 1 -#define GPENCIL_MODE_BOX 2 +#define GPENCIL_MODE_LINE 0 +#define GPENCIL_MODE_DOTS 1 +#define GPENCIL_MODE_BOX 2 /* keep this list synchronized with list in gpencil_engine.h */ -#define GPENCIL_COLOR_SOLID 0 +#define GPENCIL_COLOR_SOLID 0 #define GPENCIL_COLOR_TEXTURE 1 #define GPENCIL_COLOR_PATTERN 2 /* Function to check the point inside ellipse */ -float checkpoint(vec2 pt, vec2 radius) -{ - float p = (pow(pt.x, 2) / pow(radius.x, 2)) + (pow(pt.y, 2) / pow(radius.y, 2)); - - return p; -} +float checkpoint(vec2 pt, vec2 radius) +{ + float p = (pow(pt.x, 2) / pow(radius.x, 2)) + (pow(pt.y, 2) / pow(radius.y, 2)); + + return p; +} void main() { - vec2 centered = mTexCoord - vec2(0.5); - float ellip = checkpoint(centered, vec2(gradient_s / 2.0)); + vec2 centered = mTexCoord - vec2(0.5); + float ellip = checkpoint(centered, vec2(gradient_s / 2.0)); + + if (mode != GPENCIL_MODE_BOX) { + if (ellip > 1.0) { + discard; + } + } + + vec4 tmp_color = texture2D(myTexture, mTexCoord); - if (mode != GPENCIL_MODE_BOX) { - if (ellip > 1.0) { - discard; - } - } + /* Solid */ + if (color_type == GPENCIL_COLOR_SOLID) { + fragColor = mColor; + } + /* texture */ + if (color_type == GPENCIL_COLOR_TEXTURE) { + fragColor = texture2D(myTexture, mTexCoord); + /* mult both alpha factor to use strength factor with texture */ + fragColor.a = min(fragColor.a * mColor.a, fragColor.a); + } + /* pattern */ + if (color_type == GPENCIL_COLOR_PATTERN) { + vec4 text_color = texture2D(myTexture, mTexCoord); + fragColor = mColor; + /* mult both alpha factor to use strength factor with color alpha limit */ + fragColor.a = min(text_color.a * mColor.a, mColor.a); + } - vec4 tmp_color = texture2D(myTexture, mTexCoord); + if ((mode == GPENCIL_MODE_DOTS) && (gradient_f < 1.0)) { + float dist = length(centered) * 2; + float decay = dist * (1.0 - gradient_f) * fragColor.a; + fragColor.a = clamp(fragColor.a - decay, 0.0, 1.0); + fragColor.a = fragColor.a * (1.0 - ellip); + } - /* Solid */ - if (color_type == GPENCIL_COLOR_SOLID) { - fragColor = mColor; - } - /* texture */ - if (color_type == GPENCIL_COLOR_TEXTURE) { - fragColor = texture2D(myTexture, mTexCoord); - /* mult both alpha factor to use strength factor with texture */ - fragColor.a = min(fragColor.a * mColor.a, fragColor.a); - } - /* pattern */ - if (color_type == GPENCIL_COLOR_PATTERN) { - vec4 text_color = texture2D(myTexture, mTexCoord); - fragColor = mColor; - /* mult both alpha factor to use strength factor with color alpha limit */ - fragColor.a = min(text_color.a * mColor.a, mColor.a); - } - - if ((mode == GPENCIL_MODE_DOTS) && (gradient_f < 1.0)) { - float dist = length(centered) * 2; - float decay = dist * (1.0 - gradient_f) * fragColor.a; - fragColor.a = clamp(fragColor.a - decay, 0.0, 1.0); - fragColor.a = fragColor.a * (1.0 - ellip); - } - - if(fragColor.a < 0.0035) { - discard; - } + if (fragColor.a < 0.0035) { + discard; + } } diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_point_geom.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_point_geom.glsl index 32aaa057298..2fb48ac5147 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_point_geom.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_point_geom.glsl @@ -17,124 +17,124 @@ out vec2 mTexCoord; #define GP_XRAY_FRONT 0 #define GP_XRAY_3DSPACE 1 -#define M_PI 3.14159265358979323846 /* pi */ -#define M_2PI 6.28318530717958647692 /* 2*pi */ -#define FALSE 0 +#define M_PI 3.14159265358979323846 /* pi */ +#define M_2PI 6.28318530717958647692 /* 2*pi */ +#define FALSE 0 /* project 3d point to 2d on screen space */ vec2 toScreenSpace(vec4 vertex) { - return vec2(vertex.xy / vertex.w) * Viewport; + return vec2(vertex.xy / vertex.w) * Viewport; } /* get zdepth value */ float getZdepth(vec4 point) { - if (xraymode == GP_XRAY_FRONT) { - return 0.000001; - } - if (xraymode == GP_XRAY_3DSPACE) { - return (point.z / point.w); - } - - /* in front by default */ - return 0.000001; + if (xraymode == GP_XRAY_FRONT) { + return 0.000001; + } + if (xraymode == GP_XRAY_3DSPACE) { + return (point.z / point.w); + } + + /* in front by default */ + return 0.000001; } vec2 rotateUV(vec2 uv, float angle) { - /* translate center of rotation to the center of texture */ - vec2 new_uv = uv - vec2(0.5f, 0.5f); - vec2 rot_uv; - rot_uv.x = new_uv.x * cos(angle) - new_uv.y * sin(angle); - rot_uv.y = new_uv.y * cos(angle) + new_uv.x * sin(angle); - return rot_uv + vec2(0.5f, 0.5f); + /* translate center of rotation to the center of texture */ + vec2 new_uv = uv - vec2(0.5f, 0.5f); + vec2 rot_uv; + rot_uv.x = new_uv.x * cos(angle) - new_uv.y * sin(angle); + rot_uv.y = new_uv.y * cos(angle) + new_uv.x * sin(angle); + return rot_uv + vec2(0.5f, 0.5f); } vec2 rotatePoint(vec2 center, vec2 point, float angle) { - /* translate center of rotation to the center */ - vec2 new_point = point - center; - vec2 rot_point; - rot_point.x = new_point.x * cos(angle) - new_point.y * sin(angle); - rot_point.y = new_point.y * cos(angle) + new_point.x * sin(angle); - return rot_point + center; + /* translate center of rotation to the center */ + vec2 new_point = point - center; + vec2 rot_point; + rot_point.x = new_point.x * cos(angle) - new_point.y * sin(angle); + rot_point.y = new_point.y * cos(angle) + new_point.x * sin(angle); + return rot_point + center; } /* Calculate angle of the stroke using previous point as reference. * The angle is calculated using the x axis (1, 0) as 0 degrees */ float getAngle(vec2 pt0, vec2 pt1) { - /* do not rotate one point only (no reference to rotate) */ - if (pt0 == pt1) { - return 0.0; - } - - if (use_follow_path == FALSE) { - return 0.0; - } - - /* default horizontal line (x-axis) in screen space */ - vec2 v0 = vec2(1.0, 0.0); - - /* vector of direction */ - vec2 vn = vec2(normalize(pt1 - pt0)); - - /* angle signed (function ported from angle_signed_v2v2) */ - float perp_dot = (v0[1] * vn[0]) - (v0[0] * vn[1]); - float angle = atan(perp_dot, dot(v0, vn)); - - /* get full circle rotation */ - if (angle > 0.0) { - angle = M_PI + (M_PI - angle); - } - else { - angle *= -1.0; - } - - return angle; + /* do not rotate one point only (no reference to rotate) */ + if (pt0 == pt1) { + return 0.0; + } + + if (use_follow_path == FALSE) { + return 0.0; + } + + /* default horizontal line (x-axis) in screen space */ + vec2 v0 = vec2(1.0, 0.0); + + /* vector of direction */ + vec2 vn = vec2(normalize(pt1 - pt0)); + + /* angle signed (function ported from angle_signed_v2v2) */ + float perp_dot = (v0[1] * vn[0]) - (v0[0] * vn[1]); + float angle = atan(perp_dot, dot(v0, vn)); + + /* get full circle rotation */ + if (angle > 0.0) { + angle = M_PI + (M_PI - angle); + } + else { + angle *= -1.0; + } + + return angle; } void main(void) { - /* receive points */ - vec4 P0 = gl_in[0].gl_Position; - vec2 sp0 = toScreenSpace(P0); - - vec4 P1 = finalprev_pos[0]; - vec2 sp1 = toScreenSpace(P1); - vec2 point; - - float size = finalThickness[0]; - vec2 center = vec2(sp0.x, sp0.y); - - /* get angle of stroke to rotate texture */ - float angle = getAngle(sp0, sp1); - - /* generate the triangle strip */ - mTexCoord = rotateUV(vec2(0, 1), finaluvdata[0].y); - mColor = finalColor[0]; - point = rotatePoint(center, vec2(sp0.x - size, sp0.y + size), angle); - gl_Position = vec4(point / Viewport, getZdepth(P0), 1.0); - EmitVertex(); - - mTexCoord = rotateUV(vec2(0, 0), finaluvdata[0].y); - mColor = finalColor[0]; - point = rotatePoint(center, vec2(sp0.x - size, sp0.y - size), angle); - gl_Position = vec4(point / Viewport, getZdepth(P0), 1.0); - EmitVertex(); - - mTexCoord = rotateUV(vec2(1, 1), finaluvdata[0].y); - mColor = finalColor[0]; - point = rotatePoint(center, vec2(sp0.x + size, sp0.y + size), angle); - gl_Position = vec4(point / Viewport, getZdepth(P0), 1.0); - EmitVertex(); - - mTexCoord = rotateUV(vec2(1, 0), finaluvdata[0].y); - mColor = finalColor[0]; - point = rotatePoint(center, vec2(sp0.x + size, sp0.y - size), angle); - gl_Position = vec4(point / Viewport, getZdepth(P0), 1.0); - EmitVertex(); - - EndPrimitive(); + /* receive points */ + vec4 P0 = gl_in[0].gl_Position; + vec2 sp0 = toScreenSpace(P0); + + vec4 P1 = finalprev_pos[0]; + vec2 sp1 = toScreenSpace(P1); + vec2 point; + + float size = finalThickness[0]; + vec2 center = vec2(sp0.x, sp0.y); + + /* get angle of stroke to rotate texture */ + float angle = getAngle(sp0, sp1); + + /* generate the triangle strip */ + mTexCoord = rotateUV(vec2(0, 1), finaluvdata[0].y); + mColor = finalColor[0]; + point = rotatePoint(center, vec2(sp0.x - size, sp0.y + size), angle); + gl_Position = vec4(point / Viewport, getZdepth(P0), 1.0); + EmitVertex(); + + mTexCoord = rotateUV(vec2(0, 0), finaluvdata[0].y); + mColor = finalColor[0]; + point = rotatePoint(center, vec2(sp0.x - size, sp0.y - size), angle); + gl_Position = vec4(point / Viewport, getZdepth(P0), 1.0); + EmitVertex(); + + mTexCoord = rotateUV(vec2(1, 1), finaluvdata[0].y); + mColor = finalColor[0]; + point = rotatePoint(center, vec2(sp0.x + size, sp0.y + size), angle); + gl_Position = vec4(point / Viewport, getZdepth(P0), 1.0); + EmitVertex(); + + mTexCoord = rotateUV(vec2(1, 0), finaluvdata[0].y); + mColor = finalColor[0]; + point = rotatePoint(center, vec2(sp0.x + size, sp0.y - size), angle); + gl_Position = vec4(point / Viewport, getZdepth(P0), 1.0); + EmitVertex(); + + EndPrimitive(); } diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl index 7deca544176..92c9acf1f2a 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl @@ -1,7 +1,7 @@ uniform mat4 ModelViewProjectionMatrix; uniform mat4 ProjectionMatrix; -uniform float pixsize; /* rv3d->pixsize */ +uniform float pixsize; /* rv3d->pixsize */ uniform int keep_size; uniform float objscale; uniform float pixfactor; @@ -22,42 +22,44 @@ out vec4 finalprev_pos; #define TRUE 1 -#define OB_WIRE 2 +#define OB_WIRE 2 #define OB_SOLID 3 -#define V3D_SHADING_MATERIAL_COLOR 0 -#define V3D_SHADING_TEXTURE_COLOR 3 +#define V3D_SHADING_MATERIAL_COLOR 0 +#define V3D_SHADING_TEXTURE_COLOR 3 float defaultpixsize = pixsize * (1000.0 / pixfactor); void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); - finalprev_pos = ModelViewProjectionMatrix * vec4(prev_pos, 1.0); - finalColor = color; - - if (keep_size == TRUE) { - finalThickness = thickness; - } - else { - float size = (ProjectionMatrix[3][3] == 0.0) ? (thickness / (gl_Position.z * defaultpixsize)) : (thickness / defaultpixsize); - finalThickness = max(size * objscale, 4.0); /* minimum 4 pixels */ - } - - /* for wireframe override size and color */ - if (shading_type[0] == OB_WIRE) { - finalThickness = 2.0; - finalColor = wire_color; - } - /* for solid override color */ - if (shading_type[0] == OB_SOLID) { - if ((shading_type[1] != V3D_SHADING_MATERIAL_COLOR) && (shading_type[1] != V3D_SHADING_TEXTURE_COLOR)) { - finalColor = wire_color; - } - if (viewport_xray == 1) { - finalColor.a *= 0.5; - } - } - - finaluvdata = uvdata; + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + finalprev_pos = ModelViewProjectionMatrix * vec4(prev_pos, 1.0); + finalColor = color; + + if (keep_size == TRUE) { + finalThickness = thickness; + } + else { + float size = (ProjectionMatrix[3][3] == 0.0) ? (thickness / (gl_Position.z * defaultpixsize)) : + (thickness / defaultpixsize); + finalThickness = max(size * objscale, 4.0); /* minimum 4 pixels */ + } + + /* for wireframe override size and color */ + if (shading_type[0] == OB_WIRE) { + finalThickness = 2.0; + finalColor = wire_color; + } + /* for solid override color */ + if (shading_type[0] == OB_SOLID) { + if ((shading_type[1] != V3D_SHADING_MATERIAL_COLOR) && + (shading_type[1] != V3D_SHADING_TEXTURE_COLOR)) { + finalColor = wire_color; + } + if (viewport_xray == 1) { + finalColor.a *= 0.5; + } + } + + finaluvdata = uvdata; } diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_simple_mix_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_simple_mix_frag.glsl index dd54e38c3d0..2f4429a858f 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_simple_mix_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_simple_mix_frag.glsl @@ -6,10 +6,10 @@ uniform sampler2D strokeColor; uniform sampler2D strokeDepth; void main() { - ivec2 uv = ivec2(gl_FragCoord.xy); - float stroke_depth = texelFetch(strokeDepth, uv, 0).r; - vec4 stroke_color = texelFetch(strokeColor, uv, 0).rgba; + ivec2 uv = ivec2(gl_FragCoord.xy); + float stroke_depth = texelFetch(strokeDepth, uv, 0).r; + vec4 stroke_color = texelFetch(strokeColor, uv, 0).rgba; - FragColor = stroke_color; - gl_FragDepth = stroke_depth; + FragColor = stroke_color; + gl_FragDepth = stroke_depth; } diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_frag.glsl index a49a6e84f17..35d07306361 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_frag.glsl @@ -12,7 +12,7 @@ out vec4 fragColor; #define texture2D texture /* keep this list synchronized with list in gpencil_engine.h */ -#define GPENCIL_COLOR_SOLID 0 +#define GPENCIL_COLOR_SOLID 0 #define GPENCIL_COLOR_TEXTURE 1 #define GPENCIL_COLOR_PATTERN 2 @@ -20,53 +20,53 @@ out vec4 fragColor; void main() { - - vec4 tColor = vec4(mColor); - /* if uvfac[1] == 1, then encap */ - if (uvfac[1] == ENDCAP) { - vec2 center = vec2(uvfac[0], 0.5); - float dist = length(mTexCoord - center); - if (dist > 0.50) { - discard; - } - } - /* Solid */ - if (color_type == GPENCIL_COLOR_SOLID) { - fragColor = tColor; - } - /* texture for endcaps */ - vec4 text_color; - if (uvfac[1] == ENDCAP) { - text_color = texture2D(myTexture, vec2(mTexCoord.x, mTexCoord.y)); - } - else { - text_color = texture2D(myTexture, mTexCoord); - } + vec4 tColor = vec4(mColor); + /* if uvfac[1] == 1, then encap */ + if (uvfac[1] == ENDCAP) { + vec2 center = vec2(uvfac[0], 0.5); + float dist = length(mTexCoord - center); + if (dist > 0.50) { + discard; + } + } + /* Solid */ + if (color_type == GPENCIL_COLOR_SOLID) { + fragColor = tColor; + } - /* texture */ - if (color_type == GPENCIL_COLOR_TEXTURE) { - fragColor = text_color; - /* mult both alpha factor to use strength factor */ - fragColor.a = min(fragColor.a * tColor.a, fragColor.a); - } - /* pattern */ - if (color_type == GPENCIL_COLOR_PATTERN) { - fragColor = tColor; - /* mult both alpha factor to use strength factor with color alpha limit */ - fragColor.a = min(text_color.a * tColor.a, tColor.a); - } + /* texture for endcaps */ + vec4 text_color; + if (uvfac[1] == ENDCAP) { + text_color = texture2D(myTexture, vec2(mTexCoord.x, mTexCoord.y)); + } + else { + text_color = texture2D(myTexture, mTexCoord); + } - /* gradient */ - /* keep this disabled while the line glitch bug exists - if (gradient_f < 1.0) { - float d = abs(mTexCoord.y - 0.5) * (1.1 - gradient_f); - float alpha = 1.0 - clamp((fragColor.a - (d * 2.0)), 0.03, 1.0); - fragColor.a = smoothstep(fragColor.a, 0.0, alpha); - - } - */ + /* texture */ + if (color_type == GPENCIL_COLOR_TEXTURE) { + fragColor = text_color; + /* mult both alpha factor to use strength factor */ + fragColor.a = min(fragColor.a * tColor.a, fragColor.a); + } + /* pattern */ + if (color_type == GPENCIL_COLOR_PATTERN) { + fragColor = tColor; + /* mult both alpha factor to use strength factor with color alpha limit */ + fragColor.a = min(text_color.a * tColor.a, tColor.a); + } - if(fragColor.a < 0.0035) - discard; + /* gradient */ + /* keep this disabled while the line glitch bug exists + if (gradient_f < 1.0) { + float d = abs(mTexCoord.y - 0.5) * (1.1 - gradient_f); + float alpha = 1.0 - clamp((fragColor.a - (d * 2.0)), 0.03, 1.0); + fragColor.a = smoothstep(fragColor.a, 0.0, alpha); + + } + */ + + if (fragColor.a < 0.0035) + discard; } diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_geom.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_geom.glsl index aa38ff26a62..7e62d6f0d64 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_geom.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_geom.glsl @@ -19,7 +19,7 @@ out vec2 uvfac; #define GP_XRAY_3DSPACE 1 /* keep this list synchronized with list in gpencil_engine.h */ -#define GPENCIL_COLOR_SOLID 0 +#define GPENCIL_COLOR_SOLID 0 #define GPENCIL_COLOR_TEXTURE 1 #define GPENCIL_COLOR_PATTERN 2 @@ -28,222 +28,229 @@ out vec2 uvfac; /* project 3d point to 2d on screen space */ vec2 toScreenSpace(vec4 vertex) { - return vec2(vertex.xy / vertex.w) * Viewport; + return vec2(vertex.xy / vertex.w) * Viewport; } /* get zdepth value */ float getZdepth(vec4 point) { - if (xraymode == GP_XRAY_FRONT) { - return 0.000001; - } - if (xraymode == GP_XRAY_3DSPACE) { - return (point.z / point.w); - } - - /* in front by default */ - return 0.000001; + if (xraymode == GP_XRAY_FRONT) { + return 0.000001; + } + if (xraymode == GP_XRAY_3DSPACE) { + return (point.z / point.w); + } + + /* in front by default */ + return 0.000001; } /* check equality but with a small tolerance */ bool is_equal(vec4 p1, vec4 p2) { - float limit = 0.0001; - float x = abs(p1.x - p2.x); - float y = abs(p1.y - p2.y); - float z = abs(p1.z - p2.z); + float limit = 0.0001; + float x = abs(p1.x - p2.x); + float y = abs(p1.y - p2.y); + float z = abs(p1.z - p2.z); - if ((x < limit) && (y < limit) && (z < limit)) { - return true; - } + if ((x < limit) && (y < limit) && (z < limit)) { + return true; + } - return false; + return false; } void main(void) { - float MiterLimit = 0.75; - uvfac = vec2(0.0, 0.0); - - /* receive 4 points */ - vec4 P0 = gl_in[0].gl_Position; - vec4 P1 = gl_in[1].gl_Position; - vec4 P2 = gl_in[2].gl_Position; - vec4 P3 = gl_in[3].gl_Position; - - /* get the four vertices passed to the shader */ - vec2 sp0 = toScreenSpace(P0); // start of previous segment - vec2 sp1 = toScreenSpace(P1); // end of previous segment, start of current segment - vec2 sp2 = toScreenSpace(P2); // end of current segment, start of next segment - vec2 sp3 = toScreenSpace(P3); // end of next segment - - /* culling outside viewport */ - vec2 area = Viewport * 4.0; - if (sp1.x < -area.x || sp1.x > area.x) return; - if (sp1.y < -area.y || sp1.y > area.y) return; - if (sp2.x < -area.x || sp2.x > area.x) return; - if (sp2.y < -area.y || sp2.y > area.y) return; - - /* culling behind camera */ - if (P1.w < 0 || P2.w < 0) return; - - /* determine the direction of each of the 3 segments (previous, current, next) */ - vec2 v0 = normalize(sp1 - sp0); - vec2 v1 = normalize(sp2 - sp1); - vec2 v2 = normalize(sp3 - sp2); - - /* determine the normal of each of the 3 segments (previous, current, next) */ - vec2 n0 = vec2(-v0.y, v0.x); - vec2 n1 = vec2(-v1.y, v1.x); - vec2 n2 = vec2(-v2.y, v2.x); - - /* determine miter lines by averaging the normals of the 2 segments */ - vec2 miter_a = normalize(n0 + n1); // miter at start of current segment - vec2 miter_b = normalize(n1 + n2); // miter at end of current segment - - /* determine the length of the miter by projecting it onto normal and then inverse it */ - float an1 = dot(miter_a, n1); - float bn1 = dot(miter_b, n2); - if (an1 == 0) an1 = 1; - if (bn1 == 0) bn1 = 1; - float length_a = finalThickness[1] / an1; - float length_b = finalThickness[2] / bn1; - if (length_a <= 0.0) length_a = 0.01; - if (length_b <= 0.0) length_b = 0.01; - - /* prevent excessively long miters at sharp corners */ - if (dot(v0, v1) < -MiterLimit) { - miter_a = n1; - length_a = finalThickness[1]; - - /* close the gap */ - if (dot(v0, n1) > 0) { - mTexCoord = vec2(0, 0); - mColor = finalColor[1]; - gl_Position = vec4((sp1 + finalThickness[1] * n0) / Viewport, getZdepth(P1), 1.0); - EmitVertex(); - - mTexCoord = vec2(0, 0); - mColor = finalColor[1]; - gl_Position = vec4((sp1 + finalThickness[1] * n1) / Viewport, getZdepth(P1), 1.0); - EmitVertex(); - - mTexCoord = vec2(0, 0.5); - mColor = finalColor[1]; - gl_Position = vec4(sp1 / Viewport, getZdepth(P1), 1.0); - EmitVertex(); - - EndPrimitive(); - } - else { - mTexCoord = vec2(0, 1); - mColor = finalColor[1]; - gl_Position = vec4((sp1 - finalThickness[1] * n1) / Viewport, getZdepth(P1), 1.0); - EmitVertex(); - - mTexCoord = vec2(0, 1); - mColor = finalColor[1]; - gl_Position = vec4((sp1 - finalThickness[1] * n0) / Viewport, getZdepth(P1), 1.0); - EmitVertex(); - - mTexCoord = vec2(0, 0.5); - mColor = finalColor[1]; - gl_Position = vec4(sp1 / Viewport, getZdepth(P1), 1.0); - EmitVertex(); - - EndPrimitive(); - } - } - - if (dot(v1, v2) < -MiterLimit) { - miter_b = n1; - length_b = finalThickness[2]; - } - - /* generate the start endcap */ - if ((caps_mode[0] != GPENCIL_FLATCAP) && is_equal(P0,P2)) - { - vec4 cap_color = finalColor[1]; - - mTexCoord = vec2(2.0, 0.5); - mColor = cap_color; - vec2 svn1 = normalize(sp1 - sp2) * length_a * 4.0; - uvfac = vec2(0.0, 1.0); - gl_Position = vec4((sp1 + svn1) / Viewport, getZdepth(P1), 1.0); - EmitVertex(); - - mTexCoord = vec2(0.0, -0.5); - mColor = cap_color; - uvfac = vec2(0.0, 1.0); - gl_Position = vec4((sp1 - (length_a * 2.0) * miter_a) / Viewport, getZdepth(P1), 1.0); - EmitVertex(); - - mTexCoord = vec2(0.0, 1.5); - mColor = cap_color; - uvfac = vec2(0.0, 1.0); - gl_Position = vec4((sp1 + (length_a * 2.0) * miter_a) / Viewport, getZdepth(P1), 1.0); - EmitVertex(); - } - - float y_a = 0.0; - float y_b = 1.0; - - /* invert uv (vertical) */ - if (finaluvdata[2].x > 1.0) { - if ((finaluvdata[1].y != 0.0) && (finaluvdata[2].y != 0.0)) { - float d = ceil(finaluvdata[2].x) - 1.0; - if (floor(d / 2.0) == (d / 2.0)) { - y_a = 1.0; - y_b = 0.0; - } - } - } - /* generate the triangle strip */ - uvfac = vec2(0.0, 0.0); - mTexCoord = (color_type == GPENCIL_COLOR_SOLID) ? vec2(0, 0) : vec2(finaluvdata[1].x, y_a); - mColor = finalColor[1]; - gl_Position = vec4((sp1 + length_a * miter_a) / Viewport, getZdepth(P1), 1.0); - EmitVertex(); - - mTexCoord = (color_type == GPENCIL_COLOR_SOLID) ? vec2(0, 1) : vec2(finaluvdata[1].x, y_b); - mColor = finalColor[1]; - gl_Position = vec4((sp1 - length_a * miter_a) / Viewport, getZdepth(P1), 1.0); - EmitVertex(); - - mTexCoord = (color_type == GPENCIL_COLOR_SOLID) ? vec2(1, 0) : vec2(finaluvdata[2].x, y_a); - mColor = finalColor[2]; - gl_Position = vec4((sp2 + length_b * miter_b) / Viewport, getZdepth(P2), 1.0); - EmitVertex(); - - mTexCoord = (color_type == GPENCIL_COLOR_SOLID) ? vec2(1, 1) : vec2(finaluvdata[2].x, y_b); - mColor = finalColor[2]; - gl_Position = vec4((sp2 - length_b * miter_b) / Viewport, getZdepth(P2), 1.0); - EmitVertex(); - - /* generate the end endcap */ - if ((caps_mode[1] != GPENCIL_FLATCAP) && is_equal(P1,P3) && (finaluvdata[2].x > 0)) - { - vec4 cap_color = finalColor[2]; - - mTexCoord = vec2(finaluvdata[2].x, 1.5); - mColor = cap_color; - uvfac = vec2(finaluvdata[2].x, 1.0); - gl_Position = vec4((sp2 + (length_b * 2.0) * miter_b) / Viewport, getZdepth(P2), 1.0); - EmitVertex(); - - mTexCoord = vec2(finaluvdata[2].x, -0.5); - mColor = cap_color; - uvfac = vec2(finaluvdata[2].x, 1.0); - gl_Position = vec4((sp2 - (length_b * 2.0) * miter_b) / Viewport, getZdepth(P2), 1.0); - EmitVertex(); - - mTexCoord = vec2(finaluvdata[2].x + 2, 0.5); - mColor = cap_color; - uvfac = vec2(finaluvdata[2].x, 1.0); - vec2 svn2 = normalize(sp2 - sp1) * length_b * 4.0; - gl_Position = vec4((sp2 + svn2) / Viewport, getZdepth(P2), 1.0); - EmitVertex(); - } - - EndPrimitive(); + float MiterLimit = 0.75; + uvfac = vec2(0.0, 0.0); + + /* receive 4 points */ + vec4 P0 = gl_in[0].gl_Position; + vec4 P1 = gl_in[1].gl_Position; + vec4 P2 = gl_in[2].gl_Position; + vec4 P3 = gl_in[3].gl_Position; + + /* get the four vertices passed to the shader */ + vec2 sp0 = toScreenSpace(P0); // start of previous segment + vec2 sp1 = toScreenSpace(P1); // end of previous segment, start of current segment + vec2 sp2 = toScreenSpace(P2); // end of current segment, start of next segment + vec2 sp3 = toScreenSpace(P3); // end of next segment + + /* culling outside viewport */ + vec2 area = Viewport * 4.0; + if (sp1.x < -area.x || sp1.x > area.x) + return; + if (sp1.y < -area.y || sp1.y > area.y) + return; + if (sp2.x < -area.x || sp2.x > area.x) + return; + if (sp2.y < -area.y || sp2.y > area.y) + return; + + /* culling behind camera */ + if (P1.w < 0 || P2.w < 0) + return; + + /* determine the direction of each of the 3 segments (previous, current, next) */ + vec2 v0 = normalize(sp1 - sp0); + vec2 v1 = normalize(sp2 - sp1); + vec2 v2 = normalize(sp3 - sp2); + + /* determine the normal of each of the 3 segments (previous, current, next) */ + vec2 n0 = vec2(-v0.y, v0.x); + vec2 n1 = vec2(-v1.y, v1.x); + vec2 n2 = vec2(-v2.y, v2.x); + + /* determine miter lines by averaging the normals of the 2 segments */ + vec2 miter_a = normalize(n0 + n1); // miter at start of current segment + vec2 miter_b = normalize(n1 + n2); // miter at end of current segment + + /* determine the length of the miter by projecting it onto normal and then inverse it */ + float an1 = dot(miter_a, n1); + float bn1 = dot(miter_b, n2); + if (an1 == 0) + an1 = 1; + if (bn1 == 0) + bn1 = 1; + float length_a = finalThickness[1] / an1; + float length_b = finalThickness[2] / bn1; + if (length_a <= 0.0) + length_a = 0.01; + if (length_b <= 0.0) + length_b = 0.01; + + /* prevent excessively long miters at sharp corners */ + if (dot(v0, v1) < -MiterLimit) { + miter_a = n1; + length_a = finalThickness[1]; + + /* close the gap */ + if (dot(v0, n1) > 0) { + mTexCoord = vec2(0, 0); + mColor = finalColor[1]; + gl_Position = vec4((sp1 + finalThickness[1] * n0) / Viewport, getZdepth(P1), 1.0); + EmitVertex(); + + mTexCoord = vec2(0, 0); + mColor = finalColor[1]; + gl_Position = vec4((sp1 + finalThickness[1] * n1) / Viewport, getZdepth(P1), 1.0); + EmitVertex(); + + mTexCoord = vec2(0, 0.5); + mColor = finalColor[1]; + gl_Position = vec4(sp1 / Viewport, getZdepth(P1), 1.0); + EmitVertex(); + + EndPrimitive(); + } + else { + mTexCoord = vec2(0, 1); + mColor = finalColor[1]; + gl_Position = vec4((sp1 - finalThickness[1] * n1) / Viewport, getZdepth(P1), 1.0); + EmitVertex(); + + mTexCoord = vec2(0, 1); + mColor = finalColor[1]; + gl_Position = vec4((sp1 - finalThickness[1] * n0) / Viewport, getZdepth(P1), 1.0); + EmitVertex(); + + mTexCoord = vec2(0, 0.5); + mColor = finalColor[1]; + gl_Position = vec4(sp1 / Viewport, getZdepth(P1), 1.0); + EmitVertex(); + + EndPrimitive(); + } + } + + if (dot(v1, v2) < -MiterLimit) { + miter_b = n1; + length_b = finalThickness[2]; + } + + /* generate the start endcap */ + if ((caps_mode[0] != GPENCIL_FLATCAP) && is_equal(P0, P2)) { + vec4 cap_color = finalColor[1]; + + mTexCoord = vec2(2.0, 0.5); + mColor = cap_color; + vec2 svn1 = normalize(sp1 - sp2) * length_a * 4.0; + uvfac = vec2(0.0, 1.0); + gl_Position = vec4((sp1 + svn1) / Viewport, getZdepth(P1), 1.0); + EmitVertex(); + + mTexCoord = vec2(0.0, -0.5); + mColor = cap_color; + uvfac = vec2(0.0, 1.0); + gl_Position = vec4((sp1 - (length_a * 2.0) * miter_a) / Viewport, getZdepth(P1), 1.0); + EmitVertex(); + + mTexCoord = vec2(0.0, 1.5); + mColor = cap_color; + uvfac = vec2(0.0, 1.0); + gl_Position = vec4((sp1 + (length_a * 2.0) * miter_a) / Viewport, getZdepth(P1), 1.0); + EmitVertex(); + } + + float y_a = 0.0; + float y_b = 1.0; + + /* invert uv (vertical) */ + if (finaluvdata[2].x > 1.0) { + if ((finaluvdata[1].y != 0.0) && (finaluvdata[2].y != 0.0)) { + float d = ceil(finaluvdata[2].x) - 1.0; + if (floor(d / 2.0) == (d / 2.0)) { + y_a = 1.0; + y_b = 0.0; + } + } + } + /* generate the triangle strip */ + uvfac = vec2(0.0, 0.0); + mTexCoord = (color_type == GPENCIL_COLOR_SOLID) ? vec2(0, 0) : vec2(finaluvdata[1].x, y_a); + mColor = finalColor[1]; + gl_Position = vec4((sp1 + length_a * miter_a) / Viewport, getZdepth(P1), 1.0); + EmitVertex(); + + mTexCoord = (color_type == GPENCIL_COLOR_SOLID) ? vec2(0, 1) : vec2(finaluvdata[1].x, y_b); + mColor = finalColor[1]; + gl_Position = vec4((sp1 - length_a * miter_a) / Viewport, getZdepth(P1), 1.0); + EmitVertex(); + + mTexCoord = (color_type == GPENCIL_COLOR_SOLID) ? vec2(1, 0) : vec2(finaluvdata[2].x, y_a); + mColor = finalColor[2]; + gl_Position = vec4((sp2 + length_b * miter_b) / Viewport, getZdepth(P2), 1.0); + EmitVertex(); + + mTexCoord = (color_type == GPENCIL_COLOR_SOLID) ? vec2(1, 1) : vec2(finaluvdata[2].x, y_b); + mColor = finalColor[2]; + gl_Position = vec4((sp2 - length_b * miter_b) / Viewport, getZdepth(P2), 1.0); + EmitVertex(); + + /* generate the end endcap */ + if ((caps_mode[1] != GPENCIL_FLATCAP) && is_equal(P1, P3) && (finaluvdata[2].x > 0)) { + vec4 cap_color = finalColor[2]; + + mTexCoord = vec2(finaluvdata[2].x, 1.5); + mColor = cap_color; + uvfac = vec2(finaluvdata[2].x, 1.0); + gl_Position = vec4((sp2 + (length_b * 2.0) * miter_b) / Viewport, getZdepth(P2), 1.0); + EmitVertex(); + + mTexCoord = vec2(finaluvdata[2].x, -0.5); + mColor = cap_color; + uvfac = vec2(finaluvdata[2].x, 1.0); + gl_Position = vec4((sp2 - (length_b * 2.0) * miter_b) / Viewport, getZdepth(P2), 1.0); + EmitVertex(); + + mTexCoord = vec2(finaluvdata[2].x + 2, 0.5); + mColor = cap_color; + uvfac = vec2(finaluvdata[2].x, 1.0); + vec2 svn2 = normalize(sp2 - sp1) * length_b * 4.0; + gl_Position = vec4((sp2 + svn2) / Viewport, getZdepth(P2), 1.0); + EmitVertex(); + } + + EndPrimitive(); } diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_vert.glsl index 62740f37ae8..946b39c006a 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_vert.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_vert.glsl @@ -1,7 +1,7 @@ uniform mat4 ModelViewProjectionMatrix; uniform mat4 ProjectionMatrix; -uniform float pixsize; /* rv3d->pixsize */ +uniform float pixsize; /* rv3d->pixsize */ uniform int keep_size; uniform float objscale; uniform float pixfactor; @@ -20,41 +20,43 @@ out vec2 finaluvdata; #define TRUE 1 -#define OB_WIRE 2 +#define OB_WIRE 2 #define OB_SOLID 3 -#define V3D_SHADING_MATERIAL_COLOR 0 -#define V3D_SHADING_TEXTURE_COLOR 3 +#define V3D_SHADING_MATERIAL_COLOR 0 +#define V3D_SHADING_TEXTURE_COLOR 3 float defaultpixsize = pixsize * (1000.0 / pixfactor); void main(void) { - gl_Position = ModelViewProjectionMatrix * vec4( pos, 1.0 ); - finalColor = color; - - if (keep_size == TRUE) { - finalThickness = thickness; - } - else { - float size = (ProjectionMatrix[3][3] == 0.0) ? (thickness / (gl_Position.z * defaultpixsize)) : (thickness / defaultpixsize); - finalThickness = max(size * objscale, 1.0); - } - - /* for wireframe override size and color */ - if (shading_type[0] == OB_WIRE) { - finalThickness = 1.0; - finalColor = wire_color; - } - /* for solid override color */ - if (shading_type[0] == OB_SOLID) { - if ((shading_type[1] != V3D_SHADING_MATERIAL_COLOR) && (shading_type[1] != V3D_SHADING_TEXTURE_COLOR)) { - finalColor = wire_color; - } - if (viewport_xray == 1) { - finalColor.a *= 0.5; - } - } - - finaluvdata = uvdata; + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + finalColor = color; + + if (keep_size == TRUE) { + finalThickness = thickness; + } + else { + float size = (ProjectionMatrix[3][3] == 0.0) ? (thickness / (gl_Position.z * defaultpixsize)) : + (thickness / defaultpixsize); + finalThickness = max(size * objscale, 1.0); + } + + /* for wireframe override size and color */ + if (shading_type[0] == OB_WIRE) { + finalThickness = 1.0; + finalColor = wire_color; + } + /* for solid override color */ + if (shading_type[0] == OB_SOLID) { + if ((shading_type[1] != V3D_SHADING_MATERIAL_COLOR) && + (shading_type[1] != V3D_SHADING_TEXTURE_COLOR)) { + finalColor = wire_color; + } + if (viewport_xray == 1) { + finalColor.a *= 0.5; + } + } + + finaluvdata = uvdata; } diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_zdepth_mix_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_zdepth_mix_frag.glsl index a32fd87a446..be645548402 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_zdepth_mix_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_zdepth_mix_frag.glsl @@ -10,65 +10,65 @@ uniform int do_select; float srgb_to_linearrgb(float c) { - if (c < 0.04045) { - return (c < 0.0) ? 0.0 : c * (1.0 / 12.92); - } - else { - return pow((c + 0.055) * (1.0 / 1.055), 2.4); - } + if (c < 0.04045) { + return (c < 0.0) ? 0.0 : c * (1.0 / 12.92); + } + else { + return pow((c + 0.055) * (1.0 / 1.055), 2.4); + } } float linearrgb_to_srgb(float c) { - if (c < 0.0031308) { - return (c < 0.0) ? 0.0 : c * 12.92; - } - else { - return 1.055 * pow(c, 1.0 / 2.4) - 0.055; - } + if (c < 0.0031308) { + return (c < 0.0) ? 0.0 : c * 12.92; + } + else { + return 1.055 * pow(c, 1.0 / 2.4) - 0.055; + } } bool check_borders(ivec2 uv, int size) { - for (int x = -size; x <= size; x++) { - for (int y = -size; y <= size; y++) { - vec4 stroke_color = texelFetch(strokeColor, ivec2(uv.x + x, uv.y + y), 0).rgba; - if (stroke_color.a > 0) { - return true; - } - } - } + for (int x = -size; x <= size; x++) { + for (int y = -size; y <= size; y++) { + vec4 stroke_color = texelFetch(strokeColor, ivec2(uv.x + x, uv.y + y), 0).rgba; + if (stroke_color.a > 0) { + return true; + } + } + } - return false; + return false; } void main() { - ivec2 uv = ivec2(gl_FragCoord.xy); - float stroke_depth = texelFetch(strokeDepth, uv, 0).r; - vec4 stroke_color = texelFetch(strokeColor, uv, 0).rgba; + ivec2 uv = ivec2(gl_FragCoord.xy); + float stroke_depth = texelFetch(strokeDepth, uv, 0).r; + vec4 stroke_color = texelFetch(strokeColor, uv, 0).rgba; - /* premult alpha factor to remove double blend effects */ - if (stroke_color.a > 0) { - stroke_color = vec4(vec3(stroke_color.rgb / stroke_color.a), stroke_color.a); - } + /* premult alpha factor to remove double blend effects */ + if (stroke_color.a > 0) { + stroke_color = vec4(vec3(stroke_color.rgb / stroke_color.a), stroke_color.a); + } - /* apply color correction for render only */ - if (tonemapping == 1) { - stroke_color.r = srgb_to_linearrgb(stroke_color.r); - stroke_color.g = srgb_to_linearrgb(stroke_color.g); - stroke_color.b = srgb_to_linearrgb(stroke_color.b); - } + /* apply color correction for render only */ + if (tonemapping == 1) { + stroke_color.r = srgb_to_linearrgb(stroke_color.r); + stroke_color.g = srgb_to_linearrgb(stroke_color.g); + stroke_color.b = srgb_to_linearrgb(stroke_color.b); + } - FragColor = clamp(stroke_color, 0.0, 1.0); - gl_FragDepth = clamp(stroke_depth, 0.0, 1.0); + FragColor = clamp(stroke_color, 0.0, 1.0); + gl_FragDepth = clamp(stroke_depth, 0.0, 1.0); - if (do_select == 1) { - if (stroke_color.a == 0) { - if (check_borders(uv, 2)) { - FragColor = select_color; - gl_FragDepth = 0.000001; - } - } - } + if (do_select == 1) { + if (stroke_color.a == 0) { + if (check_borders(uv, 2)) { + FragColor = select_color; + gl_FragDepth = 0.000001; + } + } + } } |