head	3.15;
access;
symbols
	merge-1:3.14.2.2
	autoconf:3.14.0.4
	experimental-1:3.14.0.2
	mesa-3-1-with-kw3:3.10
	mesa-3-1-prior-to-kw3:3.9;
locks; strict;
comment	@ * @;


3.15
date	99.07.12.12.05.24;	author keithw;	state Exp;
branches;
next	3.14;

3.14
date	99.05.11.17.43.00;	author keithw;	state Exp;
branches
	3.14.2.1;
next	3.13;

3.13
date	99.03.31.20.18.40;	author keithw;	state Exp;
branches;
next	3.12;

3.12
date	99.03.20.21.29.36;	author keithw;	state Exp;
branches;
next	3.11;

3.11
date	99.03.20.18.58.12;	author brianp;	state Exp;
branches;
next	3.10;

3.10
date	99.02.25.14.12.31;	author keithw;	state Exp;
branches;
next	3.9;

3.9
date	99.02.24.22.48.07;	author jens;	state Exp;
branches;
next	3.8;

3.8
date	99.02.14.03.46.34;	author brianp;	state Exp;
branches;
next	3.7;

3.7
date	98.10.30.04.41.24;	author brianp;	state Exp;
branches;
next	3.6;

3.6
date	98.10.29.03.57.11;	author brianp;	state Exp;
branches;
next	3.5;

3.5
date	98.10.29.02.28.13;	author brianp;	state Exp;
branches;
next	3.4;

3.4
date	98.07.01.02.39.14;	author brianp;	state Exp;
branches;
next	3.3;

3.3
date	98.04.18.05.00.28;	author brianp;	state Exp;
branches;
next	3.2;

3.2
date	98.03.27.04.17.31;	author brianp;	state Exp;
branches;
next	3.1;

3.1
date	98.02.02.03.09.34;	author brianp;	state Exp;
branches;
next	3.0;

3.0
date	98.01.31.21.03.42;	author brianp;	state Exp;
branches;
next	;

3.14.2.1
date	99.05.21.21.29.27;	author keithw;	state Exp;
branches;
next	3.14.2.2;

3.14.2.2
date	99.06.19.15.04.14;	author keithw;	state Exp;
branches;
next	;


desc
@shading functions
@


3.15
log
@merge from experimental branch upto merge-1 tag
@
text
@/* $Id: shade.c,v 3.14.2.2 1999/06/19 15:04:14 keithw Exp $ */

/*
 * Mesa 3-D graphics library
 * Version:  3.1
 * 
 * Copyright (C) 1999  Brian Paul   All Rights Reserved.
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */





#ifdef PC_HEADER
#include "all.h"
#else
#include <math.h>
#include <stdio.h>
#include "light.h"
#include "macros.h"
#include "mmath.h"
#include "shade.h"
#include "pipeline.h"
#include "types.h"
#include "simple_list.h"
#ifdef XFree86Server
#include "GL/xf86glx.h"
#endif
#endif





#define GET_SHINE_TAB_ENTRY( tab, dp, result )	\
do {							\
   int k = (int) (dp * SHINE_TABLE_SIZE);     	\
   result = tab->tab[k];				\
} while(0)


/* Combinatorics:  
 *     rgba_spec/rgba/rgba_fast/ci
 *     one_side/two_side
 *     compacted_normals/ordinary_normals
 *     cull_mask/no_cull_mask
 *
 * We end up with an award-winning 32 seperate lighting functions.
 */


/* Table of all the shading functions.
 */
gl_shade_func gl_shade_func_tab[0x20];


/* The original case where the normal for vertex[j] is normal[j],
 * both stride-aware, and every normal is present.
 */
#define NEXT_NORMAL        STRIDE_F(normal, nstride), mask++
#define NEXT_VERTEX_NORMAL STRIDE_F(normal, nstride), mask++
#define STATE_CHANGE(a,b)  1
#define COMPACTED          0

#define TAG(x)           x##_one_sided_masked
#define INVALID(x)       0
#define IDX              CULL_MASK_ACTIVE
#define LIGHT_FRONT(x)   1
#define LIGHT_REAR(x)    0
#define LIGHT_SIDE(x,y)  1
#define CULL(x)          !((x)&VERT_FACE_FLAGS)
#define NR_SIDES         1
#include "shade_tmp.h" 

#define TAG(x)           x##_one_sided
#define INVALID(x)       0
#define IDX              0
#define LIGHT_FRONT(x)   1
#define LIGHT_REAR(x)    0
#define LIGHT_SIDE(x,y)  1
#define CULL(x)          0 
#define NR_SIDES         1
#include "shade_tmp.h" 

#define TAG(x)           x##_two_sided_masked
#define INVALID(x)       ((x)&invalid)
#define IDX              SHADE_TWOSIDE|CULL_MASK_ACTIVE
#define LIGHT_FRONT(f)   ((f)&VERT_FACE_FRONT)
#define LIGHT_REAR(f)    ((f)&VERT_FACE_REAR)
#define LIGHT_SIDE(x,y)  ((x)&(y))
#define CULL(x)          !((x)&VERT_FACE_FLAGS)
#define NR_SIDES         2
#include "shade_tmp.h"

#define TAG(x)           x##_two_sided
#define INVALID(x)       0
#define IDX              SHADE_TWOSIDE
#define LIGHT_FRONT(f)   1
#define LIGHT_REAR(f)    1
#define LIGHT_SIDE(x,y)  1
#define CULL(x)          0
#define NR_SIDES         2
#include "shade_tmp.h"

#undef NEXT_NORMAL 
#undef NEXT_VERTEX_NORMAL 
#undef STATE_CHANGE
#undef COMPACTED

/* The 'compacted normal' case, where we have a sparse list of normals
 * with flags indicating a new (valid) normal, as now built by the
 * 'glVertex' API routines.   We have a small bonus in that we know
 * in advance that the normal stride must be 3 floats.
 */
#define NEXT_NORMAL         ((flags[j]&VERT_NORM) ? normal=first_normal[j],mask=&cullmask[j] : 0)
#define NEXT_VERTEX_NORMAL  ((flags[j]&VERT_NORM) ? normal=first_normal[j],mask=&cullmask[j] : 0)
#define STATE_CHANGE(a,b)   (a & b)
#define COMPACTED            1


#define TAG(x)           x##_one_sided_masked_compacted
#define INVALID(x)       0
#define IDX              COMPACTED_NORMALS|CULL_MASK_ACTIVE
#define LIGHT_FRONT(x)   1
#define LIGHT_REAR(x)    0
#define LIGHT_SIDE(x,y)  1
#define CULL(x)          !((x)&VERT_FACE_FLAGS)
#define NR_SIDES         1
#include "shade_tmp.h" 

#define TAG(x)           x##_one_sided_compacted
#define INVALID(x)       0
#define IDX              COMPACTED_NORMALS
#define LIGHT_FRONT(x)   1
#define LIGHT_REAR(x)    0
#define LIGHT_SIDE(x,y)  1
#define CULL(x)          0
#define NR_SIDES         1
#include "shade_tmp.h" 

#define TAG(x)           x##_two_sided_masked_compacted
#define INVALID(x)       ((x)&invalid)
#define IDX              COMPACTED_NORMALS|SHADE_TWOSIDE
#define LIGHT_FRONT(f)   ((f)&VERT_FACE_FRONT)
#define LIGHT_REAR(f)    ((f)&VERT_FACE_REAR)
#define LIGHT_SIDE(x,y)  ((x)&(y))
#define CULL(x)          !((x)&VERT_FACE_FLAGS)
#define NR_SIDES         2
#include "shade_tmp.h"

#define TAG(x)           x##_two_sided_compacted
#define INVALID(x)       0
#define IDX              COMPACTED_NORMALS|CULL_MASK_ACTIVE|SHADE_TWOSIDE
#define LIGHT_FRONT(f)   1
#define LIGHT_REAR(f)    1
#define LIGHT_SIDE(x,y)  1
#define CULL(x)          0
#define NR_SIDES         2
#include "shade_tmp.h"

#undef COMPACTED
#undef NEXT_NORMAL 
#undef NEXT_VERTEX_NORMAL 
#undef STATE_CHANGE



void gl_init_shade( void )
{
   init_shade_tab_one_sided();
   init_shade_tab_one_sided_masked();
   init_shade_tab_one_sided_compacted();
   init_shade_tab_one_sided_masked_compacted();

   init_shade_tab_two_sided();
   init_shade_tab_two_sided_masked();
   init_shade_tab_two_sided_compacted();
   init_shade_tab_two_sided_masked_compacted();
}

void gl_update_lighting_function( GLcontext *ctx )
{
   GLuint idx;

   if (ctx->Visual->RGBAflag) {
      if (ctx->Light.NeedVertices) {
	 if (ctx->Texture.Enabled && 
	     ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR) 
	    idx = SHADE_RGBA_SPEC;
	 else
	    idx = SHADE_RGBA_VERTICES;	 
      }  
      else
	 idx = SHADE_RGBA_NORMALS;
   }
   else
      idx = 0;

   if (ctx->TriangleCaps & DD_TRI_LIGHT_TWOSIDE) {
      idx |= SHADE_TWOSIDE;
   }


   ctx->shade_func_flags = idx;
}



/* This has been split off to allow the normal shade routines to
 * get a little closer to the vertex buffer, and to use the 
 * GLvector objects directly.
 */
