add Anti-Aliasing (very rough draft algorithm, NOT FINAL version) to raskter lib. Code is still quite messy but will be replaced when final algo comes in anyway.

This commit is contained in:
Peter Larabell 2012-06-13 19:57:23 +00:00
parent 96099688c6
commit ceffc2cd50
12 changed files with 638 additions and 46 deletions

@ -34,7 +34,7 @@
/* from BLI_utildefines.h */
#define MIN2(x, y) ( (x) < (y) ? (x) : (y) )
#define MAX2(x, y) ( (x) > (y) ? (x) : (y) )
#define ABS(a) ( (a) < 0 ? (-(a)) : (a) )
struct e_status {
int x;
@ -67,8 +67,7 @@ struct r_fill_context {
* just the poly. Since the DEM code could end up being coupled with this, we'll keep it separate
* for now.
*/
static void preprocess_all_edges(struct r_fill_context *ctx, struct poly_vert *verts, int num_verts, struct e_status *open_edge)
{
static void preprocess_all_edges(struct r_fill_context *ctx, struct poly_vert *verts, int num_verts, struct e_status *open_edge) {
int i;
int xbeg;
int ybeg;
@ -94,8 +93,7 @@ static void preprocess_all_edges(struct r_fill_context *ctx, struct poly_vert *v
/* we're not at the last vert, so end of the edge is the previous vertex */
xend = v[i - 1].x;
yend = v[i - 1].y;
}
else {
} else {
/* we're at the first vertex, so the "end" of this edge is the last vertex */
xend = v[num_verts - 1].x;
yend = v[num_verts - 1].y;
@ -124,8 +122,7 @@ static void preprocess_all_edges(struct r_fill_context *ctx, struct poly_vert *v
if (dx > 0) {
e_new->xdir = 1;
xdist = dx;
}
else {
} else {
e_new->xdir = -1;
xdist = -dx;
}
@ -138,15 +135,13 @@ static void preprocess_all_edges(struct r_fill_context *ctx, struct poly_vert *v
/* calculate deltas for incremental drawing */
if (dx >= 0) {
e_new->drift = 0;
}
else {
} else {
e_new->drift = -dy + 1;
}
if (dy >= xdist) {
e_new->drift_inc = xdist;
e_new->xshift = 0;
}
else {
} else {
e_new->drift_inc = xdist % dy;
e_new->xshift = (xdist / dy) * e_new->xdir;
}
@ -170,8 +165,7 @@ static void preprocess_all_edges(struct r_fill_context *ctx, struct poly_vert *v
* for speed, but waiting on final design choices for curve-data before eliminating data the DEM code will need
* if it ends up being coupled with this function.
*/
static int rast_scan_fill(struct r_fill_context *ctx, struct poly_vert *verts, int num_verts)
{
static int rast_scan_fill(struct r_fill_context *ctx, struct poly_vert *verts, int num_verts, float intensity) {
int x_curr; /* current pixel position in X */
int y_curr; /* current scan line being drawn */
int yp; /* y-pixel's position in frame buffer */
@ -260,8 +254,7 @@ static int rast_scan_fill(struct r_fill_context *ctx, struct poly_vert *verts, i
edgec = &ctx->all_edges->e_next; /* Set our list to the next edge's location in memory. */
ctx->all_edges = e_temp; /* Skip the NULL or bad X edge, set pointer to next edge. */
break; /* Stop looping edges (since we ran out or hit empty X span. */
}
else {
} else {
edgec = &e_curr->e_next; /* Set the pointer to the edge list the "next" edge. */
}
}
@ -307,7 +300,7 @@ static int rast_scan_fill(struct r_fill_context *ctx, struct poly_vert *verts, i
if ((y_curr >= 0) && (y_curr < ctx->rb.sizey)) {
/* draw the pixels. */
for (; cpxl <= mpxl; *cpxl++ = 1.0f);
for(; cpxl <= mpxl; *cpxl++ += intensity);
}
}
@ -323,8 +316,7 @@ static int rast_scan_fill(struct r_fill_context *ctx, struct poly_vert *verts, i
for (edgec = &ctx->possible_edges; (e_curr = *edgec); ) {
if (!(--(e_curr->num))) {
*edgec = e_curr->e_next;
}
else {
} else {
e_curr->x += e_curr->xshift;
if ((e_curr->drift += e_curr->drift_inc) > 0) {
e_curr->x += e_curr->xdir;
@ -383,12 +375,17 @@ static int rast_scan_fill(struct r_fill_context *ctx, struct poly_vert *verts, i
}
int PLX_raskterize(float (*base_verts)[2], int num_base_verts,
float *buf, int buf_x, int buf_y)
{
float *buf, int buf_x, int buf_y, int do_mask_AA) {
int subdiv_AA = (do_mask_AA != 0)? 8:0;
int i; /* i: Loop counter. */
int sAx;
int sAy;
struct poly_vert *ply; /* ply: Pointer to a list of integer buffer-space vertex coordinates. */
struct r_fill_context ctx = {0};
const float buf_x_f = (float)(buf_x);
const float buf_y_f = (float)(buf_y);
float div_offset=(1.0f / (float)(subdiv_AA));
float div_offset_static = 0.5f * (float)(subdiv_AA) * div_offset;
/*
* Allocate enough memory for our poly_vert list. It'll be the size of the poly_vert
* data structure multiplied by the number of base_verts.
@ -400,6 +397,9 @@ int PLX_raskterize(float (*base_verts)[2], int num_base_verts,
return(0);
}
ctx.rb.buf = buf; /* Set the output buffer pointer. */
ctx.rb.sizex = buf_x; /* Set the output buffer size in X. (width) */
ctx.rb.sizey = buf_y; /* Set the output buffer size in Y. (height) */
/*
* Loop over all verts passed in to be rasterized. Each vertex's X and Y coordinates are
* then converted from normalized screen space (0.0 <= POS <= 1.0) to integer coordinates
@ -408,16 +408,25 @@ int PLX_raskterize(float (*base_verts)[2], int num_base_verts,
* It's worth noting that this function ONLY outputs fully white pixels in a mask. Every pixel
* drawn will be 1.0f in value, there is no anti-aliasing.
*/
if(!subdiv_AA) {
for (i = 0; i < num_base_verts; i++) { /* Loop over all base_verts. */
ply[i].x = (base_verts[i][0] * buf_x) + 0.5f; /* Range expand normalized X to integer buffer-space X. */
ply[i].y = (base_verts[i][1] * buf_y) + 0.5f; /* Range expand normalized Y to integer buffer-space Y. */
ply[i].x = (int)((base_verts[i][0] * buf_x_f) + 0.5f); /* Range expand normalized X to integer buffer-space X. */
ply[i].y = (int)((base_verts[i][1] * buf_y_f) + 0.5f); /* Range expand normalized Y to integer buffer-space Y. */
}
ctx.rb.buf = buf; /* Set the output buffer pointer. */
ctx.rb.sizex = buf_x; /* Set the output buffer size in X. (width) */
ctx.rb.sizey = buf_y; /* Set the output buffer size in Y. (height) */
i = rast_scan_fill(&ctx, ply, num_base_verts); /* Call our rasterizer, passing in the integer coords for each vert. */
i = rast_scan_fill(&ctx, ply, num_base_verts,1.0f); /* Call our rasterizer, passing in the integer coords for each vert. */
} else {
for(sAx=0; sAx < subdiv_AA; sAx++) {
for(sAy=0; sAy < subdiv_AA; sAy++) {
for(i=0; i < num_base_verts; i++) {
ply[i].x = (int)((base_verts[i][0]*buf_x_f)+0.5f - div_offset_static + (div_offset*(float)(sAx)));
ply[i].y = (int)((base_verts[i][1]*buf_y_f)+0.5f - div_offset_static + (div_offset*(float)(sAy)));
}
i = rast_scan_fill(&ctx, ply, num_base_verts,(1.0f / (float)(subdiv_AA*subdiv_AA)));
}
}
}
free(ply); /* Free the memory allocated for the integer coordinate table. */
return(i); /* Return the value returned by the rasterizer. */
}
@ -429,8 +438,7 @@ int PLX_raskterize(float (*base_verts)[2], int num_base_verts,
*/
static int rast_scan_feather(struct r_fill_context *ctx,
float (*base_verts_f)[2], int num_base_verts,
struct poly_vert *feather_verts, float (*feather_verts_f)[2], int num_feather_verts)
{
struct poly_vert *feather_verts, float(*feather_verts_f)[2], int num_feather_verts) {
int x_curr; /* current pixel position in X */
int y_curr; /* current scan line being drawn */
int yp; /* y-pixel's position in frame buffer */
@ -536,8 +544,7 @@ static int rast_scan_feather(struct r_fill_context *ctx,
edgec = &ctx->all_edges->e_next; /* Set our list to the next edge's location in memory. */
ctx->all_edges = e_temp; /* Skip the NULL or bad X edge, set pointer to next edge. */
break; /* Stop looping edges (since we ran out or hit empty X span. */
}
else {
} else {
edgec = &e_curr->e_next; /* Set the pointer to the edge list the "next" edge. */
}
}
@ -647,8 +654,7 @@ static int rast_scan_feather(struct r_fill_context *ctx,
for (edgec = &ctx->possible_edges; (e_curr = *edgec); ) {
if (!(--(e_curr->num))) {
*edgec = e_curr->e_next;
}
else {
} else {
e_curr->x += e_curr->xshift;
if ((e_curr->drift += e_curr->drift_inc) > 0) {
e_curr->x += e_curr->xdir;
@ -708,8 +714,7 @@ static int rast_scan_feather(struct r_fill_context *ctx,
}
int PLX_raskterize_feather(float (*base_verts)[2], int num_base_verts, float (*feather_verts)[2], int num_feather_verts,
float *buf, int buf_x, int buf_y)
{
float *buf, int buf_x, int buf_y) {
int i; /* i: Loop counter. */
struct poly_vert *fe; /* fe: Pointer to a list of integer buffer-space feather vertex coords. */
struct r_fill_context ctx = {0};
@ -751,3 +756,569 @@ int PLX_raskterize_feather(float (*base_verts)[2], int num_base_verts, float (*f
free(fe);
return i; /* Return the value returned by the rasterizer. */
}
int get_range_expanded_pixel_coord(float normalized_value, int max_value) {
return (int)((normalized_value * (float)(max_value)) + 0.5f);
}
float get_pixel_intensity(float *buf, int buf_x, int buf_y, int pos_x, int pos_y) {
if(pos_x < 0 || pos_x >= buf_x || pos_y < 0 || pos_y >= buf_y) {
return 0.0f;
}
return buf[(pos_y * buf_y) + buf_x];
}
float get_pixel_intensity_bilinear(float *buf, int buf_x, int buf_y, float u, float v) {
int a;
int b;
int a_plus_1;
int b_plus_1;
float prop_u;
float prop_v;
float inv_prop_u;
float inv_prop_v;
if(u<0.0f || u>1.0f || v<0.0f || v>1.0f) {
return 0.0f;
}
u = u * (float)(buf_x) - 0.5f;
v = v * (float)(buf_y) - 0.5f;
a = (int)(u);
b = (int)(v);
prop_u = u - (float)(a);
prop_v = v - (float)(b);
inv_prop_u = 1.0f - prop_u;
inv_prop_v = 1.0f - prop_v;
a_plus_1 = MIN2((buf_x-1),a+1);
b_plus_1 = MIN2((buf_y-1),b+1);
return (buf[(b * buf_y) + a] * inv_prop_u + buf[(b*buf_y)+(a_plus_1)] * prop_u)*inv_prop_v+(buf[((b_plus_1) * buf_y)+a] * inv_prop_u + buf[((b_plus_1)*buf_y)+(a_plus_1)] * prop_u) * prop_v;
}
void set_pixel_intensity(float *buf, int buf_x, int buf_y, int pos_x, int pos_y, float intensity) {
if(pos_x < 0 || pos_x >= buf_x || pos_y < 0 || pos_y >= buf_y) {
return;
}
buf[(pos_y * buf_y) + buf_x] = intensity;
}
#define __PLX__FAKE_AA__
int PLX_antialias_buffer(float *buf, int buf_x, int buf_y) {
#ifdef __PLX__FAKE_AA__
#ifdef __PLX_GREY_AA__
int i=0;
int sz = buf_x * buf_y;
for(i=0; i<sz; i++) {
buf[i] *= 0.5f;
}
#endif
return 1;
#else
/*XXX - TODO: THIS IS NOT FINAL CODE - IT DOES NOT WORK - DO NOT ENABLE IT */
const float p0 = 1.0f;
const float p1 = 1.0f;
const float p2 = 1.0f;
const float p3 = 1.0f;
const float p4 = 1.0f;
const float p5 = 1.5f;
const float p6 = 2.0f;
const float p7 = 2.0f;
const float p8 = 2.0f;
const float p9 = 2.0f;
const float p10 = 4.0f;
const float p11 = 8.0f;
const float edge_threshold = 0.063f;
const float edge_threshold_min = 0.0312f;
const float quality_subpix = 1.0f;
// int px_x;
// int px_y;
float posM_x,posM_y;
float posB_x,posB_y;
float posN_x,posN_y;
float posP_x,posP_y;
float offNP_x,offNP_y;
float lumaM;
float lumaS;
float lumaE;
float lumaN;
float lumaW;
float lumaNW;
float lumaSE;
float lumaNE;
float lumaSW;
float lumaNS;
float lumaWE;
float lumaNESE;
float lumaNWNE;
float lumaNWSW;
float lumaSWSE;
float lumaNN;
float lumaSS;
float lumaEndN;
float lumaEndP;
float lumaMM;
float lumaMLTZero;
float subpixNWSWNESE;
float subpixRcpRange;
float subpixNSWE;
float maxSM;
float minSM;
float maxESM;
float minESM;
float maxWN;
float minWN;
float rangeMax;
float rangeMin;
float rangeMaxScaled;
float range;
float rangeMaxClamped;
float edgeHorz;
float edgeVert;
float edgeHorz1;
float edgeVert1;
float edgeHorz2;
float edgeVert2;
float edgeHorz3;
float edgeVert3;
float edgeHorz4;
float edgeVert4;
float lengthSign;
float subpixA;
float subpixB;
float subpixC;
float subpixD;
float subpixE;
float subpixF;
float subpixG;
float subpixH;
float gradientN;
float gradientS;
float gradient;
float gradientScaled;
float dstN;
float dstP;
float dst;
float spanLength;
float spanLengthRcp;
float pixelOffset;
float pixelOffsetGood;
float pixelOffsetSubpix;
int directionN;
int goodSpan;
int goodSpanN;
int goodSpanP;
int horzSpan;
int earlyExit;
int pairN;
int doneN;
int doneP;
int doneNP;
int curr_x=0;
int curr_y=0;
for(curr_y=0; curr_y < buf_y; curr_y++) {
for(curr_x=0; curr_x < buf_x; curr_x++) {
posM_x = ((float)(curr_x) + 0.5f) * (1.0f/(float)(buf_x));
posM_y = ((float)(curr_y) + 0.5f) * (1.0f/(float)(buf_y));
lumaM = get_pixel_intensity(buf, buf_x, buf_y, curr_x, curr_y);
lumaS = get_pixel_intensity(buf, buf_x, buf_y, curr_x, curr_y - 1);
lumaE = get_pixel_intensity(buf, buf_x, buf_y, curr_x + 1, curr_y);
lumaN = get_pixel_intensity(buf, buf_x, buf_y, curr_x, curr_y + 1);
lumaW = get_pixel_intensity(buf, buf_x, buf_y, curr_x - 1, curr_y);
maxSM = MAX2(lumaS, lumaM);
minSM = MIN2(lumaS, lumaM);
maxESM = MAX2(lumaE, maxSM);
minESM = MIN2(lumaE, minSM);
maxWN = MAX2(lumaN, lumaW);
minWN = MIN2(lumaN, lumaW);
rangeMax = MAX2(maxWN, maxESM);
rangeMin = MIN2(minWN, minESM);
rangeMaxScaled = rangeMax * edge_threshold;
range = rangeMax - rangeMin;
rangeMaxClamped = MAX2(edge_threshold_min, rangeMaxScaled);
earlyExit = range < rangeMaxClamped ? 1:0;
if(earlyExit) {
set_pixel_intensity(buf, buf_x, buf_y, curr_x, curr_y, lumaM);
}
lumaNW = get_pixel_intensity(buf, buf_x, buf_y, curr_x + 1, curr_y - 1);
lumaSE = get_pixel_intensity(buf, buf_x, buf_y, curr_x - 1, curr_y + 1);
lumaNE = get_pixel_intensity(buf, buf_x, buf_y, curr_x + 1, curr_y + 1);
lumaSW = get_pixel_intensity(buf, buf_x, buf_y, curr_x - 1, curr_y - 1);
lumaNS = lumaN + lumaS;
lumaWE = lumaW + lumaE;
subpixRcpRange = 1.0f/range;
subpixNSWE = lumaNS + lumaWE;
edgeHorz1 = (-2.0f * lumaM) + lumaNS;
edgeVert1 = (-2.0f * lumaM) + lumaWE;
lumaNESE = lumaNE + lumaSE;
lumaNWNE = lumaNW + lumaNE;
edgeHorz2 = (-2.0f * lumaE) + lumaNESE;
edgeVert2 = (-2.0f * lumaN) + lumaNWNE;
lumaNWSW = lumaNW + lumaSW;
lumaSWSE = lumaSW + lumaSE;
edgeHorz4 = (ABS(edgeHorz1) * 2.0f) + ABS(edgeHorz2);
edgeVert4 = (ABS(edgeVert1) * 2.0f) + ABS(edgeVert2);
edgeHorz3 = (-2.0f * lumaW) + lumaNWSW;
edgeVert3 = (-2.0f * lumaS) + lumaSWSE;
edgeHorz = ABS(edgeHorz3) + edgeHorz4;
edgeVert = ABS(edgeVert3) + edgeVert4;
subpixNWSWNESE = lumaNWSW + lumaNESE;
lengthSign = 1.0f / (float)(buf_x);
horzSpan = edgeHorz >= edgeVert ? 1:0;
subpixA = subpixNSWE * 2.0f + subpixNWSWNESE;
if(!horzSpan) {
lumaN = lumaW;
lumaS = lumaE;
} else {
lengthSign = 1.0f / (float)(buf_y);
}
subpixB = (subpixA * (1.0f/12.0f)) - lumaM;
gradientN = lumaN - lumaM;
gradientS = lumaS - lumaM;
lumaNN = lumaN + lumaM;
lumaSS = lumaS + lumaM;
pairN = (ABS(gradientN)) >= (ABS(gradientS)) ? 1:0;
gradient = MAX2(ABS(gradientN), ABS(gradientS));
if(pairN) {
lengthSign = -lengthSign;
}
subpixC = MAX2(MIN2(ABS(subpixB) * subpixRcpRange,1.0f),0.0f);
posB_x = posM_x;
posB_y = posM_y;
offNP_x = (!horzSpan) ? 0.0f:(1.0f / (float)(buf_x));
offNP_y = (horzSpan) ? 0.0f:(1.0f / (float)(buf_y));
if(!horzSpan) {
posB_x += lengthSign * 0.5f;
} else {
posB_y += lengthSign * 0.5f;
}
posN_x = posB_x - offNP_x * p0;
posN_y = posB_y - offNP_y * p0;
posP_x = posB_x + offNP_x * p0;
posP_y = posB_y + offNP_y * p0;
subpixD = ((-2.0f)*subpixC) + 3.0f;
//may need bilinear filtered get_pixel_intensity() here...done
lumaEndN = get_pixel_intensity_bilinear(buf, buf_x, buf_y,posN_x,posN_y);
subpixE = subpixC * subpixC;
//may need bilinear filtered get_pixel_intensity() here...done
lumaEndP = get_pixel_intensity_bilinear(buf, buf_x, buf_y, posP_x,posP_y);
if(!pairN) {
lumaNN = lumaSS;
}
gradientScaled = gradient * 1.0f/4.0f;
lumaMM =lumaM - lumaNN * 0.5f;
subpixF = subpixD * subpixE;
lumaMLTZero = lumaMM < 0.0f ? 1:0;
lumaEndN -= lumaNN * 0.5f;
lumaEndP -= lumaNN * 0.5f;
doneN = (ABS(lumaEndN)) >= gradientScaled ? 1:0;
doneP = (ABS(lumaEndP)) >= gradientScaled ? 1:0;
if(!doneN) {
posN_x -= offNP_x * p1;
posN_y -= offNP_y * p1;
}
doneNP = (!doneN) || (!doneP) ? 1:0;
if(!doneP) {
posP_x += offNP_x * p1;
posP_y += offNP_y * p1;
}
if(doneNP) {
if(!doneN) {
lumaEndN = get_pixel_intensity_bilinear(buf, buf_x, buf_y, posN_x,posN_y);
}
if(!doneP) {
lumaEndP = get_pixel_intensity_bilinear(buf, buf_x, buf_y, posP_x, posP_y);
}
if(!doneN) {
lumaEndN = lumaEndN - lumaNN * 0.5;
}
if(!doneP) {
lumaEndP = lumaEndP - lumaNN * 0.5;
}
doneN = (ABS(lumaEndN)) >= gradientScaled ? 1:0;
doneP = (ABS(lumaEndP)) >= gradientScaled ? 1:0;
if(!doneN) {
posN_x -= offNP_x * p2;
posN_y -= offNP_y * p2;
}
doneNP = (!doneN) || (!doneP) ? 1:0;
if(!doneP) {
posP_x += offNP_x * p2;
posP_y += offNP_y * p2;
}
if(doneNP) {
if(!doneN) {
lumaEndN = get_pixel_intensity_bilinear(buf, buf_x, buf_y,posN_x,posN_y);
}
if(!doneP) {
lumaEndP = get_pixel_intensity_bilinear(buf, buf_x, buf_y, posP_x,posP_y);
}
if(!doneN) {
lumaEndN = lumaEndN - lumaNN * 0.5;
}
if(!doneP) {
lumaEndP = lumaEndP - lumaNN * 0.5;
}
doneN = (ABS(lumaEndN)) >= gradientScaled ? 1:0;
doneP = (ABS(lumaEndP)) >= gradientScaled ? 1:0;
if(!doneN) {
posN_x -= offNP_x * p3;
posN_y -= offNP_y * p3;
}
doneNP = (!doneN) || (!doneP) ? 1:0;
if(!doneP) {
posP_x += offNP_x * p3;
posP_y += offNP_y * p3;
}
if(doneNP) {
if(!doneN) {
lumaEndN = get_pixel_intensity_bilinear(buf, buf_x, buf_y,posN_x,posN_y);
}
if(!doneP) {
lumaEndP = get_pixel_intensity_bilinear(buf, buf_x, buf_y, posP_x,posP_y);
}
if(!doneN) {
lumaEndN = lumaEndN - lumaNN * 0.5;
}
if(!doneP) {
lumaEndP = lumaEndP - lumaNN * 0.5;
}
doneN = (ABS(lumaEndN)) >= gradientScaled ? 1:0;
doneP = (ABS(lumaEndP)) >= gradientScaled ? 1:0;
if(!doneN) {
posN_x -= offNP_x * p4;
posN_y -= offNP_y * p4;
}
doneNP = (!doneN) || (!doneP) ? 1:0;
if(!doneP) {
posP_x += offNP_x * p4;
posP_y += offNP_y * p4;
}
if(doneNP) {
if(!doneN) {
lumaEndN = get_pixel_intensity_bilinear(buf, buf_x, buf_y,posN_x,posN_y);
}
if(!doneP) {
lumaEndP = get_pixel_intensity_bilinear(buf, buf_x, buf_y, posP_x,posP_y);
}
if(!doneN) {
lumaEndN = lumaEndN - lumaNN * 0.5;
}
if(!doneP) {
lumaEndP = lumaEndP - lumaNN * 0.5;
}
doneN = (ABS(lumaEndN)) >= gradientScaled ? 1:0;
doneP = (ABS(lumaEndP)) >= gradientScaled ? 1:0;
if(!doneN) {
posN_x -= offNP_x * p5;
posN_y -= offNP_y * p5;
}
doneNP = (!doneN) || (!doneP) ? 1:0;
if(!doneP) {
posP_x += offNP_x * p5;
posP_y += offNP_y * p5;
}
if(doneNP) {
if(!doneN) {
lumaEndN = get_pixel_intensity_bilinear(buf, buf_x, buf_y,posN_x,posN_y);
}
if(!doneP) {
lumaEndP = get_pixel_intensity_bilinear(buf, buf_x, buf_y, posP_x,posP_y);
}
if(!doneN) {
lumaEndN = lumaEndN - lumaNN * 0.5;
}
if(!doneP) {
lumaEndP = lumaEndP - lumaNN * 0.5;
}
doneN = (ABS(lumaEndN)) >= gradientScaled ? 1:0;
doneP = (ABS(lumaEndP)) >= gradientScaled ? 1:0;
if(!doneN) {
posN_x -= offNP_x * p6;
posN_y -= offNP_y * p6;
}
doneNP = (!doneN) || (!doneP) ? 1:0;
if(!doneP) {
posP_x += offNP_x * p6;
posP_y += offNP_y * p6;
}
if(doneNP) {
if(!doneN) {
lumaEndN = get_pixel_intensity_bilinear(buf, buf_x, buf_y,posN_x,posN_y);
}
if(!doneP) {
lumaEndP = get_pixel_intensity_bilinear(buf, buf_x, buf_y, posP_x,posP_y);
}
if(!doneN) {
lumaEndN = lumaEndN - lumaNN * 0.5;
}
if(!doneP) {
lumaEndP = lumaEndP - lumaNN * 0.5;
}
doneN = (ABS(lumaEndN)) >= gradientScaled ? 1:0;
doneP = (ABS(lumaEndP)) >= gradientScaled ? 1:0;
if(!doneN) {
posN_x -= offNP_x * p7;
posN_y -= offNP_y * p7;
}
doneNP = (!doneN) || (!doneP) ? 1:0;
if(!doneP) {
posP_x += offNP_x * p7;
posP_y += offNP_y * p7;
}
if(doneNP) {
if(!doneN) {
lumaEndN = get_pixel_intensity_bilinear(buf, buf_x, buf_y,posN_x,posN_y);
}
if(!doneP) {
lumaEndP = get_pixel_intensity_bilinear(buf, buf_x, buf_y, posP_x,posP_y);
}
if(!doneN) {
lumaEndN = lumaEndN - lumaNN * 0.5;
}
if(!doneP) {
lumaEndP = lumaEndP - lumaNN * 0.5;
}
doneN = (ABS(lumaEndN)) >= gradientScaled ? 1:0;
doneP = (ABS(lumaEndP)) >= gradientScaled ? 1:0;
if(!doneN) {
posN_x -= offNP_x * p8;
posN_y -= offNP_y * p8;
}
doneNP = (!doneN) || (!doneP) ? 1:0;
if(!doneP) {
posP_x += offNP_x * p8;
posP_y += offNP_y * p8;
}
if(doneNP) {
if(!doneN) {
lumaEndN = get_pixel_intensity_bilinear(buf, buf_x, buf_y,posN_x,posN_y);
}
if(!doneP) {
lumaEndP = get_pixel_intensity_bilinear(buf, buf_x, buf_y, posP_x,posP_y);
}
if(!doneN) {
lumaEndN = lumaEndN - lumaNN * 0.5;
}
if(!doneP) {
lumaEndP = lumaEndP - lumaNN * 0.5;
}
doneN = (ABS(lumaEndN)) >= gradientScaled ? 1:0;
doneP = (ABS(lumaEndP)) >= gradientScaled ? 1:0;
if(!doneN) {
posN_x -= offNP_x * p9;
posN_y -= offNP_y * p9;
}
doneNP = (!doneN) || (!doneP) ? 1:0;
if(!doneP) {
posP_x += offNP_x * p9;
posP_y += offNP_y * p9;
}
if(doneNP) {
if(!doneN) {
lumaEndN = get_pixel_intensity_bilinear(buf, buf_x, buf_y,posN_x,posN_y);
}
if(!doneP) {
lumaEndP = get_pixel_intensity_bilinear(buf, buf_x, buf_y, posP_x,posP_y);
}
if(!doneN) {
lumaEndN = lumaEndN - lumaNN * 0.5;
}
if(!doneP) {
lumaEndP = lumaEndP - lumaNN * 0.5;
}
doneN = (ABS(lumaEndN)) >= gradientScaled ? 1:0;
doneP = (ABS(lumaEndP)) >= gradientScaled ? 1:0;
if(!doneN) {
posN_x -= offNP_x * p10;
posN_y -= offNP_y * p10;
}
doneNP = (!doneN) || (!doneP) ? 1:0;
if(!doneP) {
posP_x += offNP_x * p10;
posP_y += offNP_y * p10;
}
if(doneNP) {
if(!doneN) {
lumaEndN = get_pixel_intensity_bilinear(buf, buf_x, buf_y,posN_x,posN_y);
}
if(!doneP) {
lumaEndP = get_pixel_intensity_bilinear(buf, buf_x, buf_y, posP_x,posP_y);
}
if(!doneN) {
lumaEndN = lumaEndN - lumaNN * 0.5;
}
if(!doneP) {
lumaEndP = lumaEndP - lumaNN * 0.5;
}
doneN = (ABS(lumaEndN)) >= gradientScaled ? 1:0;
doneP = (ABS(lumaEndP)) >= gradientScaled ? 1:0;
if(!doneN) {
posN_x -= offNP_x * p11;
posN_y -= offNP_y * p11;
}
doneNP = (!doneN) || (!doneP) ? 1:0;
if(!doneP) {
posP_x += offNP_x * p11;
posP_y += offNP_y * p11;
}
}
}
}
}
}
}
}
}
}
}
dstN = posM_x - posN_x;
dstP = posP_x - posM_x;
if(!horzSpan) {
dstN = posM_y - posN_y;
dstP = posP_y - posM_y;
}
goodSpanN = ((lumaEndN < 0.0f) ? 1:0) != lumaMLTZero ? 1:0;
spanLength = (dstP + dstN);
goodSpanP = ((lumaEndP < 0.0f) ? 1:0) != lumaMLTZero ? 1:0;
spanLengthRcp = 1.0f/spanLength;
directionN = dstN < dstP ? 1:0;
dst = MIN2(dstN, dstP);
goodSpan = (directionN==1) ? goodSpanN:goodSpanP;
subpixG = subpixF * subpixF;
pixelOffset = (dst * (-spanLengthRcp)) + 0.5f;
subpixH = subpixG * quality_subpix;
pixelOffsetGood = (goodSpan==1) ? pixelOffset : 0.0f;
pixelOffsetSubpix = MAX2(pixelOffsetGood, subpixH);
if(!horzSpan) {
posM_x += pixelOffsetSubpix * lengthSign;
} else {
posM_y += pixelOffsetSubpix * lengthSign;
}
//may need bilinear filtered get_pixel_intensity() here...
set_pixel_intensity(buf,buf_x,buf_y,curr_x,curr_y,get_pixel_intensity_bilinear(buf, buf_x, buf_y, posM_x,posM_y)* lumaM);
}
}
return 1;
#endif
}

@ -49,11 +49,11 @@ extern "C" {
#endif
int PLX_raskterize(float (*base_verts)[2], int num_base_verts,
float *buf, int buf_x, int buf_y);
float *buf, int buf_x, int buf_y, int do_mask_AA);
int PLX_raskterize_feather(float (*base_verts)[2], int num_base_verts,
float (*feather_verts)[2], int num_feather_verts,
float *buf, int buf_x, int buf_y);
int PLX_antialias_buffer(float *buf, int buf_x, int buf_y);
#ifdef __cplusplus
}
#endif

@ -170,7 +170,7 @@ void BKE_mask_layer_shape_changed_remove(struct MaskLayer *masklay, int index, i
/* rasterization */
int BKE_mask_get_duration(struct Mask *mask);
void BKE_mask_rasterize(struct Mask *mask, int width, int height, float *buffer,
const short do_aspect_correct);
const short do_aspect_correct, int do_mask_aa);
#define MASKPOINT_ISSEL_ANY(p) ( ((p)->bezt.f1 | (p)->bezt.f2 | (p)->bezt.f2) & SELECT)
#define MASKPOINT_ISSEL_KNOT(p) ( (p)->bezt.f2 & SELECT)

@ -2089,7 +2089,7 @@ int BKE_mask_get_duration(Mask *mask)
/* rasterization */
void BKE_mask_rasterize(Mask *mask, int width, int height, float *buffer,
const short do_aspect_correct)
const short do_aspect_correct, int do_mask_aa)
{
MaskLayer *masklay;
@ -2154,7 +2154,7 @@ void BKE_mask_rasterize(Mask *mask, int width, int height, float *buffer,
if (tot_diff_point) {
PLX_raskterize(diff_points, tot_diff_point,
buffer_tmp, width, height);
buffer_tmp, width, height, do_mask_aa);
if (tot_diff_feather_points) {
PLX_raskterize_feather(diff_points, tot_diff_point,

@ -2081,7 +2081,8 @@ static ImBuf *seq_render_mask_strip(
BKE_mask_rasterize(seq->mask,
context.rectx, context.recty,
maskbuf,
TRUE);
TRUE,
FALSE /*XXX- TODO: make on/off for anti-aliasing*/);
fp_src = maskbuf;
fp_dst = ibuf->rect_float;
@ -2104,7 +2105,8 @@ static ImBuf *seq_render_mask_strip(
BKE_mask_rasterize(seq->mask,
context.rectx, context.recty,
maskbuf,
TRUE);
TRUE,
FALSE /*XXX- TODO: mask on/off for anti-aliasing*/);
fp_src = maskbuf;
ub_dst = (unsigned char *)ibuf->rect;

@ -1428,7 +1428,7 @@ static void track_mask_gpencil_layer_rasterize(int frame_width, int frame_height
fp[1] = (stroke_points[i].y - marker->search_min[1]) * frame_height / mask_height;
}
PLX_raskterize((float (*)[2])mask_points, stroke->totpoints, mask, mask_width, mask_height);
PLX_raskterize((float (*)[2])mask_points, stroke->totpoints, mask, mask_width, mask_height, FALSE /* XXX- TODO: make on/off for AA*/);
MEM_freeN(mask_points);
}

@ -54,6 +54,7 @@ void MaskNode::convertToOperations(ExecutionSystem *graph, CompositorContext * c
operation->setMask(mask);
operation->setFramenumber(context->getFramenumber());
operation->setSmooth((bool)editorNode->custom1);
graph->addOperation(operation);
}

@ -32,6 +32,7 @@
extern "C" {
#include "BKE_mask.h"
#include "../../../../intern/raskter/raskter.h"
}
MaskOperation::MaskOperation(): NodeOperation()
@ -74,7 +75,10 @@ void *MaskOperation::initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers
float *buffer;
buffer = (float *)MEM_callocN(sizeof(float) * width * height, "rasterized mask");
BKE_mask_rasterize(mask, width, height, buffer, TRUE);
BKE_mask_rasterize(mask, width, height, buffer, TRUE, this->smooth);
if(this->smooth) {
PLX_antialias_buffer(buffer, width, height);
}
this->rasterizedMask = buffer;
}

@ -40,6 +40,7 @@ protected:
int maskWidth;
int maskHeight;
int framenumber;
bool smooth;
float *rasterizedMask;
/**
@ -59,6 +60,7 @@ public:
void setMaskWidth(int width) {this->maskWidth = width;}
void setMaskHeight(int height) {this->maskHeight = height;}
void setFramenumber(int framenumber) {this->framenumber = framenumber;}
void setSmooth(bool smooth) {this->smooth = smooth;}
void executePixel(float *color, int x, int y, MemoryBuffer *inputBuffers[], void *data);
};

@ -2421,6 +2421,8 @@ static void node_composit_buts_viewer_but(uiLayout *layout, bContext *UNUSED(C),
static void node_composit_buts_mask(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
uiTemplateID(layout, C, ptr, "mask", NULL, NULL, NULL);
uiItemR(layout, ptr, "smooth_mask", 0, NULL, ICON_NONE);
}
/* only once called */

@ -3089,6 +3089,11 @@ static void def_cmp_mask(StructRNA *srna)
{
PropertyRNA *prop;
prop = RNA_def_property(srna, "smooth_mask", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "custom1", 0);
RNA_def_property_ui_text(prop, "Anti-Alias", "Apply an anti-aliasing filter to the mask");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
prop = RNA_def_property(srna, "mask", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "id");
RNA_def_property_struct_type(prop, "Mask");

@ -38,6 +38,8 @@
#include "node_composite_util.h"
#include "../../../../intern/raskter/raskter.h"
/* **************** Translate ******************** */
static bNodeSocketTemplate cmp_node_mask_out[] = {
@ -68,8 +70,11 @@ static void exec(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **
stackbuf = alloc_compbuf(sx, sy, CB_VAL, TRUE);
res = stackbuf->rect;
BKE_mask_rasterize(mask, sx, sy, res, TRUE);
BKE_mask_rasterize(mask, sx, sy, res, TRUE, node->custom1);
if(node->custom1){
PLX_antialias_buffer(res,sx,sy);
}
/* pass on output and free */
out[0]->data = stackbuf;
}