Paint: 2D paint brush stroke antialiasing
This commit enables antialiasing in 2D painting. It also includes some fixes related to line drawing in the stroke spacing code. Reviewed By: brecht Differential Revision: https://developer.blender.org/D5833
This commit is contained in:
parent
dccdc5df10
commit
ce22efb425
|
@ -540,7 +540,7 @@ static void paint_stroke_update_step(bContext *C, struct PaintStroke *stroke, Po
|
|||
RNA_float_get_array(itemptr, "mouse", mouse);
|
||||
pressure = RNA_float_get(itemptr, "pressure");
|
||||
eraser = RNA_boolean_get(itemptr, "pen_flip");
|
||||
size = max_ff(1.0f, RNA_float_get(itemptr, "size"));
|
||||
size = RNA_float_get(itemptr, "size");
|
||||
|
||||
/* stroking with fill tool only acts on stroke end */
|
||||
if (brush->imagepaint_tool == PAINT_TOOL_FILL) {
|
||||
|
|
|
@ -374,25 +374,65 @@ static void brush_painter_mask_imbuf_partial_update(BrushPainter *painter,
|
|||
/* create a mask with the falloff strength */
|
||||
static unsigned short *brush_painter_curve_mask_new(BrushPainter *painter,
|
||||
int diameter,
|
||||
float radius)
|
||||
float radius,
|
||||
const float pos[2])
|
||||
{
|
||||
Brush *brush = painter->brush;
|
||||
|
||||
int xoff = -radius;
|
||||
int yoff = -radius;
|
||||
int offset = (int)floorf(diameter / 2.0f);
|
||||
|
||||
unsigned short *mask, *m;
|
||||
int x, y;
|
||||
|
||||
mask = MEM_mallocN(sizeof(unsigned short) * diameter * diameter, "brush_painter_mask");
|
||||
m = mask;
|
||||
|
||||
for (y = 0; y < diameter; y++) {
|
||||
for (x = 0; x < diameter; x++, m++) {
|
||||
float xy[2] = {x + xoff, y + yoff};
|
||||
float len = len_v2(xy);
|
||||
int aa_samples = 1.0f / (radius * 0.20f);
|
||||
aa_samples = clamp_i(aa_samples, 3, 16);
|
||||
|
||||
*m = (unsigned short)(65535.0f * BKE_brush_curve_strength_clamped(brush, len, radius));
|
||||
/* Temporal until we have the brush properties */
|
||||
const float hardness = 1.0f;
|
||||
const float rotation = 0.0f;
|
||||
|
||||
float aa_offset = 1.0f / (2.0f * (float)aa_samples);
|
||||
float aa_step = 1.0f / (float)aa_samples;
|
||||
|
||||
float bpos[2];
|
||||
bpos[0] = pos[0] - floorf(pos[0]) + offset + aa_offset;
|
||||
bpos[1] = pos[1] - floorf(pos[1]) + offset + aa_offset;
|
||||
|
||||
const float co = cosf(DEG2RADF(rotation));
|
||||
const float si = sinf(DEG2RADF(rotation));
|
||||
|
||||
float norm_factor = 65535.0f / (float)(aa_samples * aa_samples);
|
||||
|
||||
for (int y = 0; y < diameter; y++) {
|
||||
for (int x = 0; x < diameter; x++, m++) {
|
||||
float total_samples = 0;
|
||||
for (int i = 0; i < aa_samples; i++) {
|
||||
for (int j = 0; j < aa_samples; j++) {
|
||||
float pixel_xy[2] = {x + (aa_step * i), y + (aa_step * j)};
|
||||
float xy_rot[2];
|
||||
sub_v2_v2(pixel_xy, bpos);
|
||||
|
||||
xy_rot[0] = co * pixel_xy[0] - si * pixel_xy[1];
|
||||
xy_rot[1] = si * pixel_xy[0] + co * pixel_xy[1];
|
||||
|
||||
float len = len_v2(xy_rot);
|
||||
float p = len / radius;
|
||||
if (hardness < 1.0f) {
|
||||
p = (p - hardness) / (1 - hardness);
|
||||
p = 1.0f - p;
|
||||
CLAMP(p, 0, 1);
|
||||
}
|
||||
else {
|
||||
p = 1.0;
|
||||
}
|
||||
float hardness_factor = 3.0f * p * p - 2.0f * p * p * p;
|
||||
float curve = BKE_brush_curve_strength_clamped(brush, len, radius);
|
||||
total_samples += curve * hardness_factor;
|
||||
}
|
||||
}
|
||||
*m = (unsigned short)(total_samples * norm_factor);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -721,7 +761,8 @@ static void brush_painter_2d_refresh_cache(ImagePaintState *s,
|
|||
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
|
||||
Brush *brush = painter->brush;
|
||||
BrushPainterCache *cache = &painter->cache;
|
||||
const int diameter = 2 * size;
|
||||
/* Adding 4 pixels of padding for brush antialiasing */
|
||||
const int diameter = MAX2(1, size * 2) + 4;
|
||||
|
||||
bool do_random = false;
|
||||
bool do_partial_update = false;
|
||||
|
@ -802,15 +843,13 @@ static void brush_painter_2d_refresh_cache(ImagePaintState *s,
|
|||
}
|
||||
|
||||
/* curve mask can only change if the size changes */
|
||||
if (diameter != cache->lastdiameter) {
|
||||
if (cache->curve_mask) {
|
||||
MEM_freeN(cache->curve_mask);
|
||||
cache->curve_mask = NULL;
|
||||
}
|
||||
|
||||
cache->curve_mask = brush_painter_curve_mask_new(painter, diameter, size);
|
||||
if (cache->curve_mask) {
|
||||
MEM_freeN(cache->curve_mask);
|
||||
cache->curve_mask = NULL;
|
||||
}
|
||||
|
||||
cache->curve_mask = brush_painter_curve_mask_new(painter, diameter, size, pos);
|
||||
|
||||
/* detect if we need to recreate image brush buffer */
|
||||
if ((diameter != cache->lastdiameter) || (tex_rotation != cache->last_tex_rotation) ||
|
||||
do_random || update_color) {
|
||||
|
|
|
@ -669,7 +669,7 @@ static float paint_space_stroke_spacing(bContext *C,
|
|||
return max_ff(0.001f, size_clamp * spacing / 50.f);
|
||||
}
|
||||
else {
|
||||
return max_ff(1.0, size_clamp * spacing / 50.0f);
|
||||
return max_ff(stroke->zoom_2d, size_clamp * spacing / 50.0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue