/*
 * Linear light, an example of a pseudo area light.
 * The sample positions are evenly spread out along a line segment between
 * point1 and point2.  Occlusion is computed with ray tracing.
 * The illuminate point is chosen such that L.N is 1 in the diffuse
 * calculation in the surface shader.
 */
light
linearlight(
    float intensity = 1,
    color lightcolor = 1,
    float falloff = 2,   /* 0 = none, 1 = linear, 2 = squared, ... */
    point point1 = point ("shader", 0,0,0),   /* one end of line */
    point point2 = point ("shader", 1,0,0),   /* other end of line */
    float samples = 16,   /* number of sample points on the light source */
    output float __nonspecular = 1
)
{
    vector dir = point2 - point1;
    float i;
    vector Nn = normalize(N);
    float offset = random();

    point p = Ps + Nn;   /* point above Ps to get N.L = 1 in surf. shader */

    emit(p) {
		setmessage ("__nonspecular", __nonspecular);
        for (i = 0; i < samples; i += 1)  {
            /* Compute point p on line segment between point1 and point2 */
            p = point1 + (i + offset) / samples * dir;
            /* Compute distance from point p to surface point Ps */
            vector l = p - Ps;
            float dist = length(l);
            vector ln = l / dist;
            /* Compute light from point p to surface point Ps */
            float dot = dot(ln, Nn);
            if (dot > 0) {
	        color c = intensity * lightcolor;
                c *= pow(dist, -falloff);   /* distance falloff */
	        c *= transmission(Ps, p);   /* ray traced occlusion (shadow) */
                c *= dot;   /* Lambert's cosine law at the surface */
                Cl += c; 
            }
        }
        Cl /= samples;
    }
}