void gl_shade_rastpos( GLcontext *ctx,
		       GLfloat vertex[4],
		       GLfloat normal[3],
		       GLfloat Rcolor[4],
		       GLuint *index )
{
   GLfloat (*base)[3] = ctx->Light.BaseColor;
   GLubyte *sumA = ctx->Light.BaseAlpha;
   struct gl_light *light;
   GLfloat color[4];
   GLfloat diffuse = 0, specular = 0;

   COPY_3V(color, base[0]);
   color[3] = UBYTE_COLOR_TO_FLOAT_COLOR( sumA[0] );

   foreach (light, &ctx->Light.EnabledList) {
      GLfloat n_dot_h;
      GLfloat attenuation = 1.0;
      GLfloat VP[3];  
      GLfloat n_dot_VP;
      GLfloat *h;
      GLfloat contrib[3];
      GLboolean normalized;

      if (!(light->Flags & LIGHT_POSITIONAL)) {
	 COPY_3V(VP, light->VP_inf_norm);
	 attenuation = light->VP_inf_spot_attenuation;
      }
      else {
	 GLfloat d; 
	 
	 SUB_3V(VP, light->Position, vertex);
	 d = LEN_3FV( VP );
	 
	 if ( d > 1e-6) {
	    GLfloat invd = 1.0F / d;
	    SELF_SCALE_SCALAR_3V(VP, invd);
	 }
	 attenuation = 1.0F / (light->ConstantAttenuation + d * 
			       (light->LinearAttenuation + d * 
				light->QuadraticAttenuation));
	 
	 if (light->Flags & LIGHT_SPOT) 
	 {
	    GLfloat PV_dot_dir = - DOT3(VP, light->NormDirection);
	    
	    if (PV_dot_dir<light->CosCutoff) {
	       continue; 
	    }
	    else 
	    {
	       double x = PV_dot_dir * (EXP_TABLE_SIZE-1);
	       int k = (int) x;
	       GLfloat spot = (light->SpotExpTable[k][0]
			       + (x-k)*light->SpotExpTable[k][1]);
	       attenuation *= spot;
	    }
	 }
      }

      if (attenuation < 1e-3) 
	 continue;

      n_dot_VP = DOT3( normal, VP );

      if (n_dot_VP < 0.0F) {
	 ACC_SCALE_SCALAR_3V(color, attenuation, light->MatAmbient[0]);
	 continue;
      } 

      COPY_3V(contrib, light->MatAmbient[0]);
      ACC_SCALE_SCALAR_3V(contrib, n_dot_VP, light->MatDiffuse[0]);
      diffuse += n_dot_VP * light->dli * attenuation;

      if (light->IsMatSpecular[0])
      {
	 if (ctx->Light.Model.LocalViewer) {
	    GLfloat v[3];
	    COPY_3V(v, vertex);
	    NORMALIZE_3FV(v);
	    SUB_3V(VP, VP, v);
	    h = VP;
	    normalized = 0;
	 }
	 else if (light->Flags & LIGHT_POSITIONAL) {
	    h = VP;
	    ACC_3V(h, ctx->EyeZDir);
	    normalized = 0;
	 } else {
	    h = light->h_inf_norm;
	    normalized = 1;
	 }
	 
	 n_dot_h = DOT3(normal, h);

	 if (n_dot_h > 0.0F) 
	 {
	    struct gl_material *mat = &ctx->Light.Material[0];
	    GLfloat spec_coef;
	    GLfloat shininess = mat->Shininess;

	    if (!normalized) {
	       n_dot_h *= n_dot_h;
	       n_dot_h /= LEN_SQUARED_3FV( h );
	       shininess *= .5;
	    }
	    
	    if (n_dot_h>1.0) {
	       spec_coef = pow( n_dot_h, shininess );
	    } else {
	       struct gl_shine_tab *tab = ctx->ShineTable[0];
	       GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef );
	    }

	    if (spec_coef > 1.0e-10) {
	       ACC_SCALE_SCALAR_3V( contrib, spec_coef,
				    light->MatSpecular[0]);
	       specular += spec_coef * light->sli * attenuation;
	    }
	 }
      }

      ACC_SCALE_SCALAR_3V( color, attenuation, contrib );
   } 

   if (ctx->Visual->RGBAflag) {
      COPY_4FV(Rcolor, color);
   } else {
      GLfloat ind;
      struct gl_material *mat = &ctx->Light.Material[0];
      GLfloat d_a = mat->DiffuseIndex - mat->AmbientIndex;
      GLfloat s_a = mat->SpecularIndex - mat->AmbientIndex;
      
      ind = mat->AmbientIndex
	 + diffuse * (1.0F-specular) * d_a
	 + specular * s_a;
      if (ind > mat->SpecularIndex) {
	 ind = mat->SpecularIndex;
      }
      *index = (GLuint) (GLint) ind;
   }

}

@


