Blame c++/contourgl/cl/contour-base.cl

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
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
	const float e = 1e-6f;
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;
105dfe
	float kx = fabs(d.y) < e ? 1e10 : d.x/d.y;
105dfe
	float ky = fabs(d.x) < e ? 1e10 : d.y/d.x;
105dfe
	
105dfe
	while(p0.x != p1.x || p0.y != p1.y) {
105dfe
		int ix = (int)floor(p0.x + e);
105dfe
		int iy = (int)floor(p0.y + e);
105dfe
		if (iy > h1) break;
105dfe
105dfe
		float2 px, py;
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);
105dfe
		float2 pp1 = p1;
105dfe
		if (pp1.x > px.x) pp1 = px;
105dfe
		if (pp1.y > py.y) pp1 = py;
105dfe
		
105dfe
		if (iy >= 0) {
105dfe
			float cover = pp1.y - p0.y;
105dfe
			float 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);
105dfe
			global int *row = mark_buffer + 4*iy*width;
105dfe
			global int *mark = row + 4*ix;
105dfe
			atomic_add(mark, (int)round(area*cover*65536.f));
105dfe
			atomic_add(mark + 1, (int)round(cover*65536.f));
105dfe
			int iix = (ix & (ix + 1)) - 1;
105dfe
			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
	const int scale = 65536;
105dfe
	const int scale2 = 2*scale;
105dfe
	const int scale05 = scale/2;
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
		while(c1 < width) {
82f284
			mark = &row[c1];
82f284
			m = *mark;
82f284
			*mark = (int4)(0, 0, c1 | (c1 + 1), 0); 
82f284
			if (m.x || m.y) break;
82f284
			c1 = m.z;
105dfe
		}
82f284
		c1 = min(c1, width);
105dfe
		
82f284
		//ialpha = abs(icover);
82f284
		//ialpha = evenodd ? scale - abs((ialpha % scale2) - scale)
82f284
		//				 : min(ialpha, scale);
82f284
		//if (invert) ialpha = scale - ialpha;
82f284
		if (abs(icover) > scale05)
82f284
			while(c0 < c1)
82f284
				image_row[c0++] = color;
105dfe
	
82f284
		if (c1 >= width) return;
105dfe
		
82f284
		//ialpha = abs(mark.x + icover);
82f284
		//ialpha = evenodd ? scale - abs((ialpha % scale2) - scale)
82f284
		//				 : min(ialpha, scale);
82f284
		//if (invert) ialpha = scale - ialpha;  
82f284
82f284
		alpha = (float)abs(m.x + icover)/(float)scale;
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
}