Beispiel #1
0
int
main(int ac, char **av)
{
    unsigned char rgb[4];
    float src[3];
    point_t dest;
    point_t xyz;
    size_t ret;

    if (ac > 1)
	bu_log("Usage: %s\n", av[0]);

    spectrum = bn_table_make_uniform(nsamp, min_nm, max_nm);
    BN_GET_TABDATA(curve, spectrum);

    rt_spect_make_CIE_XYZ(&cie_x, &cie_y, &cie_z, spectrum);
    make_ntsc_xyz2rgb(xyz2rgb);

    for (;;) {
	if (fread(rgb, 1, 3, stdin) != 3) break;
	if (feof(stdin)) break;

	VSET(src, rgb[0]/255., rgb[1]/255., rgb[2]/255.);

	rt_spect_reflectance_rgb(curve, src);

	spect_curve_to_xyz(xyz, curve, cie_x, cie_y, cie_z);

	MAT3X3VEC(dest, xyz2rgb, xyz);

	if (dest[0] > 1 || dest[1] > 1 || dest[2] > 1 ||
	    dest[0] < 0 || dest[1] < 0 || dest[2] < 0) {
	    VPRINT("src ", src);
	    VPRINT("dest", dest);
	}

	if (dest[0] > 1) dest[0] = 1;
	if (dest[1] > 1) dest[1] = 1;
	if (dest[2] > 1) dest[2] = 1;
	if (dest[0] < 0) dest[0] = 0;
	if (dest[1] < 0) dest[1] = 0;
	if (dest[2] < 0) dest[2] = 0;

	VSCALE(rgb, dest, 255.0);

	ret = fwrite(rgb, 1, 3, stdout);
	if (ret != 3)
	    perror("fwrite");
    }

    return 0;
}
Beispiel #2
0
/*
 Color pixel based on the energy of a point light source (Eps)
 plus some diffuse illumination (Epd) reflected from the point
 <x, y> :

 E = Epd + Eps (1)

 The energy reflected from diffuse illumination is the product
 of the reflectance coefficient at point P (Rp) and the diffuse
 illumination (Id) :

 Epd = Rp * Id (2)

 The energy reflected from the point light source is calculated
 by the sum of the diffuse reflectance (Rd) and the specular
 reflectance (Rs), multiplied by the intensity of the light
 source (Ips) :

 Eps = (Rd + Rs) * Ips (3)

 The diffuse reflectance is calculated by the product of the
 reflectance coefficient (Rp) and the cosine of the angle of
 incidence (I) :

 Rd = Rp * cos(I)	(4)

 The specular reflectance is calculated by the product of the
 specular reflectance coefficient and (the cosine of the angle (S)
 raised to the nth power) :

 Rs = W(I) * cos(S)**n (5)

 Where,
 I is the angle of incidence.
 S is the angle between the reflected ray and the observer.
 W returns the specular reflection coefficient as a function
 of the angle of incidence.
 n (roughly 1 to 10) represents the shininess of the surface.
 *
 This is the heart of the lighting model which is based on a model
 developed by Bui-Tuong Phong, [see Wm M. Newman and R. F. Sproull,
 "Principles of Interactive Computer Graphics", 	McGraw-Hill, 1979]

 Er = Ra(m)*cos(Ia) + Rd(m)*cos(I1) + W(I1, m)*cos(s)^^n
 where,

 Er	is the energy reflected in the observer's direction.
 Ra	is the diffuse reflectance coefficient at the point
 of intersection due to ambient lighting.
 Ia	is the angle of incidence associated with the ambient
 light source (angle between ray direction (negated) and
 surface normal).
 Rd	is the diffuse reflectance coefficient at the point
 of intersection due to primary lighting.
 I1	is the angle of incidence associated with the primary
 light source (angle between light source direction and
 surface normal).
 m	is the material identification code.
 W	is the specular reflectance coefficient,
 a function of the angle of incidence, range 0.0 to 1.0,
 for the material.
 s	is the angle between the reflected ray and the observer.
 `	n	'Shininess' of the material,  range 1 to 10.
*/
HIDDEN int
phong_render(register struct application *ap, const struct partition *pp, struct shadework *swp, void *dp)
{
    struct light_specific *lp;
#ifndef RT_MULTISPECTRAL
    fastf_t *intensity;
    fastf_t dist;
    point_t pt;
    vect_t color;
#endif
    fastf_t *to_light;
    fastf_t cosine;
    fastf_t refl;
    int i;
    vect_t reflected;
    vect_t work;

#ifdef RT_MULTISPECTRAL
    struct bn_tabdata *ms_matcolor = BN_TABDATA_NULL;
#else
    point_t matcolor;		/* Material color */
#endif
    struct phong_specific *ps =
	(struct phong_specific *)dp;

    if (!ps || ps->magic != PL_MAGIC)
	bu_bomb("phong_render: bad magic\n");

    if (pp == NULL)
	bu_bomb("phong_render: bad partition\n");

    if (rdebug&RDEBUG_SHADE)
	bu_struct_print("phong_render", phong_parse, (char *)ps);

    swp->sw_transmit = ps->transmit;
    swp->sw_reflect = ps->reflect;
    swp->sw_refrac_index = ps->refrac_index;
    swp->sw_extinction = ps->extinction;
#if SW_SET_TRANSMIT
    if (swp->sw_phong_set_vector & SW_SET_TRANSMIT) swp->sw_transmit = swp->sw_phong_transmit;
    if (swp->sw_phong_set_vector & SW_SET_REFLECT) swp->sw_reflect = swp->sw_phong_reflect;
    if (swp->sw_phong_set_vector & SW_SET_REFRAC_INDEX) swp->sw_refrac_index = swp->sw_phong_ri;
    if (swp->sw_phong_set_vector & SW_SET_EXTINCTION) swp->sw_extinction = swp->sw_phong_extinction;
#endif /* SW_SET_TRANSMIT */
    if (swp->sw_xmitonly) {
	if (swp->sw_xmitonly > 1)
	    return 1;	/* done -- wanted parameters only */
	if (swp->sw_reflect > 0 || swp->sw_transmit > 0) {
	    if (rdebug&RDEBUG_SHADE)
		bu_log("calling rr_render from phong, sw_xmitonly\n");
	    (void)rr_render(ap, pp, swp);
	}
	return 1;	/* done */
    }


#ifdef RT_MULTISPECTRAL
    ms_matcolor = bn_tabdata_dup(swp->msw_color);
#else
    VMOVE(matcolor, swp->sw_color);
#endif

    /* Photon Mapping */
#ifndef RT_MULTISPECTRAL
    color[0]= swp->sw_color[0];
    color[1]= swp->sw_color[1];
    color[2]= swp->sw_color[2];
#endif

#ifndef RT_MULTISPECTRAL
    if (!PM_Visualize)
#endif
    {
	/* Diffuse reflectance from "Ambient" light source (at eye) */
	if ((cosine = -VDOT(swp->sw_hit.hit_normal, ap->a_ray.r_dir)) > 0.0) {
	    if (cosine > 1.00001) {
		bu_log("cosAmb=1+%g %s surfno=%d (x%d, y%d, lvl%d)\n",
		       cosine-1,
		       pp->pt_inseg->seg_stp->st_dp->d_namep,
		       swp->sw_hit.hit_surfno,
		       ap->a_x, ap->a_y, ap->a_level);
		VPRINT(" normal", swp->sw_hit.hit_normal);
		VPRINT(" r_dir ", ap->a_ray.r_dir);
		cosine = 1;
	    }
#if SW_SET_TRANSMIT
	    if (swp->sw_phong_set_vector & SW_SET_AMBIENT) {
		cosine *= swp->sw_phong_ambient;
	    } else {
		cosine *= AmbientIntensity;
	    }
#else
	    cosine *= AmbientIntensity;
#endif
#ifdef RT_MULTISPECTRAL
	    bn_tabdata_scale(swp->msw_color, ms_matcolor, cosine);
#else
	    VSCALE(swp->sw_color, matcolor, cosine);
#endif
	} else {
#ifdef RT_MULTISPECTRAL
	    bn_tabdata_constval(swp->msw_color, 0.0);
#else
	    VSETALL(swp->sw_color, 0);
#endif
	}

	/* Emission.  0..1 is normal range, -1..0 sucks light out, like OpenGL */
#ifdef RT_MULTISPECTRAL
	{
	    float emission[3];
	    struct bn_tabdata *ms_emission = BN_TABDATA_NULL;
	    VMOVE(emission, ps->emission);
#if SW_SET_TRANSMIT
	    if (swp->sw_phong_set_vector & SW_SET_EMISSION) {
		VSETALL(emission, swp->sw_phong_emission);
	    }
#endif
	    /* XXX Really should get a curve at prep, not expand RGB samples */
	    BN_GET_TABDATA(ms_emission, spectrum);
	    rt_spect_reflectance_rgb(ms_emission, emission);
	    bn_tabdata_add(swp->msw_color, swp->msw_color, ms_emission);
	    bn_tabdata_free(ms_emission);
	}
#else
#if SW_SET_TRANSMIT
	if (swp->sw_phong_set_vector & SW_SET_EMISSION) {
	    vect_t tmp;
	    VSETALL(tmp, swp->sw_phong_emission);
	    VADD2(swp->sw_color, swp->sw_color, tmp);
	} else {
	    VADD2(swp->sw_color, swp->sw_color, ps->emission);
	}
#else
	VADD2(swp->sw_color, swp->sw_color, ps->emission);
#endif /* SW_SET_TRANSMIT */
#endif

	/* With the advent of procedural shaders, the caller can no longer
	 * provide us reliable light visibility information.  The hit point
	 * may have been changed by another shader in a stack.  There is no
	 * way that anyone else can tell us whether lights are visible.
	 */
	light_obs(ap, swp, ps->mfp->mf_inputs);

	/* Consider effects of each light source */
	for (i=ap->a_rt_i->rti_nlights-1; i>=0; i--) {

	    if ((lp = (struct light_specific *)swp->sw_visible[i]) == LIGHT_NULL)
		continue;

	    if (rdebug & RDEBUG_LIGHT) {
		bu_log("phong_render light=%s lightfract=%g\n",
		       lp->lt_name, swp->sw_lightfract[i]);
	    }

	    /* Light is not shadowed -- add this contribution */
#ifndef RT_MULTISPECTRAL
	    intensity = swp->sw_intensity+3*i;
#endif
	    to_light = swp->sw_tolight+3*i;

	    /* Diffuse reflectance from this light source. */
	    if ((cosine=VDOT(swp->sw_hit.hit_normal, to_light)) > 0.0) {
		if (cosine > 1.00001) {
		    bu_log("cosI=1+%g (x%d, y%d, lvl%d)\n", cosine-1,
			   ap->a_x, ap->a_y, ap->a_level);
		    cosine = 1;
		}
		/* Get Obj Hit Point For Attenuation */
#ifndef RT_MULTISPECTRAL
		if (PM_Activated) {
		    VJOIN1(pt, ap->a_ray.r_pt, pp->pt_inhit->hit_dist, ap->a_ray.r_dir);
		    dist= sqrt((pt[0]-lp->lt_pos[0])*(pt[0]-lp->lt_pos[0]) + (pt[1]-lp->lt_pos[1])*(pt[1]-lp->lt_pos[1]) + (pt[2]-lp->lt_pos[2])*(pt[2]-lp->lt_pos[2]))/1000.0;
		    dist= (1.0/(0.1 + 1.0*dist + 0.01*dist*dist));
		    refl= dist * ps->wgt_diffuse * cosine * swp->sw_lightfract[i] * lp->lt_intensity;
		    /* bu_log("pt: [%.3f][%.3f, %.3f, %.3f]\n", dist, pt[0], pt[1], pt[2]);*/
		} else
#endif
		{
		    refl= ps->wgt_diffuse * swp->sw_lightfract[i] * cosine * lp->lt_fraction;
		}

#ifdef RT_MULTISPECTRAL
		bn_tabdata_incr_mul3_scale(swp->msw_color,
					   lp->lt_spectrum,
					   swp->msw_intensity[i],
					   ms_matcolor,
					   refl);
#else
		VELMUL3(work, matcolor, lp->lt_color, intensity);
		VJOIN1(swp->sw_color, swp->sw_color, refl, work);
#endif
	    }

	    /* Calculate specular reflectance.
	     * Reflected ray = (2 * cos(i) * Normal) - Incident ray.
	     * Cos(s) = Reflected ray DOT Incident ray.
	     */
	    cosine *= 2;
	    VSCALE(work, swp->sw_hit.hit_normal, cosine);
	    VSUB2(reflected, work, to_light);
	    if ((cosine = -VDOT(reflected, ap->a_ray.r_dir)) > 0) {
		if (cosine > 1.00001) {
		    bu_log("cosS=1+%g (x%d, y%d, lvl%d)\n", cosine-1,
			   ap->a_x, ap->a_y, ap->a_level);
		    cosine = 1;
		}
		refl = ps->wgt_specular * swp->sw_lightfract[i] *
		    lp->lt_fraction *
#ifdef PHAST_PHONG
		    /* It is unnecessary to compute the actual
		     * exponential here since phong is just a
		     * gross hack.  We approximate re:
		     * Graphics Gems IV "A Fast Alternative to
		     * Phong's Specular Model" Pg 385
		     */
		    cosine /
		    (ps->shine - ps->shine*cosine + cosine);
#else
		phg_ipow(cosine, ps->shine);
#endif /* PHAST_PHONG */
#ifdef RT_MULTISPECTRAL
		bn_tabdata_incr_mul2_scale(swp->msw_color,
					   lp->lt_spectrum,
					   swp->msw_intensity[i],
					   refl);
#else
		VELMUL(work, lp->lt_color, intensity);
		VJOIN1(swp->sw_color, swp->sw_color, refl, work);
#endif
	    }
	}

#ifndef RT_MULTISPECTRAL
	if (PM_Activated) {
	    IrradianceEstimate(ap, work, swp->sw_hit.hit_point, swp->sw_hit.hit_normal);
	    VELMUL(work, work, color);
	    VADD2(swp->sw_color, work, swp->sw_color);
	    if (swp->sw_color[0] > 1.0) swp->sw_color[0]= 1.0;
	    if (swp->sw_color[1] > 1.0) swp->sw_color[1]= 1.0;
	    if (swp->sw_color[2] > 1.0) swp->sw_color[2]= 1.0;
	}

    } else {

	if (PM_Activated) {
	    /* IrradianceEstimate(work, swp->sw_hit.hit_point, swp->sw_hit.hit_normal);
	       VELMUL(swp->sw_color, work, color);*/
	    IrradianceEstimate(ap, swp->sw_color, swp->sw_hit.hit_point, swp->sw_hit.hit_normal);
	    if (swp->sw_color[0] > 1.0) swp->sw_color[0]= 1.0;
	    if (swp->sw_color[1] > 1.0) swp->sw_color[1]= 1.0;
	    if (swp->sw_color[2] > 1.0) swp->sw_color[2]= 1.0;
	}
#endif
    }


    if (swp->sw_reflect > 0 || swp->sw_transmit > 0)
	(void)rr_render(ap, pp, swp);

#ifdef RT_MULTISPECTRAL
    bn_tabdata_free(ms_matcolor);
#endif
    return 1;
}