/**
 * Color particle shader
 * by Andres Colubri. February 2008.
 * 
 * This GLSL fragment shader updates the color of the particles.
 * It uses the image texture to get the color of the underlying
 * pixel. However, the color a particle keeps its color for a
 * certain amount of time (to create the flow effect), so there
 * is a counter variable, stored in an auxiliar texture, to keep
 * track of the time that each particle has remained with the same
 * color.
 *
 */
 
/*
  Copyright (c) 2006 Andres Colubri

  This source is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This code is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  General Public License for more details.

  A copy of the GNU General Public License is available on the World
  Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also
  obtain it by writing to the Free Software Foundation,
  Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/

#extension GL_ARB_draw_buffers : enable

uniform sampler2D tex_unit_image;
uniform sampler2D tex_unit_newimage;
uniform sampler2D tex_unit_color;
uniform sampler2D tex_unit_coloraux;
uniform sampler2D tex_unit_pos;
uniform sampler2D tex_unit_counter;

uniform int max_brush_length;
uniform float newimage_coeff;
uniform float colorchg_frac;
uniform float colorchg_pow;
uniform vec2 inv_canvas_size;

void main(void)
{
    vec2 pos_coord = gl_TexCoord[0].st;

	vec2 part_pos = texture2D(tex_unit_pos, pos_coord).xy;
	vec2 image_coord = vec2(part_pos.x * inv_canvas_size.x, part_pos.y * inv_canvas_size.y);
	
    vec3 image_color, final_color, newimage_color;
    float inv_nsteps, arg, frac;
	int lim;

    bool color_chg = (0.0 <= newimage_coeff) && (newimage_coeff <= 1.0);

    vec3 prev_color = texture2D(tex_unit_color, pos_coord).rgb;
    vec3 aux_data = texture2D(tex_unit_coloraux, pos_coord).rgb;
	
	vec2 count_vec = texture2D(tex_unit_counter, pos_coord).xy;
	int count = int(count_vec.x);
	int max_count = int(count_vec.y * float(max_brush_length));
	max_count = max(1, max_count);
	
    if (count < max_count)
    {
        // The particle keeps the previous color.
        gl_FragData[0] = vec4(prev_color, 1.0);
        gl_FragData[1] = vec4(aux_data, 1.0);
		
		gl_FragData[2] = vec4(count + 1, count_vec.y, 0.0, 1.0);
    }
    else
    {
        // Getting new color for the particle.
        if (count == max_count)
        {
            image_color = texture2D(tex_unit_image, image_coord).rgb;
        }
        else
        {
            image_color = aux_data;
        }

        if (color_chg)
        {
            newimage_color = texture2D(tex_unit_newimage, image_coord).xyz;
            image_color = (1.0 - newimage_coeff) * image_color + newimage_coeff * newimage_color;
        }

        // Evaluating final color...
        // Continuous transition between prev_color and image_color.
        lim = int((1.0 + colorchg_frac) * float(max_count));
        if (count <= lim)
        {
            inv_nsteps = 1.0 / (colorchg_frac * float(max_count));
            arg = inv_nsteps * (float(count - max_count));
            frac = pow(arg, colorchg_pow);

            final_color = (1.0 - frac) * prev_color +  frac * image_color;
            count++;
        }
        else 
        {
		    final_color = image_color;
            count = 0;
        }
		
        gl_FragData[0] = vec4(final_color, 1.0);
        gl_FragData[1] = vec4(image_color, 1.0);	
		gl_FragData[2] = vec4(count, count_vec.y, 0.0, 1.0);
    }
}
