|
|
105dfe |
/*
|
|
|
105dfe |
......... 2015 Ivan Mahonin
|
|
|
105dfe |
|
|
|
105dfe |
This program is free software: you can redistribute it and/or modify
|
|
|
105dfe |
it under the terms of the GNU General Public License as published by
|
|
|
105dfe |
the Free Software Foundation, either version 3 of the License, or
|
|
|
105dfe |
(at your option) any later version.
|
|
|
105dfe |
|
|
|
105dfe |
This program is distributed in the hope that it will be useful,
|
|
|
105dfe |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
105dfe |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
105dfe |
GNU General Public License for more details.
|
|
|
105dfe |
|
|
|
105dfe |
You should have received a copy of the GNU General Public License
|
|
|
105dfe |
along with this program. If not, see <http: licenses="" www.gnu.org="">.</http:>
|
|
|
105dfe |
*/
|
|
|
105dfe |
|
|
|
5a7afd |
#define PRECISION 1e-6f
|
|
|
5a7afd |
#define ONE 65536
|
|
|
5a7afd |
#define TWO 131072 // (ONE)*2
|
|
|
5a7afd |
#define HALF 32768 // (ONE)/2
|
|
|
5a7afd |
#define ONE_F 65536.f // (float)(ONE)
|
|
|
5a7afd |
#define DIV_ONE_F 0.0000152587890625f // 1.f/(ONE_F)
|
|
|
5a7afd |
|
|
|
5a7afd |
|
|
|
105dfe |
kernel void clear(
|
|
|
105dfe |
int width,
|
|
|
105dfe |
int height,
|
|
|
105dfe |
global int4 *mark_buffer )
|
|
|
105dfe |
{
|
|
|
105dfe |
int id = get_global_id(0);
|
|
|
105dfe |
if (id >= width*height) return;
|
|
|
105dfe |
int c = id % width;
|
|
|
105dfe |
int4 v = { 0, 0, c | (c + 1), 0 };
|
|
|
105dfe |
mark_buffer[id] = v;
|
|
|
105dfe |
}
|
|
|
105dfe |
|
|
|
105dfe |
kernel void path(
|
|
|
105dfe |
int width,
|
|
|
105dfe |
int height,
|
|
|
105dfe |
global int *mark_buffer,
|
|
|
105dfe |
global float2 *points,
|
|
|
105dfe |
int begin,
|
|
|
105dfe |
int end )
|
|
|
105dfe |
{
|
|
|
105dfe |
int id = get_global_id(0);
|
|
|
105dfe |
if (id >= end) return;
|
|
|
105dfe |
|
|
|
105dfe |
float2 s = { (float)width, (float)height };
|
|
|
105dfe |
int w1 = width - 1;
|
|
|
105dfe |
int h1 = height - 1;
|
|
|
105dfe |
|
|
|
105dfe |
float2 p0 = points[id];
|
|
|
105dfe |
float2 p1 = points[id + 1];
|
|
|
105dfe |
bool flipx = p1.x < p0.x;
|
|
|
105dfe |
bool flipy = p1.y < p0.y;
|
|
|
105dfe |
if (flipx) { p0.x = s.x - p0.x; p1.x = s.x - p1.x; }
|
|
|
105dfe |
if (flipy) { p0.y = s.y - p0.y; p1.y = s.y - p1.y; }
|
|
|
105dfe |
float2 d = p1 - p0;
|
|
|
5a7afd |
float kx = fabs(d.y) < PRECISION ? 1e10 : d.x/d.y;
|
|
|
5a7afd |
float ky = fabs(d.x) < PRECISION ? 1e10 : d.y/d.x;
|
|
|
5a7afd |
|
|
|
5a7afd |
global int *row, *mark;
|
|
|
5a7afd |
float2 px, py, pp1;
|
|
|
5a7afd |
float cover, area;
|
|
|
5a7afd |
int ix, iy, iix;
|
|
|
105dfe |
|
|
|
105dfe |
while(p0.x != p1.x || p0.y != p1.y) {
|
|
|
5a7afd |
ix = (int)p0.x;
|
|
|
5a7afd |
iy = (int)p0.y;
|
|
|
105dfe |
if (iy > h1) break;
|
|
|
105dfe |
|
|
|
105dfe |
px.x = (float)(ix + 1);
|
|
|
105dfe |
px.y = p0.y + ky*(px.x - p0.x);
|
|
|
105dfe |
py.y = max((float)(iy + 1), 0.f);
|
|
|
105dfe |
py.x = p0.x + kx*(py.y - p0.y);
|
|
|
5a7afd |
pp1 = p1;
|
|
|
105dfe |
if (pp1.x > px.x) pp1 = px;
|
|
|
105dfe |
if (pp1.y > py.y) pp1 = py;
|
|
|
105dfe |
|
|
|
105dfe |
if (iy >= 0) {
|
|
|
5a7afd |
cover = pp1.y - p0.y;
|
|
|
5a7afd |
area = px.x - 0.5f*(p0.x + pp1.x);
|
|
|
105dfe |
if (flipx) { ix = w1 - ix; area = 1.f - area; }
|
|
|
105dfe |
if (flipy) { iy = h1 - iy; cover = -cover; }
|
|
|
105dfe |
ix = clamp(ix, 0, w1);
|
|
|
5a7afd |
row = mark_buffer + 4*iy*width;
|
|
|
5a7afd |
mark = row + 4*ix;
|
|
|
5a7afd |
atomic_add(mark, (int)(area*cover*ONE_F));
|
|
|
5a7afd |
atomic_add(mark + 1, (int)(cover*ONE_F));
|
|
|
5a7afd |
iix = (ix & (ix + 1)) - 1;
|
|
|
5a7afd |
while(iix >= 0) {
|
|
|
105dfe |
atomic_min(row + 4*iix + 2, ix);
|
|
|
105dfe |
iix = (iix & (iix + 1)) - 1;
|
|
|
105dfe |
}
|
|
|
105dfe |
}
|
|
|
105dfe |
|
|
|
105dfe |
p0 = pp1;
|
|
|
105dfe |
}
|
|
|
105dfe |
}
|
|
|
105dfe |
|
|
|
82f284 |
// TODO:
|
|
|
82f284 |
// different implementations for:
|
|
|
82f284 |
// antialiased, transparent, inverted, evenodd contours and combinations (total 16 implementations)
|
|
|
105dfe |
kernel void fill(
|
|
|
105dfe |
int width,
|
|
|
105dfe |
int height,
|
|
|
105dfe |
global int4 *mark_buffer,
|
|
|
105dfe |
global float4 *image,
|
|
|
105dfe |
float4 color,
|
|
|
105dfe |
int invert,
|
|
|
105dfe |
int evenodd )
|
|
|
105dfe |
{
|
|
|
105dfe |
int id = get_global_id(0);
|
|
|
105dfe |
if (id >= height) return;
|
|
|
105dfe |
global int4 *row = mark_buffer + id*width;
|
|
|
82f284 |
global int4 *mark;
|
|
|
105dfe |
global float4 *image_row = image + id*width;
|
|
|
82f284 |
global float4 *pixel;
|
|
|
105dfe |
|
|
|
82f284 |
int icover = 0;
|
|
|
82f284 |
//int ialpha;
|
|
|
82f284 |
int c0 = 0;
|
|
|
82f284 |
int c1 = 0;
|
|
|
82f284 |
int i = 0;
|
|
|
82f284 |
float alpha;
|
|
|
82f284 |
int4 m;
|
|
|
82f284 |
while(c0 < width) {
|
|
|
82f284 |
c1 = min(c1, width);
|
|
|
5a7afd |
mark = &row[c1];
|
|
|
5a7afd |
m = *mark;
|
|
|
5a7afd |
*mark = (int4)(0, 0, c1 | (c1 + 1), 0);
|
|
|
105dfe |
|
|
|
82f284 |
//ialpha = abs(icover);
|
|
|
5a7afd |
//ialpha = evenodd ? ONE - abs((ialpha % TWO) - ONE)
|
|
|
5a7afd |
// : min(ialpha, ONE);
|
|
|
5a7afd |
//if (invert) ialpha = ONE - ialpha;
|
|
|
5a7afd |
if (abs(icover) > HALF)
|
|
|
82f284 |
while(c0 < c1)
|
|
|
82f284 |
image_row[c0++] = color;
|
|
|
105dfe |
|
|
|
82f284 |
if (c1 >= width) return;
|
|
|
105dfe |
|
|
|
82f284 |
//ialpha = abs(mark.x + icover);
|
|
|
5a7afd |
//ialpha = evenodd ? ONE - abs((ialpha % TWO) - ONE)
|
|
|
5a7afd |
// : min(ialpha, ONE);
|
|
|
5a7afd |
//if (invert) ialpha = ONE - ialpha;
|
|
|
82f284 |
|
|
|
5a7afd |
alpha = (float)abs(m.x + icover)*DIV_ONE_F;
|
|
|
82f284 |
pixel = &image_row[c1];
|
|
|
82f284 |
*pixel = (float4)( pixel->xyz*(1.f - alpha) + color.xyz*alpha,
|
|
|
82f284 |
min(pixel->w + alpha, 1.f) );
|
|
|
105dfe |
|
|
|
82f284 |
c0 = c1 + 1;
|
|
|
82f284 |
c1 = m.z;
|
|
|
82f284 |
icover += m.y;
|
|
|
105dfe |
}
|
|
|
105dfe |
}
|