Пример #1
0
HIDDEN int
ckr_render(struct application *ap, const struct partition *pp, register struct shadework *swp, void *dp)
{
    register struct ckr_specific *ckp =
	(struct ckr_specific *)dp;
    register int *cp;
    int u, v;

    u = swp->sw_uv.uv_u * ckp->ckr_scale;
    v = swp->sw_uv.uv_v * ckp->ckr_scale;

    if (((u&1) && (v&1)) || (!(u&1) && !(v&1))) {
	cp = ckp->ckr_a;
    } else {
	cp = ckp->ckr_b;
    }

    VSET(swp->sw_color,
	 (unsigned char)cp[0] / 255.0,
	 (unsigned char)cp[1] / 255.0,
	 (unsigned char)cp[2] / 255.0);

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

    return 1;
}
Пример #2
0
/*
 * Sort of a surface spot transparency shader.  Picks transparency
 * based upon noise value of surface spot.
 */
int
tsplat_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp)
{
    register struct scloud_specific *scloud_sp =
        (struct scloud_specific *)dp;
    point_t in_pt;	/* point where ray enters scloud solid */
    double val;

    RT_CHECK_PT(pp);
    RT_AP_CHECK(ap);
    RT_CK_REGION(pp->pt_regionp);


    /* just shade the surface with a transparency */
    MAT4X3PNT(in_pt, scloud_sp->mtos, swp->sw_hit.hit_point);
    val = bn_noise_fbm(in_pt, scloud_sp->h_val,
                       scloud_sp->lacunarity, scloud_sp->octaves);
    CLAMP(val, 0.0, 1.0);
    swp->sw_transmit = 1.0 - val;


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

    return 1;
}
Пример #3
0
/*
 * Render a map which varies red with U and blue with V values.
 * Mostly useful for debugging ft_uv() routines.
 */
HIDDEN int
tstm_render(struct application *ap, const struct partition *pp, register struct shadework *swp, void *UNUSED(dp))
{
    VSET(swp->sw_color, swp->sw_uv.uv_u, 0, swp->sw_uv.uv_v);

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

    return 1;
}
/*
 * This is called (from viewshade() in shade.c) once for each hit point
 * to be shaded.  The purpose here is to fill in values in the shadework
 * structure.
 */
int
toon_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp)
{
    int i;
    struct toon_specific *toon_sp = (struct toon_specific *)dp;
    struct light_specific *lp;
    fastf_t cosi, scale;

    /* check the validity of the arguments we got */
    RT_AP_CHECK(ap);
    RT_CHECK_PT(pp);
    CK_TOON_SP(toon_sp);

    if (rdebug&RDEBUG_SHADE)
	bu_struct_print("toon_render Parameters:", toon_print_tab, (char *)toon_sp);

    /* if surface normal is nearly orthogonal to the ray, make a black line */
    if (VDOT(swp->sw_hit.hit_normal, ap->a_inv_dir) >= 0.8) {
	VSETALL(swp->sw_color, 0);
	return 1;
    }

    /* probably need to set some swp values here to avoid the infinite recursion
     * if specified lights exist. */
    light_obs(ap, swp, MFI_HIT);

    /* 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;

	cosi = VDOT(swp->sw_hit.hit_normal, swp->sw_tolight);
	if (cosi <= 0.0) scale = 0.0;
	else if (cosi <= 0.5) scale = 0.5;
	else if (cosi <= 0.8) scale = 0.8;
	else scale = 1.0;
	VSCALE(swp->sw_color, swp->sw_color, scale);
	return 1;
    }

    /* no paths to light source, so just paint it black */
    VSETALL(swp->sw_color, 0);

    if (swp->sw_reflect > 0 || swp->sw_transmit > 0)
	(void)rr_render(ap, pp, swp);
    return 1;
}
Пример #5
0
/*
 *	N U L L _ R E N D E R
 *
 *	This is called (from viewshade() in shade.c) once for each hit point
 *	to be shaded.  The purpose here is to fill in values in the shadework
 *	structure.  This is, of course, not necessary when setup returns 0.
 *
 *  The null shader actually does "something", though it is not called.
 *  It has to at least pass the ray through so that it can actually
 *  raytrace what is visible behind the invisible object.  Otherwise,
 *  an empty black void would be rendered.  this is not really important
 *  though, since it shouldn't normally be called.
 */
HIDDEN int
sh_null_render( struct application *ap, struct partition *pp, struct shadework *swp, char *dp ) {

    /* check the validity of the arguments we got */
    RT_AP_CHECK(ap);
    RT_CHECK_PT(pp);
    /* shadework structures do not have magic numbers or other means to test
     * their validity
     */

    bu_log("Who called sh_null_render explicitly?");

    /* here is what actually makes the object invisible/null instead of being a
     * black void (if render ever is called).
     */
    (void)rr_render(ap, pp, swp);

    return(1);
}
Пример #6
0
/*
 * This is called (from viewshade() in shade.c) once for each hit point
 * to be shaded.  The purpose here is to fill in values in the shadework
 * structure.
 *
 * The flat shader is probably the second most simple shader (second to
 * the null/invisible shader -- it does nothing).  It shades an object
 * a constant color.  The only complexity comes into play when a
 * transparency value is set.  Then we get the color value behind the
 * one we are shading and blend accordingly with the flat color.
 */
