diff options
24 files changed, 328 insertions, 18 deletions
diff --git a/release/scripts/startup/bl_ui/properties_material_gpencil.py b/release/scripts/startup/bl_ui/properties_material_gpencil.py index 24ba786f7af..8cb59ceee5c 100644 --- a/release/scripts/startup/bl_ui/properties_material_gpencil.py +++ b/release/scripts/startup/bl_ui/properties_material_gpencil.py @@ -148,6 +148,9 @@ class MATERIAL_PT_gpencil_strokecolor(GPMaterialButtonsPanel, Panel): if gpcolor.stroke_style == 'SOLID' or gpcolor.use_stroke_pattern is True: col.prop(gpcolor, "color", text="Color") + if gpcolor.mode in {'DOTS', 'BOX'}: + col.prop(gpcolor, "use_follow_path", text="Follow Drawing Path") + class MATERIAL_PT_gpencil_fillcolor(GPMaterialButtonsPanel, Panel): bl_label = "Fill" diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index 17dd35d9fc4..7c1fa0f9663 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -1716,9 +1716,9 @@ class VIEW3D_PT_tools_grease_pencil_brush_option(View3DPanel, Panel): layout.use_property_decorate = False brush = context.tool_settings.gpencil_paint.brush - gp_settings = brush.gpencil_settings if brush is not None: + gp_settings = brush.gpencil_settings col = layout.column(align=True) col.prop(gp_settings, "input_samples") col.separator() @@ -1728,7 +1728,20 @@ class VIEW3D_PT_tools_grease_pencil_brush_option(View3DPanel, Panel): col.prop(gp_settings, "angle", slider=True) col.prop(gp_settings, "angle_factor", text="Factor", slider=True) + + ob = context.object + if ob: + ma = ob.active_material + + if brush.gpencil_settings.material: + ma = brush.gpencil_settings.material + col.separator() + subcol = col.column(align=True) + if ma and ma.grease_pencil.mode != 'DOTS': + subcol.enabled = False + subcol.prop(gp_settings, "gradient_factor", slider=True) + subcol.prop(gp_settings, "gradient_shape") class VIEW3D_PT_tools_grease_pencil_brush_stabilizer(View3DPanel, Panel): diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index ea5605d8ed1..e0bc914dd78 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -304,6 +304,10 @@ void BKE_brush_gpencil_presets(bContext *C) brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS; brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR; + brush->gpencil_settings->gradient_f = 1.0f; + brush->gpencil_settings->gradient_s[0] = 1.0f; + brush->gpencil_settings->gradient_s[1] = 1.0f; + /* Pen brush */ brush = BKE_brush_add_gpencil(bmain, ts, "Draw Pen"); deft = brush; /* save default brush */ @@ -336,6 +340,10 @@ void BKE_brush_gpencil_presets(bContext *C) brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS; brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR; + brush->gpencil_settings->gradient_f = 1.0f; + brush->gpencil_settings->gradient_s[0] = 1.0f; + brush->gpencil_settings->gradient_s[1] = 1.0f; + /* Ink brush */ brush = BKE_brush_add_gpencil(bmain, ts, "Draw Ink"); brush->size = 60.0f; @@ -365,6 +373,10 @@ void BKE_brush_gpencil_presets(bContext *C) brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS; brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR; + brush->gpencil_settings->gradient_f = 1.0f; + brush->gpencil_settings->gradient_s[0] = 1.0f; + brush->gpencil_settings->gradient_s[1] = 1.0f; + /* Curve */ custom_curve = brush->gpencil_settings->curve_sensitivity; curvemapping_set_defaults(custom_curve, 0, 0.0f, 0.0f, 1.0f, 1.0f); @@ -408,6 +420,10 @@ void BKE_brush_gpencil_presets(bContext *C) curvemapping_initialize(custom_curve); brush_gpencil_curvemap_reset(custom_curve->cm, 3, GPCURVE_PRESET_INKNOISE); + brush->gpencil_settings->gradient_f = 1.0f; + brush->gpencil_settings->gradient_s[0] = 1.0f; + brush->gpencil_settings->gradient_s[1] = 1.0f; + /* Block Basic brush */ brush = BKE_brush_add_gpencil(bmain, ts, "Draw Block"); brush->size = 150.0f; @@ -436,6 +452,10 @@ void BKE_brush_gpencil_presets(bContext *C) brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS; brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR; + brush->gpencil_settings->gradient_f = 1.0f; + brush->gpencil_settings->gradient_s[0] = 1.0f; + brush->gpencil_settings->gradient_s[1] = 1.0f; + /* Marker brush */ brush = BKE_brush_add_gpencil(bmain, ts, "Draw Marker"); brush->size = 80.0f; @@ -472,6 +492,10 @@ void BKE_brush_gpencil_presets(bContext *C) curvemapping_initialize(custom_curve); brush_gpencil_curvemap_reset(custom_curve->cm, 4, GPCURVE_PRESET_MARKER); + brush->gpencil_settings->gradient_f = 1.0f; + brush->gpencil_settings->gradient_s[0] = 1.0f; + brush->gpencil_settings->gradient_s[1] = 1.0f; + /* Fill brush */ brush = BKE_brush_add_gpencil(bmain, ts, "Fill Area"); brush->size = 1.0f; @@ -495,6 +519,10 @@ void BKE_brush_gpencil_presets(bContext *C) brush->gpencil_settings->draw_strength = 1.0f; + brush->gpencil_settings->gradient_f = 1.0f; + brush->gpencil_settings->gradient_s[0] = 1.0f; + brush->gpencil_settings->gradient_s[1] = 1.0f; + /* Soft Eraser brush */ brush = BKE_brush_add_gpencil(bmain, ts, "Eraser Soft"); brush->size = 30.0f; diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index c204a8128c1..d47b3f20a28 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -467,6 +467,10 @@ bGPDstroke *BKE_gpencil_add_stroke(bGPDframe *gpf, int mat_idx, int totpoints, s bGPDstroke *gps = MEM_callocN(sizeof(bGPDstroke), "gp_stroke"); gps->thickness = thickness; + gps->gradient_f = 1.0f; + gps->gradient_s[0] = 1.0f; + gps->gradient_s[1] = 1.0f; + gps->inittime = 0; /* enable recalculation flag by default */ diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index ce2345b44db..41b1627e873 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -3110,6 +3110,33 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) } } } + + /* init grease pencil brush gradients */ + if (!DNA_struct_elem_find(fd->filesdna, "BrushGpencilSettings", "float", "gradient_f")) { + for (Brush *brush = bmain->brushes.first; brush; brush = brush->id.next) { + if (brush->gpencil_settings != NULL) { + BrushGpencilSettings *gp = brush->gpencil_settings; + gp->gradient_f = 1.0f; + gp->gradient_s[0] = 1.0f; + gp->gradient_s[1] = 1.0f; + } + } + } + + /* init grease pencil stroke gradients */ + if (!DNA_struct_elem_find(fd->filesdna, "bGPDstroke", "float", "gradient_f")) { + for (bGPdata *gpd = bmain->gpencils.first; gpd; gpd = gpd->id.next) { + for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { + for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) { + for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { + gps->gradient_f = 1.0f; + gps->gradient_s[0] = 1.0f; + gps->gradient_s[1] = 1.0f; + } + } + } + } + } } { 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 b72a6ebebbd..3bcc963c966 100644 --- a/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c +++ b/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c @@ -95,6 +95,7 @@ void DRW_gpencil_get_point_geom(GpencilBatchCacheElem *be, bGPDstroke *gps, shor 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); @@ -123,6 +124,26 @@ void DRW_gpencil_get_point_geom(GpencilBatchCacheElem *be, bGPDstroke *gps, shor 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++; } } diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c index 6aefd2a69c5..8ecee86d92b 100644 --- a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c +++ b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c @@ -532,6 +532,10 @@ DRWShadingGroup *DRW_gpencil_shgroup_stroke_create( 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); @@ -565,6 +569,8 @@ DRWShadingGroup *DRW_gpencil_shgroup_stroke_create( 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); @@ -611,7 +617,7 @@ DRWShadingGroup *DRW_gpencil_shgroup_stroke_create( /* 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, + bGPdata *gpd, bGPDlayer *gpl, bGPDstroke *gps, MaterialGPencilStyle *gp_style, int id, bool onion, const float scale, const int shading_type[2]) { @@ -651,6 +657,11 @@ static DRWShadingGroup *DRW_gpencil_shgroup_point_create( 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); @@ -684,6 +695,10 @@ static DRWShadingGroup *DRW_gpencil_shgroup_point_create( 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); @@ -693,12 +708,21 @@ static DRWShadingGroup *DRW_gpencil_shgroup_point_create( 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; @@ -1374,6 +1398,12 @@ void DRW_gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data, void *vedata, T * 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)) { @@ -1385,7 +1415,7 @@ void DRW_gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data, void *vedata, T 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, gp_style, -1, + gpd, NULL, NULL, gp_style, -1, false, 1.0f, (const int *)stl->storage->shade_render); } @@ -1582,7 +1612,7 @@ static void DRW_gpencil_shgroups_create( shgrp = DRW_gpencil_shgroup_point_create( e_data, vedata, stroke_pass, e_data->gpencil_point_sh, - ob, gpd, gpl, gp_style, stl->storage->shgroup_id, elm->onion, + ob, gpd, gpl, gps, gp_style, stl->storage->shgroup_id, elm->onion, scale, cache_ob->shading_type); DRW_shgroup_call_range_add( diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h index 8af74ec7451..5d0d2397f8d 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.h +++ b/source/blender/draw/engines/gpencil/gpencil_engine.h @@ -119,6 +119,10 @@ typedef struct GPENCIL_shgroup { 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]; @@ -164,6 +168,10 @@ typedef struct GPENCIL_Storage { 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]; @@ -334,6 +342,7 @@ typedef struct GpencilBatchCacheElem { uint color_id; uint thickness_id; uint uvdata_id; + uint prev_pos_id; /* size for VBO alloc */ int tot_vertex; 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 a1285029e4c..ca8c888fe21 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_point_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_point_frag.glsl @@ -2,6 +2,9 @@ uniform int color_type; uniform int mode; uniform sampler2D myTexture; +uniform float gradient_f; +uniform vec2 gradient_s; + in vec4 mColor; in vec2 mTexCoord; out vec4 fragColor; @@ -17,15 +20,23 @@ out vec4 fragColor; #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; +} + void main() { vec2 centered = mTexCoord - vec2(0.5); - float dist_squared = dot(centered, centered); - const float rad_squared = 0.25; + float ellip = checkpoint(centered, vec2(gradient_s / 2.0)); - /* Round point with jaggy edges. */ - if ((mode != GPENCIL_MODE_BOX) && (dist_squared > rad_squared)) { - discard; + if (mode != GPENCIL_MODE_BOX) { + if (ellip > 1.0) { + discard; + } } vec4 tmp_color = texture2D(myTexture, mTexCoord); @@ -47,6 +58,15 @@ void main() /* mult both alpha factor to use strength factor with color alpha limit */ fragColor.a = min(text_color.a * mColor.a, mColor.a); } - if(fragColor.a < 0.0035) + + 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; + } } 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 6c22633c521..32aaa057298 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_point_geom.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_point_geom.glsl @@ -1,6 +1,7 @@ uniform mat4 ModelViewProjectionMatrix; uniform vec2 Viewport; uniform int xraymode; +uniform int use_follow_path; layout(points) in; layout(triangle_strip, max_vertices = 4) out; @@ -8,6 +9,7 @@ layout(triangle_strip, max_vertices = 4) out; in vec4 finalColor[1]; in float finalThickness[1]; in vec2 finaluvdata[1]; +in vec4 finalprev_pos[1]; out vec4 mColor; out vec2 mTexCoord; @@ -15,6 +17,10 @@ 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 + /* project 3d point to 2d on screen space */ vec2 toScreenSpace(vec4 vertex) { @@ -45,33 +51,89 @@ vec2 rotateUV(vec2 uv, float 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; +} + +/* 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; +} + void main(void) { - /* receive 4 points */ + /* 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]; - float aspect = 1.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]; - gl_Position = vec4(vec2(sp0.x - size, sp0.y + size * aspect) / Viewport, getZdepth(P0), 1.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]; - gl_Position = vec4(vec2(sp0.x - size, sp0.y - size * aspect) / Viewport, getZdepth(P0), 1.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]; - gl_Position = vec4(vec2(sp0.x + size, sp0.y + size * aspect) / Viewport, getZdepth(P0), 1.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]; - gl_Position = vec4(vec2(sp0.x + size, sp0.y - size * aspect) / Viewport, getZdepth(P0), 1.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 2606bbf878e..7deca544176 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl @@ -13,10 +13,12 @@ in vec3 pos; in vec4 color; in float thickness; in vec2 uvdata; +in vec3 prev_pos; out vec4 finalColor; out float finalThickness; out vec2 finaluvdata; +out vec4 finalprev_pos; #define TRUE 1 @@ -30,7 +32,8 @@ float defaultpixsize = pixsize * (1000.0 / pixfactor); void main() { - gl_Position = ModelViewProjectionMatrix * vec4( pos, 1.0 ); + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + finalprev_pos = ModelViewProjectionMatrix * vec4(prev_pos, 1.0); finalColor = color; if (keep_size == TRUE) { 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 80fa899b13a..a49a6e84f17 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_frag.glsl @@ -1,6 +1,8 @@ uniform int color_type; uniform sampler2D myTexture; +uniform float gradient_f; + in vec4 mColor; in vec2 mTexCoord; in vec2 uvfac; @@ -18,6 +20,7 @@ out vec4 fragColor; void main() { + vec4 tColor = vec4(mColor); /* if uvfac[1] == 1, then encap */ if (uvfac[1] == ENDCAP) { @@ -54,6 +57,16 @@ void main() fragColor.a = min(text_color.a * tColor.a, tColor.a); } + /* 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/editors/gpencil/annotate_paint.c b/source/blender/editors/gpencil/annotate_paint.c index 5152bcb0a90..dcecd87a862 100644 --- a/source/blender/editors/gpencil/annotate_paint.c +++ b/source/blender/editors/gpencil/annotate_paint.c @@ -681,6 +681,9 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) /* copy appropriate settings for stroke */ gps->totpoints = totelem; gps->thickness = gpl->thickness; + gps->gradient_f = 1.0f; + gps->gradient_s[0] = 1.0f; + gps->gradient_s[1] = 1.0f; gps->flag = gpd->runtime.sbuffer_sflag; gps->inittime = p->inittime; diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c index e13dfb38c7d..76d15557055 100644 --- a/source/blender/editors/gpencil/gpencil_fill.c +++ b/source/blender/editors/gpencil/gpencil_fill.c @@ -1011,6 +1011,8 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf) /* create new stroke */ bGPDstroke *gps = MEM_callocN(sizeof(bGPDstroke), "bGPDstroke"); gps->thickness = brush->size; + gps->gradient_f = brush->gpencil_settings->gradient_f; + copy_v2_v2(gps->gradient_s, brush->gpencil_settings->gradient_s); gps->inittime = 0.0f; /* the polygon must be closed, so enabled cyclic */ diff --git a/source/blender/editors/gpencil/gpencil_merge.c b/source/blender/editors/gpencil/gpencil_merge.c index 80b26a366fe..10bf45a9e2f 100644 --- a/source/blender/editors/gpencil/gpencil_merge.c +++ b/source/blender/editors/gpencil/gpencil_merge.c @@ -127,6 +127,8 @@ static bGPDstroke *gpencil_prepare_stroke(bContext *C, wmOperator *op, int totpo gps->totpoints = totpoints; gps->inittime = 0.0f; gps->thickness = brush->size; + gps->gradient_f = brush->gpencil_settings->gradient_f; + copy_v2_v2(gps->gradient_s, brush->gpencil_settings->gradient_s); gps->flag |= GP_STROKE_SELECT; gps->flag |= GP_STROKE_3DSPACE; gps->mat_nr = ob->actcol - 1; diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index daea24ecaa3..aadaff5b7cc 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -944,6 +944,8 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) /* copy appropriate settings for stroke */ gps->totpoints = totelem; gps->thickness = brush->size; + gps->gradient_f = brush->gpencil_settings->gradient_f; + copy_v2_v2(gps->gradient_s, brush->gpencil_settings->gradient_s); gps->flag = gpd->runtime.sbuffer_sflag; gps->inittime = p->inittime; diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c index f92398520fa..374dbbf4d9c 100644 --- a/source/blender/editors/gpencil/gpencil_primitive.c +++ b/source/blender/editors/gpencil/gpencil_primitive.c @@ -319,6 +319,9 @@ static void gp_primitive_set_initdata(bContext *C, tGPDprimitive *tgpi) /* create new temp stroke */ bGPDstroke *gps = MEM_callocN(sizeof(bGPDstroke), "Temp bGPDstroke"); gps->thickness = 2.0f; + gps->gradient_f = 1.0f; + gps->gradient_s[0] = 1.0f; + gps->gradient_s[1] = 1.0f; gps->inittime = 0.0f; /* enable recalculation flag by default */ @@ -1199,6 +1202,7 @@ static void gpencil_primitive_interaction_end(bContext *C, wmOperator *op, wmWin bGPDstroke *gps; ToolSettings *ts = tgpi->scene->toolsettings; + Brush *brush = tgpi->brush; const int def_nr = tgpi->ob->actdef - 1; const bool have_weight = (bool)BLI_findlink(&tgpi->ob->defbase, def_nr); @@ -1221,7 +1225,10 @@ static void gpencil_primitive_interaction_end(bContext *C, wmOperator *op, wmWin /* prepare stroke to get transferred */ gps = tgpi->gpf->strokes.first; if (gps) { - gps->thickness = tgpi->brush->size; + gps->thickness = brush->size; + gps->gradient_f = brush->gpencil_settings->gradient_f; + copy_v2_v2(gps->gradient_s, brush->gpencil_settings->gradient_s); + gps->flag |= GP_STROKE_RECALC_GEOMETRY; gps->tot_triangles = 0; diff --git a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c index f8f92d8bef8..253e02ca639 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c @@ -437,6 +437,9 @@ static bool view3d_ruler_to_gpencil(bContext *C, wmGizmoGroup *gzgroup) } gps->flag = GP_STROKE_3DSPACE; gps->thickness = 3; + gps->gradient_f = 1.0f; + gps->gradient_s[0] = 1.0f; + gps->gradient_s[1] = 1.0f; BLI_addtail(&gpf->strokes, gps); changed = true; diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h index 4bfbb3655af..9aa6ff8c1c8 100644 --- a/source/blender/makesdna/DNA_brush_types.h +++ b/source/blender/makesdna/DNA_brush_types.h @@ -111,6 +111,12 @@ typedef struct BrushGpencilSettings { /** Internal grease pencil drawing flags. */ int flag; + /** gradient control along y for color */ + float gradient_f; + /** factor xy of shape for dots gradients */ + float gradient_s[2]; + char _pad_2[4]; + struct CurveMapping *curve_sensitivity; struct CurveMapping *curve_strength; struct CurveMapping *curve_jitter; diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h index 56e17fe9149..dc752cc0bc9 100644 --- a/source/blender/makesdna/DNA_gpencil_types.h +++ b/source/blender/makesdna/DNA_gpencil_types.h @@ -199,6 +199,12 @@ typedef struct bGPDstroke { /** Caps mode for each stroke extreme */ short caps[2]; + /** gradient control along y for color */ + float gradient_f; + /** factor xy of shape for dots gradients */ + float gradient_s[2]; + char _pad_3[4]; + /** Vertex weight data. */ struct MDeformVert *dvert; void *_pad3; diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h index 3db8bf92f56..a8f3384ea85 100644 --- a/source/blender/makesdna/DNA_material_types.h +++ b/source/blender/makesdna/DNA_material_types.h @@ -121,6 +121,8 @@ typedef enum eMaterialGPencilStyle_Flag { GP_STYLE_STROKE_SHOW = (1 << 8), /* Fill show main switch */ GP_STYLE_FILL_SHOW = (1 << 9), + /* Don't rotate dots/boxes */ + GP_STYLE_COLOR_LOCK_DOTS = (1 << 10) } eMaterialGPencilStyle_Flag; typedef enum eMaterialGPencilStyle_Mode { diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index ce5b18331c6..23ae314f885 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -1197,6 +1197,25 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + /* gradient control */ + prop = RNA_def_property(srna, "gradient_factor", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "gradient_f"); + RNA_def_property_range(prop, 0.001f, 1.0f); + RNA_def_property_float_default(prop, 1.0f); + RNA_def_property_ui_text( + prop, "Border Opacity Factor", + "Amount of gradient for Dot strokes (set to 1 for full solid)"); + RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0); + + /* gradient shape ratio */ + prop = RNA_def_property(srna, "gradient_shape", PROP_FLOAT, PROP_XYZ); + RNA_def_property_float_sdna(prop, NULL, "gradient_s"); + RNA_def_property_array(prop, 2); + RNA_def_property_range(prop, 0.01f, 1.0f); + RNA_def_property_float_default(prop, 1.0f); + RNA_def_property_ui_text(prop, "Aspect Ratio", ""); + RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0); + prop = RNA_def_property(srna, "input_samples", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "input_samples"); RNA_def_property_range(prop, 0, GP_MAX_INPUT_SAMPLES); diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c index 73203beb3e2..d154f8de4ad 100644 --- a/source/blender/makesrna/intern/rna_gpencil.c +++ b/source/blender/makesrna/intern/rna_gpencil.c @@ -998,6 +998,24 @@ static void rna_def_gpencil_stroke(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Thickness", "Thickness of stroke (in pixels)"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); + /* gradient control along y */ + prop = RNA_def_property(srna, "gradient_factor", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "gradient_f"); + RNA_def_property_range(prop, 0.001f, 1.0f); + RNA_def_property_float_default(prop, 1.0f); + RNA_def_property_ui_text(prop, "Border Opacity Factor", + "Amount of gradient along section of stroke"); + RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); + + /* gradient shape ratio */ + prop = RNA_def_property(srna, "gradient_shape", PROP_FLOAT, PROP_XYZ); + RNA_def_property_float_sdna(prop, NULL, "gradient_s"); + RNA_def_property_array(prop, 2); + RNA_def_property_range(prop, 0.01f, 1.0f); + RNA_def_property_float_default(prop, 1.0f); + RNA_def_property_ui_text(prop, "Aspect Ratio", ""); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); } static void rna_def_gpencil_strokes_api(BlenderRNA *brna, PropertyRNA *cprop) diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c index 8e5f486fea1..a57f47a8090 100644 --- a/source/blender/makesrna/intern/rna_material.c +++ b/source/blender/makesrna/intern/rna_material.c @@ -585,6 +585,13 @@ static void rna_def_material_greasepencil(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Show Fill", "Show stroke fills of this material"); RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update"); + /* keep Dots and Boxes aligned to screen and not to drawing path */ + prop = RNA_def_property(srna, "use_follow_path", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", GP_STYLE_COLOR_LOCK_DOTS); + RNA_def_property_ui_text(prop, "Follow Path", + "Keep Dots and Boxes aligned to drawing path"); + RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_nopreview_update"); + /* pass index for future compositing and editing tools */ prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "index"); |