3.14
log
@miscellaneous bug fixes
@
text
@d1 1
a1 1
/* $Id: shade.c,v 3.13 1999/03/31 20:18:40 keithw Exp $ */
d40 1
d216 1
a216 1
   if (ctx->LightTwoSide) {
@


3.14.2.1
log
@Quake3 inspired optimizations
@
text
@d1 1
a1 1
/* $Id: shade.c,v 3.14 1999/05/11 17:43:00 keithw Exp $ */
a39 1
#include "pipeline.h"
@


3.14.2.2
log
@Removed SGIS multitexture, added FX/X86 assm directory
@
text
@d1 1
a1 1
/* $Id: shade.c,v 3.14.2.1 1999/05/21 21:29:27 keithw Exp $ */
d216 1
a216 1
   if (ctx->TriangleCaps & DD_TRI_LIGHT_TWOSIDE) {
@


3.13
log
@Compiled vertex arrays
@
text
@d1 1
a1 1
/* $Id: shade.c,v 3.12 1999/03/20 21:29:36 keithw Exp $ */
d35 1
d76 2
a77 2
#define NEXT_NORMAL        STRIDE_F(normal, nstride)
#define NEXT_VERTEX_NORMAL STRIDE_F(normal, nstride)
d131 2
a132 2
#define NEXT_NORMAL         normal=first_normal[j]
#define NEXT_VERTEX_NORMAL  ((flags[j]&VERT_NORM) ? normal=first_normal[j] : 0)
@


3.12
log
@fixed size of table
@
text
@d1 1
a1 1
/* $Id: shade.c,v 3.11 1999/03/20 18:58:12 brianp Exp $ */
d49 1
d354 1
a354 1
      COPY_4V(Rcolor, color);
@


3.11
log
@fixed IRIX compiler warnings
@
text
@d1 1
a1 1
/* $Id: shade.c,v 3.10 1999/02/25 14:12:31 keithw Exp $ */
d68 1
a68 1
gl_shade_func gl_shade_func_tab[0x1f];
@


3.10
log
@Merged in kw3 patch
@
text
@d1 1
a1 1
/* $Id: shade.c,v 3.9 1999/02/24 22:48:07 jens Exp $ */
d182 1
a182 1
void gl_init_shade()
@


3.9
log
@Added header file to get XMesa to compile standalone and inside XFree86
@
text
@d1 1
a1 1
/* $Id: shade.c,v 3.8 1999/02/14 03:46:34 brianp Exp $ */
d28 1
a28 30
/*
 * $Log: shade.c,v $
 * Revision 3.8  1999/02/14 03:46:34  brianp
 * new copyright
 *
 * Revision 3.7  1998/10/30 04:41:24  brianp
 * inserted a missing vector length computation in shade_ci_any_sided()
 *
 * Revision 3.6  1998/10/29 03:57:11  brianp
 * misc clean-up of new vertex transformation code
 *
 * Revision 3.5  1998/10/29 02:28:13  brianp
 * incorporated Keith Whitwell's transformation optimizations
 *
 * Revision 3.4  1998/07/01 02:39:14  brianp
 * added a hack to work around suspected gcc bug
 *
 * Revision 3.3  1998/04/18 05:00:28  brianp
 * now using FLOAT_COLOR_TO_UBYTE_COLOR macro
 *
 * Revision 3.2  1998/03/27 04:17:31  brianp
 * fixed G++ warnings
 *
 * Revision 3.1  1998/02/02 03:09:34  brianp
 * added GL_LIGHT_MODEL_COLOR_CONTROL (separate specular color interpolation)
 *
 * Revision 3.0  1998/01/31 21:03:42  brianp
 * initial rev
 *
 */
d35 1
d40 1
d49 1
a49 5
/* Ugh, I think there's a bug in gcc 2.7.2.3.  If the following
 * no-op code isn't here then the results of the above
 * FLOAT_COLOR_TO_UBYTE_COLOR() macro are unpredictable!
 */
#define DODGY_NOOP(x)					\
d51 2
a52 18
   GLubyte r0 = FloatToInt(CLAMP(x, 0, 1) * 255.0);	\
   (void) r0;						\
} while( 0 )

#define SH_TAB_MAX 1.0

#define GET_SHINE_TAB_ENTRY( tab, dp, shininess, result )	\
do {								\
   int k = (int) (dp * ((SHINE_TABLE_SIZE-1)/SH_TAB_MAX));		\
   if (tab[k] < 0.0F) {						\
      GLdouble z = pow(dp, shininess);				\
      if (z<1.0e-10)						\
	 result = tab[k] = 0.0F;				\
      else							\
	 result = tab[k] = (GLfloat) z;				\
   }								\
   else								\
      result = tab[k];						\
d56 8
a64 12
static void shade_rgba_spec_any_sided( GLcontext *ctx,
				       struct gl_shade_context *sc,
				       GLuint start,
				       GLuint n )
{
   GLuint j;
   GLfloat Fbase[3], FbaseA;
   GLfloat Bbase[3], BbaseA;
   GLint FsumA;
   GLint BsumA;
   struct gl_light *light;
   struct gl_material *mat;
d66 3
a68 25
   GLuint side_flags = sc->side_flags;
   GLuint  vstride = sc->vertex_stride;
   const GLfloat *vertex = sc->vertices + (start * vstride);
   GLuint  nstride = sc->normal_stride;
   const GLfloat *normal = sc->normals + (start * nstride);
   GLubyte (*Fcolor)[4] = sc->Fcolor + start;
   GLubyte (*Bcolor)[4] = sc->Bcolor + start; 
   GLubyte (*Fspec)[4] = sc->Fspec + start;
   GLubyte (*Bspec)[4] = sc->Bspec + start; 


   mat = &ctx->Light.Material[0];
   SCALE_3V( Fbase, ctx->Light.Model.Ambient, mat->Ambient);
   ACC_3V( Fbase, mat->Emission );
   FbaseA = mat->Diffuse[3];  /* Alpha is simple, same for all vertices */
   FLOAT_COLOR_TO_UBYTE_COLOR( FsumA, FbaseA );

   if (side_flags & 2)
   {
      mat = &ctx->Light.Material[1];
      SCALE_3V( Bbase, ctx->Light.Model.Ambient, mat->Ambient);
      ACC_3V( Bbase, mat->Emission );
      BbaseA = mat->Diffuse[3];  /* Alpha is simple, same for all vertices */
      FLOAT_COLOR_TO_UBYTE_COLOR( BsumA, BbaseA );
   }
a69 9
   for ( j = 0 ; j < n ; j++, vertex += vstride, normal += nstride ) {
      GLfloat sum[2][3], spec[2][3];
      COPY_3V(sum[0], Fbase);
      ZERO_3V(spec[0]);
      
      if (side_flags & 2) {
	 COPY_3V(sum[1], Bbase);
	 ZERO_3V(spec[1]);
      }
d71 108
a178 31
      /* Add contribution from each enabled light source */
      for (light=ctx->Light.FirstEnabled; light; light=light->NextEnabled) {
	 struct gl_material *mat;
	 GLfloat n_dot_h;
	 GLfloat correction = 1;
	 GLint side = 0; 
	 GLfloat contrib[3];
         GLfloat attenuation = 1.0;
         GLfloat VP[3];  /* unit vector from vertex to light */
         GLfloat n_dot_VP;       /* n dot VP */
	 GLfloat *h;
	 GLboolean normalized;

         /* compute VP and attenuation */
         if (!light->IsPositional) {
            /* directional light */
            COPY_3V(VP, light->VP_inf_norm);
         }
         else {
            GLfloat d;     /* distance from vertex to light */
            SUB_3V(VP, light->Position, vertex);
            d = LEN_3FV( VP );
            if ( d > 1e-6) {
               GLfloat invd = 1.0F / d;
               SELF_SCALE_SCALAR_3V(VP, invd);
            }
	    /* if (light->Attenuated) */
	    attenuation = 1.0F / (light->ConstantAttenuation + d * 
				  (light->LinearAttenuation + d * 
				   light->QuadraticAttenuation));
         }
a179 15
         /* spotlight attenuation */
         if (light->IsSpot) 
	 {
            GLfloat PV_dot_dir = - DOT3(VP, light->NormDirection);
            if (PV_dot_dir<=0.0F || PV_dot_dir<light->CosCutoff) {
	       continue; /* this light makes no contribution */
            }
            else {
               double x = PV_dot_dir * (EXP_TABLE_SIZE-1);
               int k = (int) x;
               GLfloat spot = (light->SpotExpTable[k][0]
			       + (x-k)*light->SpotExpTable[k][1]);
	       attenuation *= spot;
            }
         }
a180 2
	 if (attenuation < 1e-5) 
	    continue;		/* this light makes no contribution */
d182 11
a192 92
         /* Compute dot product or normal and vector from V to light pos */
         n_dot_VP = DOT3( normal, VP );

         /* which side are we lighting? */
         if (n_dot_VP < 0.0F) {
	    ACC_SCALE_SCALAR_3V(sum[0], attenuation, light->MatAmbient[0]);
	    if (!(side_flags & 2)) {
	       continue;
	    }
	    side = 1;
	    correction = -1;
	    n_dot_VP = -n_dot_VP;
	 } else if (side_flags & 2) {
	    ACC_SCALE_SCALAR_3V( sum[1], attenuation, light->MatAmbient[1] );
	 } 

	 /* diffuse term */
	 COPY_3V(contrib, light->MatAmbient[side]);
	 ACC_SCALE_SCALAR_3V(contrib, n_dot_VP, light->MatDiffuse[side]);
	 ACC_SCALE_SCALAR_3V(sum[side], attenuation, contrib );

	 if (!light->IsMatSpecular[side])
	    continue;

	 /* specular term - cannibalize VP... */
	 if (ctx->Light.Model.LocalViewer) {
	    GLfloat v[3];
	    COPY_3V(v, vertex);
	    NORMALIZE_3FV(v);
	    SUB_3V(VP, VP, v);                /* h = VP + VPe */
	    h = VP;
	    normalized = 0;
	 }
	 else if (light->IsPositional) {
	    h = VP;
	    /*h[2] += 1.0;                     h = VP + eye<0,0,1> */
	    ACC_3V(h, ctx->EyeZDir);
	    normalized = 0;
	 } else {
	    h = light->h_inf_norm;
	    normalized = 1;
	 }
	 
	 n_dot_h = correction * DOT3(normal, h);

	 if (n_dot_h > 0.0F) 
	 {
	    GLfloat spec_coef;
	    mat = &ctx->Light.Material[side];

	    if (!normalized)
	       n_dot_h /= LEN_3FV( h );
	    
	    if (n_dot_h>SH_TAB_MAX) 
	       spec_coef = pow( n_dot_h, mat->Shininess );
	    else {
	       GET_SHINE_TAB_ENTRY( mat->ShineTable, n_dot_h, 
				    mat->Shininess, spec_coef );
	    }

	    if (spec_coef > 1.0e-10) {
	       spec_coef *= attenuation;
	       ACC_SCALE_SCALAR_3V( spec[side], spec_coef,
				    light->MatSpecular[side]);
	    }
         }
      } /*loop over lights*/

      /* clamp and convert to integer or fixed point */
      FLOAT_COLOR_TO_UBYTE_COLOR( Fcolor[j][0], sum[0][0] );
      FLOAT_COLOR_TO_UBYTE_COLOR( Fcolor[j][1], sum[0][1] );
      FLOAT_COLOR_TO_UBYTE_COLOR( Fcolor[j][2], sum[0][2] );
      Fcolor[j][3] = FsumA;


      FLOAT_COLOR_TO_UBYTE_COLOR( Fspec[j][0], spec[0][0] );
      FLOAT_COLOR_TO_UBYTE_COLOR( Fspec[j][1], spec[0][1] );
      FLOAT_COLOR_TO_UBYTE_COLOR( Fspec[j][2], spec[0][2] );
      Fspec[j][3] = 255;  /* but never used */

      if (side_flags & 2) {
	 FLOAT_COLOR_TO_UBYTE_COLOR( Bcolor[j][0], sum[1][0] );
	 FLOAT_COLOR_TO_UBYTE_COLOR( Bcolor[j][1], sum[1][1] );
	 FLOAT_COLOR_TO_UBYTE_COLOR( Bcolor[j][2], sum[1][2] );
	 Bcolor[j][3] = BsumA;
	 
	 FLOAT_COLOR_TO_UBYTE_COLOR( Bspec[j][0], spec[1][0] );
	 FLOAT_COLOR_TO_UBYTE_COLOR( Bspec[j][1], spec[1][1] );
	 FLOAT_COLOR_TO_UBYTE_COLOR( Bspec[j][2], spec[1][2] );
	 Bspec[j][3] = 255;  /* but never used */
      }
   } 
d195 1
a195 6


static void shade_rgba_twosided( GLcontext *ctx,
				 struct gl_shade_context *sc,
				 GLuint start,
				 GLuint n )
d197 1
a197 7
   GLuint j;
   GLfloat Fbase[3], FbaseA;
   GLfloat Bbase[3], BbaseA;
   GLint FsumA;
   GLint BsumA;
   struct gl_light *light;
   struct gl_material *mat;
d199 13
a211 58
   GLuint  vstride = sc->vertex_stride;
   const GLfloat *vertex = sc->vertices + (start * vstride);
   GLuint  nstride = sc->normal_stride;
   const GLfloat *normal = sc->normals + (start * nstride);
   GLubyte (*Fcolor)[4] = sc->Fcolor + start;
   GLubyte (*Bcolor)[4] = sc->Bcolor + start; 


   mat = &ctx->Light.Material[0];
   Fbase[0] = mat->Emission[0] + ctx->Light.Model.Ambient[0] * mat->Ambient[0];
   Fbase[1] = mat->Emission[1] + ctx->Light.Model.Ambient[1] * mat->Ambient[1];
   Fbase[2] = mat->Emission[2] + ctx->Light.Model.Ambient[2] * mat->Ambient[2];
   FbaseA = mat->Diffuse[3];  /* Alpha is simple, same for all vertices */
   FLOAT_COLOR_TO_UBYTE_COLOR( FsumA, FbaseA );

   mat = &ctx->Light.Material[0];
   Bbase[0] = mat->Emission[0] + ctx->Light.Model.Ambient[0] * mat->Ambient[0];
   Bbase[1] = mat->Emission[1] + ctx->Light.Model.Ambient[1] * mat->Ambient[1];
   Bbase[2] = mat->Emission[2] + ctx->Light.Model.Ambient[2] * mat->Ambient[2];
   BbaseA = mat->Diffuse[3];  /* Alpha is simple, same for all vertices */
   FLOAT_COLOR_TO_UBYTE_COLOR( BsumA, BbaseA );

   for (j = 0; j < n ; j++, vertex += vstride, normal += nstride) {
      GLfloat sum[2][3];

      COPY_3V(sum[0], Fbase);
      COPY_3V(sum[1], Bbase);

      /* Add contribution from each enabled light source */
      for (light=ctx->Light.FirstEnabled; light; light=light->NextEnabled) {
	 GLfloat n_dot_h;
	 GLfloat correction = 1;
	 GLint side = 0; 
	 GLfloat contrib[2][3];
         GLfloat attenuation = 1.0;
         GLfloat VP[3];          /* unit vector from vertex to light */
         GLfloat n_dot_VP;       /* n dot VP */
	 GLfloat *h;
	 GLboolean normalized;

         /* compute VP and attenuation */
         if (!light->IsPositional) {
            /* directional light */
            COPY_3V(VP, light->VP_inf_norm);
         }
         else {
            GLfloat d;     /* distance from vertex to light */
            SUB_3V(VP, light->Position, vertex);
            d = LEN_3FV( VP );
            if ( d > 1e-6) {
               GLfloat invd = 1.0F / d;
               SELF_SCALE_SCALAR_3V(VP, invd);
            }
	    /* if (light->Attenuated) */
	    attenuation = 1.0F / (light->ConstantAttenuation + d * 
				  (light->LinearAttenuation + d * 
				   light->QuadraticAttenuation));
         }
d213 3
a215 15
         /* spotlight attenuation */
         if (light->IsSpot) 
	 {
            GLfloat PV_dot_dir = - DOT3(VP, light->NormDirection);
            if (PV_dot_dir<=0.0F || PV_dot_dir<light->CosCutoff) {
	       continue; /* this light makes no contribution */
            }
            else {
               double x = PV_dot_dir * (EXP_TABLE_SIZE-1);
               int k = (int) x;
               GLfloat spot = (light->SpotExpTable[k][0]
			       + (x-k)*light->SpotExpTable[k][1]);
	       attenuation *= spot;
            }
         }
a216 2
	 if (attenuation < 1e-5) 
	    continue;		/* this light makes no contribution */
d218 1
a218 76
	 COPY_3V(contrib[0], light->MatAmbient[0]);
	 COPY_3V(contrib[1], light->MatAmbient[1]);

         /* Compute dot product or normal and vector from V to light pos */
         n_dot_VP = DOT3( normal, VP );

         /* which side are we lighting? */
         if (n_dot_VP < 0.0F) {
	    side = 1;
	    correction = -1;
	    n_dot_VP = -n_dot_VP;
	 }
      
	 /* diffuse term */
	 ACC_SCALE_SCALAR_3V(contrib[side], n_dot_VP, light->MatDiffuse[side]);

	 /* specular term - cannibalize VP... */
	 if (light->IsMatSpecular[side])
	 {
	    if (ctx->Light.Model.LocalViewer) {
	       GLfloat v[3];
	       COPY_3V(v, vertex);
	       NORMALIZE_3FV(v);
	       SUB_3V(VP, VP, v);                /* h = VP + VPe */
	       h = VP;
	       normalized = 0;
	    }
	    else if (light->IsPositional) {
	       h = VP;
	       /* h[2] += 1.0;                     h = VP + eye<0,0,1> */
	       ACC_3V(h, ctx->EyeZDir);
	       normalized = 0;
	    } else {
	       h = light->h_inf_norm;
	       normalized = 1;
	    }
	 
	    n_dot_h = correction * DOT3(normal, h);

	    if (n_dot_h > 0.0F) 
	    {
	       GLfloat spec_coef;
	       
	       if (!normalized)
		  n_dot_h /= LEN_3FV( h );
	       
	       if (n_dot_h>SH_TAB_MAX) 
		  spec_coef = pow( n_dot_h, mat->Shininess );
	       else {
		  GET_SHINE_TAB_ENTRY( mat->ShineTable, n_dot_h, 
				       mat->Shininess, spec_coef );
	       }

	       if (spec_coef > 1.0e-10) {
		  ACC_SCALE_SCALAR_3V( contrib[side], spec_coef,
				       light->MatSpecular[side]);
	       }
	    }
         }

	 ACC_SCALE_SCALAR_3V( sum[0], attenuation, contrib[0] );
	 ACC_SCALE_SCALAR_3V( sum[1], attenuation, contrib[1] );
      } /*loop over lights*/

      /* clamp and convert to integer or fixed point */
      FLOAT_COLOR_TO_UBYTE_COLOR( Fcolor[j][0], sum[0][0] );
      FLOAT_COLOR_TO_UBYTE_COLOR( Fcolor[j][1], sum[0][1] );
      FLOAT_COLOR_TO_UBYTE_COLOR( Fcolor[j][2], sum[0][2] );
      Fcolor[j][3] = FsumA;

      FLOAT_COLOR_TO_UBYTE_COLOR( Bcolor[j][0], sum[1][0] );
      FLOAT_COLOR_TO_UBYTE_COLOR( Bcolor[j][1], sum[1][1] );
      FLOAT_COLOR_TO_UBYTE_COLOR( Bcolor[j][2], sum[1][2] );
      Bcolor[j][3] = BsumA;

   } /*loop over vertices*/
d223 3
a225 9

/*
 * Use current lighting/material settings to compute the RGBA colors of
 * an array of vertexes.
 * Input:  side - 0=use front material, 1=use back material
 *         n - number of vertexes to process
 *         vertex - array of vertex positions in eye coordinates
 *         normal - array of surface normal vectors
 * Output:  color - array of resulting colors
d227 5
a231 4
static void shade_rgba( GLcontext *ctx,
			struct gl_shade_context *sc,
			GLuint start,
			GLuint n )
d233 2
a234 3
   GLuint j;
   GLfloat base[3], baseA;
   GLint sumA;
d236 2
a237 1
   struct gl_material *mat;
d239 2
a240 43
   GLuint  vstride = sc->vertex_stride;
   const GLfloat *vertex = sc->vertices + (start * vstride);
   GLuint  nstride = sc->normal_stride;
   const GLfloat *normal = sc->normals + (start * nstride);
   GLubyte (*Fcolor)[4] = sc->Fcolor + start;

   mat = &ctx->Light.Material[0];
   base[0] = mat->Emission[0] + ctx->Light.Model.Ambient[0] * mat->Ambient[0];
   base[1] = mat->Emission[1] + ctx->Light.Model.Ambient[1] * mat->Ambient[1];
   base[2] = mat->Emission[2] + ctx->Light.Model.Ambient[2] * mat->Ambient[2];
   baseA = mat->Diffuse[3];  /* Alpha is simple, same for all vertices */

   FLOAT_COLOR_TO_UBYTE_COLOR( sumA, baseA );

   for (j = 0; j < n ; j++, vertex += vstride, normal += nstride) {
      GLfloat sum[3];
      COPY_3V(sum, base);

      /* Add contribution from each enabled light source */
      for (light=ctx->Light.FirstEnabled; light; light=light->NextEnabled) {
         GLfloat contrib[3];
         GLfloat attenuation = 1.0;
         GLfloat VP[3];  /* unit vector from vertex to light */
         GLfloat n_dot_VP;       /* n dot VP */

         /* compute VP and attenuation */
         if (!light->IsPositional) {
            /* directional light */
            COPY_3V(VP, light->VP_inf_norm);
         }
         else {
            GLfloat d;     /* distance from vertex to light */
            SUB_3V(VP, light->Position, vertex);
            d = LEN_3FV( VP );
            if ( d > 1e-6) {
               GLfloat invd = 1.0F / d;
               SELF_SCALE_SCALAR_3V(VP, invd);
            }
	    /* if (light->Attenuated) */
	    attenuation = 1.0F / (light->ConstantAttenuation + d * 
				  (light->LinearAttenuation + d * 
				   light->QuadraticAttenuation));
         }
d242 15
a256 131
         /* spotlight attenuation */
         if (light->IsSpot) 
	 {
            GLfloat PV_dot_dir = - DOT3(VP, light->NormDirection);
            if (PV_dot_dir<=0.0F || PV_dot_dir<light->CosCutoff) {
	       continue; /* this light makes no contribution */
            }
            else {
               double x = PV_dot_dir * (EXP_TABLE_SIZE-1);
               int k = (int) x;
               GLfloat spot = (light->SpotExpTable[k][0]
			       + (x-k)*light->SpotExpTable[k][1]);
	       attenuation *= spot;
            }
         }

	 if (attenuation < 1e-5) 
	    continue;		/* this light makes no contribution */

	 COPY_3V(contrib, light->MatAmbient[0]);

         /* Compute dot product or normal and vector from V to light pos */
         n_dot_VP = DOT3( normal, VP );

         /* diffuse and specular terms */
         if (n_dot_VP > 0.0F) {
            GLfloat *h, n_dot_h;
            GLboolean normalized = 0;
      

            /* diffuse term */
	    ACC_SCALE_SCALAR_3V( contrib, n_dot_VP, light->MatDiffuse[0] );

            /* specular term - cannibalize VP... */
	    if (light->IsMatSpecular[0]) 
	    {
	       if (ctx->Light.Model.LocalViewer) {
		  GLfloat v[3];
		  COPY_3V(v, vertex);
		  NORMALIZE_3FV(v);
		  SUB_3V(VP, VP, v);           /* h = VP + VPe */
		  h = VP;
	       }
	       else if (light->IsPositional) {
		  h = VP;
		  /*h[2] += 1.0;*/           /* h = VP + eye-space<0,0,1> */
		  ACC_3V(h, ctx->EyeZDir);
	       } else {
		  h = light->h_inf_norm;
		  normalized = 1;
	       }

	       /* attention: h may not be normalized, done later if needed */
	       n_dot_h = DOT3(normal, h);

	       if (n_dot_h > 0.0F) 
	       {
		  GLfloat spec_coef;

		  /* now `correct' the dot product */
		  if (!normalized)
		     n_dot_h /= LEN_3FV( h );

		  if (n_dot_h>SH_TAB_MAX) {
		     /* only happens if normal vector length > 1.0 */
		     spec_coef = pow( n_dot_h, mat->Shininess );
		  }
		  else {
		     /* use table lookup approximation */
		     GET_SHINE_TAB_ENTRY( mat->ShineTable, n_dot_h, 
					  mat->Shininess, spec_coef );
		  }
		  if (spec_coef > 1.0e-10) {
		     ACC_SCALE_SCALAR_3V( contrib, spec_coef,
					  light->MatSpecular[0]);
		  }
	       }
	    }
         }
	 ACC_SCALE_SCALAR_3V( sum, attenuation, contrib );
      } /*loop over lights*/

      /* clamp and convert to integer or fixed point */
      FLOAT_COLOR_TO_UBYTE_COLOR( Fcolor[j][0], sum[0] );
      FLOAT_COLOR_TO_UBYTE_COLOR( Fcolor[j][1], sum[1] );
      FLOAT_COLOR_TO_UBYTE_COLOR( Fcolor[j][2], sum[2] );
      Fcolor[j][3] = sumA;

   } /*loop over vertices*/
}


static void shade_rgba_fast_specular( GLcontext *ctx,
				      struct gl_shade_context *sc,
				      GLuint start,
				      GLuint n )
{
   GLuint j;

   GLuint  nstride = sc->normal_stride;
   const GLfloat *normal = sc->normals + (start * nstride);
   GLubyte (*Fcolor)[4] = sc->Fcolor + start;

   GLint FsumA = (GLint) (ctx->Light.BaseColor[0][3] * 255.0F);

   for (j = 0; j < n; j++, normal += nstride) {
      GLfloat sum[3];
      struct gl_light *light;

      COPY_3V(sum, ctx->Light.BaseColor[0]);

      for (light=ctx->Light.FirstEnabled; light; light=light->NextEnabled) 
      {
	 struct gl_material *m;
	 GLfloat n_dot_h;
         GLfloat n_dot_VP = DOT3(normal, light->VP_inf_norm);

         if (n_dot_VP < 0.0F)
	    continue;

	 ACC_SCALE_SCALAR_3V(sum, n_dot_VP, light->MatDiffuse[0]);
	    
	 if (!light->IsMatSpecular[0]) 
	    continue;

	 m = &ctx->Light.Material[0];

	 n_dot_h = DOT3(normal, light->h_inf_norm);	 

	 if (n_dot_h < 0.0F) 
	    continue;
d258 2
a259 71
	 if (n_dot_h > SH_TAB_MAX) 
	 {
	    GLfloat spec = pow( n_dot_h, m->Shininess );
	    if (spec > 1.0e-10F) {
	       ACC_SCALE_SCALAR_3V(sum, spec, light->MatSpecular[0]);
	    }
	 }
	 else 
	 {
	    GLfloat spec;
	    GET_SHINE_TAB_ENTRY( m->ShineTable, n_dot_h, m->Shininess, spec );
	    ACC_SCALE_SCALAR_3V( sum, spec, light->MatSpecular[0] );
	 }
      } 

      /* clamp and convert to integer or fixed point */
      FLOAT_COLOR_TO_UBYTE_COLOR( Fcolor[j][0], sum[0] );
      FLOAT_COLOR_TO_UBYTE_COLOR( Fcolor[j][1], sum[1] );
      FLOAT_COLOR_TO_UBYTE_COLOR( Fcolor[j][2], sum[2] );
      Fcolor[j][3] = FsumA;

      DODGY_NOOP(sum[0]);
   } 
}

static void shade_rgba_fast_specular_twosided( GLcontext *ctx,
					       struct gl_shade_context *sc,
					       GLuint start,
					       GLuint n )
{
   GLuint j;


   GLuint  nstride = sc->normal_stride;
   const GLfloat *normal = sc->normals + (start * nstride);
   GLubyte (*Fcolor)[4] = sc->Fcolor + start;
   GLubyte (*Bcolor)[4] = sc->Bcolor + start; 


   /* Alpha is easy to compute, same for all vertices */
   GLint FsumA = (GLint) (ctx->Light.BaseColor[0][3] * 255.0F);
   GLint BsumA = (GLint) (ctx->Light.BaseColor[1][3] * 255.0F);

   for (j = 0;j<n;j++, normal += nstride) {
      GLfloat sum[2][3];
      struct gl_light *light;

      COPY_3V(sum[0], ctx->Light.BaseColor[0]);
      COPY_3V(sum[1], ctx->Light.BaseColor[1]);

      for (light=ctx->Light.FirstEnabled; light; light=light->NextEnabled) 
      {
	 struct gl_material *m;
	 GLfloat n_dot_h;
	 GLfloat correction = 1;
	 GLint side = 0;
         GLfloat n_dot_VP = DOT3(normal, light->VP_inf_norm);

         if (n_dot_VP < 0.0F) {
	    side = 1;
	    n_dot_VP = -n_dot_VP;
	    correction = -1;
	 }

	 ACC_SCALE_SCALAR_3V(sum[side], n_dot_VP, light->MatDiffuse[side]);
	    
	 if (!light->IsMatSpecular[side]) 
	    continue;

	 m = &ctx->Light.Material[side];
	 n_dot_h = correction * DOT3(normal, light->h_inf_norm);
d261 7
a267 2
	 if (n_dot_h < 0.0F) 
	    continue;
d269 1
a269 1
	 if (n_dot_h > SH_TAB_MAX) 
d271 12
a282 3
	    GLfloat spec = pow( n_dot_h, m->Shininess );
	    if (spec > 1.0e-10F) {
	       ACC_SCALE_SCALAR_3V(sum[side], spec, light->MatSpecular[side]);
a284 53
	 else 
	 {
	    GLfloat spec;
	    GET_SHINE_TAB_ENTRY( m->ShineTable, n_dot_h, m->Shininess, spec );
	    ACC_SCALE_SCALAR_3V( sum[side], spec, light->MatSpecular[side] );
	 }
      } 

      /* clamp and convert to integer or fixed point */
      FLOAT_COLOR_TO_UBYTE_COLOR( Fcolor[j][0], sum[0][0] );
      FLOAT_COLOR_TO_UBYTE_COLOR( Fcolor[j][1], sum[0][1] );
      FLOAT_COLOR_TO_UBYTE_COLOR( Fcolor[j][2], sum[0][2] );
      Fcolor[j][3] = FsumA;

      FLOAT_COLOR_TO_UBYTE_COLOR( Bcolor[j][0], sum[1][0] );
      FLOAT_COLOR_TO_UBYTE_COLOR( Bcolor[j][1], sum[1][1] );
      FLOAT_COLOR_TO_UBYTE_COLOR( Bcolor[j][2], sum[1][2] );
      Bcolor[j][3] = BsumA;

      DODGY_NOOP(sum[0][0]);
   } 
}



/*
 * It's hard to say whether there is any benefit to having these
 * functions hanging around:
 */
static void shade_rgba_diffuse( GLcontext *ctx,
				struct gl_shade_context *sc,
				GLuint start,
				GLuint n )
{
   GLuint j;

   GLuint  nstride = sc->normal_stride;
   const GLfloat *normal = sc->normals + (start * nstride);
   GLubyte (*Fcolor)[4] = sc->Fcolor + start;

   GLint sumA = (GLint) (ctx->Light.BaseColor[0][3] * 255.0F);

   for ( j = 0 ; j < n ; j++, normal += nstride ) 
   {
      GLfloat sum[3];
      struct gl_light *light;
      COPY_3V(sum, ctx->Light.BaseColor[0]);

      for (light=ctx->Light.FirstEnabled; light; light=light->NextEnabled) 
      {
         GLfloat n_dot_VP = DOT3(normal, light->VP_inf_norm);
         if (n_dot_VP > 0.0F) 
	    ACC_SCALE_SCALAR_3V( sum, n_dot_VP, light->MatDiffuse[0] );
d287 2
a288 8
      FLOAT_COLOR_TO_UBYTE_COLOR( Fcolor[j][0], sum[0] );
      FLOAT_COLOR_TO_UBYTE_COLOR( Fcolor[j][1], sum[1] );
      FLOAT_COLOR_TO_UBYTE_COLOR( Fcolor[j][2], sum[2] );
      Fcolor[j][3] = sumA;

      DODGY_NOOP(sum[0]);
   } 
}
d290 1
d292 4
d297 3
a299 20
static void shade_rgba_diffuse_twosided( GLcontext *ctx,
					 struct gl_shade_context *sc,
					 GLuint start,
					 GLuint n )
{
   GLuint j;

   GLuint  nstride = sc->normal_stride;
   const GLfloat *normal = sc->normals + (start * nstride);
   GLubyte (*Fcolor)[4] = sc->Fcolor + start;
   GLubyte (*Bcolor)[4] = sc->Bcolor + start; 

   GLint FsumA = (GLint) (ctx->Light.BaseColor[0][3] * 255.0F);
   GLint BsumA = (GLint) (ctx->Light.BaseColor[1][3] * 255.0F);

   /* Loop over vertices */
   for ( j = 0 ; j < n ; j++, normal += nstride ) 
   {
      GLfloat sum[2][3];
      struct gl_light *light;
d301 1
a301 4
      COPY_3V(sum[0], ctx->Light.BaseColor[0]);
      COPY_3V(sum[1], ctx->Light.BaseColor[1]);

      for (light=ctx->Light.FirstEnabled; light; light=light->NextEnabled) 
a302 130
         GLfloat n_dot_VP = DOT3(normal, light->VP_inf_norm);
         if (n_dot_VP > 0.0F) 
	 {
  	    ACC_SCALE_SCALAR_3V( sum[0], n_dot_VP, light->MatDiffuse[0] );
	 }
	 else
	 {
  	    ACC_SCALE_SCALAR_3V( sum[1], -n_dot_VP, light->MatDiffuse[1] );
	 }
      }

      /* clamp and convert to integer or fixed point */
      FLOAT_COLOR_TO_UBYTE_COLOR( Fcolor[j][0], sum[0][0] );
      FLOAT_COLOR_TO_UBYTE_COLOR( Fcolor[j][1], sum[0][1] );
      FLOAT_COLOR_TO_UBYTE_COLOR( Fcolor[j][2], sum[0][2] );
      Fcolor[j][3] = FsumA;

      FLOAT_COLOR_TO_UBYTE_COLOR( Bcolor[j][0], sum[1][0] );
      FLOAT_COLOR_TO_UBYTE_COLOR( Bcolor[j][1], sum[1][1] );
      FLOAT_COLOR_TO_UBYTE_COLOR( Bcolor[j][2], sum[1][2] );
      Bcolor[j][3] = BsumA;

      DODGY_NOOP(sum[0][0]);
   } 
}



/*
 * Use current lighting/material settings to compute the color indexes
 * for an array of vertices.
 * Input:  n - number of vertices to shade
 *         side - 0=use front material, 1=use back material
 *         vertex - array of [n] vertex position in eye coordinates
 *         normal - array of [n] surface normal vector
 * Output:  indexResult - resulting array of [n] color indexes
 */
static void shade_ci_any_sided( GLcontext *ctx,
				struct gl_shade_context *sc,
				GLuint start,
				GLuint n )
{
   struct gl_material *mat;
   GLuint j;

   GLuint  side_flags = sc->side_flags;
   GLuint  vstride = sc->vertex_stride;
   const GLfloat *vertex = sc->vertices + (start * vstride);
   GLuint  nstride = sc->normal_stride;
   const GLfloat *normal = sc->normals + (start * nstride);
   GLuint  *indexResult[2];

   indexResult[0] = sc->Findex + start;
   indexResult[1] = sc->Bindex + start;

   /* loop over vertices */
   for (j = 0 ; j < n ; j++, vertex += vstride, normal += nstride) {
      GLfloat diffuse[2], specular[2];
      GLuint side = 0;
      struct gl_light *light;

      diffuse[0] = specular[0] = 0.0F;
      diffuse[1] = specular[1] = 0.0F;

      /* Accumulate diffuse and specular from each light source */
      for (light=ctx->Light.FirstEnabled; light; light=light->NextEnabled) {
         GLfloat attenuation = 1.0F;
         GLfloat VP[3];  /* unit vector from vertex to light */
         GLfloat n_dot_VP;  /* dot product of l and n */
	 GLfloat *h, n_dot_h, correction = 1.0;
	 GLboolean normalized;

         /* compute l and attenuation */
         if (!light->IsPositional) {
            /* directional light */
	    COPY_3V(VP, light->VP_inf_norm);
         }
         else {
            GLfloat d;     /* distance from vertex to light */
	    SUB_3V(VP, light->Position, vertex);
            d = LEN_3FV( VP );
	    if ( d > 1e-6) {
               GLfloat invd = 1.0F / d;
               SELF_SCALE_SCALAR_3V(VP, invd);
            }
	    /* if (light->Attenuated) */
	    attenuation = 1.0F / (light->ConstantAttenuation + d * 
				  (light->LinearAttenuation + d * 
				   light->QuadraticAttenuation));
         }

         /* spotlight attenuation */
         if (light->IsSpot) 
	 {
            GLfloat PV_dot_dir = - DOT3(VP, light->NormDirection);
            if (PV_dot_dir<=0.0F || PV_dot_dir<light->CosCutoff) {
	       continue; /* this light makes no contribution */
            }
            else {
               double x = PV_dot_dir * (EXP_TABLE_SIZE-1);
               int k = (int) x;
               GLfloat spot = (light->SpotExpTable[k][0]
			       + (x-k)*light->SpotExpTable[k][1]);
	       attenuation *= spot;
            }
         }

	 if (attenuation < 1e-5) 
	    continue;		/* this light makes no contribution */

         n_dot_VP = DOT3( normal, VP );

	 /* which side are we lighting? */
         if (n_dot_VP < 0.0F) {
	    if (!(side_flags & 2)) {
	       continue;
	    }
	    side = 1;
	    correction = -1;
	    n_dot_VP = -n_dot_VP;
	 } 


	 /* accumulate diffuse term */
	 diffuse[side] += n_dot_VP * light->dli * attenuation;

	 /* specular term */
	 if (!light->IsSpecular)
	    continue;

d307 1
a307 1
	    SUB_3V(VP, VP, v);                /* h = VP + VPe */
d311 1
a311 1
	 else if (light->IsPositional) {
a312 1
	    /*h[2] += 1.0;                     h = VP + eye<0,0,1> */
d319 2
a320 2

	 n_dot_h = correction * DOT3(normal, h);
d324 1
d326 7
a332 4
	    mat = &ctx->Light.Material[side];
	    
	    if (!normalized)
	       n_dot_h /= LEN_3FV( h );
d334 2
a335 2
	    if (n_dot_h>SH_TAB_MAX) {
	       spec_coef = pow( n_dot_h, mat->Shininess );
d337 2
a338 2
	       GET_SHINE_TAB_ENTRY( mat->ShineTable, n_dot_h, 
				    mat->Shininess, spec_coef );
a339 3
	    specular[side] += spec_coef * light->sli * attenuation;
         }
      } /*loop over lights*/
d341 4
a344 22
      /* Now compute final color index */
      for (side = 0 ; side < 2 ; side++)
      {
	 GLfloat index;

	 if (!(side_flags & (1<<side)))
	    continue;

	 mat = &ctx->Light.Material[side];
	 if (specular[side] > 1.0F) {
	    index = mat->SpecularIndex;
	 }
	 else {
	    GLfloat d_a, s_a;
	    d_a = mat->DiffuseIndex - mat->AmbientIndex;
	    s_a = mat->SpecularIndex - mat->AmbientIndex;
	       
	    index = mat->AmbientIndex
	       + diffuse[side] * (1.0F-specular[side]) * d_a
	       + specular[side] * s_a;
	    if (index > mat->SpecularIndex) {
	       index = mat->SpecularIndex;
a346 1
	 indexResult[side][j] = (GLuint) (GLint) index;
a347 2
   } /*for vertex*/
}
d349 16
a364 22
void gl_update_lighting_function( GLcontext *ctx )
{
   if (ctx->Visual->RGBAflag)
   { 
      if (ctx->Texture.Enabled && 
	  ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR) 
      {
	 ctx->shade_func = shade_rgba_spec_any_sided;
      } 
      else if (ctx->Light.NeedVertices) 
      {
	 if (ctx->LightTwoSide) 
	    ctx->shade_func = shade_rgba_twosided;
	 else
	    ctx->shade_func = shade_rgba;
      } 
      else if (ctx->Light.AnySpecular) 
      {
	 if (ctx->LightTwoSide)
	    ctx->shade_func = shade_rgba_fast_specular_twosided;
	 else
	    ctx->shade_func = shade_rgba_fast_specular;
d366 1
a366 6
      else if (ctx->LightTwoSide) 
	 ctx->shade_func = shade_rgba_diffuse_twosided;
      else
	 ctx->shade_func = shade_rgba_diffuse;
   } else {
      ctx->shade_func = shade_ci_any_sided;
d368 1
a369 7







@


3.8
log
@new copyright
@
text
@d1 1
a1 1
/* $Id: shade.c,v 3.7 1998/10/30 04:41:24 brianp Exp brianp $ */
d30 3
d68 3
@


3.7
log
@inserted a missing vector length computation in shade_ci_any_sided()
@
text
@d1 1
a1 1
/* $Id: shade.c,v 3.6 1998/10/29 03:57:11 brianp Exp brianp $ */
d6 19
a24 15
 * Copyright (C) 1995-1998  Brian Paul
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
d30 3
@


3.6
log
@misc clean-up of new vertex transformation code
@
text
@d1 1
a1 1
/* $Id: shade.c,v 3.5 1998/10/29 02:28:13 brianp Exp brianp $ */
d26 3
d909 1
@


3.5
log
@incorporated Keith Whitwell's transformation optimizations
@
text
@d1 1
a1 1
/* $Id: shade.c,v 3.4 1998/07/01 02:39:14 brianp Exp brianp $ */
d26 3
d67 1
d103 1
a103 1
   GLfloat *vertex = sc->vertices + (start * vstride);
d105 1
a105 1
   GLfloat *normal = sc->normals + (start * nstride);
d298 1
a298 1
   GLfloat *vertex = sc->vertices + (start * vstride);
d300 1
a300 1
   GLfloat *normal = sc->normals + (start * nstride);
d477 1
a477 1
   GLfloat *vertex = sc->vertices + (start * vstride);
d479 1
a479 1
   GLfloat *normal = sc->normals + (start * nstride);
d620 1
a620 1
   GLfloat *normal = sc->normals + (start * nstride);
d686 1
a686 1
   GLfloat *normal = sc->normals + (start * nstride);
d771 1
a771 1
   GLfloat *normal = sc->normals + (start * nstride);
d808 1
a808 1
   GLfloat *normal = sc->normals + (start * nstride);
d873 1
a873 1
   GLfloat *vertex = sc->vertices + (start * vstride);
d875 1
a875 1
   GLfloat *normal = sc->normals + (start * nstride);
@


3.4
log
@added a hack to work around suspected gcc bug
@
text
@d1 1
a1 1
/* $Id: shade.c,v 3.3 1998/04/18 05:00:28 brianp Exp brianp $ */
d5 1
a5 1
 * Version:  3.0
d26 3
d56 4
a59 2
/*
 * Return x^y.
d61 20
a80 8
static GLfloat gl_pow( GLfloat x, GLfloat y )
{
   GLdouble z = pow(x, y);
   if (z<1.0e-10)
      return 0.0F;
   else
      return (GLfloat) z;
}
d84 4
a87 15
/*
 * Use current lighting/material settings to compute the RGBA colors of
 * an array of vertexes.
 * Input:  side - 0=use front material, 1=use back material
 *         n - number of vertexes to process
 *         vertex - array of vertex positions in eye coordinates
 *         normal - array of surface normal vectors
 * Output:  color - array of resulting colors
 */
void gl_shade_rgba( GLcontext *ctx,
                    GLuint side,
                    GLuint n,
                    /*const*/ GLfloat vertex[][4],
                    /*const*/ GLfloat normal[][3],
                    GLubyte color[][4] )
d90 4
a93 2
   GLfloat baseR, baseG, baseB, baseA;
   GLint sumA;
d97 34
a130 25
   mat = &ctx->Light.Material[side];

   /*** Compute color contribution from global lighting ***/
   baseR = mat->Emission[0] + ctx->Light.Model.Ambient[0] * mat->Ambient[0];
   baseG = mat->Emission[1] + ctx->Light.Model.Ambient[1] * mat->Ambient[1];
   baseB = mat->Emission[2] + ctx->Light.Model.Ambient[2] * mat->Ambient[2];
   baseA = mat->Diffuse[3];  /* Alpha is simple, same for all vertices */

   FLOAT_COLOR_TO_UBYTE_COLOR( sumA, baseA );

   for (j=0;j<n;j++) {
      GLfloat sumR, sumG, sumB;
      GLfloat nx, ny, nz;

      if (side==0) {
         /* shade frontside */
         nx = normal[j][0];
         ny = normal[j][1];
         nz = normal[j][2];
      }
      else {
         /* shade backside */
         nx = -normal[j][0];
         ny = -normal[j][1];
         nz = -normal[j][2];
a132 4
      sumR = baseR;
      sumG = baseG;
      sumB = baseB;

d135 7
a141 3
         GLfloat ambientR, ambientG, ambientB;
         GLfloat attenuation, spot;
         GLfloat VPx, VPy, VPz;  /* unit vector from vertex to light */
d143 2
d147 1
a147 1
         if (light->Position[3]==0.0) {
d149 1
a149 4
            VPx = light->VP_inf_norm[0];
            VPy = light->VP_inf_norm[1];
            VPz = light->VP_inf_norm[2];
            attenuation = 1.0F;
a151 1
            /* positional light */
d153 3
a155 5
            VPx = light->Position[0] - vertex[j][0];
            VPy = light->Position[1] - vertex[j][1];
            VPz = light->Position[2] - vertex[j][2];
            d = (GLfloat) GL_SQRT( VPx*VPx + VPy*VPy + VPz*VPz );
            if (d>0.001F) {
d157 6
a162 7
               VPx *= invd;
               VPy *= invd;
               VPz *= invd;
            }
            attenuation = 1.0F / (light->ConstantAttenuation
                        + d * (light->LinearAttenuation
                        + d * light->QuadraticAttenuation));
d165 4
a168 13
         /* spotlight factor */
         if (light->SpotCutoff==180.0F) {
            /* not a spot light */
            spot = 1.0F;
         }
         else {
            GLfloat PVx, PVy, PVz, PV_dot_dir;
            PVx = -VPx;
            PVy = -VPy;
            PVz = -VPz;
            PV_dot_dir = PVx*light->NormDirection[0]
                       + PVy*light->NormDirection[1]
                       + PVz*light->NormDirection[2];
d170 1
a170 2
               /* outside of cone */
               spot = 0.0F;
d175 3
a177 2
               spot = light->SpotExpTable[k][0]
                    + (x-k)*light->SpotExpTable[k][1];
d181 2
a182 3
         ambientR = mat->Ambient[0] * light->Ambient[0];
         ambientG = mat->Ambient[1] * light->Ambient[1];
         ambientB = mat->Ambient[2] * light->Ambient[2];
d185 147
a331 1
         n_dot_VP = nx * VPx + ny * VPy + nz * VPz;
d333 4
a336 8
         /* diffuse and specular terms */
         if (n_dot_VP<=0.0F) {
            /* surface face away from light, no diffuse or specular */
            GLfloat t = attenuation * spot;
            sumR += t * ambientR;
            sumG += t * ambientG;
            sumB += t * ambientB;
            /* done with this light */
d339 19
a357 26
            GLfloat diffuseR, diffuseG, diffuseB;
            GLfloat specularR, specularG, specularB;
            GLfloat h_x, h_y, h_z, n_dot_h, t;
                  
            /* diffuse term */
            diffuseR = n_dot_VP * mat->Diffuse[0] * light->Diffuse[0];
            diffuseG = n_dot_VP * mat->Diffuse[1] * light->Diffuse[1];
            diffuseB = n_dot_VP * mat->Diffuse[2] * light->Diffuse[2];

            /* specular term */
            if (ctx->Light.Model.LocalViewer) {
               GLfloat vx, vy, vz, vlen;
               vx = vertex[j][0];
               vy = vertex[j][1];
               vz = vertex[j][2];
               vlen = GL_SQRT( vx*vx + vy*vy + vz*vz );
               if (vlen>0.0001F) {
                  GLfloat invlen = 1.0F / vlen;
                  vx *= invlen;
                  vy *= invlen;
                  vz *= invlen;
               }
               /* h = VP + VPe */
               h_x = VPx - vx;
               h_y = VPy - vy;
               h_z = VPz - vz;
d360 5
a364 4
               /* h = VP + <0,0,1> */
               h_x = VPx;
               h_y = VPy;
               h_z = VPz + 1.0F;
d366 10
d377 52
a428 39
            /* attention: h is not normalized, done later if needed */
            n_dot_h = nx*h_x + ny*h_y + nz*h_z;

            if (n_dot_h<=0.0F) {
               specularR = 0.0F;
               specularG = 0.0F;
               specularB = 0.0F;
            }
            else {
               GLfloat spec_coef;
               /* now `correct' the dot product */
               n_dot_h = n_dot_h / GL_SQRT( h_x*h_x + h_y*h_y + h_z*h_z );
               if (n_dot_h>1.0F) {
                  /* only happens if normal vector length > 1.0 */
                  spec_coef = pow( n_dot_h, mat->Shininess );
               }
               else {
                  /* use table lookup approximation */
                  int k = (int) (n_dot_h * (GLfloat) (SHINE_TABLE_SIZE-1));
                  if (mat->ShineTable[k] < 0.0F)
                     mat->ShineTable[k] = gl_pow( n_dot_h, mat->Shininess );
                  spec_coef = mat->ShineTable[k];
               }
               if (spec_coef<1.0e-10) {
                  specularR = 0.0F;
                  specularG = 0.0F;
                  specularB = 0.0F;
               }
               else {
                  specularR = spec_coef * mat->Specular[0]*light->Specular[0];
                  specularG = spec_coef * mat->Specular[1]*light->Specular[1];
                  specularB = spec_coef * mat->Specular[2]*light->Specular[2];
               }
            }

            t = attenuation * spot;
            sumR += t * (ambientR + diffuseR + specularR);
            sumG += t * (ambientG + diffuseG + specularG);
            sumB += t * (ambientB + diffuseB + specularB);
d431 2
d436 9
a444 4
      FLOAT_COLOR_TO_UBYTE_COLOR( color[j][0], sumR );
      FLOAT_COLOR_TO_UBYTE_COLOR( color[j][1], sumG );
      FLOAT_COLOR_TO_UBYTE_COLOR( color[j][2], sumB );
      color[j][3] = sumA;
d451 1
d453 2
a454 1
 * Compute separate base and specular colors.
d459 1
a459 2
 * Output:  baseColor - array of base colors (emission, ambient, diffuse)
 *          specColor - array of specular colors
d461 4
a464 6
void gl_shade_rgba_spec( GLcontext *ctx,
                         GLuint side,
                         GLuint n,
                         /*const*/ GLfloat vertex[][4],
                         /*const*/ GLfloat normal[][3],
                         GLubyte baseColor[][4], GLubyte specColor[][4] )
d467 2
a468 2
   GLfloat baseR, baseG, baseB, baseA;
   GLint sumBaseA;
d472 10
a481 6
   mat = &ctx->Light.Material[side];

   /*** Compute color contribution from global lighting ***/
   baseR = mat->Emission[0] + ctx->Light.Model.Ambient[0] * mat->Ambient[0];
   baseG = mat->Emission[1] + ctx->Light.Model.Ambient[1] * mat->Ambient[1];
   baseB = mat->Emission[2] + ctx->Light.Model.Ambient[2] * mat->Ambient[2];
d484 1
a484 1
   FLOAT_COLOR_TO_UBYTE_COLOR( sumBaseA, baseA );
d486 3
a488 22
   for (j=0;j<n;j++) {
      GLfloat sumBaseR, sumBaseG, sumBaseB;
      GLfloat sumSpecR, sumSpecG, sumSpecB;
      GLfloat nx, ny, nz;

      if (side==0) {
         /* shade frontside */
         nx = normal[j][0];
         ny = normal[j][1];
         nz = normal[j][2];
      }
      else {
         /* shade backside */
         nx = -normal[j][0];
         ny = -normal[j][1];
         nz = -normal[j][2];
      }

      sumBaseR = baseR;
      sumBaseG = baseG;
      sumBaseB = baseB;
      sumSpecR = sumSpecG = sumSpecB = 0.0;
d492 3
a494 3
         GLfloat ambientR, ambientG, ambientB;
         GLfloat attenuation, spot;
         GLfloat VPx, VPy, VPz;  /* unit vector from vertex to light */
d498 1
a498 1
         if (light->Position[3]==0.0) {
d500 1
a500 4
            VPx = light->VP_inf_norm[0];
            VPy = light->VP_inf_norm[1];
            VPz = light->VP_inf_norm[2];
            attenuation = 1.0F;
a502 1
            /* positional light */
d504 3
a506 5
            VPx = light->Position[0] - vertex[j][0];
            VPy = light->Position[1] - vertex[j][1];
            VPz = light->Position[2] - vertex[j][2];
            d = (GLfloat) GL_SQRT( VPx*VPx + VPy*VPy + VPz*VPz );
            if (d>0.001F) {
d508 6
a513 7
               VPx *= invd;
               VPy *= invd;
               VPz *= invd;
            }
            attenuation = 1.0F / (light->ConstantAttenuation
                        + d * (light->LinearAttenuation
                        + d * light->QuadraticAttenuation));
d516 4
a519 13
         /* spotlight factor */
         if (light->SpotCutoff==180.0F) {
            /* not a spot light */
            spot = 1.0F;
         }
         else {
            GLfloat PVx, PVy, PVz, PV_dot_dir;
            PVx = -VPx;
            PVy = -VPy;
            PVz = -VPz;
            PV_dot_dir = PVx*light->NormDirection[0]
                       + PVy*light->NormDirection[1]
                       + PVz*light->NormDirection[2];
d521 1
a521 2
               /* outside of cone */
               spot = 0.0F;
d526 3
a528 2
               spot = light->SpotExpTable[k][0]
                    + (x-k)*light->SpotExpTable[k][1];
d532 4
a535 3
         ambientR = mat->Ambient[0] * light->Ambient[0];
         ambientG = mat->Ambient[1] * light->Ambient[1];
         ambientB = mat->Ambient[2] * light->Ambient[2];
d538 1
a538 1
         n_dot_VP = nx * VPx + ny * VPy + nz * VPz;
d541 5
a545 13
         if (n_dot_VP<=0.0F) {
            /* surface face away from light, no diffuse or specular */
            GLfloat t = attenuation * spot;
            sumBaseR += t * ambientR;
            sumBaseG += t * ambientG;
            sumBaseB += t * ambientB;
            /* done with this light */
         }
         else {
            GLfloat diffuseR, diffuseG, diffuseB;
            GLfloat specularR, specularG, specularB;
            GLfloat h_x, h_y, h_z, n_dot_h, t;
                  
d547 1
a547 28
            diffuseR = n_dot_VP * mat->Diffuse[0] * light->Diffuse[0];
            diffuseG = n_dot_VP * mat->Diffuse[1] * light->Diffuse[1];
            diffuseB = n_dot_VP * mat->Diffuse[2] * light->Diffuse[2];

            /* specular term */
            if (ctx->Light.Model.LocalViewer) {
               GLfloat vx, vy, vz, vlen;
               vx = vertex[j][0];
               vy = vertex[j][1];
               vz = vertex[j][2];
               vlen = GL_SQRT( vx*vx + vy*vy + vz*vz );
               if (vlen>0.0001F) {
                  GLfloat invlen = 1.0F / vlen;
                  vx *= invlen;
                  vy *= invlen;
                  vz *= invlen;
               }
               /* h = VP + VPe */
               h_x = VPx - vx;
               h_y = VPy - vy;
               h_z = VPz - vz;
            }
            else {
               /* h = VP + <0,0,1> */
               h_x = VPx;
               h_y = VPy;
               h_z = VPz + 1.0F;
            }
d549 45
a593 42
            /* attention: h is not normalized, done later if needed */
            n_dot_h = nx*h_x + ny*h_y + nz*h_z;

            if (n_dot_h<=0.0F) {
               specularR = 0.0F;
               specularG = 0.0F;
               specularB = 0.0F;
            }
            else {
               GLfloat spec_coef;
               /* now `correct' the dot product */
               n_dot_h = n_dot_h / GL_SQRT( h_x*h_x + h_y*h_y + h_z*h_z );
               if (n_dot_h>1.0F) {
                  /* only happens if normal vector length > 1.0 */
                  spec_coef = pow( n_dot_h, mat->Shininess );
               }
               else {
                  /* use table lookup approximation */
                  int k = (int) (n_dot_h * (GLfloat) (SHINE_TABLE_SIZE-1));
                  if (mat->ShineTable[k] < 0.0F)
                     mat->ShineTable[k] = gl_pow( n_dot_h, mat->Shininess );
                  spec_coef = mat->ShineTable[k];
               }
               if (spec_coef<1.0e-10) {
                  specularR = 0.0F;
                  specularG = 0.0F;
                  specularB = 0.0F;
               }
               else {
                  specularR = spec_coef * mat->Specular[0]*light->Specular[0];
                  specularG = spec_coef * mat->Specular[1]*light->Specular[1];
                  specularB = spec_coef * mat->Specular[2]*light->Specular[2];
               }
            }

            t = attenuation * spot;
            sumBaseR += t * (ambientR + diffuseR);
            sumBaseG += t * (ambientG + diffuseG);
            sumBaseB += t * (ambientB + diffuseB);
            sumSpecR += t * specularR;
            sumSpecG += t * specularG;
            sumSpecB += t * specularB;
d595 1
a595 1

d599 4
a602 9
      FLOAT_COLOR_TO_UBYTE_COLOR( baseColor[j][0], sumBaseR );
      FLOAT_COLOR_TO_UBYTE_COLOR( baseColor[j][1], sumBaseG );
      FLOAT_COLOR_TO_UBYTE_COLOR( baseColor[j][2], sumBaseB );
      baseColor[j][3] = sumBaseA;

      FLOAT_COLOR_TO_UBYTE_COLOR( specColor[j][0], sumSpecR );
      FLOAT_COLOR_TO_UBYTE_COLOR( specColor[j][1], sumSpecG );
      FLOAT_COLOR_TO_UBYTE_COLOR( specColor[j][2], sumSpecB );
      specColor[j][3] = 255;  /* but never used */
d608 146
d756 2
a757 1
 * This is an optimized version of the above function.
d759 4
a762 5
void gl_shade_rgba_fast( GLcontext *ctx,
                         GLuint side,
                         GLuint n,
                         /*const*/ GLfloat normal[][3],
                         GLubyte color[][4] )
a764 2
   GLint sumA;
   GLfloat *baseColor = ctx->Light.BaseColor[side];
d766 9
a774 7
   /* Alpha is easy to compute, same for all vertices */
   sumA = (GLint) (baseColor[3] * 255.0F);

   /* Loop over vertices */
   for (j=0;j<n;j++) {
      GLfloat sumR, sumG, sumB;
      GLfloat nx, ny, nz;
d776 1
d778 5
a782 10
      /* the normal vector */
      if (side==0) {
         nx = normal[j][0];
         ny = normal[j][1];
         nz = normal[j][2];
      }
      else {
         nx = -normal[j][0];
         ny = -normal[j][1];
         nz = -normal[j][2];
d785 10
a794 9
#ifdef SPEED_HACK
      if (nz<0.0F) {
         color[j][0] = 0.0F;
         color[j][1] = 0.0F;
         color[j][2] = 0.0F;
         color[j][3] = A;
         continue;
      }
#endif
d796 6
a801 4
      /* base color from global illumination and enabled light's ambient */
      sumR = baseColor[0];
      sumG = baseColor[1];
      sumB = baseColor[2];
d803 4
a806 3
      /* Add contribution from each light source */
      for (light=ctx->Light.FirstEnabled; light; light=light->NextEnabled) {
         GLfloat n_dot_VP;     /* n dot VP */
d808 2
a809 3
         n_dot_VP = nx * light->VP_inf_norm[0]
                  + ny * light->VP_inf_norm[1]
                  + nz * light->VP_inf_norm[2];
d811 5
a815 40
         /* diffuse and specular terms */
         if (n_dot_VP>0.0F) {
            GLfloat n_dot_h;
            GLfloat *lightMatDiffuse = light->MatDiffuse[side];

            /** add diffuse term **/
            sumR += n_dot_VP * lightMatDiffuse[0];
            sumG += n_dot_VP * lightMatDiffuse[1];
            sumB += n_dot_VP * lightMatDiffuse[2];

            /** specular term **/
            /* dot product of n and h_inf_norm */
            n_dot_h = nx * light->h_inf_norm[0]
                    + ny * light->h_inf_norm[1]
                    + nz * light->h_inf_norm[2];
            if (n_dot_h>0.0F) {
               if (n_dot_h>1.0F) {
                  /* only happens if Magnitude(n) > 1.0 */
                  GLfloat spec_coef = pow( n_dot_h,
                                        ctx->Light.Material[side].Shininess );
                  if (spec_coef>1.0e-10F) {
                     sumR += spec_coef * light->MatSpecular[side][0];
                     sumG += spec_coef * light->MatSpecular[side][1];
                     sumB += spec_coef * light->MatSpecular[side][2];
                  }
               }
               else {
                  /* use table lookup approximation */
                  int k = (int) (n_dot_h * (GLfloat) (SHINE_TABLE_SIZE-1));
                  struct gl_material *m = &ctx->Light.Material[side];
                  GLfloat spec_coef;
                  if (m->ShineTable[k] < 0.0F)
                     m->ShineTable[k] = gl_pow( n_dot_h, m->Shininess );
                  spec_coef = m->ShineTable[k];
                  sumR += spec_coef * light->MatSpecular[side][0];
                  sumG += spec_coef * light->MatSpecular[side][1];
                  sumB += spec_coef * light->MatSpecular[side][2];
               }
            }
         }
d817 2
a818 1
      } /*loop over lights*/
d820 1
a820 10
      /* clamp and convert to integer or fixed point */
      FLOAT_COLOR_TO_UBYTE_COLOR( color[j][0], sumR );
      FLOAT_COLOR_TO_UBYTE_COLOR( color[j][1], sumG );
      FLOAT_COLOR_TO_UBYTE_COLOR( color[j][2], sumB );
      color[j][3] = sumA;

      /* Ugh, I think there's a bug in gcc 2.7.2.3.  If the following
       * no-op code isn't here then the results of the above
       * FLOAT_COLOR_TO_UBYTE_COLOR() macro are unpredictable!
       */
d822 9
a830 1
         GLubyte r0 = FloatToInt(CLAMP(sumR, 0, 1) * 255.0);
d833 13
a845 1
   } /*loop over vertices*/
d859 4
a862 6
void gl_shade_ci( GLcontext *ctx,
                  GLuint side,
                  GLuint n,
                  GLfloat vertex[][4],
                  GLfloat normal[][3],
                  GLuint indexResult[] )
d864 1
a864 1
   struct gl_material *mat = &ctx->Light.Material[side];
d867 10
d878 3
a880 4
   for (j=0;j<n;j++) {
      GLfloat index;
      GLfloat diffuse, specular;  /* accumulated diffuse and specular */
      GLfloat nx, ny, nz;  /* normal vector */
d883 2
a884 14
      if (side==0) {
         /* shade frontside */
         nx = normal[j][0];
         ny = normal[j][1];
         nz = normal[j][2];
      }
      else {
         /* shade backside */
         nx = -normal[j][0];
         ny = -normal[j][1];
         nz = -normal[j][2];
      }

      diffuse = specular = 0.0F;
d888 5
a892 3
         GLfloat attenuation;
         GLfloat lx, ly, lz;  /* unit vector from vertex to light */
         GLfloat l_dot_norm;  /* dot product of l and n */
d895 1
a895 1
         if (light->Position[3]==0.0) {
d897 1
a897 5
            /* Effectively, l is a vector from the origin to the light. */
            lx = light->VP_inf_norm[0];
            ly = light->VP_inf_norm[1];
            lz = light->VP_inf_norm[2];
            attenuation = 1.0F;
a899 1
            /* positional light */
d901 2
a902 5
            lx = light->Position[0] - vertex[j][0];
            ly = light->Position[1] - vertex[j][1];
            lz = light->Position[2] - vertex[j][2];
            d = (GLfloat) GL_SQRT( lx*lx + ly*ly + lz*lz );
            if (d>0.001F) {
d904 1
a904 3
               lx *= invd;
               ly *= invd;
               lz *= invd;
d906 4
a909 3
            attenuation = 1.0F / (light->ConstantAttenuation
                        + d * (light->LinearAttenuation
                        + d * light->QuadraticAttenuation));
d912 6
a917 9
         l_dot_norm = lx*nx + ly*ny + lz*nz;

         if (l_dot_norm>0.0F) {
            GLfloat spot_times_atten;

            /* spotlight factor */
            if (light->SpotCutoff==180.0F) {
               /* not a spot light */
               spot_times_atten = attenuation;
d920 5
a924 67
               GLfloat v[3], dot;
               v[0] = -lx;  /* v points from light to vertex */
               v[1] = -ly;
               v[2] = -lz;
               dot = DOT3( v, light->NormDirection );
               if (dot<=0.0F || dot<light->CosCutoff) {
                  /* outside of cone */
                  spot_times_atten = 0.0F;
               }
               else {
                  double x = dot * (EXP_TABLE_SIZE-1);
                  int k = (int) x;
                  GLfloat spot = light->SpotExpTable[k][0]
                               + (x-k)*light->SpotExpTable[k][1];
                  spot_times_atten = spot * attenuation;
               }
            }

            /* accumulate diffuse term */
            diffuse += l_dot_norm * light->dli * spot_times_atten;

            /* accumulate specular term */
            {
               GLfloat h_x, h_y, h_z, n_dot_h, spec_coef;

               /* specular term */
               if (ctx->Light.Model.LocalViewer) {
                  GLfloat vx, vy, vz, vlen;
                  vx = vertex[j][0];
                  vy = vertex[j][1];
                  vz = vertex[j][2];
                  vlen = GL_SQRT( vx*vx + vy*vy + vz*vz );
                  if (vlen>0.0001F) {
                     GLfloat invlen = 1.0F / vlen;
                     vx *= invlen;
                     vy *= invlen;
                     vz *= invlen;
                  }
                  h_x = lx - vx;
                  h_y = ly - vy;
                  h_z = lz - vz;
               }
               else {
                  h_x = lx;
                  h_y = ly;
                  h_z = lz + 1.0F;
               }
               /* attention: s is not normalized, done later if necessary */
               n_dot_h = h_x*nx + h_y*ny + h_z*nz;

               if (n_dot_h <= 0.0F) {
                  spec_coef = 0.0F;
               }
               else {
                  /* now `correct' the dot product */
                  n_dot_h = n_dot_h / GL_SQRT(h_x*h_x + h_y*h_y + h_z*h_z);
                  if (n_dot_h>1.0F) {
                     spec_coef = pow( n_dot_h, mat->Shininess );
                  }
                  else {
                     int k = (int) (n_dot_h * (GLfloat)(SHINE_TABLE_SIZE-1));
                     if (mat->ShineTable[k] < 0.0F)
                        mat->ShineTable[k] = gl_pow( n_dot_h, mat->Shininess );
                     spec_coef = mat->ShineTable[k];
                  }
               }
               specular += spec_coef * light->sli * spot_times_atten;
d928 59
d990 24
a1013 2
      if (specular>1.0F) {
         index = mat->SpecularIndex;
d1015 25
a1039 11
      else {
         GLfloat d_a, s_a;
         d_a = mat->DiffuseIndex - mat->AmbientIndex;
         s_a = mat->SpecularIndex - mat->AmbientIndex;

         index = mat->AmbientIndex
               + diffuse * (1.0F-specular) * d_a
               + specular * s_a;
         if (index>mat->SpecularIndex) {
            index = mat->SpecularIndex;
         }
d1041 14
a1054 1
      indexResult[j] = (GLuint) (GLint) index;
a1055 2
   } /*for vertex*/
}
@


3.3
log
@now using FLOAT_COLOR_TO_UBYTE_COLOR macro
@
text
@d1 1
a1 1
/* $Id: shade.c,v 3.2 1998/03/27 04:17:31 brianp Exp brianp $ */
d26 3
d614 8
@


3.2
log
@fixed G++ warnings
@
text
@d1 1
a1 1
/* $Id: shade.c,v 3.1 1998/02/02 03:09:34 brianp Exp brianp $ */
d26 3
d94 1
a94 1
   sumA = (GLint) (CLAMP( baseA, 0.0F, 1.0F ) * 255.0F);
d270 3
a272 3
      color[j][0] = FloatToInt(CLAMP( sumR, 0.0F, 1.0F ) * 255.0F);
      color[j][1] = FloatToInt(CLAMP( sumG, 0.0F, 1.0F ) * 255.0F);
      color[j][2] = FloatToInt(CLAMP( sumB, 0.0F, 1.0F ) * 255.0F);
d310 1
a310 1
   sumBaseA = (GLint) (CLAMP( baseA, 0.0F, 1.0F ) * 255.0F);
d491 3
a493 3
      baseColor[j][0] = FloatToInt(CLAMP( sumBaseR, 0.0F, 1.0F ) * 255.0F);
      baseColor[j][1] = FloatToInt(CLAMP( sumBaseG, 0.0F, 1.0F ) * 255.0F);
      baseColor[j][2] = FloatToInt(CLAMP( sumBaseB, 0.0F, 1.0F ) * 255.0F);
d496 3
a498 3
      specColor[j][0] = FloatToInt(CLAMP( sumSpecR, 0.0F, 1.0F ) * 255.0F);
      specColor[j][1] = FloatToInt(CLAMP( sumSpecG, 0.0F, 1.0F ) * 255.0F);
      specColor[j][2] = FloatToInt(CLAMP( sumSpecB, 0.0F, 1.0F ) * 255.0F);
d607 3
a609 3
      color[j][0] = FloatToInt(MIN2( sumR, 1.0F ) * 255.0F);
      color[j][1] = FloatToInt(MIN2( sumG, 1.0F ) * 255.0F);
      color[j][2] = FloatToInt(MIN2( sumB, 1.0F ) * 255.0F);
@


3.1
log
@added GL_LIGHT_MODEL_COLOR_CONTROL (separate specular color interpolation)
@
text
@d1 1
a1 1
/* $Id: shade.c,v 3.0 1998/01/31 21:03:42 brianp Exp brianp $ */
d26 3
d77 1
a77 1
   GLint j;
d293 1
a293 1
   GLint j;
d512 1
a512 1
   GLint j;
d631 1
a631 1
   GLint j;
@


3.0
log
@initial rev
@
text
@d1 1
a1 1
/* $Id$ */
d25 4
a28 1
 * $Log$
d67 6
a72 6
void gl_color_shade_vertices( GLcontext *ctx,
                              GLuint side,
                              GLuint n,
                              /*const*/ GLfloat vertex[][4],
                              /*const*/ GLfloat normal[][3],
                              GLubyte color[][4] )
d275 226
d503 5
a507 5
void gl_color_shade_vertices_fast( GLcontext *ctx,
                                   GLuint side,
                                   GLuint n,
                                   /*const*/ GLfloat normal[][3],
                                   GLubyte color[][4] )
d620 6
a625 6
void gl_index_shade_vertices( GLcontext *ctx,
                              GLuint side,
                              GLuint n,
                              GLfloat vertex[][4],
                              GLfloat normal[][3],
                              GLuint indexResult[] )
@