int
flat_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp)
{

    register struct flat_specific *flat_sp = (struct flat_specific *)dp;
    const point_t unit = {1.0, 1.0, 1.0};
    point_t intensity;

    /* check the validity of the arguments we got */
    RT_AP_CHECK(ap);
    RT_CHECK_PT(pp);
    CK_FLAT_SP(flat_sp);

    if (rdebug&RDEBUG_SHADE)
	bu_struct_print("flat_render Parameters:", flat_parse_tab, (char *)flat_sp);

    /* do the actual flat color shading for the flat object. if the object is
     * not transparent, just put the color.  if the object is transparent, do
     * a little more work determining the background pixel, and then blend with
     * the flat foreground object.
     */
    if (VNEAR_ZERO(flat_sp->transparency, SMALL_FASTF)) {

	/* just put the flat value */
	VMOVE(swp->sw_color, flat_sp->color);
    } else {

	/* this gets the background pixel value, if the transparency is not 0 */
	swp->sw_transmit = 1.0; /*!!! try to remove */
	VMOVE(swp->sw_basecolor, flat_sp->transparency);
	(void)rr_render(ap, pp, swp);

	/* now blend with the foreground object being shaded */
	VSUB2(intensity, unit, flat_sp->transparency);  /* inverse transparency is how much we want */
	VELMUL(intensity, intensity, flat_sp->color); /* ??? is there a way to merge this mul->add step? */
	VADD2(swp->sw_color, swp->sw_color, intensity);
    }

    return 1;
}
Пример #7
0
HIDDEN int
star_render(register struct application *ap, const struct partition *pp, struct shadework *swp, void *UNUSED(dp))
{
    /* Probably want to diddle parameters based on what part of sky */
    if (bn_rand0to1(ap->a_resource->re_randptr) >= 0.98) {
	register int i;
	register fastf_t f;
	i = (sizeof(star_colors)-1) / sizeof(star_colors[0]);

	/* "f" used for intermediate result to avoid an SGI compiler error */
	f = bn_rand0to1(ap->a_resource->re_randptr);
	i = ((double)i) * f;

	f = bn_rand0to1(ap->a_resource->re_randptr);
	VSCALE(swp->sw_color, star_colors[i], f);
    } else {
	VSETALL(swp->sw_color, 0);
    }

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

    return 1;
}
Пример #8
0
/*
 * Given a u, v coordinate within the texture (0 <= u, v <= 1.0),
 * compute a new surface normal.
 * For now we come up with a local coordinate system, and
 * make bump perturbations from the red and blue channels of
 * an RGB image.
 *
 * Note that .pix files are stored left-to-right, bottom-to-top,
 * which works out very naturally for the indexing scheme.
 */
HIDDEN int
bmp_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp)
{
    register struct txt_specific *tp =
	(struct txt_specific *)dp;
    unsigned char *cp=NULL;
    fastf_t pertU, pertV;
    vect_t y;		/* world coordinate axis vectors */
    vect_t u, v;		/* surface coord system vectors */
    int i, j;		/* bump map pixel indices */

    /*
     * If no texture file present, or if
     * texture isn't and can't be read, give debug color.
     */
    if ((bu_vls_strlen(&tp->tx_name) <= 0) || (!tp->tx_mp && !tp->tx_binunifp)) {
	VSET(swp->sw_color, swp->sw_uv.uv_u, 0, swp->sw_uv.uv_v);
	if (swp->sw_reflect > 0 || swp->sw_transmit > 0)
	    (void)rr_render(ap, pp, swp);
	return 1;
    }
    /* u is left->right index, v is line number bottom->top */
    if (swp->sw_uv.uv_u < 0 || swp->sw_uv.uv_u > 1 || swp->sw_uv.uv_v < 0 || swp->sw_uv.uv_v > 1) {
	bu_log("bmp_render:  bad u, v=%g, %g du, dv=%g, %g seg=%s\n",
	       swp->sw_uv.uv_u, swp->sw_uv.uv_v,
	       swp->sw_uv.uv_du, swp->sw_uv.uv_dv,
	       pp->pt_inseg->seg_stp->st_name);
	VSET(swp->sw_color, 0, 1, 0);
	if (swp->sw_reflect > 0 || swp->sw_transmit > 0)
	    (void)rr_render(ap, pp, swp);
	return 1;
    }

    /* Find a local coordinate system */
    VSET(y, 0, 1, 0);
    VCROSS(u, y, swp->sw_hit.hit_normal);
    VUNITIZE(u);
    VCROSS(v, swp->sw_hit.hit_normal, u);

    /* Find our RGB value */
    i = swp->sw_uv.uv_u * (tp->tx_w-1);
    j = swp->sw_uv.uv_v * (tp->tx_n-1);

    if (tp->tx_mp) {
	cp = ((unsigned char *)(tp->tx_mp->buf)) +
	    (j) * tp->tx_w * 3 + i * 3;
    } else if (tp->tx_binunifp) {
	cp = ((unsigned char *)(tp->tx_binunifp->u.uint8)) +
	    (j) * tp->tx_w * 3 + i * 3;
    } else {
	/* not reachable */
	bu_bomb("sh_text.c -- Unreachable code reached while reading datasource\n");
    }
    pertU = ((fastf_t)(*cp) - 128.0) / 128.0;
    pertV = ((fastf_t)(*(cp+2)) - 128.0) / 128.0;

    if (rdebug&RDEBUG_LIGHT) {
	VPRINT("normal", swp->sw_hit.hit_normal);
	VPRINT("u", u);
	VPRINT("v", v);
	bu_log("cu = %d, cv = %d\n", *cp, *(cp+2));
	bu_log("pertU = %g, pertV = %g\n", pertU, pertV);
    }
    VJOIN2(swp->sw_hit.hit_normal, swp->sw_hit.hit_normal, pertU, u, pertV, v);
    VUNITIZE(swp->sw_hit.hit_normal);
    if (rdebug&RDEBUG_LIGHT) {
	VPRINT("after", swp->sw_hit.hit_normal);
    }

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

    return 1;
}
Пример #9
0
/*
 * Given a u, v coordinate within the texture (0 <= u, v <= 1.0),
 * return the filtered intensity.
 *
 * Note that .bw files are stored left-to-right, bottom-to-top,
 * which works out very naturally for the indexing scheme.
 */
