Fix T75677: Annotation in compositor/shading tabs loose AA after drawing stroke

The drawing of annotations in 2D was using a very old code created in 2.6x versions. Now it's using a standard shader as it's done while drawing.
This commit is contained in:
Antonio Vazquez 2020-04-13 15:15:47 +02:00
parent 2ec6eca518
commit 2e75172c45
Notes: blender-bot 2023-02-14 02:27:56 +01:00
Referenced by issue #75677, Annotation in compositor/shading tabs loose AA after drawing stroke.
1 changed files with 72 additions and 164 deletions

View File

@ -328,13 +328,10 @@ static void annotation_draw_stroke_3d(
immUnbindProgram();
}
/* ----- Fancy 2D-Stroke Drawing ------ */
/* draw a given stroke in 2d */
/* Draw a given stroke in 2d. */
static void annotation_draw_stroke_2d(const bGPDspoint *points,
int totpoints,
short thickness_s,
short dflag,
short sflag,
int offsx,
int offsy,
@ -342,167 +339,84 @@ static void annotation_draw_stroke_2d(const bGPDspoint *points,
int winy,
const float ink[4])
{
/* otherwise thickness is twice that of the 3D view */
float thickness = (float)thickness_s * 0.5f;
/* strokes in Image Editor need a scale factor, since units there are not pixels! */
float scalefac = 1.0f;
if ((dflag & GP_DRAWDATA_IEDITHACK) && (dflag & GP_DRAWDATA_ONLYV2D)) {
scalefac = 0.001f;
if (totpoints == 0) {
return;
}
float thickness = (float)thickness_s;
/* Tessellation code - draw stroke as series of connected quads
* (triangle strips in fact) with connection edges rotated to minimize shrinking artifacts,
* and rounded end-caps.
*/
{
const bGPDspoint *pt1, *pt2;
float s0[2], s1[2]; /* segment 'center' points */
float pm[2]; /* normal from previous segment. */
int i;
GPUVertFormat *format = immVertexFormat();
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
GPUVertFormat *format = immVertexFormat();
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
const bGPDspoint *pt;
const bGPDspoint *pt_prev;
int draw_points = 0;
float co[2];
float oldpressure = points[0].pressure;
if (totpoints == 1) {
/* if drawing a single point, draw it larger */
GPU_point_size((float)(thickness + 2) * points->pressure);
immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
immUniformColor3fvAlpha(ink, ink[3]);
immBegin(GPU_PRIM_POINTS, 1);
annotation_calc_2d_stroke_fxy(&points->x, sflag, offsx, offsy, winx, winy, co);
immVertex2fv(pos, co);
}
else {
/* draw stroke curve */
GPU_line_width(max_ff(oldpressure * thickness, 1.0));
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor3fvAlpha(ink, ink[3]);
immBegin(GPU_PRIM_TRI_STRIP, totpoints * 2 + 4);
/* get x and y coordinates from first point */
annotation_calc_2d_stroke_fxy(&points->x, sflag, offsx, offsy, winx, winy, s0);
immBeginAtMost(GPU_PRIM_LINE_STRIP, totpoints);
for (i = 0, pt1 = points, pt2 = points + 1; i < (totpoints - 1); i++, pt1++, pt2++) {
float t0[2], t1[2]; /* tessellated coordinates */
float m1[2], m2[2]; /* gradient and normal */
float mt[2], sc[2]; /* gradient for thickness, point for end-cap */
float pthick; /* thickness at segment point */
/* Get x and y coordinates from point2
* (point1 has already been computed in previous iteration). */
annotation_calc_2d_stroke_fxy(&pt2->x, sflag, offsx, offsy, winx, winy, s1);
/* calculate gradient and normal - 'angle'=(ny/nx) */
m1[1] = s1[1] - s0[1];
m1[0] = s1[0] - s0[0];
normalize_v2(m1);
m2[1] = -m1[0];
m2[0] = m1[1];
/* always use pressure from first point here */
pthick = (pt1->pressure * thickness * scalefac);
/* if the first segment, start of segment is segment's normal */
if (i == 0) {
/* draw start cap first
* - make points slightly closer to center (about halfway across)
*/
mt[0] = m2[0] * pthick * 0.5f;
mt[1] = m2[1] * pthick * 0.5f;
sc[0] = s0[0] - (m1[0] * pthick * 0.75f);
sc[1] = s0[1] - (m1[1] * pthick * 0.75f);
t0[0] = sc[0] - mt[0];
t0[1] = sc[1] - mt[1];
t1[0] = sc[0] + mt[0];
t1[1] = sc[1] + mt[1];
/* First two points of cap. */
immVertex2fv(pos, t0);
immVertex2fv(pos, t1);
/* calculate points for start of segment */
mt[0] = m2[0] * pthick;
mt[1] = m2[1] * pthick;
t0[0] = s0[0] - mt[0];
t0[1] = s0[1] - mt[1];
t1[0] = s0[0] + mt[0];
t1[1] = s0[1] + mt[1];
/* Last two points of start cap (and first two points of first segment). */
immVertex2fv(pos, t0);
immVertex2fv(pos, t1);
}
/* if not the first segment, use bisector of angle between segments */
else {
float mb[2]; /* bisector normal */
float athick, dfac; /* actual thickness, difference between thicknesses */
/* calculate gradient of bisector (as average of normals) */
mb[0] = (pm[0] + m2[0]) / 2;
mb[1] = (pm[1] + m2[1]) / 2;
normalize_v2(mb);
/* calculate gradient to apply
* - as basis, use just pthick * bisector gradient
* - if cross-section not as thick as it should be, add extra padding to fix it
*/
mt[0] = mb[0] * pthick;
mt[1] = mb[1] * pthick;
athick = len_v2(mt);
dfac = pthick - (athick * 2);
if (((athick * 2.0f) < pthick) && (IS_EQF(athick, pthick) == 0)) {
mt[0] += (mb[0] * dfac);
mt[1] += (mb[1] * dfac);
for (int i = 0; i < totpoints; i++) {
pt = &points[i];
/* If there was a significant pressure change,
* stop the curve, change the thickness of the stroke,
* and continue drawing again (since line-width cannot change in middle of GL_LINE_STRIP).
*/
if (fabsf(pt->pressure - oldpressure) > 0.2f) {
/* need to have 2 points to avoid immEnd assert error */
if (draw_points < 2) {
pt_prev = &points[i - 1];
annotation_calc_2d_stroke_fxy(&pt_prev->x, sflag, offsx, offsy, winx, winy, co);
immVertex2fv(pos, co);
}
/* calculate points for start of segment */
t0[0] = s0[0] - mt[0];
t0[1] = s0[1] - mt[1];
t1[0] = s0[0] + mt[0];
t1[1] = s0[1] + mt[1];
immEnd();
draw_points = 0;
/* Last two points of previous segment, and first two points of current segment. */
immVertex2fv(pos, t0);
immVertex2fv(pos, t1);
GPU_line_width(max_ff(pt->pressure * thickness, 1.0f));
immBeginAtMost(GPU_PRIM_LINE_STRIP, totpoints - i + 1);
/* need to roll-back one point to ensure that there are no gaps in the stroke */
if (i != 0) {
pt_prev = &points[i - 1];
annotation_calc_2d_stroke_fxy(&pt_prev->x, sflag, offsx, offsy, winx, winy, co);
immVertex2fv(pos, co);
draw_points++;
}
oldpressure = pt->pressure; /* reset our threshold */
}
/* if last segment, also draw end of segment (defined as segment's normal) */
if (i == totpoints - 2) {
/* for once, we use second point's pressure (otherwise it won't be drawn) */
pthick = (pt2->pressure * thickness * scalefac);
/* calculate points for end of segment */
mt[0] = m2[0] * pthick;
mt[1] = m2[1] * pthick;
t0[0] = s1[0] - mt[0];
t0[1] = s1[1] - mt[1];
t1[0] = s1[0] + mt[0];
t1[1] = s1[1] + mt[1];
/* Last two points of last segment (and first two points of end cap). */
immVertex2fv(pos, t0);
immVertex2fv(pos, t1);
/* draw end cap as last step
* - make points slightly closer to center (about halfway across)
*/
mt[0] = m2[0] * pthick * 0.5f;
mt[1] = m2[1] * pthick * 0.5f;
sc[0] = s1[0] + (m1[0] * pthick * 0.75f);
sc[1] = s1[1] + (m1[1] * pthick * 0.75f);
t0[0] = sc[0] - mt[0];
t0[1] = sc[1] - mt[1];
t1[0] = sc[0] + mt[0];
t1[1] = sc[1] + mt[1];
/* Last two points of end cap. */
immVertex2fv(pos, t0);
immVertex2fv(pos, t1);
}
/* store computed point2 coordinates as point1 ones of next segment. */
copy_v2_v2(s0, s1);
/* store stroke's 'natural' normal for next stroke to use */
copy_v2_v2(pm, m2);
/* now the point we want */
annotation_calc_2d_stroke_fxy(&pt->x, sflag, offsx, offsy, winx, winy, co);
immVertex2fv(pos, co);
draw_points++;
}
/* need to have 2 points to avoid immEnd assert error */
if (draw_points < 2) {
pt_prev = &points[0];
annotation_calc_2d_stroke_fxy(&pt_prev->x, sflag, offsx, offsy, winx, winy, co);
immVertex2fv(pos, co);
}
immEnd();
immUnbindProgram();
}
immEnd();
immUnbindProgram();
}
/* ----- Strokes Drawing ------ */
@ -601,16 +515,8 @@ static void annotation_draw_strokes(const bGPDframe *gpf,
gps->points, lthick, gps->flag, offsx, offsy, winx, winy, color);
}
else {
annotation_draw_stroke_2d(gps->points,
gps->totpoints,
lthick,
dflag,
gps->flag,
offsx,
offsy,
winx,
winy,
color);
annotation_draw_stroke_2d(
gps->points, gps->totpoints, lthick, gps->flag, offsx, offsy, winx, winy, color);
}
}
}
@ -862,7 +768,8 @@ static void annotation_draw_data_layers(
annotation_draw_strokes(gpf, offsx, offsy, winx, winy, dflag, lthick, ink);
/* Draw verts of selected strokes:
* - when doing OpenGL renders, we don't want to be showing these, as that ends up flickering
* - when doing OpenGL renders, we don't want to be showing these, as that ends up
* flickering
* - locked layers can't be edited, so there's no point showing these verts
* as they will have no bearings on what gets edited
* - only show when in editmode, since operators shouldn't work otherwise
@ -1126,8 +1033,8 @@ void ED_annotation_draw_view2d(const bContext *C, bool onlyv2d)
}
}
/* draw annotations sketches to specified 3d-view assuming that matrices are already set correctly
* Note: this gets called twice - first time with only3d=true to draw 3d-strokes,
/* draw annotations sketches to specified 3d-view assuming that matrices are already set
* correctly Note: this gets called twice - first time with only3d=true to draw 3d-strokes,
* second time with only3d=false for screen-aligned strokes */
void ED_annotation_draw_view3d(
Scene *scene, struct Depsgraph *depsgraph, View3D *v3d, ARegion *region, bool only3d)
@ -1137,7 +1044,8 @@ void ED_annotation_draw_view3d(
int offsx, offsy, winx, winy;
/* check that we have grease-pencil stuff to draw */
/* XXX: Hardcoded reference here may get out of sync if we change how we fetch annotation data */
/* XXX: Hardcoded reference here may get out of sync if we change how we fetch annotation data
*/
bGPdata *gpd = scene->gpd;
if (gpd == NULL) {
return;