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

d989ab
/*
d989ab
    ......... 2015 Ivan Mahonin
d989ab
d989ab
    This program is free software: you can redistribute it and/or modify
d989ab
    it under the terms of the GNU General Public License as published by
d989ab
    the Free Software Foundation, either version 3 of the License, or
d989ab
    (at your option) any later version.
d989ab
d989ab
    This program is distributed in the hope that it will be useful,
d989ab
    but WITHOUT ANY WARRANTY; without even the implied warranty of
d989ab
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
d989ab
    GNU General Public License for more details.
d989ab
d989ab
    You should have received a copy of the GNU General Public License
d989ab
    along with this program.  If not, see <http: licenses="" www.gnu.org="">.</http:>
d989ab
*/
d989ab
c7fa36
kernel void clear(
c7fa36
	global int2 *mark_buffer )
67876c
{
c7fa36
	const int2 v = { 0, 0 };
c7fa36
	mark_buffer[get_global_id(0)] = v;
67876c
}
67876c
c7fa36
kernel void path(
c7fa36
	int width,
c7fa36
	int height,
c7fa36
	global int *mark_buffer,
c7fa36
	global float2 *path )
d989ab
{
5890eb
	const float e = 1e-6f;
c7fa36
	size_t id = get_global_id(0);
c7fa36
	
c7fa36
	float2 s = { (float)width, (float)height }; 
c7fa36
	int w1 = width - 1;
c7fa36
	int h1 = height - 1;
d989ab
c7fa36
	float2 p0 = path[id];
c7fa36
	float2 p1 = path[id + 1];
c7fa36
	bool flipx = p1.x < p0.x;
c7fa36
	bool flipy = p1.y < p0.y;
c7fa36
	if (flipx) { p0.x = s.x - p0.x; p1.x = s.x - p1.x; }
c7fa36
	if (flipy) { p0.y = s.y - p0.y; p1.y = s.y - p1.y; }
c7fa36
	float2 d = p1 - p0;
c7fa36
	float kx = fabs(d.y) < e ? 1e10 : d.x/d.y;
c7fa36
	float ky = fabs(d.x) < e ? 1e10 : d.y/d.x;
c7fa36
	
c7fa36
	while(p0.x != p1.x || p0.y != p1.y) {
c7fa36
		int ix = (int)floor(p0.x + e);
c7fa36
		int iy = (int)floor(p0.y + e);
c7fa36
		if (iy > h1) break;
d989ab
c7fa36
		float2 px, py;
c7fa36
		px.x = (float)(ix + 1);
c7fa36
		px.y = p0.y + ky*(px.x - p0.x);
c7fa36
		py.y = max((float)(iy + 1), 0.f);
c7fa36
		py.x = p0.x + kx*(py.y - p0.y);
c7fa36
		float2 pp1 = p1;
c7fa36
		if (pp1.x > px.x) pp1 = px;
c7fa36
		if (pp1.y > py.y) pp1 = py;
c7fa36
		
c7fa36
		if (iy >= 0) {
c7fa36
			float cover = pp1.y - p0.y;
c7fa36
			float area = px.x - 0.5f*(p0.x + pp1.x);
c7fa36
			if (flipx) { ix = w1 - ix; area = 1.f - area; }
c7fa36
			if (flipy) { iy = h1 - iy; cover = -cover; }
c7fa36
			global int *mark = mark_buffer + 2*(iy*width + clamp(ix, 0, w1));
c7fa36
			atomic_add(mark, (int)round(area*cover*65536));
c7fa36
			atomic_add(mark + 1, (int)round(cover*65536));
d989ab
		}
c7fa36
		
c7fa36
		p0 = pp1;
d989ab
	}
d989ab
}
d989ab
c7fa36
kernel void fill(
5890eb
	int width,
c7fa36
	global int2 *mark_buffer,
c7fa36
	read_only image2d_t surface_read_image,
c7fa36
	write_only image2d_t surface_write_image,
a04770
	float4 color,
5890eb
	int invert,
5890eb
	int evenodd )
d989ab
{
5890eb
	size_t id = get_global_id(0);
d989ab
	int w = width;
67876c
	const sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE
67876c
							| CLK_ADDRESS_NONE
67876c
			                | CLK_FILTER_NEAREST;
a04770
	float4 cl = color;
5890eb
	float cover = 0.f;
c7fa36
	global int2 *mark = mark_buffer + id*w;
c7fa36
	const int2 izero = { 0, 0 };
67876c
	for(int2 coord = { 0, id }; coord.x < w; ++coord.x, ++mark) {
c7fa36
		int2 im = *mark;
c7fa36
		//*mark = izero;
c7fa36
		float alpha = fabs((float)im.x/65536.f + cover);
c7fa36
		cover += (float)im.y/65536.f;
67876c
		alpha = evenodd ? (1.f - fabs(1.f - alpha - 2.f*floor(0.5f*alpha)))
c7fa36
						: fmin(alpha, 1.f);
a04770
		alpha *= cl.w;
5890eb
		if (invert) alpha = 1.f - alpha;
5890eb
		float alpha_inv = 1.f - alpha;
a04770
		
67876c
		float4 c = read_imagef(surface_read_image, sampler, coord);
a04770
		c.x = c.x*alpha_inv + cl.x*alpha;
a04770
		c.y = c.y*alpha_inv + cl.y*alpha;
a04770
		c.z = c.z*alpha_inv + cl.z*alpha;
67876c
		c.w = min(c.w + alpha, 1.f);
67876c
		write_imagef(surface_write_image, coord, c);
d989ab
	}
d989ab
}