mirror of https://github.com/GNOME/gimp.git
735 lines
18 KiB
C
735 lines
18 KiB
C
/*****************/
|
|
/* Shading stuff */
|
|
/*****************/
|
|
|
|
#include "config.h"
|
|
|
|
#include <libgimp/gimp.h>
|
|
|
|
#include "lighting_main.h"
|
|
#include "lighting_image.h"
|
|
#include "lighting_shade.h"
|
|
|
|
|
|
static GimpVector3 *triangle_normals[2] = { NULL, NULL };
|
|
static GimpVector3 *vertex_normals[3] = { NULL, NULL, NULL };
|
|
static gdouble *heights[3] = { NULL, NULL, NULL };
|
|
static gdouble xstep, ystep;
|
|
static guchar *bumprow = NULL;
|
|
|
|
static gint pre_w = -1;
|
|
static gint pre_h = -1;
|
|
|
|
/*****************/
|
|
/* Phong shading */
|
|
/*****************/
|
|
|
|
static GimpRGB
|
|
phong_shade (GimpVector3 *position,
|
|
GimpVector3 *viewpoint,
|
|
GimpVector3 *normal,
|
|
GimpVector3 *lightposition,
|
|
GimpRGB *diff_col,
|
|
GimpRGB *spec_col,
|
|
LightType light_type)
|
|
{
|
|
GimpRGB ambient_color, diffuse_color, specular_color;
|
|
gdouble nl, rv, dist;
|
|
GimpVector3 l, v, n, lnormal, h;
|
|
|
|
/* Compute ambient intensity */
|
|
/* ========================= */
|
|
|
|
n = *normal;
|
|
ambient_color = *diff_col;
|
|
gimp_rgb_multiply (&ambient_color, mapvals.material.ambient_int);
|
|
|
|
/* Compute (N*L) term of Phong's equation */
|
|
/* ====================================== */
|
|
|
|
if (light_type == POINT_LIGHT)
|
|
gimp_vector3_sub (&l, lightposition, position);
|
|
else
|
|
l = *lightposition;
|
|
|
|
dist = gimp_vector3_length (&l);
|
|
|
|
if (dist != 0.0)
|
|
gimp_vector3_mul (&l, 1.0 / dist);
|
|
|
|
nl = 2.0 * gimp_vector3_inner_product (&n, &l);
|
|
|
|
lnormal.x = l.x;
|
|
lnormal.y = l.y;
|
|
lnormal.z = l.z;
|
|
|
|
gimp_vector3_normalize (&lnormal);
|
|
|
|
if (nl >= 0.0)
|
|
{
|
|
/* Compute (R*V)^alpha term of Phong's equation */
|
|
/* ============================================ */
|
|
|
|
gimp_vector3_sub (&v, viewpoint, position);
|
|
gimp_vector3_normalize (&v);
|
|
|
|
gimp_vector3_add (&h, &lnormal, &v);
|
|
gimp_vector3_normalize (&h);
|
|
|
|
rv = MAX (0., gimp_vector3_inner_product (&n, &h));
|
|
rv = pow (rv, mapvals.material.highlight);
|
|
rv *= nl;
|
|
|
|
/* Compute diffuse and specular intensity contribution */
|
|
/* =================================================== */
|
|
|
|
diffuse_color = *diff_col;
|
|
gimp_rgb_multiply (&diffuse_color, mapvals.material.diffuse_ref);
|
|
gimp_rgb_multiply (&diffuse_color, nl);
|
|
|
|
specular_color = *spec_col;
|
|
gimp_rgb_multiply (&specular_color, mapvals.material.specular_ref);
|
|
gimp_rgb_multiply (&specular_color, rv);
|
|
|
|
gimp_rgb_add (&diffuse_color, &specular_color);
|
|
gimp_rgb_multiply (&diffuse_color, mapvals.material.diffuse_int);
|
|
gimp_rgb_clamp (&diffuse_color);
|
|
|
|
gimp_rgb_add (&ambient_color, &diffuse_color);
|
|
}
|
|
|
|
gimp_rgb_clamp (&ambient_color);
|
|
|
|
return ambient_color;
|
|
}
|
|
|
|
/*
|
|
static void
|
|
get_normal (gdouble xf,
|
|
gdouble yf,
|
|
GimpVector3 *normal)
|
|
{
|
|
GimpVector3 v1,v2,n;
|
|
gint numvecs=0,x,y,f;
|
|
gdouble val,val1=-1.0,val2=-1.0,val3=-1.0,val4=-1.0, xstep,ystep;
|
|
|
|
x=(gint)(xf+0.5);
|
|
y=(gint)(yf+0.5);
|
|
|
|
xstep=1.0/(gdouble)width;
|
|
ystep=1.0/(gdouble)height;
|
|
|
|
val=mapvals.bumpmax*get_map_value(&bump_region, xf,yf, &f)/255.0;
|
|
if (check_bounds(x-1,y)) val1=mapvals.bumpmax*get_map_value(&bump_region, xf-1.0,yf, &f)/255.0 - val;
|
|
if (check_bounds(x,y-1)) val2=mapvals.bumpmax*get_map_value(&bump_region, xf,yf-1.0, &f)/255.0 - val;
|
|
if (check_bounds(x+1,y)) val3=mapvals.bumpmax*get_map_value(&bump_region, xf+1.0,yf, &f)/255.0 - val;
|
|
if (check_bounds(x,y+1)) val4=mapvals.bumpmax*get_map_value(&bump_region, xf,yf+1.0, &f)/255.0 - val;
|
|
|
|
gimp_vector3_set(normal, 0.0,0.0,0.0);
|
|
|
|
if (val1!=-1.0 && val4!=-1.0)
|
|
{
|
|
v1.x=-xstep; v1.y=0.0; v1.z=val1;
|
|
v2.x=0.0; v2.y=ystep; v2.z=val4;
|
|
n=gimp_vector3_cross_product(&v1,&v2);
|
|
gimp_vector3_normalize(&n);
|
|
|
|
if (n.z<0.0)
|
|
n.z=-n.z;
|
|
|
|
gimp_vector3_add(normal,normal,&n);
|
|
numvecs++;
|
|
}
|
|
|
|
if (val1!=-1.0 && val2!=-1.0)
|
|
{
|
|
v1.x=-xstep; v1.y=0.0; v1.z=val1;
|
|
v2.x=0.0; v2.y=-ystep; v2.z=val2;
|
|
n=gimp_vector3_cross_product(&v1,&v2);
|
|
gimp_vector3_normalize(&n);
|
|
|
|
if (n.z<0.0)
|
|
n.z=-n.z;
|
|
|
|
gimp_vector3_add(normal,normal,&n);
|
|
numvecs++;
|
|
}
|
|
|
|
if (val2!=-1.0 && val3!=-1.0)
|
|
{
|
|
v1.x=0.0; v1.y=-ystep; v1.z=val2;
|
|
v2.x=xstep; v2.y=0.0; v2.z=val3;
|
|
n=gimp_vector3_cross_product(&v1,&v2);
|
|
gimp_vector3_normalize(&n);
|
|
|
|
if (n.z<0.0)
|
|
n.z=-n.z;
|
|
|
|
gimp_vector3_add(normal,normal,&n);
|
|
numvecs++;
|
|
}
|
|
|
|
if (val3!=-1.0 && val4!=-1.0)
|
|
{
|
|
v1.x=xstep; v1.y=0.0; v1.z=val3;
|
|
v2.x=0.0; v2.y=ystep; v2.z=val4;
|
|
n=gimp_vector3_cross_product(&v1,&v2);
|
|
gimp_vector3_normalize(&n);
|
|
|
|
if (n.z<0.0)
|
|
n.z=-n.z;
|
|
|
|
gimp_vector3_add(normal,normal,&n);
|
|
numvecs++;
|
|
}
|
|
|
|
gimp_vector3_mul(normal,1.0/(gdouble)numvecs);
|
|
gimp_vector3_normalize(normal);
|
|
}
|
|
*/
|
|
|
|
void
|
|
precompute_init (gint w,
|
|
gint h)
|
|
{
|
|
gint n;
|
|
gint bpp=1;
|
|
|
|
xstep = 1.0 / (gdouble) width;
|
|
ystep = 1.0 / (gdouble) height;
|
|
|
|
pre_w = w;
|
|
pre_h = h;
|
|
|
|
for (n = 0; n < 3; n++)
|
|
{
|
|
if (vertex_normals[n] != NULL)
|
|
g_free (vertex_normals[n]);
|
|
if (heights[n] != NULL)
|
|
g_free (heights[n]);
|
|
|
|
heights[n] = g_new (gdouble, w);
|
|
vertex_normals[n] = g_new (GimpVector3, w);
|
|
}
|
|
|
|
for (n = 0; n < 2; n++)
|
|
if (triangle_normals[n] != NULL)
|
|
g_free (triangle_normals[n]);
|
|
|
|
if (bumprow != NULL)
|
|
{
|
|
g_free (bumprow);
|
|
bumprow = NULL;
|
|
}
|
|
if (mapvals.bumpmap_id != -1)
|
|
{
|
|
bpp = gimp_drawable_bpp(mapvals.bumpmap_id);
|
|
}
|
|
|
|
bumprow = g_new (guchar, w * bpp);
|
|
|
|
triangle_normals[0] = g_new (GimpVector3, (w << 1) + 2);
|
|
triangle_normals[1] = g_new (GimpVector3, (w << 1) + 2);
|
|
|
|
for (n = 0; n < (w << 1) + 1; n++)
|
|
{
|
|
gimp_vector3_set (&triangle_normals[0][n], 0.0, 0.0, 1.0);
|
|
gimp_vector3_set (&triangle_normals[1][n], 0.0, 0.0, 1.0);
|
|
}
|
|
|
|
for (n = 0; n < w; n++)
|
|
{
|
|
gimp_vector3_set (&vertex_normals[0][n], 0.0, 0.0, 1.0);
|
|
gimp_vector3_set (&vertex_normals[1][n], 0.0, 0.0, 1.0);
|
|
gimp_vector3_set (&vertex_normals[2][n], 0.0, 0.0, 1.0);
|
|
heights[0][n] = 0.0;
|
|
heights[1][n] = 0.0;
|
|
heights[2][n] = 0.0;
|
|
}
|
|
}
|
|
|
|
/********************************************/
|
|
/* Compute triangle and then vertex normals */
|
|
/********************************************/
|
|
|
|
void
|
|
precompute_normals (gint x1,
|
|
gint x2,
|
|
gint y)
|
|
{
|
|
GimpVector3 *tmpv, p1, p2, p3, normal;
|
|
gdouble *tmpd;
|
|
gint n, i, nv;
|
|
guchar *map = NULL;
|
|
gint bpp = 1;
|
|
guchar mapval;
|
|
|
|
|
|
/* First, compute the heights */
|
|
/* ========================== */
|
|
|
|
tmpv = triangle_normals[0];
|
|
triangle_normals[0] = triangle_normals[1];
|
|
triangle_normals[1] = tmpv;
|
|
|
|
tmpv = vertex_normals[0];
|
|
vertex_normals[0] = vertex_normals[1];
|
|
vertex_normals[1] = vertex_normals[2];
|
|
vertex_normals[2] = tmpv;
|
|
|
|
tmpd = heights[0];
|
|
heights[0] = heights[1];
|
|
heights[1] = heights[2];
|
|
heights[2] = tmpd;
|
|
|
|
if (mapvals.bumpmap_id != -1)
|
|
{
|
|
bpp = gimp_drawable_bpp(mapvals.bumpmap_id);
|
|
}
|
|
|
|
gimp_pixel_rgn_get_row (&bump_region, bumprow, x1, y, x2 - x1);
|
|
|
|
if (mapvals.bumpmaptype > 0)
|
|
{
|
|
switch (mapvals.bumpmaptype)
|
|
{
|
|
case 1:
|
|
map = logmap;
|
|
break;
|
|
case 2:
|
|
map = sinemap;
|
|
break;
|
|
default:
|
|
map = spheremap;
|
|
break;
|
|
}
|
|
|
|
for (n = 0; n < (x2 - x1); n++)
|
|
{
|
|
if (bpp>1)
|
|
{
|
|
mapval = (guchar)((float)((bumprow[n * bpp] +bumprow[n * bpp +1] + bumprow[n * bpp + 2])/3.0 )) ;
|
|
}
|
|
else
|
|
{
|
|
mapval = bumprow[n * bpp];
|
|
}
|
|
|
|
heights[2][n] = (gdouble) mapvals.bumpmax * (gdouble) map[mapval] / 255.0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (n = 0; n < (x2 - x1); n++)
|
|
{
|
|
if (bpp>1)
|
|
{
|
|
mapval = (guchar)((float)((bumprow[n * bpp] +bumprow[n * bpp +1] + bumprow[n * bpp + 2])/3.0 )) ;
|
|
}
|
|
else
|
|
{
|
|
mapval = bumprow[n * bpp];
|
|
}
|
|
heights[2][n] = (gdouble) mapvals.bumpmax * (gdouble) mapval / 255.0;
|
|
}
|
|
}
|
|
|
|
/* Compute triangle normals */
|
|
/* ======================== */
|
|
|
|
i = 0;
|
|
for (n = 0; n < (x2 - x1 - 1); n++)
|
|
{
|
|
p1.x = 0.0;
|
|
p1.y = ystep;
|
|
p1.z = heights[2][n] - heights[1][n];
|
|
|
|
p2.x = xstep;
|
|
p2.y = ystep;
|
|
p2.z = heights[2][n+1] - heights[1][n];
|
|
|
|
p3.x = xstep;
|
|
p3.y = 0.0;
|
|
p3.z = heights[1][n+1] - heights[1][n];
|
|
|
|
triangle_normals[1][i] = gimp_vector3_cross_product (&p2, &p1);
|
|
triangle_normals[1][i+1] = gimp_vector3_cross_product (&p3, &p2);
|
|
|
|
gimp_vector3_normalize (&triangle_normals[1][i]);
|
|
gimp_vector3_normalize (&triangle_normals[1][i+1]);
|
|
|
|
i += 2;
|
|
}
|
|
|
|
/* Compute vertex normals */
|
|
/* ====================== */
|
|
|
|
i = 0;
|
|
gimp_vector3_set (&normal, 0.0, 0.0, 0.0);
|
|
|
|
for (n = 0; n < (x2 - x1 - 1); n++)
|
|
{
|
|
nv = 0;
|
|
|
|
if (n > 0)
|
|
{
|
|
if (y > 0)
|
|
{
|
|
gimp_vector3_add (&normal, &normal, &triangle_normals[0][i-1]);
|
|
gimp_vector3_add (&normal, &normal, &triangle_normals[0][i-2]);
|
|
nv += 2;
|
|
}
|
|
|
|
if (y < pre_h)
|
|
{
|
|
gimp_vector3_add (&normal, &normal, &triangle_normals[1][i-1]);
|
|
nv++;
|
|
}
|
|
}
|
|
|
|
if (n <pre_w)
|
|
{
|
|
if (y > 0)
|
|
{
|
|
gimp_vector3_add (&normal, &normal, &triangle_normals[0][i]);
|
|
gimp_vector3_add (&normal, &normal, &triangle_normals[0][i+1]);
|
|
nv += 2;
|
|
}
|
|
|
|
if (y < pre_h)
|
|
{
|
|
gimp_vector3_add (&normal, &normal, &triangle_normals[1][i]);
|
|
gimp_vector3_add (&normal, &normal, &triangle_normals[1][i+1]);
|
|
nv += 2;
|
|
}
|
|
}
|
|
|
|
gimp_vector3_mul (&normal, 1.0 / (gdouble) nv);
|
|
gimp_vector3_normalize (&normal);
|
|
vertex_normals[1][n] = normal;
|
|
|
|
i += 2;
|
|
}
|
|
}
|
|
|
|
/***********************************************************************/
|
|
/* Compute the reflected ray given the normalized normal and ins. vec. */
|
|
/***********************************************************************/
|
|
|
|
static GimpVector3
|
|
compute_reflected_ray (GimpVector3 *normal,
|
|
GimpVector3 *view)
|
|
{
|
|
GimpVector3 ref;
|
|
gdouble nl;
|
|
|
|
nl = 2.0 * gimp_vector3_inner_product (normal, view);
|
|
|
|
ref = *normal;
|
|
|
|
gimp_vector3_mul (&ref, nl);
|
|
gimp_vector3_sub (&ref, &ref, view);
|
|
|
|
return ref;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Given the NorthPole, Equator and a third vector (normal) compute */
|
|
/* the conversion from spherical coordinates to image space coordinates */
|
|
/************************************************************************/
|
|
|
|
static void
|
|
sphere_to_image (GimpVector3 *normal,
|
|
gdouble *u,
|
|
gdouble *v)
|
|
{
|
|
static gdouble alpha, fac;
|
|
static GimpVector3 cross_prod;
|
|
static GimpVector3 firstaxis = { 1.0, 0.0, 0.0 };
|
|
static GimpVector3 secondaxis = { 0.0, 1.0, 0.0 };
|
|
|
|
alpha = acos (-gimp_vector3_inner_product (&secondaxis, normal));
|
|
|
|
*v = alpha / G_PI;
|
|
|
|
if (*v==0.0 || *v==1.0)
|
|
{
|
|
*u = 0.0;
|
|
}
|
|
else
|
|
{
|
|
fac = gimp_vector3_inner_product (&firstaxis, normal) / sin (alpha);
|
|
|
|
/* Make sure that we map to -1.0..1.0 (take care of rounding errors) */
|
|
/* ================================================================= */
|
|
|
|
if (fac>1.0)
|
|
fac = 1.0;
|
|
else if (fac<-1.0)
|
|
fac = -1.0;
|
|
|
|
*u = acos (fac) / (2.0 * G_PI);
|
|
|
|
cross_prod = gimp_vector3_cross_product (&secondaxis, &firstaxis);
|
|
|
|
if (gimp_vector3_inner_product (&cross_prod, normal) < 0.0)
|
|
*u = 1.0 - *u;
|
|
}
|
|
}
|
|
|
|
/*********************************************************************/
|
|
/* These routines computes the color of the surface at a given point */
|
|
/*********************************************************************/
|
|
|
|
GimpRGB
|
|
get_ray_color (GimpVector3 *position)
|
|
{
|
|
GimpRGB color;
|
|
gint x, f;
|
|
gdouble xf, yf;
|
|
GimpVector3 normal, *p;
|
|
|
|
pos_to_float (position->x, position->y, &xf, &yf);
|
|
|
|
x = RINT (xf);
|
|
|
|
if (mapvals.transparent_background && heights[1][x] == 0)
|
|
{
|
|
gimp_rgb_set_alpha (&color, 0.0);
|
|
}
|
|
else
|
|
{
|
|
color = get_image_color (xf, yf, &f);
|
|
|
|
if (mapvals.lightsource.type == POINT_LIGHT)
|
|
p = &mapvals.lightsource.position;
|
|
else
|
|
p = &mapvals.lightsource.direction;
|
|
|
|
if (mapvals.bump_mapped == FALSE || mapvals.bumpmap_id == -1)
|
|
{
|
|
color = phong_shade (position,
|
|
&mapvals.viewpoint,
|
|
&mapvals.planenormal,
|
|
p,
|
|
&color,
|
|
&mapvals.lightsource.color,
|
|
mapvals.lightsource.type);
|
|
}
|
|
else
|
|
{
|
|
normal = vertex_normals[1][(gint) RINT (xf)];
|
|
|
|
color = phong_shade (position,
|
|
&mapvals.viewpoint,
|
|
&normal,
|
|
p,
|
|
&color,
|
|
&mapvals.lightsource.color,
|
|
mapvals.lightsource.type);
|
|
}
|
|
}
|
|
|
|
return color;
|
|
}
|
|
|
|
GimpRGB
|
|
get_ray_color_ref (GimpVector3 *position)
|
|
{
|
|
GimpRGB color, env_color;
|
|
gint x, f;
|
|
gdouble xf, yf;
|
|
GimpVector3 normal, *p, v, r;
|
|
|
|
pos_to_float (position->x, position->y, &xf, &yf);
|
|
|
|
x = RINT (xf);
|
|
|
|
if (mapvals.transparent_background && heights[1][x] == 0)
|
|
{
|
|
gimp_rgb_set_alpha (&color, 0.0);
|
|
}
|
|
else
|
|
{
|
|
color = get_image_color (xf, yf, &f);
|
|
|
|
if (mapvals.lightsource.type == POINT_LIGHT)
|
|
p = &mapvals.lightsource.position;
|
|
else
|
|
p = &mapvals.lightsource.direction;
|
|
|
|
if (mapvals.bump_mapped == FALSE || mapvals.bumpmap_id == -1)
|
|
{
|
|
color = phong_shade (position,
|
|
&mapvals.viewpoint,
|
|
&mapvals.planenormal,
|
|
p,
|
|
&color,
|
|
&mapvals.lightsource.color,
|
|
mapvals.lightsource.type);
|
|
}
|
|
else
|
|
{
|
|
normal = vertex_normals[1][(gint) RINT (xf)];
|
|
|
|
gimp_vector3_sub (&v, &mapvals.viewpoint,position);
|
|
gimp_vector3_normalize (&v);
|
|
|
|
r = compute_reflected_ray (&normal, &v);
|
|
|
|
/* Get color in the direction of r */
|
|
/* =============================== */
|
|
|
|
sphere_to_image (&r, &xf, &yf);
|
|
env_color = peek_env_map (RINT (env_width * xf),
|
|
RINT (env_height * yf));
|
|
|
|
color = phong_shade (position,
|
|
&mapvals.viewpoint,
|
|
&normal,
|
|
p,
|
|
&env_color,
|
|
&mapvals.lightsource.color,
|
|
mapvals.lightsource.type);
|
|
}
|
|
}
|
|
|
|
return color;
|
|
}
|
|
|
|
GimpRGB
|
|
get_ray_color_no_bilinear (GimpVector3 *position)
|
|
{
|
|
GimpRGB color;
|
|
gint x;
|
|
gdouble xf, yf;
|
|
GimpVector3 normal, *p;
|
|
|
|
|
|
pos_to_float (position->x, position->y, &xf, &yf);
|
|
|
|
x = RINT (xf);
|
|
|
|
if (mapvals.transparent_background && heights[1][x] == 0)
|
|
{
|
|
gimp_rgb_set_alpha (&color, 0.0);
|
|
}
|
|
else
|
|
{
|
|
color = peek (x, RINT (yf));
|
|
|
|
if (mapvals.lightsource.type == POINT_LIGHT)
|
|
p = &mapvals.lightsource.position;
|
|
else
|
|
p = &mapvals.lightsource.direction;
|
|
|
|
if (mapvals.bump_mapped == FALSE || mapvals.bumpmap_id == -1)
|
|
{
|
|
color = phong_shade (position,
|
|
&mapvals.viewpoint,
|
|
&mapvals.planenormal,
|
|
p,
|
|
&color,
|
|
&mapvals.lightsource.color,
|
|
mapvals.lightsource.type);
|
|
}
|
|
else
|
|
{
|
|
normal = vertex_normals[1][x];
|
|
|
|
color = phong_shade (position,
|
|
&mapvals.viewpoint,
|
|
&normal,
|
|
p,
|
|
&color,
|
|
&mapvals.lightsource.color,
|
|
mapvals.lightsource.type);
|
|
}
|
|
}
|
|
|
|
return color;
|
|
}
|
|
|
|
GimpRGB
|
|
get_ray_color_no_bilinear_ref (GimpVector3 *position)
|
|
{
|
|
GimpRGB color, env_color;
|
|
gint x;
|
|
gdouble xf, yf;
|
|
GimpVector3 normal, *p, v, r;
|
|
|
|
pos_to_float (position->x, position->y, &xf, &yf);
|
|
|
|
x = RINT (xf);
|
|
|
|
if (mapvals.transparent_background && heights[1][x] == 0)
|
|
{
|
|
gimp_rgb_set_alpha (&color, 0.0);
|
|
}
|
|
else
|
|
{
|
|
color = peek (RINT (xf), RINT (yf));
|
|
|
|
if (mapvals.lightsource.type == POINT_LIGHT)
|
|
p = &mapvals.lightsource.position;
|
|
else
|
|
p = &mapvals.lightsource.direction;
|
|
|
|
if (mapvals.bump_mapped == FALSE || mapvals.bumpmap_id == -1)
|
|
{
|
|
pos_to_float (position->x, position->y, &xf, &yf);
|
|
|
|
color = peek (RINT (xf), RINT (yf));
|
|
|
|
gimp_vector3_sub (&v, &mapvals.viewpoint, position);
|
|
gimp_vector3_normalize (&v);
|
|
|
|
r = compute_reflected_ray (&mapvals.planenormal, &v);
|
|
|
|
/* Get color in the direction of r */
|
|
/* =============================== */
|
|
|
|
sphere_to_image (&r, &xf, &yf);
|
|
env_color = peek_env_map (RINT (env_width * xf),
|
|
RINT (env_height * yf));
|
|
|
|
color = phong_shade (position,
|
|
&mapvals.viewpoint,
|
|
&mapvals.planenormal,
|
|
p,
|
|
&env_color,
|
|
&mapvals.lightsource.color,
|
|
mapvals.lightsource.type);
|
|
}
|
|
else
|
|
{
|
|
normal = vertex_normals[1][(gint) RINT (xf)];
|
|
|
|
pos_to_float (position->x, position->y, &xf, &yf);
|
|
color = peek (RINT (xf), RINT (yf));
|
|
|
|
gimp_vector3_sub (&v, &mapvals.viewpoint, position);
|
|
gimp_vector3_normalize (&v);
|
|
|
|
r = compute_reflected_ray (&normal, &v);
|
|
|
|
/* Get color in the direction of r */
|
|
/* =============================== */
|
|
|
|
sphere_to_image (&r, &xf, &yf);
|
|
env_color = peek_env_map (RINT (env_width * xf),
|
|
RINT (env_height * yf));
|
|
|
|
color = phong_shade (position,
|
|
&mapvals.viewpoint,
|
|
&normal,
|
|
p,
|
|
&env_color,
|
|
&mapvals.lightsource.color,
|
|
mapvals.lightsource.type);
|
|
}
|
|
}
|
|
|
|
return color;
|
|
}
|