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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntonioya <blendergit@gmail.com>2019-04-15 11:32:06 +0300
committerAntonioya <blendergit@gmail.com>2019-04-15 11:32:25 +0300
commit240940c58ca3ce65e4bbceebea71dd9d1c2c08bc (patch)
tree97a9c60a7c2e059cef2541667ade5e00c70c21f5 /source/blender/draw
parent7c79455297d818a94aab2a9be5807b4d9ca43827 (diff)
GPencil: New Dots gradient
This commit adds support for drawing Dots strokes with a gradient factor to get artistic effects like watercolor. Currently, the option is only supported by Dots materials, and in the future will be added to line strokes, but now there is a limitation on drawing engine and we will keep disabled on Line materials. Also, added the option to align Dots and Boxes strokes textures aligned with the drawing path to get more fluid strokes.
Diffstat (limited to 'source/blender/draw')
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c21
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_draw_utils.c36
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.h9
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_point_frag.glsl32
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_point_geom.glsl74
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl5
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_stroke_frag.glsl13
7 files changed, 174 insertions, 16 deletions
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;
}