HIDDEN int
bwtxt_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp)
{
    register struct txt_specific *tp =
	(struct txt_specific *)dp;
    fastf_t xmin, xmax, ymin, ymax;
    int line;
    int dx, dy;
    int x, y;
    register long bw;
    struct uvcoord uvc;
    long tmp;

    uvc = swp->sw_uv;

    /*
     * If no texture file present, or if
     * texture isn't and can't be read, give debug colors
     */
    if ((bu_vls_strlen(&tp->tx_name) <= 0) || (!tp->tx_mp && !tp->tx_binunifp)) {
	VSET(swp->sw_color, uvc.uv_u, 0, uvc.uv_v);
	if (swp->sw_reflect > 0 || swp->sw_transmit > 0)
	    (void)rr_render(ap, pp, swp);
	return 1;
    }

    /* take care of scaling U, V coordinates to get the desired amount
     * of replication of the texture
     */
    uvc.uv_u *= tp->tx_scale[X];
    tmp = uvc.uv_u;
    uvc.uv_u -= tmp;
    if (tp->tx_mirror && (tmp & 1))
	uvc.uv_u = 1.0 - uvc.uv_u;

    uvc.uv_v *= tp->tx_scale[Y];
    tmp = uvc.uv_v;
    uvc.uv_v -= tmp;
    if (tp->tx_mirror && (tmp & 1))
	uvc.uv_v = 1.0 - uvc.uv_v;

    uvc.uv_du /= tp->tx_scale[X];
    uvc.uv_dv /= tp->tx_scale[Y];


    /* u is left->right index, v is line number bottom->top */
    /* Don't filter more than 1/8 of the texture for 1 pixel! */
    if (uvc.uv_du > 0.125) uvc.uv_du = 0.125;
    if (uvc.uv_dv > 0.125) uvc.uv_dv = 0.125;

    if (uvc.uv_du < 0 || uvc.uv_dv < 0) {
	bu_log("bwtxt_render uv=%g, %g, du dv=%g %g seg=%s\n",
	       uvc.uv_u, uvc.uv_v, uvc.uv_du, uvc.uv_dv,
	       pp->pt_inseg->seg_stp->st_name);
	uvc.uv_du = uvc.uv_dv = 0;
    }
    xmin = uvc.uv_u - uvc.uv_du;
    xmax = uvc.uv_u + uvc.uv_du;
    ymin = uvc.uv_v - uvc.uv_dv;
    ymax = uvc.uv_v + uvc.uv_dv;
    if (xmin < 0) xmin = 0;
    if (ymin < 0) ymin = 0;
    if (xmax > 1) xmax = 1;
    if (ymax > 1) ymax = 1;
    x = xmin * (tp->tx_w-1);
    y = ymin * (tp->tx_n-1);
    dx = (xmax - xmin) * (tp->tx_w-1);
    dy = (ymax - ymin) * (tp->tx_n-1);
    if (dx < 1) dx = 1;
    if (dy < 1) dy = 1;
    bw = 0;
    for (line = 0; line < dy; line++) {
	register unsigned char *cp=NULL;
	register unsigned char *ep;

	if (tp->tx_mp) {
	    cp = ((unsigned char *)(tp->tx_mp->buf)) +
		(y+line) * tp->tx_w + x;
	} else if (tp->tx_binunifp) {
	    cp = ((unsigned char *)(tp->tx_binunifp->u.uint8)) +
		(y+line) * tp->tx_w + x;
	} else {
	    /* not reachable */
	    bu_bomb("sh_text.c -- Unable to read datasource\n");
	}

	ep = cp + dx;
	while (cp < ep) {
	    bw += *cp++;
	}
    }

    if (!tp->tx_trans_valid) {
    opaque:
	VSETALL(swp->sw_color,
		(bw / 255.0) / (dx*dy));
	if (swp->sw_reflect > 0 || swp->sw_transmit > 0)
	    (void)rr_render(ap, pp, swp);
	return 1;
    }
    /* This circumlocution needed to keep expression simple for Cray,
     * and others
     */
    if (bw / (dx*dy) != ((long)tp->tx_transp[0])) goto opaque;

    /*
     * Transparency mapping is enabled, and we hit a transparent spot.
     * Let higher level handle it in reflect/refract code.
     */
    swp->sw_transmit = 1.0;
    swp->sw_reflect = 0.0;
    if (swp->sw_reflect > 0 || swp->sw_transmit > 0)
	(void)rr_render(ap, pp, swp);
    return 1;
}
Пример #10
0
/*
 * Given a u, v coordinate within the texture (0 <= u, v <= 1.0),
 * return a pointer to the relevant pixel.
 *
 * Note that .pix files are stored left-to-right, bottom-to-top,
 * which works out very naturally for the indexing scheme.
 */
