home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / plug-ins / Lighting / lighting_shade.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-28  |  17.7 KB  |  665 lines

  1. /*****************/
  2. /* Shading stuff */
  3. /*****************/
  4.  
  5. #include <sys/types.h>
  6.  
  7. #include <libgimp/gimp.h>
  8.  
  9. #include <gck/gck.h>
  10.  
  11. #include "lighting_main.h"
  12. #include "lighting_image.h"
  13. #include "lighting_shade.h"
  14.  
  15. static GimpVector3 *triangle_normals[2] = { NULL, NULL };
  16. static GimpVector3 *vertex_normals[3]   = { NULL, NULL, NULL };
  17. static gdouble *heights[3] = { NULL, NULL, NULL };
  18. static gdouble  xstep, ystep;
  19. static guchar  *bumprow = NULL;
  20.  
  21. static gint pre_w = -1;
  22. static gint pre_h = -1;
  23.  
  24. /*****************/
  25. /* Phong shading */
  26. /*****************/
  27.  
  28. static GckRGB
  29. phong_shade (GimpVector3 *position,
  30.          GimpVector3 *viewpoint,
  31.          GimpVector3 *normal,
  32.          GimpVector3 *lightposition,
  33.          GckRGB      *diff_col,
  34.          GckRGB      *spec_col,
  35.          LightType    light_type)
  36. {
  37.   GckRGB ambient_color,diffuse_color,specular_color;
  38.   gdouble nl,rv,dist;
  39.   GimpVector3 l,nn,v,n;
  40.  
  41.   /* Compute ambient intensity */
  42.   /* ========================= */
  43.  
  44.   n=*normal;
  45.   ambient_color=*diff_col;
  46.   gck_rgb_mul(&ambient_color,mapvals.material.ambient_int);
  47.  
  48.   /* Compute (N*L) term of Phong's equation */
  49.   /* ====================================== */
  50.  
  51.   if (light_type==POINT_LIGHT)
  52.     gimp_vector3_sub(&l,lightposition,position);
  53.   else
  54.     l=*lightposition;
  55.   
  56.   dist=gimp_vector3_length(&l);
  57.   
  58.   if (dist!=0.0)
  59.     gimp_vector3_mul(&l,1.0/dist);
  60.  
  61.   nl=2.0*gimp_vector3_inner_product(&n,&l);
  62.  
  63.   if (nl>=0.0)
  64.     {
  65.       /* Compute (R*V)^alpha term of Phong's equation */
  66.       /* ============================================ */
  67.  
  68.       gimp_vector3_sub(&v,viewpoint,position);
  69.       gimp_vector3_normalize(&v);
  70.  
  71.       gimp_vector3_mul(&n,nl);
  72.       gimp_vector3_sub(&nn,&n,&l);
  73.       rv=gimp_vector3_inner_product(&nn,&v);
  74.       rv=pow(rv,mapvals.material.highlight);
  75.  
  76.       /* Compute diffuse and specular intensity contribution */
  77.       /* =================================================== */
  78.  
  79.       diffuse_color=*diff_col;
  80.       gck_rgb_mul(&diffuse_color,mapvals.material.diffuse_ref);
  81.       gck_rgb_mul(&diffuse_color,nl);
  82.  
  83.       specular_color=*spec_col;
  84.       gck_rgb_mul(&specular_color,mapvals.material.specular_ref);
  85.       gck_rgb_mul(&specular_color,rv);
  86.  
  87.       gck_rgb_add(&diffuse_color,&specular_color);
  88.       gck_rgb_mul(&diffuse_color,mapvals.material.diffuse_int);
  89.       gck_rgb_clamp(&diffuse_color);
  90.  
  91.       gck_rgb_add(&ambient_color,&diffuse_color);
  92.     }
  93.  
  94.   gck_rgb_clamp(&ambient_color);
  95.   return(ambient_color);
  96. }
  97.  
  98. /*
  99. static void
  100. get_normal (gdouble      xf,
  101.         gdouble      yf,
  102.         GimpVector3 *normal)
  103. {
  104.   GimpVector3 v1,v2,n;
  105.   gint numvecs=0,x,y,f;
  106.   gdouble val,val1=-1.0,val2=-1.0,val3=-1.0,val4=-1.0, xstep,ystep;
  107.  
  108.   x=(gint)(xf+0.5);
  109.   y=(gint)(yf+0.5);
  110.  
  111.   xstep=1.0/(gdouble)width;
  112.   ystep=1.0/(gdouble)height;
  113.  
  114.   val=mapvals.bumpmax*get_map_value(&bump_region, xf,yf, &f)/255.0;
  115.   if (check_bounds(x-1,y)) val1=mapvals.bumpmax*get_map_value(&bump_region, xf-1.0,yf, &f)/255.0 - val;
  116.   if (check_bounds(x,y-1)) val2=mapvals.bumpmax*get_map_value(&bump_region, xf,yf-1.0, &f)/255.0 - val;
  117.   if (check_bounds(x+1,y)) val3=mapvals.bumpmax*get_map_value(&bump_region, xf+1.0,yf, &f)/255.0 - val;
  118.   if (check_bounds(x,y+1)) val4=mapvals.bumpmax*get_map_value(&bump_region, xf,yf+1.0, &f)/255.0 - val;
  119.  
  120.   gimp_vector3_set(normal, 0.0,0.0,0.0);
  121.  
  122.   if (val1!=-1.0 && val4!=-1.0)
  123.     {
  124.       v1.x=-xstep; v1.y=0.0; v1.z=val1;
  125.       v2.x=0.0; v2.y=ystep; v2.z=val4;
  126.       n=gimp_vector3_cross_product(&v1,&v2);
  127.       gimp_vector3_normalize(&n);
  128.       
  129.       if (n.z<0.0)
  130.         n.z=-n.z;
  131.       
  132.       gimp_vector3_add(normal,normal,&n);
  133.       numvecs++;
  134.     }
  135.  
  136.   if (val1!=-1.0 && val2!=-1.0)
  137.     {
  138.       v1.x=-xstep; v1.y=0.0;    v1.z=val1;
  139.       v2.x=0.0;    v2.y=-ystep; v2.z=val2;
  140.       n=gimp_vector3_cross_product(&v1,&v2);
  141.       gimp_vector3_normalize(&n);
  142.       
  143.       if (n.z<0.0)
  144.         n.z=-n.z;
  145.       
  146.       gimp_vector3_add(normal,normal,&n);
  147.       numvecs++;
  148.     }
  149.  
  150.   if (val2!=-1.0 && val3!=-1.0)
  151.     {
  152.       v1.x=0.0;   v1.y=-ystep; v1.z=val2;
  153.       v2.x=xstep; v2.y=0.0;    v2.z=val3;
  154.       n=gimp_vector3_cross_product(&v1,&v2);
  155.       gimp_vector3_normalize(&n);
  156.       
  157.       if (n.z<0.0)
  158.         n.z=-n.z;
  159.       
  160.       gimp_vector3_add(normal,normal,&n);
  161.       numvecs++;
  162.     }
  163.  
  164.   if (val3!=-1.0 && val4!=-1.0)
  165.     {
  166.       v1.x=xstep; v1.y=0.0;   v1.z=val3;
  167.       v2.x=0.0;   v2.y=ystep; v2.z=val4;
  168.       n=gimp_vector3_cross_product(&v1,&v2);
  169.       gimp_vector3_normalize(&n);
  170.       
  171.       if (n.z<0.0)
  172.         n.z=-n.z;
  173.       
  174.       gimp_vector3_add(normal,normal,&n);
  175.       numvecs++;
  176.     }
  177.  
  178.   gimp_vector3_mul(normal,1.0/(gdouble)numvecs);
  179.   gimp_vector3_normalize(normal);
  180. }
  181. */
  182.  
  183. void
  184. precompute_init (gint w,
  185.          gint h)
  186. {
  187.   gint n;
  188.  
  189.   xstep=1.0/(gdouble)width;
  190.   ystep=1.0/(gdouble)height;
  191.  
  192.   pre_w=w;
  193.   pre_h=h;
  194.     
  195.   for (n=0;n<3;n++)
  196.     {
  197.       if (vertex_normals[n]!=NULL)
  198.         g_free(vertex_normals[n]);
  199.       if (heights[n]!=NULL)
  200.         g_free(heights[n]);
  201.       
  202.       heights[n]=(gdouble *)g_malloc(sizeof(gdouble)*(size_t)w);
  203.       vertex_normals[n]=(GimpVector3 *)g_malloc(sizeof(GimpVector3)*(size_t)w);
  204.     }
  205.  
  206.   for (n=0;n<2;n++)
  207.     if (triangle_normals[n]!=NULL)
  208.       g_free(triangle_normals[n]);
  209.  
  210.   if (bumprow!=NULL)
  211.     {
  212.       g_free(bumprow);
  213.       bumprow=NULL;
  214.     }
  215.  
  216.   bumprow=(guchar *)g_malloc(sizeof(guchar)*(size_t)w);
  217.  
  218.   triangle_normals[0]=(GimpVector3 *)g_malloc(sizeof(GimpVector3)*(size_t)((w<<1)+2));
  219.   triangle_normals[1]=(GimpVector3 *)g_malloc(sizeof(GimpVector3)*(size_t)((w<<1)+2));
  220.   
  221.   for (n=0;n<(w<<1)+1;n++)
  222.     {
  223.       gimp_vector3_set(&triangle_normals[0][n],0.0,0.0,1.0);
  224.       gimp_vector3_set(&triangle_normals[1][n],0.0,0.0,1.0);
  225.     }
  226.  
  227.   for (n=0;n<w;n++)
  228.     {
  229.       gimp_vector3_set(&vertex_normals[0][n],0.0,0.0,1.0);
  230.       gimp_vector3_set(&vertex_normals[1][n],0.0,0.0,1.0);
  231.       gimp_vector3_set(&vertex_normals[2][n],0.0,0.0,1.0);
  232.       heights[0][n]=0.0;
  233.       heights[1][n]=0.0;
  234.       heights[2][n]=0.0;
  235.     }
  236. }
  237.  
  238. /********************************************/
  239. /* Compute triangle and then vertex normals */
  240. /********************************************/
  241.  
  242. void
  243. precompute_normals (gint x1,
  244.             gint x2,
  245.             gint y)
  246. {
  247.   GimpVector3 *tmpv,p1,p2,p3,normal;
  248.   gdouble *tmpd;
  249.   gint n,i,nv;
  250.   guchar *map=NULL;
  251.  
  252.   /* First, compute the heights */
  253.   /* ========================== */
  254.  
  255.   tmpv=triangle_normals[0];
  256.   triangle_normals[0]=triangle_normals[1];
  257.   triangle_normals[1]=tmpv;
  258.  
  259.   tmpv=vertex_normals[0];
  260.   vertex_normals[0]=vertex_normals[1];
  261.   vertex_normals[1]=vertex_normals[2];
  262.   vertex_normals[2]=tmpv;
  263.   
  264.   tmpd=heights[0];
  265.   heights[0]=heights[1];
  266.   heights[1]=heights[2];
  267.   heights[2]=tmpd;
  268.  
  269. /*  printf("Get row (%d,%d,%d) to %p\n",x1,y,x2-x1,bumprow); */
  270.  
  271.   gimp_pixel_rgn_get_row(&bump_region,bumprow,x1,y,x2-x1);
  272.  
  273.   if (mapvals.bumpmaptype>0)
  274.     {
  275.       switch (mapvals.bumpmaptype)
  276.         {
  277.           case 1:
  278.             map=logmap;
  279.             break;
  280.           case 2:
  281.             map=sinemap;
  282.             break;
  283.           default:
  284.             map=spheremap;
  285.             break;
  286.         }
  287.       for (n=0;n<(x2-x1);n++)
  288.        heights[2][n]=(gdouble)mapvals.bumpmax*(gdouble)map[bumprow[n]]/255.0;
  289.     }
  290.   else for (n=0;n<(x2-x1);n++)
  291.     heights[2][n]=(gdouble)mapvals.bumpmax*(gdouble)bumprow[n]/255.0;
  292.  
  293.   /* Compute triangle normals */
  294.   /* ======================== */
  295.   
  296.   i=0;
  297.   for (n=0;n<(x2-x1-1);n++)
  298.     {
  299.       p1.x=0.0;
  300.       p1.y=ystep; 
  301.       p1.z=heights[2][n]-heights[1][n];
  302.       
  303.       p2.x=xstep;
  304.       p2.y=ystep;
  305.       p2.z=heights[2][n+1]-heights[1][n];
  306.  
  307.       p3.x=xstep;
  308.       p3.y=0.0;
  309.       p3.z=heights[1][n+1]-heights[1][n];
  310.       
  311.       triangle_normals[1][i]=gimp_vector3_cross_product(&p2,&p1);
  312.       triangle_normals[1][i+1]=gimp_vector3_cross_product(&p3,&p2);
  313.  
  314.       gimp_vector3_normalize(&triangle_normals[1][i]);
  315.       gimp_vector3_normalize(&triangle_normals[1][i+1]);
  316.       
  317.       i+=2;
  318.     }
  319.   
  320.   /* Compute vertex normals */
  321.   /* ====================== */
  322.  
  323.   i=0;
  324.   gimp_vector3_set(&normal, 0.0,0.0,0.0);
  325.   for (n=0;n<(x2-x1-1);n++)
  326.     {
  327.       nv=0;
  328.       if (n>0)
  329.         {
  330.           if (y>0)
  331.             {
  332.               gimp_vector3_add(&normal, &normal, &triangle_normals[0][i-1]);
  333.               gimp_vector3_add(&normal, &normal, &triangle_normals[0][i-2]);
  334.               nv+=2;
  335.             }
  336.           if (y<pre_h)
  337.             {
  338.               gimp_vector3_add(&normal, &normal, &triangle_normals[1][i-1]);
  339.               nv++;
  340.             }
  341.         }
  342.       if (n<pre_w)
  343.         {
  344.           if (y>0)
  345.             {
  346.               gimp_vector3_add(&normal, &normal, &triangle_normals[0][i]);
  347.               gimp_vector3_add(&normal, &normal, &triangle_normals[0][i+1]);
  348.               nv+=2;
  349.             }
  350.           if (y<pre_h)
  351.             {
  352.               gimp_vector3_add(&normal, &normal, &triangle_normals[1][i]);
  353.               gimp_vector3_add(&normal, &normal, &triangle_normals[1][i+1]);
  354.               nv+=2;                  
  355.             }
  356.         }
  357.       
  358.       gimp_vector3_mul(&normal, 1.0/(gdouble)nv);
  359.       gimp_vector3_normalize(&normal);
  360.       vertex_normals[1][n]=normal;
  361.  
  362.       i+=2;
  363.     }
  364. }
  365.  
  366. /***********************************************************************/
  367. /* Compute the reflected ray given the normalized normal and ins. vec. */
  368. /***********************************************************************/
  369.  
  370. static GimpVector3
  371. compute_reflected_ray (GimpVector3 *normal,
  372.                GimpVector3 *view)
  373. {
  374.   GimpVector3 ref;
  375.   gdouble nl;
  376.  
  377.   nl = 2.0*gimp_vector3_inner_product(normal,view);
  378.   
  379.   ref = *normal;
  380.   
  381.   gimp_vector3_mul(&ref,nl);
  382.   gimp_vector3_sub(&ref,&ref,view);
  383.   
  384.   return(ref);
  385. }
  386.  
  387. /************************************************************************/
  388. /* Given the NorthPole, Equator and a third vector (normal) compute     */
  389. /* the conversion from spherical coordinates to image space coordinates */
  390. /************************************************************************/
  391.  
  392. static void
  393. sphere_to_image (GimpVector3 *normal,
  394.          gdouble     *u,
  395.          gdouble     *v)
  396. {
  397.   static gdouble alpha,fac;
  398.   static GimpVector3 cross_prod;
  399.   static GimpVector3 firstaxis  = { 1.0, 0.0, 0.0 };
  400.   static GimpVector3 secondaxis  = { 0.0, 1.0, 0.0 };
  401.  
  402.   alpha=acos(-gimp_vector3_inner_product(&secondaxis,normal));
  403.  
  404.   *v=alpha/G_PI;
  405.  
  406.   if (*v==0.0 || *v==1.0) *u=0.0;
  407.   else
  408.     {
  409.       fac=gimp_vector3_inner_product(&firstaxis,normal)/sin(alpha);
  410.  
  411.       /* Make sure that we map to -1.0..1.0 (take care of rounding errors) */
  412.       /* ================================================================= */
  413.  
  414.       if (fac>1.0)
  415.         fac=1.0;
  416.       else if (fac<-1.0) 
  417.         fac=-1.0;
  418.  
  419.       *u=acos(fac)/(2.0*G_PI);
  420.       
  421.       cross_prod=gimp_vector3_cross_product(&secondaxis,&firstaxis);
  422.       
  423.       if (gimp_vector3_inner_product(&cross_prod,normal)<0.0)
  424.         *u=1.0-*u;
  425.     }
  426. }
  427.  
  428. /*********************************************************************/
  429. /* These routines computes the color of the surface at a given point */
  430. /*********************************************************************/
  431.  
  432. GckRGB
  433. get_ray_color (GimpVector3 *position)
  434. {
  435.   GckRGB color;
  436.   gint x,f;
  437.   gdouble xf,yf;
  438.   GimpVector3 normal,*p;
  439.  
  440.   pos_to_float(position->x,position->y,&xf,&yf);
  441.  
  442.   x = (gint)(xf+0.5);
  443.  
  444.   if (mapvals.transparent_background && heights[1][x]==0)
  445.     color.a=0.0;
  446.   else
  447.     {
  448.       color=get_image_color(xf,yf,&f);
  449.  
  450.       if (mapvals.lightsource.type==POINT_LIGHT)
  451.         p=&mapvals.lightsource.position;
  452.       else
  453.         p=&mapvals.lightsource.direction;
  454.  
  455.       if (mapvals.bump_mapped==FALSE || mapvals.bumpmap_id==-1)
  456.         color=phong_shade(position,
  457.                          &mapvals.viewpoint,
  458.                          &mapvals.planenormal,
  459.                          p,
  460.                          &color,
  461.                          &mapvals.lightsource.color,
  462.                           mapvals.lightsource.type);
  463.       else
  464.         {
  465.           normal=vertex_normals[1][(gint)(xf+0.5)];
  466.     
  467.           color=phong_shade(position,
  468.                            &mapvals.viewpoint,
  469.                            &normal,
  470.                            p,
  471.                            &color,
  472.                            &mapvals.lightsource.color,
  473.                             mapvals.lightsource.type);
  474.         }
  475.     }
  476.  
  477.   return(color);
  478. }
  479.  
  480. GckRGB
  481. get_ray_color_ref (GimpVector3 *position)
  482. {
  483.   GckRGB color,env_color;
  484.   gint x,f;
  485.   gdouble xf,yf;
  486.   GimpVector3 normal,*p,v,r;
  487.  
  488.   pos_to_float(position->x,position->y,&xf,&yf);
  489.  
  490.   x = (gint)(xf+0.5);
  491.  
  492.   if (mapvals.transparent_background && heights[1][x]==0)
  493.     color.a=0.0;
  494.   else
  495.     {
  496.       color=get_image_color(xf,yf,&f);
  497.  
  498.       if (mapvals.lightsource.type==POINT_LIGHT)
  499.         p=&mapvals.lightsource.position;
  500.       else
  501.         p=&mapvals.lightsource.direction;
  502.     
  503.       if (mapvals.bump_mapped==FALSE || mapvals.bumpmap_id==-1)
  504.         color=phong_shade(position,
  505.                          &mapvals.viewpoint,
  506.                          &mapvals.planenormal,
  507.                          p,
  508.                          &color,
  509.                          &mapvals.lightsource.color,
  510.                           mapvals.lightsource.type);
  511.       else
  512.         {
  513.           normal=vertex_normals[1][(gint)(xf+0.5)];
  514.     
  515.           gimp_vector3_sub(&v,&mapvals.viewpoint,position);
  516.           gimp_vector3_normalize(&v);
  517.     
  518.           r = compute_reflected_ray(&normal,&v);
  519.     
  520.           /* Get color in the direction of r */
  521.           /* =============================== */
  522.     
  523.           sphere_to_image(&r,&xf,&yf);
  524.           env_color = peek_env_map((gint)(env_width*xf+0.5),(gint)(env_height*yf+0.5));
  525.     
  526.           color=phong_shade(position,
  527.                            &mapvals.viewpoint,
  528.                            &normal,
  529.                            p,
  530.                            &env_color,
  531.                            &mapvals.lightsource.color,
  532.                             mapvals.lightsource.type);
  533.         }
  534.     }
  535.  
  536.   return(color);
  537. }
  538.  
  539. GckRGB
  540. get_ray_color_no_bilinear (GimpVector3 *position)
  541. {
  542.   GckRGB color;
  543.   gint x;
  544.   gdouble xf,yf;
  545.   GimpVector3 normal,*p;
  546.  
  547.   pos_to_float(position->x,position->y,&xf,&yf);
  548.  
  549.   x = (gint)(xf+0.5);
  550.   
  551.   if (mapvals.transparent_background && heights[1][x]==0)
  552.     color.a=0.0;
  553.   else
  554.     {
  555.       color=peek(x,(gint)(yf+0.5));
  556.     
  557.       if (mapvals.lightsource.type==POINT_LIGHT)
  558.         p=&mapvals.lightsource.position;
  559.       else
  560.         p=&mapvals.lightsource.direction;
  561.     
  562.       if (mapvals.bump_mapped==FALSE || mapvals.bumpmap_id==-1)
  563.         color=phong_shade(position,
  564.                          &mapvals.viewpoint,
  565.                          &mapvals.planenormal,
  566.                          p,
  567.                          &color,
  568.                          &mapvals.lightsource.color,
  569.                           mapvals.lightsource.type);
  570.       else
  571.         {
  572.           normal=vertex_normals[1][x];
  573.     
  574.           color=phong_shade(position,
  575.                            &mapvals.viewpoint,
  576.                            &normal,
  577.                            p,
  578.                            &color,
  579.                            &mapvals.lightsource.color,
  580.                             mapvals.lightsource.type);
  581.         }
  582.     }
  583.  
  584.   return(color);
  585. }
  586.  
  587. GckRGB
  588. get_ray_color_no_bilinear_ref (GimpVector3 *position)
  589. {
  590.   GckRGB color,env_color;
  591.   gint x;
  592.   gdouble xf,yf;
  593.   GimpVector3 normal,*p,v,r;
  594.  
  595.   pos_to_float(position->x,position->y,&xf,&yf);
  596.  
  597.   x = (gint)(xf+0.5);
  598.   
  599.   if (mapvals.transparent_background && heights[1][x]==0)
  600.     color.a=0.0;
  601.   else
  602.     {
  603.       color=peek((gint)(xf+0.5),(gint)(yf+0.5));
  604.  
  605.       if (mapvals.lightsource.type==POINT_LIGHT)
  606.         p=&mapvals.lightsource.position;
  607.       else
  608.         p=&mapvals.lightsource.direction;
  609.     
  610.       if (mapvals.bump_mapped==FALSE || mapvals.bumpmap_id==-1)
  611.         {
  612.           pos_to_float(position->x,position->y,&xf,&yf);
  613.     
  614.           color=peek((gint)(xf+0.5),(gint)(yf+0.5));
  615.     
  616.           gimp_vector3_sub(&v,&mapvals.viewpoint,position);
  617.           gimp_vector3_normalize(&v);
  618.     
  619.           r = compute_reflected_ray(&mapvals.planenormal,&v);
  620.     
  621.           /* Get color in the direction of r */
  622.           /* =============================== */
  623.     
  624.           sphere_to_image(&r,&xf,&yf);
  625.           env_color = peek_env_map((gint)(env_width*xf+0.5),(gint)(env_height*yf+0.5));
  626.     
  627.           color=phong_shade(position,
  628.                            &mapvals.viewpoint,
  629.                            &mapvals.planenormal,
  630.                            p,
  631.                            &env_color,
  632.                            &mapvals.lightsource.color,
  633.                            mapvals.lightsource.type);
  634.         }
  635.       else
  636.         {
  637.           normal=vertex_normals[1][(gint)(xf+0.5)];
  638.     
  639.           pos_to_float(position->x,position->y,&xf,&yf);
  640.           color=peek((gint)(xf+0.5),(gint)(yf+0.5));
  641.     
  642.           gimp_vector3_sub(&v,&mapvals.viewpoint,position);
  643.           gimp_vector3_normalize(&v);
  644.     
  645.           r = compute_reflected_ray(&normal,&v);
  646.     
  647.           /* Get color in the direction of r */
  648.           /* =============================== */
  649.     
  650.           sphere_to_image(&r,&xf,&yf);
  651.           env_color = peek_env_map((gint)(env_width*xf+0.5),(gint)(env_height*yf+0.5));
  652.     
  653.           color=phong_shade(position,
  654.                            &mapvals.viewpoint,
  655.                            &normal,
  656.                            p,
  657.                            &env_color,
  658.                            &mapvals.lightsource.color,
  659.                             mapvals.lightsource.type);
  660.         }
  661.     }
  662.  
  663.   return(color);
  664. }
  665.