HIDDEN int
txt_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp)
{
    register struct txt_specific *tp =
	(struct txt_specific *)dp;
    fastf_t xmin, xmax, ymin, ymax;
    int dx, dy;
    register fastf_t r, g, b;
    struct uvcoord uvc;
    long tmp;

    RT_CK_AP(ap);
    RT_CHECK_PT(pp);

    uvc = swp->sw_uv;

    if (rdebug & RDEBUG_SHADE)
	bu_log("in txt_render(): du=%g, dv=%g\n",
	       uvc.uv_du, uvc.uv_dv);

    /* take care of scaling U, V coordinates to get the desired amount
     * of replication of the texture
     */
    uvc.uv_u *= tp->tx_scale[X];
    tmp = uvc.uv_u;
    uvc.uv_u -= tmp;
    if (tp->tx_mirror && (tmp & 1))
	uvc.uv_u = 1.0 - uvc.uv_u;

    uvc.uv_v *= tp->tx_scale[Y];
    tmp = uvc.uv_v;
    uvc.uv_v -= tmp;
    if (tp->tx_mirror && (tmp & 1))
	uvc.uv_v = 1.0 - uvc.uv_v;

    uvc.uv_du /= tp->tx_scale[X];
    uvc.uv_dv /= tp->tx_scale[Y];

    /*
     * If no texture file present, or if
     * texture isn't and can't be read, give debug colors
     */

    if ((bu_vls_strlen(&tp->tx_name) <= 0) || (!tp->tx_mp && !tp->tx_binunifp)) {
	bu_log("WARNING: texture [%s] could not be read\n", bu_vls_addr(&tp->tx_name));
	VSET(swp->sw_color, uvc.uv_u, 0, uvc.uv_v);
	if (swp->sw_reflect > 0 || swp->sw_transmit > 0)
	    (void)rr_render(ap, pp, swp);
	return 1;
    }

    /* u is left->right index, v is line number bottom->top */
    /* Don't filter more than 1/8 of the texture for 1 pixel! */
    if (uvc.uv_du > 0.125) uvc.uv_du = 0.125;
    if (uvc.uv_dv > 0.125) uvc.uv_dv = 0.125;

    if (uvc.uv_du < 0 || uvc.uv_dv < 0) {
	bu_log("txt_render uv=%g, %g, du dv=%g %g seg=%s\n",
	       uvc.uv_u, uvc.uv_v, uvc.uv_du, uvc.uv_dv,
	       pp->pt_inseg->seg_stp->st_name);
	uvc.uv_du = uvc.uv_dv = 0;
    }

    xmin = uvc.uv_u - uvc.uv_du;
    xmax = uvc.uv_u + uvc.uv_du;
    ymin = uvc.uv_v - uvc.uv_dv;
    ymax = uvc.uv_v + uvc.uv_dv;
    if (xmin < 0) xmin = 0;
    if (ymin < 0) ymin = 0;
    if (xmax > 1) xmax = 1;
    if (ymax > 1) ymax = 1;

    if (rdebug & RDEBUG_SHADE)
	bu_log("footprint in texture space is (%g %g) <-> (%g %g)\n",
	       xmin * (tp->tx_w-1), ymin * (tp->tx_n-1),
	       xmax * (tp->tx_w-1), ymax * (tp->tx_n-1));

    dx = (int)(xmax * (tp->tx_w-1)) - (int)(xmin * (tp->tx_w-1));
    dy = (int)(ymax * (tp->tx_n-1)) - (int)(ymin * (tp->tx_n-1));

    if (rdebug & RDEBUG_SHADE)
	bu_log("\tdx = %d, dy = %d\n", dx, dy);

    if (dx == 0 && dy == 0) {
	/* No averaging necessary */

	register unsigned char *cp=NULL;

	if (tp->tx_mp) {
	    cp = ((unsigned char *)(tp->tx_mp->buf)) +
		(int)(ymin * (tp->tx_n-1)) * tp->tx_w * 3 +
		(int)(xmin * (tp->tx_w-1)) * 3;
	} else if (tp->tx_binunifp) {
	    cp = ((unsigned char *)(tp->tx_binunifp->u.uint8)) +
		(int)(ymin * (tp->tx_n-1)) * tp->tx_w * 3 +
		(int)(xmin * (tp->tx_w-1)) * 3;
	} else {
	    bu_bomb("sh_text.c -- No texture data found\n");
	}
	r = *cp++;
	g = *cp++;
	b = *cp;
    } else {
	/* Calculate weighted average of cells in footprint */

	fastf_t tot_area = 0.0;
	fastf_t cell_area;
	int start_line, stop_line, line;
	int start_col, stop_col, col;
	fastf_t xstart, xstop, ystart, ystop;

	xstart = xmin * (tp->tx_w-1);
	xstop = xmax * (tp->tx_w-1);
	ystart = ymin * (tp->tx_n-1);
	ystop = ymax * (tp->tx_n-1);

	start_line = ystart;
	stop_line = ystop;
	start_col = xstart;
	stop_col = xstop;

	r = g = b = 0.0;

	if (rdebug & RDEBUG_SHADE) {
	    bu_log("\thit in texture space = (%g %g)\n", uvc.uv_u * (tp->tx_w-1), uvc.uv_v * (tp->tx_n-1));
	    bu_log("\t averaging from  (%g %g) to (%g %g)\n", xstart, ystart, xstop, ystop);
	    bu_log("\tcontributions to average:\n");
	}

	for (line = start_line; line <= stop_line; line++) {
	    register unsigned char *cp=NULL;
	    fastf_t line_factor;
	    fastf_t line_upper, line_lower;

	    line_upper = line + 1.0;
	    if (line_upper > ystop)
		line_upper = ystop;
	    line_lower = line;
	    if (line_lower < ystart)
		line_lower = ystart;
	    line_factor = line_upper - line_lower;

	    if (tp->tx_mp) {
		cp = ((unsigned char *)(tp->tx_mp->buf)) +
		    line * tp->tx_w * 3 + (int)(xstart) * 3;
	    } else if (tp->tx_binunifp) {
		cp = ((unsigned char *)(tp->tx_binunifp->u.uint8)) +
		    line * tp->tx_w * 3 + (int)(xstart) * 3;
	    } else {
		/* not reachable */
		bu_bomb("sh_text.c -- Unable to read datasource\n");
	    }

	    for (col = start_col; col <= stop_col; col++) {
		fastf_t col_upper, col_lower;

		col_upper = col + 1.0;
		if (col_upper > xstop) col_upper = xstop;
		col_lower = col;
		if (col_lower < xstart) col_lower = xstart;

		cell_area = line_factor * (col_upper - col_lower);
		tot_area += cell_area;

		if (rdebug & RDEBUG_SHADE)
		    bu_log("\t %d %d %d weight=%g (from col=%d line=%d)\n", *cp, *(cp+1), *(cp+2), cell_area, col, line);

		r += (*cp++) * cell_area;
		g += (*cp++) * cell_area;
		b += (*cp++) * cell_area;
	    }

	}
	r /= tot_area;
	g /= tot_area;
	b /= tot_area;
    }

    if (rdebug & RDEBUG_SHADE)
	bu_log(" average: %g %g %g\n", r, g, b);

    if (!tp->tx_trans_valid) {
    opaque:
	VSET(swp->sw_color,
	     r / 255.0,
	     g / 255.0,
	     b / 255.0);

	if (swp->sw_reflect > 0 || swp->sw_transmit > 0)
	    (void)rr_render(ap, pp, swp);
	return 1;
    }
    /* This circumlocution needed to keep expression simple for Cray,
     * and others
     */
    if (!EQUAL(r, ((long)tp->tx_transp[0]))) goto opaque;
    if (!EQUAL(g, ((long)tp->tx_transp[1]))) goto opaque;
    if (!EQUAL(b, ((long)tp->tx_transp[2]))) goto opaque;

    /*
     * Transparency mapping is enabled, and we hit a transparent spot.
     * Let higher level handle it in reflect/refract code.
     */
    swp->sw_transmit = 1.0;
    swp->sw_reflect = 0.0;

    bu_log("leaving txt_render()\n");

    if (swp->sw_reflect > 0 || swp->sw_transmit > 0)
	(void)rr_render(ap, pp, swp);
    return 1;
}
Пример #11
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;
}
Пример #12
0
int
scloud_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp)
{
    register struct scloud_specific *scloud_sp =
        (struct scloud_specific *)dp;
    point_t in_pt;	/* point where ray enters scloud solid */
    point_t out_pt; /* point where ray leaves scloud solid */
    point_t pt;
    vect_t v_cloud;/* vector representing ray/solid intersection */
    double thickness; /* magnitude of v_cloud (distance through solid) */
    int steps;	   /* # of samples along ray/solid intersection */
    double step_delta;/* distance between sample points, texture space */
    int i;
    double val;
    double trans;
    point_t incident_light = VINIT_ZERO;
    double delta_dpmm;
    double density;
    struct shadework sub_sw;
    struct light_specific *lp;

    RT_CHECK_PT(pp);
    RT_AP_CHECK(ap);
    RT_CK_REGION(pp->pt_regionp);

    /* compute the ray/solid in and out points,
     * and transform them into "shader space" coordinates
     */
    VJOIN1(pt, ap->a_ray.r_pt, pp->pt_inhit->hit_dist, ap->a_ray.r_dir);
    MAT4X3PNT(in_pt, scloud_sp->mtos, pt);

    VJOIN1(pt, ap->a_ray.r_pt, pp->pt_outhit->hit_dist, ap->a_ray.r_dir);
    MAT4X3PNT(out_pt, scloud_sp->mtos, pt);


    /* get ray/solid intersection vector (in noise space)
     * and compute thickness of solid (in noise space) along ray path
     */
    VSUB2(v_cloud, out_pt, in_pt);
    thickness = MAGNITUDE(v_cloud);

    /* The noise field used by the bn_noise_turb and bn_noise_fbm routines
     * has a maximum frequency of about 1 cycle per integer step in
     * noise space.  Each octave increases this frequency by the
     * "lacunarity" factor.  To sample this space adequately we need
     *
     * 4 samples per integer step for the first octave,
     * lacunarity * 4 samples/step for the second octave,
     * lacunarity^2 * 4 samples/step for the third octave,
     * lacunarity^3 * 4 samples/step for the forth octave,
     *
     * so for a computation with 4 octaves we need something on the
     * order of lacunarity^3 * 4 samples per integer step in noise space.
     */

    steps = pow(scloud_sp->lacunarity, scloud_sp->octaves-1) * 4;
    step_delta = thickness / (double)steps;

    if (rdebug&RDEBUG_SHADE)
        bu_log("steps=%d  delta=%g  thickness=%g\n",
               steps, step_delta, thickness);

    VUNITIZE(v_cloud);
    VMOVE(pt, in_pt);
    trans = 1.0;

    delta_dpmm = scloud_sp->max_d_p_mm - scloud_sp->min_d_p_mm;

    sub_sw = *swp; /* struct copy */
    sub_sw.sw_inputs = MFI_HIT;

    for (i=0; i < steps; i++) {
        /* compute the next point in the cloud space */
        VJOIN1(pt, in_pt, i*step_delta, v_cloud);

        /* get turbulence value (0 .. 1) */
        val = bn_noise_turb(pt, scloud_sp->h_val,
                            scloud_sp->lacunarity, scloud_sp->octaves);

        density = scloud_sp->min_d_p_mm + val * delta_dpmm;

        val = exp(- density * step_delta);
        trans *= val;

        if (swp->sw_xmitonly) continue;

        /* need to set the hit in our fake shadework structure */
        MAT4X3PNT(sub_sw.sw_hit.hit_point, scloud_sp->stom, pt);
        sub_sw.sw_transmit = trans;

        sub_sw.sw_inputs = MFI_HIT;

        light_obs(ap, &sub_sw, swp->sw_inputs);
        /* now we know how much light has arrived from each
         * light source to this point
         */
        for (i=ap->a_rt_i->rti_nlights-1; i >= 0; i--) {
            lp = (struct light_specific *)swp->sw_visible[i];
            if (lp == LIGHT_NULL) continue;

            /* compute how much light has arrived at
             * this location
             */
            incident_light[0] += sub_sw.sw_intensity[3*i+0] *
                                 lp->lt_color[0] * sub_sw.sw_lightfract[i];
            incident_light[1] += sub_sw.sw_intensity[3*i+1] *
                                 lp->lt_color[1] * sub_sw.sw_lightfract[i];
            incident_light[2] += sub_sw.sw_intensity[3*i+2] *
                                 lp->lt_color[2] * sub_sw.sw_lightfract[i];
        }

        VSCALE(incident_light, incident_light, trans);


    }

    /* scloud is basically a white object with partial transparency */
    swp->sw_transmit = trans;
    if (swp->sw_xmitonly) return 1;


    /*
     * At the point of maximum opacity, check light visibility
     * for light color and cloud shadowing.
     * OOPS:  Don't use an interior point, or light_visibility()
     * will see an attenuated light source.
     */
    swp->sw_hit.hit_dist = pp->pt_inhit->hit_dist;
    VJOIN1(swp->sw_hit.hit_point, ap->a_ray.r_pt, swp->sw_hit.hit_dist,
           ap->a_ray.r_dir);
    VREVERSE(swp->sw_hit.hit_normal, ap->a_ray.r_dir);
    swp->sw_inputs |= MFI_HIT | MFI_NORMAL;
    light_obs(ap, swp, swp->sw_inputs);
    VSETALL(incident_light, 0);
    for (i=ap->a_rt_i->rti_nlights-1; i>=0; i--) {
        struct light_specific *lp2;
        if ((lp2 = (struct light_specific *)swp->sw_visible[i]) == LIGHT_NULL)
            continue;
        /* XXX don't have a macro for this */
        incident_light[0] += swp->sw_intensity[3*i+0] * lp2->lt_color[0];
        incident_light[1] += swp->sw_intensity[3*i+1] * lp2->lt_color[1];
        incident_light[2] += swp->sw_intensity[3*i+2] * lp2->lt_color[2];
    }
    VELMUL(swp->sw_color, swp->sw_color, incident_light);


    if (rdebug&RDEBUG_SHADE) {
        pr_shadework("scloud: after light vis, before rr_render", swp);
    }

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

    return 1;
}
Пример #13
0
/*
 *	F I R E _ R E N D E R
 *
 *	This is called (from viewshade() in shade.c) once for each hit point
 *	to be shaded.  The purpose here is to fill in values in the shadework
 *	structure.
 */
int
fire_render(struct application *ap, struct partition *pp, struct shadework *swp, char *dp)


    /* defined in material.h */
    /* ptr to the shader-specific struct */
{
#define DEBUG_SPACE_PRINT(str, i_pt, o_pt) \
	if (rdebug&RDEBUG_SHADE || fire_sp->fire_debug ) { \
		bu_log("fire_render() %s space \n", str); \
		bu_log("fire_render() i_pt(%g %g %g)\n", V3ARGS(i_pt) ); \
		bu_log("fire_render() o_pt(%g %g %g)\n", V3ARGS(o_pt) ); \
	}

#define	SHADER_TO_NOISE(n_pt, sh_pt, fire_sp, zdelta) { \
	point_t tmp_pt; \
	tmp_pt[X] = sh_pt[X]; \
	tmp_pt[Y] = sh_pt[Y]; \
	if ( ! NEAR_ZERO(fire_sp->fire_stretch, SQRT_SMALL_FASTF) ) \
		tmp_pt[Z] = exp( (sh_pt[Z]+0.125) * -fire_sp->fire_stretch ); \
	else \
		tmp_pt[Z] = sh_pt[Z]; \
	MAT4X3PNT(n_pt, fire_sp->fire_sh_to_noise, tmp_pt); \
	n_pt[Z] += zdelta; \
}

    register struct fire_specific *fire_sp =
	(struct fire_specific *)dp;
    point_t	m_i_pt, m_o_pt;	/* model space in/out points */
    point_t sh_i_pt, sh_o_pt;	/* shader space in/out points */
    point_t noise_i_pt, noise_o_pt;	/* shader space in/out points */
    point_t noise_pt;
    point_t	color;
    vect_t	noise_r_dir;
    double	noise_r_thick;
    int	i;
    double	samples_per_unit_noise;
    double	noise_dist_per_sample;
    point_t	shader_pt;
    vect_t	shader_r_dir;
    double	shader_r_thick;
    double	shader_dist_per_sample;
    double	noise_zdelta;

    int	samples;
    double	dist;
    double	noise_val;
    double	lumens;

    /* check the validity of the arguments we got */
    RT_AP_CHECK(ap);
    RT_CHECK_PT(pp);
    CK_fire_SP(fire_sp);

    if (rdebug&RDEBUG_SHADE || fire_sp->fire_debug ) {
/*		bu_struct_print( "fire_render Parameters:", fire_print_tab, (char *)fire_sp ); */
	bu_log("fire_render()\n");
    }
    /* If we are performing the shading in "region" space, we must
     * transform the hit point from "model" space to "region" space.
     * See the call to db_region_mat in fire_setup().
     */

    /*
     * Compute the ray/solid in and out points,
     */
    VMOVE(m_i_pt, swp->sw_hit.hit_point);
    VJOIN1(m_o_pt, ap->a_ray.r_pt, pp->pt_outhit->hit_dist, ap->a_ray.r_dir);
    DEBUG_SPACE_PRINT("model", m_i_pt, m_o_pt);

    /* map points into shader space */
    MAT4X3PNT(sh_i_pt, fire_sp->fire_m_to_sh, m_i_pt);
    MAT4X3PNT(sh_o_pt, fire_sp->fire_m_to_sh, m_o_pt);
    DEBUG_SPACE_PRINT("shader", sh_i_pt, sh_o_pt);

    noise_zdelta = fire_sp->fire_flicker * swp->sw_frametime;

    SHADER_TO_NOISE(noise_i_pt, sh_i_pt, fire_sp, noise_zdelta);
    SHADER_TO_NOISE(noise_o_pt, sh_o_pt, fire_sp, noise_zdelta);

    VSUB2(noise_r_dir, noise_o_pt, noise_i_pt);

    noise_r_thick = MAGNITUDE(noise_r_dir);

    if (rdebug&RDEBUG_SHADE || fire_sp->fire_debug ) {
	bu_log("fire_render() noise_r_dir (%g %g %g)\n",
	       V3ARGS(noise_r_dir) );
	bu_log("fire_render() noise_r_thick %g\n", noise_r_thick);
    }


    /* compute number of samples per unit length in noise space.
     *
     * The noise field used by the bn_noise_turb and bn_noise_fbm routines
     * has a maximum frequency of about 1 cycle per integer step in
     * noise space.  Each octave increases this frequency by the
     * "lacunarity" factor.  To sample this space adequately, nyquist
     * tells us we need at least 4 samples/cycle at the highest octave
     * rate.
     */

    samples_per_unit_noise =
	pow(fire_sp->noise_lacunarity, fire_sp->noise_octaves-1) * 4.0;

    noise_dist_per_sample = 1.0 / samples_per_unit_noise;

    samples = samples_per_unit_noise * noise_r_thick;

    if (samples < 1) samples = 1;

    if (rdebug&RDEBUG_SHADE || fire_sp->fire_debug ) {
	bu_log("samples:%d\n", samples);
	bu_log("samples_per_unit_noise %g\n", samples_per_unit_noise);
	bu_log("noise_dist_per_sample %g\n", noise_dist_per_sample);
    }

    /* To do the exponential stretch and decay properly we need to
     * do the computations in shader space, and convert the points
     * to noise space.  Performance pig.
     */

    VSUB2(shader_r_dir, sh_o_pt, sh_i_pt);
    shader_r_thick = MAGNITUDE(shader_r_dir);
    VUNITIZE(shader_r_dir);

    shader_dist_per_sample = shader_r_thick / samples;

    lumens = 0.0;
    for (i = 0; i < samples; i++) {
	dist = (double)i * shader_dist_per_sample;
	VJOIN1(shader_pt, sh_i_pt, dist, shader_r_dir);

	SHADER_TO_NOISE(noise_pt, shader_pt, fire_sp, noise_zdelta);

	noise_val = bn_noise_turb(noise_pt, fire_sp->noise_h_val,
				  fire_sp->noise_lacunarity, fire_sp->noise_octaves);

	if (rdebug&RDEBUG_SHADE || fire_sp->fire_debug )
	    bu_log("bn_noise_turb(%g %g %g) = %g\n",
		   V3ARGS(noise_pt),
		   noise_val);

	/* XXX
	 * When doing the exponential stretch, we scale the noise
	 * value by the height in shader space
	 */

	if ( NEAR_ZERO(fire_sp->fire_stretch, SQRT_SMALL_FASTF) )
	    lumens += noise_val * 0.025;
	else {
	    register double t;
	    t = lumens;
	    lumens += noise_val * 0.025 *  (1.0 -shader_pt[Z]);
	    if (rdebug&RDEBUG_SHADE || fire_sp->fire_debug )
		bu_log("lumens:%g = %g + %g * %g\n",
		       lumens, t, noise_val,
		       0.025 * (1.0 - shader_pt[Z]) );

	}
	if (lumens >= 1.0) {
	    lumens = 1.0;
	    if (rdebug&RDEBUG_SHADE || fire_sp->fire_debug )
		bu_log("early exit from lumens loop\n");
	    break;
	}

    }

    if (rdebug&RDEBUG_SHADE || fire_sp->fire_debug )
	bu_log("lumens = %g\n", lumens);

    if (lumens < 0.0) lumens = 0.0;
    else if (lumens > 1.0) lumens = 1.0;


    rt_dspline_n(color, fire_sp->fire_colorspline_mat, (double *)flame_colors,
		 18, 3, lumens);

    VMOVE(swp->sw_color, color);
/*	VSETALL(swp->sw_basecolor, 1.0);*/

    swp->sw_transmit = 1.0 - (lumens * 4.);
    if (swp->sw_reflect > 0 || swp->sw_transmit > 0 )
	(void)rr_render( ap, pp, swp );

    return(1);
}
Пример #14
0
/*
 *			B R D F _ R E N D E R
 *
 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) and normalized by PI :

 Rd = Rp * cos(I) / PI	(4)

 The specular reflectance is calculated by the product of the
 specular reflectance coeffient and a term dependent on the
 surface roughness :

 Rs = W(I, O) * R(I, O, r)	(5)

 Where,
 I is the angle of incidence.
 O is the angle to the observer.
 r is the standard deviation (RMS) of the surface slope.
 W returns the specular reflection coefficient as a function
 of the angle of incidence, and the viewer angle.
 R is a surface roughness term.

*/
HIDDEN int
brdf_render(register struct application *ap, struct partition *pp, struct shadework *swp, char *dp)
{
    register struct light_specific *lp;
    register fastf_t *intensity, *to_light;
    register int	i;
    register fastf_t cosi, cosr;
    register fastf_t refl;
    vect_t h_dir;
    vect_t to_eye;
    vect_t	work;
    vect_t	cprod;			/* color product */
    point_t	matcolor;		/* Material color */
    struct brdf_specific *ps =
	(struct brdf_specific *)dp;

    if (ps->magic != BRDF_MAGIC )  bu_log("brdf_render: bad magic\n");

    if (rdebug&RDEBUG_SHADE)
	bu_struct_print( "brdf_render", brdf_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 (swp->sw_xmitonly ) {
	if (swp->sw_reflect > 0 || swp->sw_transmit > 0 )
	    (void)rr_render( ap, pp, swp );
	return(1);	/* done */
    }

    VMOVE( matcolor, swp->sw_color );

    /* Diffuse reflectance from "Ambient" light source (at eye) */
    if ((cosr = -VDOT( swp->sw_hit.hit_normal, ap->a_ray.r_dir )) > 0.0 )  {
	if (cosr > 1.00001 )  {
	    bu_log("cosAmb=1+%g (x%d, y%d, lvl%d)\n", cosr-1,
		   ap->a_x, ap->a_y, ap->a_level);
	    cosr = 1;
	}
	refl = cosr * AmbientIntensity;
	VSCALE( swp->sw_color, matcolor, refl );
    } else {
	VSETALL( swp->sw_color, 0 );
    }

    VREVERSE( to_eye, ap->a_ray.r_dir );

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

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

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

	if ((cosi = VDOT( swp->sw_hit.hit_normal, to_light )) > 0.0 )  {
	    if (cosi > 1.00001 )  {
		bu_log("cosI=1+%g (x%d, y%d, lvl%d)\n", cosi-1,
		       ap->a_x, ap->a_y, ap->a_level);
		cosi = 1;
	    }

	    /* Diffuse reflectance from this light source. */
	    refl = cosi * lp->lt_fraction * ps->diffuse_refl;
	    VELMUL( work, lp->lt_color,
		    intensity );
	    VELMUL( cprod, matcolor, work );
	    VJOIN1( swp->sw_color, swp->sw_color,
		    refl, cprod );

	    /* Calculate specular reflectance. */
	    if (NEAR_ZERO( ps->rms_sq, SMALL_FASTF ) )
		continue;
	    VADD2( h_dir, to_eye, to_light )
		VUNITIZE( h_dir );
	    cos_tmp = VDOT( h_dir, swp->sw_hit.hit_normal );
	    if (cos_tmp <= 0.0 )
		continue;
	    cos_tmp *= cos_tmp;
	    if (NEAR_ZERO( cos_tmp, SMALL_FASTF ) )
		continue;

	    tan_sq = (1.0-cos_tmp)/cos_tmp;
	    exponent = (-tan_sq/ps->rms_sq );
	    refl = ps->specular_refl * lp->lt_fraction * exp( exponent ) /
		sqrt( cosi * cosr ) / ps->denom;
	    if (refl > 1.0 )
		refl = 1.0;

	    VELMUL( work, lp->lt_color, intensity );
	    VJOIN1( swp->sw_color, swp->sw_color, refl, work );

	}
    }

    if (swp->sw_reflect > 0 || swp->sw_transmit > 0 )
	(void)rr_render( ap, pp, swp );
    return(1);
}
/*
 * This is called (from viewshade() in shade.c) once for each hit point
 * to be shaded.  The purpose here is to fill in values in the shadework
 * structure.
 *
 * dp is a pointer to the shader-specific struct
 */
int
bbd_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp)
{
    register struct bbd_specific *bbd_sp = (struct bbd_specific *)dp;
    union tree *tp;
    struct bbd_img *bi;
    struct imgdist id[MAX_IMAGES];
    size_t i;

    /* check the validity of the arguments we got */
    RT_AP_CHECK(ap);
    RT_CHECK_PT(pp);
    CK_bbd_SP(bbd_sp);

    if (rdebug&RDEBUG_SHADE) {
	bu_struct_print("bbd_render Parameters:",
			bbd_print_tab, (char *)bbd_sp);
	bu_log("pixel %d %d\n", ap->a_x, ap->a_y);
	bu_log("bbd region: %s\n", pp->pt_regionp->reg_name);
    }
    tp = pp->pt_regionp->reg_treetop;
    if (tp->tr_a.tu_op != OP_SOLID) {
	bu_log("%s:%d region %s rendering bbd should have found OP_SOLID, not %d\n",
	       __FILE__, __LINE__, pp->pt_regionp->reg_name, tp->tr_a.tu_op);
	bu_bomb("\n");
    }


    swp->sw_transmit = 1.0;
    VSETALL(swp->sw_color, 0.0);
    VSETALL(swp->sw_basecolor, 1.0);

    i = 0;
    for (BU_LIST_FOR(bi, bbd_img, &bbd_sp->imgs)) {
	/* find out if the ray hits the plane */
	id[i].index = i;
	id[i].bi = bi;
	id[i].status = bn_isect_line3_plane(&id[i].dist,
					    ap->a_ray.r_pt, ap->a_ray.r_dir,
					    bi->img_plane, &ap->a_rt_i->rti_tol);
	i++;
    }

    bu_sort(id, bbd_sp->img_count, sizeof(id[0]), &imgdist_compare, NULL);

    for (i = 0; i < bbd_sp->img_count && swp->sw_transmit > 0.0; i++) {
	if (id[i].status > 0) do_ray_image(ap, pp, swp, bbd_sp, id[i].bi, id[i].dist);
    }
    if (rdebug&RDEBUG_SHADE) {
	bu_log("color %g %g %g\n", V3ARGS(swp->sw_color));
    }
    /* shader must perform transmission/reflection calculations
     *
     * 0 < swp->sw_transmit <= 1 causes transmission computations
     * 0 < swp->sw_reflect <= 1 causes reflection computations
     */
    if (swp->sw_reflect > 0 || swp->sw_transmit > 0) {
	int level = ap->a_level;
	ap->a_level = 0; /* Bogus hack to keep rr_render from giving up */
	(void)rr_render(ap, pp, swp);
	ap->a_level = level;
    }
    if (rdebug&RDEBUG_SHADE) {
	bu_log("color %g %g %g\n", V3ARGS(swp->sw_color));
    }
    return 1;
}