mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3956 lines
133 KiB
3956 lines
133 KiB
/******************************Module*Header*******************************\
|
|
* Module Name: so_phong.c
|
|
*
|
|
* Routines to draw primitives
|
|
*
|
|
* Created: 10-16-1995
|
|
* Author: Hock San Lee [hockl]
|
|
*
|
|
* Copyright (c) 1995 Microsoft Corporation
|
|
\**************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
#include <fixed.h>
|
|
#include <glmath.h>
|
|
|
|
#ifdef GL_WIN_phong_shading
|
|
|
|
#ifdef _X86_
|
|
#include <gli386.h>
|
|
#endif
|
|
|
|
#define __FASTEST
|
|
|
|
// Macros
|
|
#define DOT(m,a,b) m = (a)->x*(b)->x + (a)->y*(b)->y + (a)->z*(b)->z
|
|
#define MAGN2(m,v) DOT(m,v,v)
|
|
|
|
#if _X86_
|
|
|
|
#define SHADER __GLcontext.polygon.shader
|
|
|
|
#define GET_HALF_AREA(gc, a, b, c)\
|
|
\
|
|
__asm{ mov eax, a };\
|
|
__asm{ mov ecx, c };\
|
|
__asm{ mov ebx, b };\
|
|
__asm{ mov edx, gc };\
|
|
__asm{ fld DWORD PTR [OFFSET(__GLvertex.window.x)][eax] };\
|
|
__asm{ fsub DWORD PTR [OFFSET(__GLvertex.window.x)][ecx] /* dxAC */ };\
|
|
__asm{ fld DWORD PTR [OFFSET(__GLvertex.window.y)][ebx] };\
|
|
__asm{ fsub DWORD PTR [OFFSET(__GLvertex.window.y)][ecx] /* dyBC dxAC */ };\
|
|
__asm{ fld DWORD PTR [OFFSET(__GLvertex.window.x)][ebx] };\
|
|
__asm{ fsub DWORD PTR [OFFSET(__GLvertex.window.x)][ecx] /* dxBC dyBC dxAC */ };\
|
|
__asm{ fld DWORD PTR [OFFSET(__GLvertex.window.y)][eax] };\
|
|
__asm{ fsub DWORD PTR [OFFSET(__GLvertex.window.y)][ecx] /* dyAC dxBC dyBC dxAC */ };\
|
|
__asm{ fxch ST(2) /* dyBC dxBC dyAC dxAC */ };\
|
|
__asm{ fst DWORD PTR [OFFSET(SHADER.dyBC)][edx] };\
|
|
__asm{ fmul ST, ST(3) /* dxACdyBC dxBC dyAC dxAC */ };\
|
|
__asm{ fxch ST(2) /* dyAC dxBC dxACdyBC dxAC */ };\
|
|
__asm{ fst DWORD PTR [OFFSET(SHADER.dyAC)][edx] };\
|
|
__asm{ fmul ST, ST(1) /* dxBCdyAC dxBC dxACdyBC dxAC */};\
|
|
__asm{ fxch ST(1) /* dxBC dxBCdyAC dxACdyBC dxAC */};\
|
|
__asm{ fstp DWORD PTR [OFFSET(SHADER.dxBC)][edx] /* dxBCdyAC dxACdyBC dxAC */ };\
|
|
__asm{ fsubp ST(1), ST /* +1*/ /* area dxAC */ };\
|
|
__asm{ fxch ST(1) /* dxAC area */ };\
|
|
__asm{ fstp DWORD PTR [OFFSET(SHADER.dxAC)][edx] /* area */ };\
|
|
__asm{ fstp DWORD PTR [OFFSET(SHADER.area)][edx] /* +1*/ /* (empty) */ };
|
|
|
|
#define STORE_AREA_PARAMS
|
|
|
|
#else
|
|
|
|
#define GET_HALF_AREA(gc, a, b, c)\
|
|
/* Compute signed half-area of the triangle */ \
|
|
dxAC = a->window.x - c->window.x; \
|
|
dxBC = b->window.x - c->window.x; \
|
|
dyAC = a->window.y - c->window.y; \
|
|
dyBC = b->window.y - c->window.y; \
|
|
gc->polygon.shader.area = dxAC * dyBC - dxBC * dyAC;
|
|
|
|
#define STORE_AREA_PARAMS\
|
|
gc->polygon.shader.dxAC = dxAC; \
|
|
gc->polygon.shader.dxBC = dxBC; \
|
|
gc->polygon.shader.dyAC = dyAC; \
|
|
gc->polygon.shader.dyBC = dyBC;
|
|
|
|
#endif
|
|
|
|
|
|
#if 0
|
|
#define ACCUM_MAT_CHANGE(dst,src) \
|
|
if ((src)->dirtyBits & __GL_MATERIAL_AMBIENT) \
|
|
(dst).ambient = (src)->ambient; \
|
|
if ((src)->dirtyBits & __GL_MATERIAL_DIFFUSE) \
|
|
(dst).diffuse = (src)->diffuse; \
|
|
if ((src)->dirtyBits & __GL_MATERIAL_SPECULAR) \
|
|
(dst).specular = (src)->specular; \
|
|
if ((src)->dirtyBits & __GL_MATERIAL_EMISSIVE) \
|
|
(dst).emissive = (src)->emissive; \
|
|
if ((src)->dirtyBits & __GL_MATERIAL_SHININESS) \
|
|
(dst).shininess = (src)->shininess; \
|
|
if ((src)->dirtyBits & __GL_MATERIAL_COLORINDEXES) \
|
|
{ \
|
|
(dst).cmapa = (src)->cmapa; \
|
|
(dst).cmapd = (src)->cmapd; \
|
|
(dst).cmaps = (src)->cmaps; \
|
|
} \
|
|
(dst).dirtyBits |= (src)->dirtyBits;
|
|
#endif
|
|
|
|
#define SORT_AND_CULL_FACE(a, b, c, face, ccw)\
|
|
\
|
|
/* \
|
|
** Sort vertices in y. Keep track if a reversal of the winding \
|
|
** occurs in direction (0 means no reversal, 1 means reversal). \
|
|
** Save old vertex pointers in case we end up not doing a fill. \
|
|
*/ \
|
|
reversed = 0; \
|
|
if (__GL_VERTEX_COMPARE(a->window.y, <, b->window.y)) { \
|
|
if (__GL_VERTEX_COMPARE(b->window.y, <, c->window.y)) { \
|
|
/* Already sorted */ \
|
|
} else { \
|
|
if (__GL_VERTEX_COMPARE(a->window.y, <, c->window.y)) { \
|
|
temp=b; b=c; c=temp; \
|
|
reversed = 1; \
|
|
} else { \
|
|
temp=a; a=c; c=b; b=temp; \
|
|
} \
|
|
} \
|
|
} else { \
|
|
if (__GL_VERTEX_COMPARE(b->window.y, <, c->window.y)) { \
|
|
if (__GL_VERTEX_COMPARE(a->window.y, <, c->window.y)) { \
|
|
temp=a; a=b; b=temp; \
|
|
reversed = 1; \
|
|
} else { \
|
|
temp=a; a=b; b=c; c=temp; \
|
|
} \
|
|
} else { \
|
|
temp=a; a=c; c=temp; \
|
|
reversed = 1; \
|
|
} \
|
|
} \
|
|
\
|
|
GET_HALF_AREA(gc, a, b, c); \
|
|
ccw = !__GL_FLOAT_LTZ(gc->polygon.shader.area); \
|
|
\
|
|
/* \
|
|
** Figure out if face is culled or not. The face check needs to be \
|
|
** based on the vertex winding before sorting. This code uses the \
|
|
** reversed flag to invert the sense of ccw - an xor accomplishes \
|
|
** this conversion without an if test. \
|
|
** \
|
|
** ccw reversed xor \
|
|
** --- -------- --- \
|
|
** 0 0 0 (remain !ccw) \
|
|
** 1 0 1 (remain ccw) \
|
|
** 0 1 1 (become ccw) \
|
|
** 1 1 0 (become cw) \
|
|
*/ \
|
|
face = gc->polygon.face[ccw ^ reversed]; \
|
|
if (face == gc->polygon.cullFace) { \
|
|
/* Culled */ \
|
|
return; \
|
|
} \
|
|
\
|
|
STORE_AREA_PARAMS;
|
|
|
|
|
|
//*************** Local functions *******************
|
|
void SnapXLeft(__GLcontext *gc, __GLfloat xLeft, __GLfloat dxdyLeft);
|
|
void SnapXRight(__GLshade *sh, __GLfloat xRight, __GLfloat dxdyRight);
|
|
|
|
void InitLineParamsVan (__GLcontext *gc, __GLvertex *v0, __GLvertex *v1,
|
|
__GLfloat invDelta);
|
|
void InitLineParamsAccel (__GLcontext *gc, __GLvertex *v0, __GLvertex *v1,
|
|
__GLfloat invDelta);
|
|
|
|
static void SetInitialPhongParameters(__GLcontext *gc, __GLvertex *a,
|
|
__GLcoord *an, __GLcolor *ac,
|
|
__GLfloat aFog,
|
|
__GLfloat dx, __GLfloat dy);
|
|
|
|
void FASTCALL FillPhongSubTriangle(__GLcontext *gc, GLint iyBottom,
|
|
GLint iyTop);
|
|
|
|
void InitSpanInterpolationAccel (__GLcontext *gc);
|
|
void InitSpanNEInterpolationVan (__GLcontext *gc);
|
|
void InitSpanNInterpolationVan (__GLcontext *gc);
|
|
|
|
void UpdateParamsAlongSpanAccel (__GLcontext *gc);
|
|
void UpdateNAlongSpanVan (__GLcontext *gc);
|
|
void UpdateNEAlongSpanVan (__GLcontext *gc);
|
|
|
|
void ComputeRGBColorVanZippy (__GLcontext *gc, __GLcolor *outColor);
|
|
void ComputeRGBColorVanFast (__GLcontext *gc, __GLcolor *outColor);
|
|
void ComputeRGBColorVanSlow (__GLcontext *gc, __GLcolor *outColor);
|
|
|
|
void ComputeRGBColorAccelZippy (__GLcontext *gc, __GLcolor *outColor);
|
|
void ComputeRGBColorAccelFast (__GLcontext *gc, __GLcolor *outColor);
|
|
// Not implemented yet. This is to accelerate Slow Lights
|
|
void ComputeRGBColorAccelSlow (__GLcontext *gc, __GLcolor *outColor);
|
|
|
|
|
|
// No Zippy versions for CI color
|
|
// since there is no Color material for CI
|
|
void ComputeCIColorVanFast (__GLcontext *gc, __GLcolor *outColor);
|
|
void ComputeCIColorVanSlow (__GLcontext *gc, __GLcolor *outColor);
|
|
|
|
void ComputeCIColorAccelFast (__GLcontext *gc, __GLcolor *outColor);
|
|
|
|
void ComputePhongInvarientRGBColor (__GLcontext *gc);
|
|
|
|
void __glCalcForwardDifferences( GLint w, __GLfloat p0, __GLfloat p1,
|
|
__GLfloat p2, __GLfloat *d1, __GLfloat *d2 );
|
|
#ifdef GL_WIN_specular_fog
|
|
__GLfloat ComputeSpecValue (__GLcontext *gc, __GLvertex *vx);
|
|
#endif //GL_WIN_specular_fog
|
|
|
|
/********************* Code **************************************/
|
|
#ifdef GL_WIN_specular_fog
|
|
__GLfloat ComputeSpecValue (__GLcontext *gc, __GLvertex *vx)
|
|
{
|
|
__GLfloat nxi, nyi, nzi;
|
|
__GLfloat zero;
|
|
__GLlightSourcePerMaterialMachine *lspmm;
|
|
__GLlightSourceMachine *lsm;
|
|
__GLlightSourceState *lss;
|
|
__GLmaterialMachine *msm;
|
|
GLboolean eyeWIsZero, localViewer;
|
|
static __GLcoord Pe = { 0, 0, 0, 1 };
|
|
__GLcoord n, e;
|
|
__GLfloat fog = 0;
|
|
__GLfloat msm_threshold, msm_scale, *msm_specTable;
|
|
|
|
zero = __glZero;
|
|
|
|
n = vx->normal;
|
|
e.x = vx->eyeX;
|
|
e.y = vx->eyeY;
|
|
e.z = vx->eyeZ;
|
|
e.w = vx->eyeW;
|
|
|
|
if (gc->state.enables.general & __GL_NORMALIZE_ENABLE)
|
|
__glNormalize(&n.x, &n.x);
|
|
|
|
msm = &gc->light.front;
|
|
nxi = n.x;
|
|
nyi = n.y;
|
|
nzi = n.z;
|
|
|
|
msm_scale = msm->scale;
|
|
msm_threshold = msm->threshold;
|
|
msm_specTable = msm->specTable;
|
|
|
|
localViewer = gc->state.light.model.localViewer;
|
|
|
|
eyeWIsZero = __GL_FLOAT_EQZ(vx->eyeW);
|
|
|
|
for (lsm = gc->light.sources; lsm; lsm = lsm->next)
|
|
{
|
|
__GLfloat n1, n2;
|
|
|
|
lss = lsm->state;
|
|
lspmm = &lsm->front;
|
|
|
|
if (lsm->slowPath || eyeWIsZero)
|
|
{
|
|
__GLcoord hHat, vPli, vPliHat, vPeHat;
|
|
__GLfloat att, attSpot;
|
|
__GLfloat hv[3];
|
|
|
|
/* Compute unit h[i] */
|
|
__glVecSub4(&vPli, &e, &lsm->position);
|
|
__glNormalize(&vPliHat.x, &vPli.x);
|
|
if (localViewer)
|
|
{
|
|
__glVecSub4(&vPeHat, &e, &Pe);
|
|
__glNormalize(&vPeHat.x, &vPeHat.x);
|
|
hv[0] = vPliHat.x + vPeHat.x;
|
|
hv[1] = vPliHat.y + vPeHat.y;
|
|
hv[2] = vPliHat.z + vPeHat.z;
|
|
}
|
|
else
|
|
{
|
|
hv[0] = vPliHat.x;
|
|
hv[1] = vPliHat.y;
|
|
hv[2] = vPliHat.z + __glOne;
|
|
}
|
|
__glNormalize(&hHat.x, hv);
|
|
|
|
/* Compute attenuation */
|
|
if (__GL_FLOAT_NEZ(lsm->position.w))
|
|
{
|
|
__GLfloat k0, k1, k2, dist;
|
|
|
|
k0 = lsm->constantAttenuation;
|
|
k1 = lsm->linearAttenuation;
|
|
k2 = lsm->quadraticAttenuation;
|
|
if (__GL_FLOAT_EQZ(k1) && __GL_FLOAT_EQZ(k2))
|
|
{
|
|
/* Use pre-computed 1/k0 */
|
|
att = lsm->attenuation;
|
|
}
|
|
else
|
|
{
|
|
__GLfloat den;
|
|
|
|
dist = __GL_SQRTF(vPli.x*vPli.x + vPli.y*vPli.y
|
|
+ vPli.z*vPli.z);
|
|
den = k0 + k1 * dist + k2 * dist * dist;
|
|
att = __GL_FLOAT_EQZ(den) ? __glOne : __glOne / den;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
att = __glOne;
|
|
}
|
|
|
|
/* Compute spot effect if light is a spot light */
|
|
attSpot = att;
|
|
if (lsm->isSpot)
|
|
{
|
|
__GLfloat dot, px, py, pz;
|
|
|
|
px = -vPliHat.x;
|
|
py = -vPliHat.y;
|
|
pz = -vPliHat.z;
|
|
dot = px * lsm->direction.x + py * lsm->direction.y
|
|
+ pz * lsm->direction.z;
|
|
if ((dot >= lsm->threshold) && (dot >= lsm->cosCutOffAngle))
|
|
{
|
|
GLint ix = (GLint)((dot - lsm->threshold) * lsm->scale
|
|
+ __glHalf);
|
|
if (ix < __GL_SPOT_LOOKUP_TABLE_SIZE)
|
|
attSpot = att * lsm->spotTable[ix];
|
|
}
|
|
else
|
|
{
|
|
attSpot = zero;
|
|
}
|
|
}
|
|
|
|
/* Add in remaining effect of light, if any */
|
|
if (attSpot)
|
|
{
|
|
__GLfloat n1, n2;
|
|
__GLcolor sum;
|
|
|
|
n1 = nxi * vPliHat.x + nyi * vPliHat.y + nzi * vPliHat.z;
|
|
if (__GL_FLOAT_GTZ(n1))
|
|
{
|
|
n2 = nxi * hHat.x + nyi * hHat.y + nzi * hHat.z;
|
|
n2 -= msm_threshold;
|
|
if (__GL_FLOAT_GEZ(n2))
|
|
{
|
|
__GLfloat fx = n2 * msm_scale + __glHalf;
|
|
if( fx < (__GLfloat)__GL_SPEC_LOOKUP_TABLE_SIZE )
|
|
n2 = msm_specTable[(GLint)fx];
|
|
else
|
|
n2 = __glOne;
|
|
fog += n2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
__GLfloat n1, n2;
|
|
|
|
/* Add in specular and diffuse effect of light, if any */
|
|
n1 = nxi * lsm->unitVPpli.x + nyi * lsm->unitVPpli.y +
|
|
nzi * lsm->unitVPpli.z;
|
|
if (__GL_FLOAT_GTZ(n1))
|
|
{
|
|
n2= nxi * lsm->hHat.x + nyi * lsm->hHat.y + nzi * lsm->hHat.z;
|
|
n2 -= msm_threshold;
|
|
if (__GL_FLOAT_GEZ(n2))
|
|
{
|
|
__GLfloat fx = n2 * msm_scale + __glHalf;
|
|
if( fx < (__GLfloat)__GL_SPEC_LOOKUP_TABLE_SIZE )
|
|
n2 = msm_specTable[(GLint)fx];
|
|
else
|
|
n2 = __glOne;
|
|
fog += n2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fog = 1.0 - fog;
|
|
if (__GL_FLOAT_LTZ (fog)) fog = __glZero;
|
|
return fog;
|
|
}
|
|
#endif //GL_WIN_specular_fog
|
|
|
|
static void AccumMatChange (__GLmatChange *dst, __GLmatChange *src)
|
|
{
|
|
if (src->dirtyBits & __GL_MATERIAL_AMBIENT)
|
|
dst->ambient = src->ambient;
|
|
|
|
if (src->dirtyBits & __GL_MATERIAL_DIFFUSE)
|
|
dst->diffuse = src->diffuse;
|
|
if (src->dirtyBits & __GL_MATERIAL_SPECULAR)
|
|
dst->specular = src->specular;
|
|
if (src->dirtyBits & __GL_MATERIAL_EMISSIVE)
|
|
dst->emissive = src->emissive;
|
|
if (src->dirtyBits & __GL_MATERIAL_SHININESS)
|
|
dst->shininess = src->shininess;
|
|
if (src->dirtyBits & __GL_MATERIAL_COLORINDEXES)
|
|
{
|
|
dst->cmapa = src->cmapa;
|
|
dst->cmapd = src->cmapd;
|
|
dst->cmaps = src->cmaps;
|
|
}
|
|
dst->dirtyBits |= src->dirtyBits;
|
|
}
|
|
|
|
// Propagate the valid Normals through the vertex buffer.
|
|
//
|
|
// IN: color, normal (front)
|
|
// OUT: color, normal (front) (all vertices are updated)
|
|
|
|
void FASTCALL PolyArrayPhongPropagateColorNormal(__GLcontext *gc,
|
|
POLYARRAY *pa)
|
|
{
|
|
POLYDATA *pd;
|
|
POLYDATA *pdLast;
|
|
GLuint paNeeds;
|
|
GLboolean doFrontColor, doBackColor;
|
|
POLYMATERIAL *pm;
|
|
__GLphongMaterialData *pmdata = NULL;
|
|
|
|
|
|
paNeeds = gc->vertex.paNeeds;
|
|
doFrontColor = paNeeds & PANEEDS_FRONT_COLOR;
|
|
doBackColor = paNeeds & PANEEDS_BACK_COLOR;
|
|
|
|
if (gc->polygon.shader.phong.flags & __GL_PHONG_NEED_EYE_XPOLATE)
|
|
ASSERTOPENGL(pa->flags & POLYARRAY_EYE_PROCESSED,
|
|
"Eye coordinate should be available now\n");
|
|
|
|
// If color is not needed, fill in the colors field
|
|
// with default.
|
|
|
|
if (paNeeds & PANEEDS_SKIP_LIGHTING)
|
|
{
|
|
/////?????????!!!!!!!!!!! Look again!!!
|
|
if (doFrontColor) (*gc->procs.paCalcColorSkip)(gc, pa, 0);
|
|
if (doBackColor) (*gc->procs.paCalcColorSkip)(gc, pa, 1);
|
|
return ;
|
|
}
|
|
|
|
|
|
pdLast = pa->pdNextVertex-1;
|
|
|
|
// Check is there are any glMaterial calls that were made
|
|
// immediately after glBegin, the ones made after the first
|
|
// glVertex call are ignored.
|
|
|
|
if (pa->flags & (POLYARRAY_MATERIAL_BACK | POLYARRAY_MATERIAL_BACK))
|
|
{
|
|
pm = GLTEB_CLTPOLYMATERIAL();
|
|
|
|
//DbgPrint ("Has the costly material change\n");
|
|
pmdata = (__GLphongMaterialData *)
|
|
GCALLOC(gc, sizeof(__GLphongMaterialData));
|
|
if (pmdata == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
pmdata->flags = 0;
|
|
pmdata->matChange[__GL_PHONG_FRONT_FIRST].dirtyBits = 0;
|
|
pmdata->matChange[__GL_PHONG_BACK_FIRST].dirtyBits = 0;
|
|
pmdata->matChange[__GL_PHONG_FRONT_TRAIL].dirtyBits = 0;
|
|
pmdata->matChange[__GL_PHONG_BACK_TRAIL].dirtyBits = 0;
|
|
|
|
if (pa->pd0->flags & POLYARRAY_MATERIAL_BACK)
|
|
{
|
|
AccumMatChange (&(pmdata->matChange[__GL_PHONG_BACK_FIRST]),
|
|
*(&pm->pdMaterial0[pa->pd0 - pa->pdBuffer0].front
|
|
+1));
|
|
pmdata->flags |= __GL_PHONG_BACK_FIRST_VALID;
|
|
}
|
|
|
|
if (pa->pd0->flags & POLYARRAY_MATERIAL_FRONT)
|
|
{
|
|
AccumMatChange (&(pmdata->matChange[__GL_PHONG_FRONT_FIRST]),
|
|
*(&pm->pdMaterial0[pa->pd0 - pa->pdBuffer0].front));
|
|
pmdata->flags |= __GL_PHONG_FRONT_FIRST_VALID;
|
|
}
|
|
|
|
// Accumulate the remaining material changes to be applied later
|
|
for (pd = pa->pd0 + 1; pd <= pdLast; pd++)
|
|
{
|
|
if (pd->flags & POLYARRAY_MATERIAL_BACK)
|
|
{
|
|
AccumMatChange (&(pmdata->matChange[__GL_PHONG_BACK_TRAIL]),
|
|
*(&pm->pdMaterial0[pd - pa->pdBuffer0].front+1));
|
|
pmdata->flags |= __GL_PHONG_BACK_TRAIL_VALID;
|
|
}
|
|
|
|
if (pd->flags & POLYARRAY_MATERIAL_FRONT)
|
|
{
|
|
AccumMatChange (&(pmdata->matChange[__GL_PHONG_FRONT_TRAIL]),
|
|
*(&pm->pdMaterial0[pd - pa->pdBuffer0].front));
|
|
pmdata->flags |= __GL_PHONG_FRONT_TRAIL_VALID;
|
|
}
|
|
|
|
}
|
|
pa->phong = pmdata;
|
|
pa->flags |= POLYARRAY_PHONG_DATA_VALID;
|
|
}
|
|
|
|
|
|
for (pd = pa->pd0; pd <= pdLast; pd++)
|
|
{
|
|
if (gc->state.enables.general & __GL_COLOR_MATERIAL_ENABLE)
|
|
{
|
|
if (!(pd->flags & POLYDATA_COLOR_VALID))
|
|
{
|
|
// If color has not changed for this vertex,
|
|
// use the previously computed color.
|
|
|
|
ASSERTOPENGL(pd != pa->pd0, "no initial color\n");
|
|
if (gc->modes.colorIndexMode)
|
|
{
|
|
pd->colors[0].r = (pd-1)->colors[0].r;
|
|
}
|
|
else
|
|
{
|
|
pd->colors[0].r = (pd-1)->colors[0].r;
|
|
pd->colors[0].g = (pd-1)->colors[0].g;
|
|
pd->colors[0].b = (pd-1)->colors[0].b;
|
|
pd->colors[0].a = (pd-1)->colors[0].a;
|
|
}
|
|
pd->flags |= POLYDATA_COLOR_VALID;
|
|
}
|
|
else if (pa->flags & POLYARRAY_CLAMP_COLOR)
|
|
{
|
|
if (gc->modes.colorIndexMode)
|
|
{
|
|
__GL_CLAMP_CI(pd->colors[0].r, gc, pd->colors[0].r);
|
|
}
|
|
else
|
|
{
|
|
__GL_CLAMP_R(pd->colors[0].r, gc, pd->colors[0].r);
|
|
__GL_CLAMP_G(pd->colors[0].g, gc, pd->colors[0].g);
|
|
__GL_CLAMP_B(pd->colors[0].b, gc, pd->colors[0].b);
|
|
__GL_CLAMP_A(pd->colors[0].a, gc, pd->colors[0].a);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!(pd->flags & POLYDATA_NORMAL_VALID))
|
|
{
|
|
// If the normal has not changed for this vertex,
|
|
// use the previously computed normal.
|
|
ASSERTOPENGL(pd != pa->pd0, "no initial normal\n");
|
|
pd->normal = (pd-1)->normal;
|
|
pd->flags |= POLYDATA_NORMAL_VALID;
|
|
}
|
|
else
|
|
{
|
|
if (gc->vertex.paNeeds & PANEEDS_NORMAL)
|
|
{
|
|
(*gc->mInv->xf3)(&pd->normal, &pd->normal.x, gc->mInv);
|
|
if (gc->state.enables.general & __GL_NORMALIZE_ENABLE)
|
|
__glNormalize(&pd->normal.x, &pd->normal.x);
|
|
}
|
|
}
|
|
}
|
|
|
|
gc->vertex.paNeeds &= ~PANEEDS_NORMAL;
|
|
pa->flags &= ~POLYARRAY_MATERIAL_FRONT;
|
|
pa->flags &= ~POLYARRAY_MATERIAL_BACK;
|
|
pa->flags &= ~POLYARRAY_SAME_COLOR_DATA;
|
|
|
|
}
|
|
|
|
|
|
void FASTCALL
|
|
__glRenderPhongTriangle(__GLcontext *gc, __GLvertex *a,
|
|
__GLvertex *b, __GLvertex *c)
|
|
{
|
|
GLuint needs, modeFlags;
|
|
GLint ccw, colorFace, reversed, face;
|
|
__GLfloat dxAC, dxBC, dyAC, dyBC;
|
|
__GLvertex *temp;
|
|
|
|
#ifdef NO_RENDERING
|
|
return;
|
|
#endif
|
|
|
|
//Assert that Lighting is on for Phong-shading to take place
|
|
ASSERTOPENGL(gc->state.enables.general & __GL_LIGHTING_ENABLE,
|
|
"No lighting. Should be smooth-shaded\n");
|
|
|
|
SORT_AND_CULL_FACE(a, b, c, face, ccw);
|
|
|
|
if (__GL_FLOAT_EQZ(gc->polygon.shader.area))
|
|
return;
|
|
/*
|
|
** Pick face to use for coloring
|
|
*/
|
|
modeFlags = gc->polygon.shader.modeFlags;
|
|
if (modeFlags & __GL_SHADE_TWOSIDED && face == __GL_BACKFACE)
|
|
{
|
|
gc->polygon.shader.phong.face = __GL_BACKFACE;
|
|
}
|
|
else
|
|
{
|
|
gc->polygon.shader.phong.face = __GL_FRONTFACE;
|
|
}
|
|
|
|
(*gc->procs.fillTriangle) (gc, a, b, c, (GLboolean) ccw);;
|
|
}
|
|
|
|
|
|
|
|
|
|
void FASTCALL
|
|
__glFillPhongTriangle(__GLcontext *gc, __GLvertex *a, __GLvertex *b,
|
|
__GLvertex *c, GLboolean ccw)
|
|
{
|
|
__GLfloat oneOverArea, t1, t2, t3, t4;
|
|
__GLfloat dxAC, dxBC, dyAC, dyBC;
|
|
__GLfloat aFog, bFog;
|
|
__GLfloat dxAB, dyAB;
|
|
__GLfloat dx, dy, dxdyLeft, dxdyRight;
|
|
__GLcolor *ac, *bc;
|
|
__GLcoord *an, *bn;
|
|
__GLcoord ae, be, ce;
|
|
GLint aIY, bIY, cIY;
|
|
GLuint modeFlags;
|
|
__GLfloat dxdyAC;
|
|
__GLcoord dnAC, dnBC, *cn;
|
|
__GLcoord deAC, deBC;
|
|
__GLphongShader *phong = &gc->polygon.shader.phong;
|
|
GLuint flags = 0, msm_colorMaterialChange;
|
|
GLboolean needColor;
|
|
|
|
//CHOP_ROUND_ON();
|
|
FPU_SAVE_MODE ();
|
|
FPU_CHOP_ON ();
|
|
|
|
/* Pre-compute one over polygon area */
|
|
|
|
__GL_FLOAT_BEGIN_DIVIDE(__glOne, gc->polygon.shader.area, &oneOverArea);
|
|
|
|
modeFlags = gc->polygon.shader.modeFlags;
|
|
|
|
if (gc->polygon.shader.phong.face == __GL_FRONTFACE)
|
|
msm_colorMaterialChange = gc->light.front.colorMaterialChange;
|
|
else
|
|
msm_colorMaterialChange = gc->light.back.colorMaterialChange;
|
|
|
|
if ((gc->state.enables.general & __GL_COLOR_MATERIAL_ENABLE) &&
|
|
msm_colorMaterialChange && (modeFlags & __GL_SHADE_RGB))
|
|
{
|
|
flags |= __GL_PHONG_NEED_COLOR_XPOLATE;
|
|
needColor = GL_TRUE;
|
|
}
|
|
|
|
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
//!!! Compute Invariant color if possible !!!!!!!!
|
|
//!!! Use Otto's optimizations here !!!!!!!!
|
|
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
if (((!(flags & __GL_PHONG_NEED_COLOR_XPOLATE) ||
|
|
!(msm_colorMaterialChange & (__GL_MATERIAL_AMBIENT |
|
|
__GL_MATERIAL_EMISSIVE))) &&
|
|
(modeFlags & __GL_SHADE_RGB)) &&
|
|
!(phong->flags & __GL_PHONG_NEED_EYE_XPOLATE))
|
|
{
|
|
ComputePhongInvarientRGBColor (gc);
|
|
flags |= __GL_PHONG_INV_COLOR_VALID;
|
|
}
|
|
|
|
//Store the flags
|
|
phong->flags |= flags;
|
|
|
|
|
|
/* Fetch some stuff we are going to reuse */
|
|
modeFlags = gc->polygon.shader.modeFlags;
|
|
dxAC = gc->polygon.shader.dxAC;
|
|
dxBC = gc->polygon.shader.dxBC;
|
|
dyAC = gc->polygon.shader.dyAC;
|
|
dyBC = gc->polygon.shader.dyBC;
|
|
ac = a->color;
|
|
bc = b->color;
|
|
an = &(a->normal);
|
|
bn = &(b->normal);
|
|
ae.x = a->eyeX; ae.y = a->eyeY; ae.z = a->eyeZ; ae.w = a->eyeW;
|
|
be.x = b->eyeX; be.y = b->eyeY; be.z = b->eyeZ; be.w = b->eyeW;
|
|
|
|
/*
|
|
** Compute delta values for unit changes in x or y for each
|
|
** parameter.
|
|
*/
|
|
|
|
__GL_FLOAT_SIMPLE_END_DIVIDE(oneOverArea);
|
|
t1 = dyAC * oneOverArea;
|
|
t2 = dyBC * oneOverArea;
|
|
t3 = dxAC * oneOverArea;
|
|
t4 = dxBC * oneOverArea;
|
|
|
|
/* Normals */
|
|
cn = &(c->normal);
|
|
dnAC.x = an->x - cn->x;
|
|
dnAC.y = an->y - cn->y;
|
|
dnAC.z = an->z - cn->z;
|
|
|
|
dnBC.x = bn->x - cn->x;
|
|
dnBC.y = bn->y - cn->y;
|
|
dnBC.z = bn->z - cn->z;
|
|
|
|
gc->polygon.shader.phong.dndx.x = dnAC.x * t2 - dnBC.x * t1;
|
|
gc->polygon.shader.phong.dndy.x = dnBC.x * t3 - dnAC.x * t4;
|
|
gc->polygon.shader.phong.dndx.y = dnAC.y * t2 - dnBC.y * t1;
|
|
gc->polygon.shader.phong.dndy.y = dnBC.y * t3 - dnAC.y * t4;
|
|
gc->polygon.shader.phong.dndx.z = dnAC.z * t2 - dnBC.z * t1;
|
|
gc->polygon.shader.phong.dndy.z = dnBC.z * t3 - dnAC.z * t4;
|
|
|
|
if (phong->flags & __GL_PHONG_NEED_EYE_XPOLATE)
|
|
{
|
|
ce.x = c->eyeX; ce.y = c->eyeY; ce.z = c->eyeZ; ce.w = c->eyeW;
|
|
|
|
deAC.x = ae.x - ce.x;
|
|
deAC.y = ae.y - ce.y;
|
|
deAC.z = ae.z - ce.z;
|
|
deAC.w = ae.w - ce.w;
|
|
|
|
deBC.x = be.x - ce.x;
|
|
deBC.y = be.y - ce.y;
|
|
deBC.z = be.z - ce.z;
|
|
deBC.w = be.w - ce.w;
|
|
|
|
gc->polygon.shader.phong.dedx.x = deAC.x * t2 - deBC.x * t1;
|
|
gc->polygon.shader.phong.dedy.x = deBC.x * t3 - deAC.x * t4;
|
|
gc->polygon.shader.phong.dedx.y = deAC.y * t2 - deBC.y * t1;
|
|
gc->polygon.shader.phong.dedy.y = deBC.y * t3 - deAC.y * t4;
|
|
gc->polygon.shader.phong.dedx.z = deAC.z * t2 - deBC.z * t1;
|
|
gc->polygon.shader.phong.dedy.z = deBC.z * t3 - deAC.z * t4;
|
|
gc->polygon.shader.phong.dedx.w = deAC.w * t2 - deBC.w * t1;
|
|
gc->polygon.shader.phong.dedy.w = deBC.w * t3 - deAC.w * t4;
|
|
}
|
|
|
|
if (modeFlags & __GL_SHADE_RGB)
|
|
{
|
|
__GLfloat drAC, dgAC, dbAC, daAC;
|
|
__GLfloat drBC, dgBC, dbBC, daBC;
|
|
__GLcolor *cc;
|
|
|
|
/* Colors */
|
|
if (needColor)
|
|
{
|
|
cc = c->color;
|
|
drAC = ac->r - cc->r;
|
|
drBC = bc->r - cc->r;
|
|
dgAC = ac->g - cc->g;
|
|
dgBC = bc->g - cc->g;
|
|
dbAC = ac->b - cc->b;
|
|
dbBC = bc->b - cc->b;
|
|
daAC = ac->a - cc->a;
|
|
daBC = bc->a - cc->a;
|
|
|
|
|
|
gc->polygon.shader.drdx = drAC * t2 - drBC * t1;
|
|
gc->polygon.shader.drdy = drBC * t3 - drAC * t4;
|
|
gc->polygon.shader.dgdx = dgAC * t2 - dgBC * t1;
|
|
gc->polygon.shader.dgdy = dgBC * t3 - dgAC * t4;
|
|
gc->polygon.shader.dbdx = dbAC * t2 - dbBC * t1;
|
|
gc->polygon.shader.dbdy = dbBC * t3 - dbAC * t4;
|
|
gc->polygon.shader.dadx = daAC * t2 - daBC * t1;
|
|
gc->polygon.shader.dady = daBC * t3 - daAC * t4;
|
|
}
|
|
|
|
if (modeFlags & __GL_SHADE_TEXTURE)
|
|
{
|
|
__GLfloat awinv, bwinv, cwinv, scwinv, tcwinv, qwcwinv;
|
|
__GLfloat dsAC, dsBC, dtAC, dtBC, dqwAC, dqwBC;
|
|
|
|
awinv = a->window.w;
|
|
bwinv = b->window.w;
|
|
cwinv = c->window.w;
|
|
scwinv = c->texture.x * cwinv;
|
|
tcwinv = c->texture.y * cwinv;
|
|
qwcwinv = c->texture.w * cwinv;
|
|
|
|
dsAC = a->texture.x * awinv - scwinv;
|
|
dsBC = b->texture.x * bwinv - scwinv;
|
|
dtAC = a->texture.y * awinv - tcwinv;
|
|
dtBC = b->texture.y * bwinv - tcwinv;
|
|
dqwAC = a->texture.w * awinv - qwcwinv;
|
|
dqwBC = b->texture.w * bwinv - qwcwinv;
|
|
|
|
gc->polygon.shader.dsdx = dsAC * t2 - dsBC * t1;
|
|
gc->polygon.shader.dsdy = dsBC * t3 - dsAC * t4;
|
|
gc->polygon.shader.dtdx = dtAC * t2 - dtBC * t1;
|
|
gc->polygon.shader.dtdy = dtBC * t3 - dtAC * t4;
|
|
gc->polygon.shader.dqwdx = dqwAC * t2 - dqwBC * t1;
|
|
gc->polygon.shader.dqwdy = dqwBC * t3 - dqwAC * t4;
|
|
}
|
|
}
|
|
|
|
if (modeFlags & __GL_SHADE_DEPTH_ITER)
|
|
{
|
|
__GLfloat dzAC, dzBC;
|
|
|
|
dzAC = a->window.z - c->window.z;
|
|
dzBC = b->window.z - c->window.z;
|
|
|
|
gc->polygon.shader.dzdxf = dzAC * t2 - dzBC * t1;
|
|
gc->polygon.shader.dzdyf = dzBC * t3 - dzAC * t4;
|
|
if(( gc->modes.depthBits == 16 ) &&
|
|
( gc->depthBuffer.scale <= (GLuint)0xffff )) {
|
|
gc->polygon.shader.dzdx =
|
|
FLT_TO_Z16_SCALE(gc->polygon.shader.dzdxf);
|
|
}
|
|
else {
|
|
gc->polygon.shader.dzdx = FTOL(gc->polygon.shader.dzdxf);
|
|
}
|
|
}
|
|
|
|
#ifdef GL_WIN_specular_fog
|
|
if (gc->polygon.shader.modeFlags & __GL_SHADE_COMPUTE_FOG)
|
|
{
|
|
__GLfloat dfAC, dfBC, cFog;
|
|
|
|
/* Use eyeZ for interpolation value */
|
|
aFog = a->eyeZ;
|
|
bFog = b->eyeZ;
|
|
cFog = c->eyeZ;
|
|
|
|
dfAC = aFog - cFog;
|
|
dfBC = bFog - cFog;
|
|
|
|
gc->polygon.shader.dfdx = dfAC * t2 - dfBC * t1;
|
|
gc->polygon.shader.dfdy = dfBC * t3 - dfAC * t4;
|
|
}
|
|
else if (gc->polygon.shader.modeFlags & __GL_SHADE_INTERP_FOG)
|
|
{
|
|
__GLfloat dfAC, dfBC, cFog;
|
|
|
|
aFog = bFog = cFog = 1.0f;
|
|
|
|
if (gc->polygon.shader.modeFlags & __GL_SHADE_SPEC_FOG)
|
|
{
|
|
aFog = ComputeSpecValue (gc, a);
|
|
bFog = ComputeSpecValue (gc, b);
|
|
cFog = ComputeSpecValue (gc, c);
|
|
}
|
|
|
|
if (gc->polygon.shader.modeFlags & __GL_SHADE_SLOW_FOG)
|
|
{
|
|
aFog *= a->fog;
|
|
bFog *= b->fog;
|
|
cFog *= c->fog;
|
|
}
|
|
|
|
dfAC = aFog - cFog;
|
|
dfBC = bFog - cFog;
|
|
|
|
gc->polygon.shader.dfdx = dfAC * t2 - dfBC * t1;
|
|
gc->polygon.shader.dfdy = dfBC * t3 - dfAC * t4;
|
|
}
|
|
#else //GL_WIN_specular_fog
|
|
if (modeFlags & __GL_SHADE_COMPUTE_FOG)
|
|
{
|
|
__GLfloat dfAC, dfBC, cFog;
|
|
|
|
/* Use eyeZ for interpolation value */
|
|
aFog = a->eyeZ;
|
|
bFog = b->eyeZ;
|
|
cFog = c->eyeZ;
|
|
|
|
dfAC = aFog - cFog;
|
|
dfBC = bFog - cFog;
|
|
|
|
gc->polygon.shader.dfdx = dfAC * t2 - dfBC * t1;
|
|
gc->polygon.shader.dfdy = dfBC * t3 - dfAC * t4;
|
|
}
|
|
else if (modeFlags & __GL_SHADE_INTERP_FOG)
|
|
{
|
|
/* Use fog for interpolation value */
|
|
aFog = a->fog;
|
|
bFog = b->fog;
|
|
cFog = c->fog;
|
|
|
|
dfAC = aFog - cFog;
|
|
dfBC = bFog - cFog;
|
|
|
|
gc->polygon.shader.dfdx = dfAC * t2 - dfBC * t1;
|
|
gc->polygon.shader.dfdy = dfBC * t3 - dfAC * t4;
|
|
}
|
|
#endif //GL_WIN_specular_fog
|
|
|
|
__GL_FLOAT_SIMPLE_BEGIN_DIVIDE(dxAC, dyAC, dxdyAC);
|
|
|
|
/* Snap each y coordinate to its pixel center */
|
|
aIY = __GL_VERTEX_FIXED_TO_INT(__GL_VERTEX_FLOAT_TO_FIXED(a->window.y)+
|
|
__GL_VERTEX_FRAC_HALF);
|
|
bIY = __GL_VERTEX_FIXED_TO_INT(__GL_VERTEX_FLOAT_TO_FIXED(b->window.y)+
|
|
__GL_VERTEX_FRAC_HALF);
|
|
cIY = __GL_VERTEX_FIXED_TO_INT(__GL_VERTEX_FLOAT_TO_FIXED(c->window.y)+
|
|
__GL_VERTEX_FRAC_HALF);
|
|
|
|
#ifdef __DBG_PRINT
|
|
DbgPrint ("aIY=%d, bIY=%d, cIY=%d\n", aIY, bIY, cIY);
|
|
#endif
|
|
|
|
/*
|
|
** This algorithim always fills from bottom to top, left to right.
|
|
** Because of this, ccw triangles are inherently faster because
|
|
** the parameter values need not be recomputed.
|
|
*/
|
|
dxAB = a->window.x - b->window.x;
|
|
dyAB = a->window.y - b->window.y;
|
|
if (ccw) {
|
|
dy = (aIY + __glHalf) - a->window.y;
|
|
__GL_FLOAT_SIMPLE_END_DIVIDE(dxdyAC);
|
|
SnapXLeft(gc, a->window.x + dy*dxdyAC, dxdyAC);
|
|
dx = (gc->polygon.shader.ixLeft + __glHalf) - a->window.x;
|
|
SetInitialPhongParameters(gc, a, an, ac, aFog, dx, dy);
|
|
if (aIY != bIY) {
|
|
dxdyRight = dxAB / dyAB;
|
|
SnapXRight(&gc->polygon.shader, a->window.x + dy*dxdyRight,
|
|
dxdyRight);
|
|
#ifdef __DBG_PRINT
|
|
DbgPrint ("dxdyRight = %f\n", dxdyRight);
|
|
#endif
|
|
FillPhongSubTriangle(gc, aIY, bIY);
|
|
}
|
|
|
|
if (bIY != cIY) {
|
|
dxdyRight = dxBC / dyBC;
|
|
dy = (bIY + __glHalf) - b->window.y;
|
|
SnapXRight(&gc->polygon.shader, b->window.x + dy*dxdyRight,
|
|
dxdyRight);
|
|
#ifdef __DBG_PRINT
|
|
DbgPrint ("dxdyRight = %f\n", dxdyRight);
|
|
#endif
|
|
FillPhongSubTriangle(gc, bIY, cIY);
|
|
}
|
|
} else {
|
|
dy = (aIY + __glHalf) - a->window.y;
|
|
__GL_FLOAT_SIMPLE_END_DIVIDE(dxdyAC);
|
|
SnapXRight(&gc->polygon.shader, a->window.x + dy*dxdyAC, dxdyAC);
|
|
#ifdef __DBG_PRINT
|
|
DbgPrint ("dxdyRight = %f\n", dxdyAC);
|
|
#endif
|
|
if (aIY != bIY) {
|
|
dxdyLeft = dxAB / dyAB;
|
|
SnapXLeft(gc, a->window.x + dy*dxdyLeft, dxdyLeft);
|
|
dx = (gc->polygon.shader.ixLeft + __glHalf) - a->window.x;
|
|
SetInitialPhongParameters(gc, a, an, ac, aFog, dx, dy);
|
|
FillPhongSubTriangle(gc, aIY, bIY);
|
|
}
|
|
|
|
if (bIY != cIY) {
|
|
dxdyLeft = dxBC / dyBC;
|
|
dy = (bIY + __glHalf) - b->window.y;
|
|
SnapXLeft(gc, b->window.x + dy*dxdyLeft, dxdyLeft);
|
|
dx = (gc->polygon.shader.ixLeft + __glHalf) - b->window.x;
|
|
SetInitialPhongParameters(gc, b, bn, bc, bFog, dx, dy);
|
|
FillPhongSubTriangle(gc, bIY, cIY);
|
|
}
|
|
}
|
|
|
|
FPU_RESTORE_MODE(); // CHOP_ROUND_OFF();
|
|
}
|
|
|
|
|
|
|
|
static void SetInitialPhongParameters(__GLcontext *gc, __GLvertex *a,
|
|
__GLcoord *an, __GLcolor *ac,
|
|
__GLfloat aFog, __GLfloat dx,
|
|
__GLfloat dy)
|
|
{
|
|
GLint face = gc->polygon.shader.phong.face;
|
|
__GLshade *sh = &gc->polygon.shader;
|
|
__GLphongShader *phong = &gc->polygon.shader.phong;
|
|
__GLfloat little = sh->dxLeftLittle;
|
|
__GLfloat big = sh->dxLeftBig;
|
|
GLuint modeFlags = sh->modeFlags;
|
|
GLboolean needColor = (gc->polygon.shader.phong.flags &
|
|
__GL_PHONG_NEED_COLOR_XPOLATE);
|
|
|
|
#define bPolygonOffset \
|
|
(gc->state.enables.general & __GL_POLYGON_OFFSET_FILL_ENABLE )
|
|
|
|
|
|
/* Set parameters for the shader */
|
|
phong->nCur.x = an->x + dx*phong->dndx.x + dy*phong->dndy.x;
|
|
phong->nCur.y = an->y + dx*phong->dndx.y + dy*phong->dndy.y;
|
|
phong->nCur.z = an->z + dx*phong->dndx.z + dy*phong->dndy.z;
|
|
|
|
phong->nLittle.x = phong->dndy.x + little * phong->dndx.x;
|
|
phong->nLittle.y = phong->dndy.y + little * phong->dndx.y;
|
|
phong->nLittle.z = phong->dndy.z + little * phong->dndx.z;
|
|
|
|
if (big > little)
|
|
{
|
|
phong->nBig.x = phong->nLittle.x + phong->dndx.x;
|
|
phong->nBig.y = phong->nLittle.y + phong->dndx.y;
|
|
phong->nBig.z = phong->nLittle.z + phong->dndx.z;
|
|
}
|
|
else
|
|
{
|
|
phong->nBig.x = phong->nLittle.x - phong->dndx.x;
|
|
phong->nBig.y = phong->nLittle.y - phong->dndx.y;
|
|
phong->nBig.z = phong->nLittle.z - phong->dndx.z;
|
|
}
|
|
|
|
if (phong->flags & __GL_PHONG_NEED_EYE_XPOLATE)
|
|
{
|
|
phong->eCur.x = a->eyeX + dx*phong->dedx.x + dy*phong->dedy.x;
|
|
phong->eCur.y = a->eyeY + dx*phong->dedx.y + dy*phong->dedy.y;
|
|
phong->eCur.z = a->eyeZ + dx*phong->dedx.z + dy*phong->dedy.z;
|
|
phong->eCur.w = a->eyeW + dx*phong->dedx.w + dy*phong->dedy.w;
|
|
|
|
phong->eLittle.x = phong->dedy.x + little * phong->dedx.x;
|
|
phong->eLittle.y = phong->dedy.y + little * phong->dedx.y;
|
|
phong->eLittle.z = phong->dedy.z + little * phong->dedx.z;
|
|
phong->eLittle.w = phong->dedy.w + little * phong->dedx.w;
|
|
|
|
if (big > little)
|
|
{
|
|
phong->eBig.x = phong->eLittle.x + phong->dedx.x;
|
|
phong->eBig.y = phong->eLittle.y + phong->dedx.y;
|
|
phong->eBig.z = phong->eLittle.z + phong->dedx.z;
|
|
phong->eBig.w = phong->eLittle.w + phong->dedx.w;
|
|
}
|
|
else
|
|
{
|
|
phong->eBig.x = phong->eLittle.x - phong->dedx.x;
|
|
phong->eBig.y = phong->eLittle.y - phong->dedx.y;
|
|
phong->eBig.z = phong->eLittle.z - phong->dedx.z;
|
|
phong->eBig.w = phong->eLittle.w - phong->dedx.w;
|
|
}
|
|
}
|
|
|
|
if (big > little)
|
|
{
|
|
if (modeFlags & __GL_SHADE_RGB)
|
|
{
|
|
if (needColor)
|
|
{
|
|
|
|
sh->frag.color.r = ac->r + dx*sh->drdx + dy*sh->drdy;
|
|
|
|
sh->rLittle = sh->drdy + little * sh->drdx;
|
|
sh->rBig = sh->rLittle + sh->drdx;
|
|
|
|
sh->frag.color.g = ac->g + dx*sh->dgdx + dy*sh->dgdy;
|
|
sh->gLittle = sh->dgdy + little * sh->dgdx;
|
|
sh->gBig = sh->gLittle + sh->dgdx;
|
|
|
|
sh->frag.color.b = ac->b + dx*sh->dbdx + dy*sh->dbdy;
|
|
sh->bLittle = sh->dbdy + little * sh->dbdx;
|
|
sh->bBig = sh->bLittle + sh->dbdx;
|
|
|
|
sh->frag.color.a = ac->a + dx*sh->dadx + dy*sh->dady;
|
|
sh->aLittle = sh->dady + little * sh->dadx;
|
|
sh->aBig =sh->aLittle + sh->dadx;
|
|
}
|
|
if (modeFlags & __GL_SHADE_TEXTURE)
|
|
{
|
|
__GLfloat oneOverW = a->window.w;
|
|
sh->frag.s = a->texture.x * oneOverW + dx*sh->dsdx
|
|
+ dy*sh->dsdy;
|
|
sh->sLittle = sh->dsdy + little * sh->dsdx;
|
|
sh->sBig = sh->sLittle + sh->dsdx;
|
|
|
|
sh->frag.t = a->texture.y * oneOverW + dx*sh->dtdx
|
|
+ dy*sh->dtdy;
|
|
sh->tLittle = sh->dtdy + little * sh->dtdx;
|
|
sh->tBig = sh->tLittle + sh->dtdx;
|
|
|
|
sh->frag.qw = a->texture.w * oneOverW + dx*sh->dqwdx
|
|
+ dy*sh->dqwdy;
|
|
sh->qwLittle = sh->dqwdy + little * sh->dqwdx;
|
|
sh->qwBig = sh->qwLittle + sh->dqwdx;
|
|
}
|
|
}
|
|
|
|
if (modeFlags & __GL_SHADE_DEPTH_ITER)
|
|
{
|
|
__GLfloat zLittle, zOffset;
|
|
|
|
zOffset = bPolygonOffset ? __glPolygonOffsetZ(gc) : 0.0f;
|
|
if (gc->modes.depthBits == 16)
|
|
{
|
|
sh->frag.z = (__GLzValue)
|
|
FLT_TO_Z16_SCALE(a->window.z + dx*sh->dzdxf + dy*sh->dzdyf
|
|
+ zOffset );
|
|
zLittle = sh->dzdyf + little * sh->dzdxf;
|
|
sh->zLittle = FLT_TO_Z16_SCALE(zLittle);
|
|
sh->zBig = FLT_TO_Z16_SCALE(zLittle + sh->dzdxf);
|
|
}
|
|
else
|
|
{
|
|
sh->frag.z = (__GLzValue)
|
|
FTOL(a->window.z + dx*sh->dzdxf + dy*sh->dzdyf +
|
|
zOffset );
|
|
zLittle = sh->dzdyf + little * sh->dzdxf;
|
|
sh->zLittle = FTOL(zLittle);
|
|
sh->zBig = FTOL(zLittle + sh->dzdxf);
|
|
}
|
|
}
|
|
|
|
if (modeFlags & (__GL_SHADE_COMPUTE_FOG | __GL_SHADE_INTERP_FOG))
|
|
{
|
|
sh->frag.f = aFog + dx*sh->dfdx + dy*sh->dfdy;
|
|
sh->fLittle = sh->dfdy + little * sh->dfdx;
|
|
sh->fBig = sh->fLittle + sh->dfdx;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (modeFlags & __GL_SHADE_RGB)
|
|
{
|
|
if (needColor)
|
|
{
|
|
sh->frag.color.r = ac->r + dx*sh->drdx + dy*sh->drdy;
|
|
sh->rLittle = sh->drdy + little * sh->drdx;
|
|
sh->rBig = sh->rLittle - sh->drdx;
|
|
|
|
sh->frag.color.g = ac->g + dx*sh->dgdx + dy*sh->dgdy;
|
|
sh->gLittle = sh->dgdy + little * sh->dgdx;
|
|
sh->gBig = sh->gLittle - sh->dgdx;
|
|
|
|
sh->frag.color.b = ac->b + dx*sh->dbdx + dy*sh->dbdy;
|
|
sh->bLittle = sh->dbdy + little * sh->dbdx;
|
|
sh->bBig = sh->bLittle - sh->dbdx;
|
|
|
|
sh->frag.color.a = ac->a + dx*sh->dadx + dy*sh->dady;
|
|
sh->aLittle = sh->dady + little * sh->dadx;
|
|
sh->aBig =sh->aLittle - sh->dadx;
|
|
}
|
|
if (modeFlags & __GL_SHADE_TEXTURE)
|
|
{
|
|
__GLfloat oneOverW = a->window.w;
|
|
sh->frag.s = a->texture.x * oneOverW + dx*sh->dsdx
|
|
+ dy*sh->dsdy;
|
|
sh->sLittle = sh->dsdy + little * sh->dsdx;
|
|
sh->sBig = sh->sLittle - sh->dsdx;
|
|
|
|
sh->frag.t = a->texture.y * oneOverW + dx*sh->dtdx
|
|
+ dy*sh->dtdy;
|
|
sh->tLittle = sh->dtdy + little * sh->dtdx;
|
|
sh->tBig = sh->tLittle - sh->dtdx;
|
|
|
|
sh->frag.qw = a->texture.w * oneOverW + dx*sh->dqwdx
|
|
+ dy*sh->dqwdy;
|
|
sh->qwLittle = sh->dqwdy + little * sh->dqwdx;
|
|
sh->qwBig = sh->qwLittle - sh->dqwdx;
|
|
}
|
|
}
|
|
|
|
if (modeFlags & __GL_SHADE_DEPTH_ITER)
|
|
{
|
|
__GLfloat zLittle, zOffset;
|
|
|
|
zOffset = bPolygonOffset ? __glPolygonOffsetZ(gc) : 0.0f;
|
|
if(( gc->modes.depthBits == 16 ) &&
|
|
( gc->depthBuffer.scale <= (GLuint)0xffff ))
|
|
{
|
|
sh->frag.z = (__GLzValue)
|
|
FLT_TO_Z16_SCALE(a->window.z + dx*sh->dzdxf + dy*sh->dzdyf
|
|
+ zOffset );
|
|
zLittle = sh->dzdyf + little * sh->dzdxf;
|
|
sh->zLittle = FLT_TO_Z16_SCALE(zLittle);
|
|
sh->zBig = FLT_TO_Z16_SCALE(zLittle - sh->dzdxf);
|
|
}
|
|
else
|
|
{
|
|
sh->frag.z = (__GLzValue)
|
|
FTOL( a->window.z + dx*sh->dzdxf + dy*sh->dzdyf+ zOffset );
|
|
zLittle = sh->dzdyf + little * sh->dzdxf;
|
|
sh->zLittle = FTOL(zLittle);
|
|
sh->zBig = FTOL(zLittle - sh->dzdxf);
|
|
}
|
|
}
|
|
if (modeFlags & (__GL_SHADE_COMPUTE_FOG | __GL_SHADE_INTERP_FOG))
|
|
{
|
|
sh->frag.f = aFog + dx*sh->dfdx + dy*sh->dfdy;
|
|
sh->fLittle = sh->dfdy + little * sh->dfdx;
|
|
sh->fBig = sh->fLittle - sh->dfdx;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* This routine sets gc->polygon.shader.cfb to gc->drawBuffer */
|
|
|
|
static void FASTCALL FillPhongSubTriangle(__GLcontext *gc, GLint iyBottom, GLint iyTop)
|
|
{
|
|
GLint ixLeft, ixRight;
|
|
GLint ixLeftFrac, ixRightFrac;
|
|
GLint dxLeftFrac, dxRightFrac;
|
|
GLint dxLeftLittle, dxRightLittle;
|
|
GLint dxLeftBig, dxRightBig;
|
|
GLint spanWidth, clipY0, clipY1;
|
|
GLuint modeFlags;
|
|
__GLphongShader *phong = &(gc->polygon.shader.phong);
|
|
GLboolean needColor = (phong->flags & __GL_PHONG_NEED_COLOR_XPOLATE);
|
|
__GLstippleWord stackWords[__GL_MAX_STACK_STIPPLE_WORDS];
|
|
__GLstippleWord *words;
|
|
__GLcolor colors[__GL_MAX_STACKED_COLORS>>1];
|
|
__GLcolor fbcolors[__GL_MAX_STACKED_COLORS>>1];
|
|
__GLcolor *vColors, *vFbcolors;
|
|
int iMaxWidth, iDy, dxLeft, dxRight;
|
|
|
|
ixLeft = gc->polygon.shader.ixLeft;
|
|
dxLeft = (gc->polygon.shader.dxLeftBig < gc->polygon.shader.dxLeftLittle) ?
|
|
gc->polygon.shader.dxLeftBig : gc->polygon.shader.dxLeftLittle;
|
|
ixRight = gc->polygon.shader.ixRight;
|
|
dxRight = (gc->polygon.shader.dxRightBig > gc->polygon.shader.dxRightLittle) ?
|
|
gc->polygon.shader.dxRightBig : gc->polygon.shader.dxRightLittle;
|
|
iMaxWidth = ixRight - ixLeft;
|
|
iDy = iyTop - iyBottom - 1;
|
|
ixRight += dxRight * iDy;
|
|
ixLeft += dxLeft * iDy;
|
|
iMaxWidth = (iMaxWidth < (ixRight - ixLeft)) ? ixRight - ixLeft :
|
|
iMaxWidth;
|
|
|
|
if (iMaxWidth > __GL_MAX_STACK_STIPPLE_BITS)
|
|
{
|
|
words = gcTempAlloc(gc, (iMaxWidth+__GL_STIPPLE_BITS-1)/8);
|
|
if (words == NULL)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
words = stackWords;
|
|
}
|
|
|
|
if (iMaxWidth > (__GL_MAX_STACKED_COLORS>>1))
|
|
{
|
|
vColors = (__GLcolor *) gcTempAlloc(gc,
|
|
iMaxWidth * sizeof(__GLcolor));
|
|
if (NULL == vColors)
|
|
{
|
|
if (iMaxWidth > __GL_MAX_STACK_STIPPLE_BITS)
|
|
{
|
|
gcTempFree(gc, words);
|
|
}
|
|
return;
|
|
}
|
|
|
|
vFbcolors = (__GLcolor *) gcTempAlloc(gc,
|
|
iMaxWidth * sizeof(__GLcolor));
|
|
if (NULL == vFbcolors) {
|
|
if (iMaxWidth > __GL_MAX_STACK_STIPPLE_BITS)
|
|
{
|
|
gcTempFree(gc, words);
|
|
}
|
|
gcTempFree(gc, vColors);
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
vColors = colors;
|
|
vFbcolors = fbcolors;
|
|
}
|
|
|
|
ixLeft = gc->polygon.shader.ixLeft;
|
|
ixLeftFrac = gc->polygon.shader.ixLeftFrac;
|
|
ixRight = gc->polygon.shader.ixRight;
|
|
ixRightFrac = gc->polygon.shader.ixRightFrac;
|
|
clipY0 = gc->transform.clipY0;
|
|
clipY1 = gc->transform.clipY1;
|
|
dxLeftFrac = gc->polygon.shader.dxLeftFrac;
|
|
dxLeftBig = gc->polygon.shader.dxLeftBig;
|
|
dxLeftLittle = gc->polygon.shader.dxLeftLittle;
|
|
dxRightFrac = gc->polygon.shader.dxRightFrac;
|
|
dxRightBig = gc->polygon.shader.dxRightBig;
|
|
dxRightLittle = gc->polygon.shader.dxRightLittle;
|
|
modeFlags = gc->polygon.shader.modeFlags;
|
|
|
|
gc->polygon.shader.colors = vColors;
|
|
gc->polygon.shader.fbcolors = vFbcolors;
|
|
gc->polygon.shader.stipplePat = words;
|
|
if (modeFlags & __GL_SHADE_STENCIL_TEST) {
|
|
gc->polygon.shader.sbuf =
|
|
__GL_STENCIL_ADDR(&gc->stencilBuffer, (__GLstencilCell*),
|
|
ixLeft, iyBottom);
|
|
}
|
|
if (modeFlags & __GL_SHADE_DEPTH_TEST) {
|
|
if( gc->modes.depthBits == 32 )
|
|
gc->polygon.shader.zbuf = (__GLzValue *)
|
|
__GL_DEPTH_ADDR(&gc->depthBuffer, (__GLzValue*),
|
|
ixLeft, iyBottom);
|
|
else
|
|
gc->polygon.shader.zbuf = (__GLzValue *)
|
|
__GL_DEPTH_ADDR(&gc->depthBuffer, (__GLz16Value*),
|
|
ixLeft, iyBottom);
|
|
}
|
|
gc->polygon.shader.cfb = gc->drawBuffer;
|
|
while (iyBottom < iyTop)
|
|
{
|
|
spanWidth = ixRight - ixLeft;
|
|
/*
|
|
** Only render spans that have non-zero width and which are
|
|
** not scissored out vertically.
|
|
*/
|
|
if ((spanWidth > 0) && (iyBottom >= clipY0) && (iyBottom < clipY1))
|
|
{
|
|
gc->polygon.shader.frag.x = ixLeft;
|
|
gc->polygon.shader.frag.y = iyBottom;
|
|
gc->polygon.shader.length = spanWidth;
|
|
/* Initialize Parameters to interpolate */
|
|
(*gc->procs.phong.InitSpanInterpolation) (gc);
|
|
(*gc->procs.span.processSpan)(gc);
|
|
}
|
|
|
|
/* Advance right edge fixed point, adjusting for carry */
|
|
ixRightFrac += dxRightFrac;
|
|
if (ixRightFrac < 0)
|
|
{
|
|
/* Carry/Borrow'd. Use large step */
|
|
ixRight += dxRightBig;
|
|
ixRightFrac &= ~0x80000000;
|
|
}
|
|
else
|
|
{
|
|
ixRight += dxRightLittle;
|
|
}
|
|
|
|
iyBottom++;
|
|
ixLeftFrac += dxLeftFrac;
|
|
|
|
if (ixLeftFrac < 0)
|
|
{
|
|
/* Carry/Borrow'd. Use large step */
|
|
ixLeft += dxLeftBig;
|
|
ixLeftFrac &= ~0x80000000;
|
|
|
|
phong->nCur.x += phong->nBig.x;
|
|
phong->nCur.y += phong->nBig.y;
|
|
phong->nCur.z += phong->nBig.z;
|
|
|
|
if (phong->flags & __GL_PHONG_NEED_EYE_XPOLATE)
|
|
{
|
|
phong->eCur.x += phong->eBig.x;
|
|
phong->eCur.y += phong->eBig.y;
|
|
phong->eCur.z += phong->eBig.z;
|
|
phong->eCur.w += phong->eBig.w;
|
|
}
|
|
|
|
if (modeFlags & __GL_SHADE_RGB)
|
|
{
|
|
if (needColor)
|
|
{
|
|
gc->polygon.shader.frag.color.r +=gc->polygon.shader.rBig;
|
|
gc->polygon.shader.frag.color.g +=gc->polygon.shader.gBig;
|
|
gc->polygon.shader.frag.color.b +=gc->polygon.shader.bBig;
|
|
gc->polygon.shader.frag.color.a +=gc->polygon.shader.aBig;
|
|
}
|
|
if (modeFlags & __GL_SHADE_TEXTURE)
|
|
{
|
|
gc->polygon.shader.frag.s += gc->polygon.shader.sBig;
|
|
gc->polygon.shader.frag.t += gc->polygon.shader.tBig;
|
|
gc->polygon.shader.frag.qw += gc->polygon.shader.qwBig;
|
|
}
|
|
}
|
|
|
|
if (modeFlags & __GL_SHADE_STENCIL_TEST) {
|
|
/* The implicit multiply is taken out of the loop */
|
|
gc->polygon.shader.sbuf = (__GLstencilCell*)
|
|
((GLubyte*) gc->polygon.shader.sbuf
|
|
+ gc->polygon.shader.sbufBig);
|
|
}
|
|
if (modeFlags & __GL_SHADE_DEPTH_ITER) {
|
|
gc->polygon.shader.frag.z += gc->polygon.shader.zBig;
|
|
}
|
|
|
|
if (modeFlags & __GL_SHADE_DEPTH_TEST) {
|
|
/* The implicit multiply is taken out of the loop */
|
|
gc->polygon.shader.zbuf = (__GLzValue*)
|
|
((GLubyte*) gc->polygon.shader.zbuf
|
|
+ gc->polygon.shader.zbufBig);
|
|
}
|
|
|
|
if (modeFlags & (__GL_SHADE_COMPUTE_FOG | __GL_SHADE_INTERP_FOG))
|
|
{
|
|
gc->polygon.shader.frag.f += gc->polygon.shader.fBig;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Use small step */
|
|
ixLeft += dxLeftLittle;
|
|
|
|
phong->nCur.x += phong->nLittle.x;
|
|
phong->nCur.y += phong->nLittle.y;
|
|
phong->nCur.z += phong->nLittle.z;
|
|
|
|
if (phong->flags & __GL_PHONG_NEED_EYE_XPOLATE)
|
|
{
|
|
phong->eCur.x += phong->eLittle.x;
|
|
phong->eCur.y += phong->eLittle.y;
|
|
phong->eCur.z += phong->eLittle.z;
|
|
phong->eCur.w += phong->eLittle.w;
|
|
}
|
|
|
|
if (modeFlags & __GL_SHADE_RGB)
|
|
{
|
|
if (needColor)
|
|
{
|
|
gc->polygon.shader.frag.color.r +=
|
|
gc->polygon.shader.rLittle;
|
|
gc->polygon.shader.frag.color.g +=
|
|
gc->polygon.shader.gLittle;
|
|
gc->polygon.shader.frag.color.b +=
|
|
gc->polygon.shader.bLittle;
|
|
gc->polygon.shader.frag.color.a +=
|
|
gc->polygon.shader.aLittle;
|
|
}
|
|
|
|
if (modeFlags & __GL_SHADE_TEXTURE) {
|
|
gc->polygon.shader.frag.s += gc->polygon.shader.sLittle;
|
|
gc->polygon.shader.frag.t += gc->polygon.shader.tLittle;
|
|
gc->polygon.shader.frag.qw += gc->polygon.shader.qwLittle;
|
|
}
|
|
}
|
|
|
|
if (modeFlags & __GL_SHADE_STENCIL_TEST) {
|
|
/* The implicit multiply is taken out of the loop */
|
|
gc->polygon.shader.sbuf = (__GLstencilCell*)
|
|
((GLubyte*) gc->polygon.shader.sbuf
|
|
+ gc->polygon.shader.sbufLittle);
|
|
}
|
|
if (modeFlags & __GL_SHADE_DEPTH_ITER) {
|
|
gc->polygon.shader.frag.z += gc->polygon.shader.zLittle;
|
|
}
|
|
if (modeFlags & __GL_SHADE_DEPTH_TEST) {
|
|
/* The implicit multiply is taken out of the loop */
|
|
gc->polygon.shader.zbuf = (__GLzValue*)
|
|
((GLubyte*) gc->polygon.shader.zbuf
|
|
+ gc->polygon.shader.zbufLittle);
|
|
}
|
|
if (modeFlags & (__GL_SHADE_COMPUTE_FOG | __GL_SHADE_INTERP_FOG))
|
|
{
|
|
gc->polygon.shader.frag.f += gc->polygon.shader.fLittle;
|
|
}
|
|
}
|
|
}
|
|
gc->polygon.shader.ixLeft = ixLeft;
|
|
gc->polygon.shader.ixLeftFrac = ixLeftFrac;
|
|
gc->polygon.shader.ixRight = ixRight;
|
|
gc->polygon.shader.ixRightFrac = ixRightFrac;
|
|
#ifdef NT
|
|
if (iMaxWidth > __GL_MAX_STACK_STIPPLE_BITS)
|
|
{
|
|
gcTempFree(gc, words);
|
|
}
|
|
if (iMaxWidth > (__GL_MAX_STACKED_COLORS>>1))
|
|
{
|
|
gcTempFree(gc, vColors);
|
|
gcTempFree(gc, vFbcolors);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static void SnapXLeft(__GLcontext *gc, __GLfloat xLeft, __GLfloat dxdyLeft)
|
|
{
|
|
GLint ixLeft, ixLeftFrac, lineBytes, elementSize, iLittle, iBig;
|
|
|
|
ASSERT_CHOP_ROUND();
|
|
|
|
ixLeft = __GL_VERTEX_FLOAT_TO_INT(xLeft);
|
|
/* Pre-add .5 to allow truncation in spanWidth calculation */
|
|
ixLeftFrac = __GL_VERTEX_PROMOTED_FRACTION(xLeft) + 0x40000000;
|
|
|
|
#ifdef __DBG_PRINT
|
|
DbgPrint ("dxdyLeft = %f\n", dxdyLeft);
|
|
#endif
|
|
|
|
gc->polygon.shader.ixLeft = ixLeft + (((GLuint) ixLeftFrac) >> 31);
|
|
gc->polygon.shader.ixLeftFrac = ixLeftFrac & ~0x80000000;
|
|
|
|
/* Compute big and little steps */
|
|
iLittle = FTOL(dxdyLeft);
|
|
gc->polygon.shader.dxLeftFrac = FLT_FRACTION(dxdyLeft - iLittle);
|
|
if (dxdyLeft < 0) {
|
|
iBig = iLittle - 1;
|
|
} else {
|
|
iBig = iLittle + 1;
|
|
}
|
|
if (gc->polygon.shader.modeFlags & __GL_SHADE_STENCIL_TEST) {
|
|
/*
|
|
** Compute the big and little stencil buffer steps. We walk the
|
|
** memory pointers for the stencil buffer along the edge of the
|
|
** triangle as we walk the edge. This way we don't have to
|
|
** recompute the buffer address as we go.
|
|
*/
|
|
elementSize = gc->stencilBuffer.buf.elementSize;
|
|
lineBytes = elementSize * gc->stencilBuffer.buf.outerWidth;
|
|
gc->polygon.shader.sbufLittle = lineBytes + iLittle * elementSize;
|
|
gc->polygon.shader.sbufBig = lineBytes + iBig * elementSize;
|
|
}
|
|
if (gc->polygon.shader.modeFlags & __GL_SHADE_DEPTH_TEST) {
|
|
/*
|
|
** Compute the big and little depth buffer steps. We walk the
|
|
** memory pointers for the depth buffer along the edge of the
|
|
** triangle as we walk the edge. This way we don't have to
|
|
** recompute the buffer address as we go.
|
|
*/
|
|
elementSize = gc->depthBuffer.buf.elementSize;
|
|
lineBytes = elementSize * gc->depthBuffer.buf.outerWidth;
|
|
gc->polygon.shader.zbufLittle = lineBytes + iLittle * elementSize;
|
|
gc->polygon.shader.zbufBig = lineBytes + iBig * elementSize;
|
|
}
|
|
gc->polygon.shader.dxLeftLittle = iLittle;
|
|
gc->polygon.shader.dxLeftBig = iBig;
|
|
}
|
|
|
|
static void SnapXRight(__GLshade *sh, __GLfloat xRight, __GLfloat dxdyRight)
|
|
{
|
|
GLint ixRight, ixRightFrac, iLittle, iBig;
|
|
|
|
ASSERT_CHOP_ROUND();
|
|
|
|
ixRight = __GL_VERTEX_FLOAT_TO_INT(xRight);
|
|
/* Pre-add .5 to allow truncation in spanWidth calculation */
|
|
ixRightFrac = __GL_VERTEX_PROMOTED_FRACTION(xRight) + 0x40000000;
|
|
|
|
sh->ixRight = ixRight + (((GLuint) ixRightFrac) >> 31);
|
|
sh->ixRightFrac = ixRightFrac & ~0x80000000;
|
|
|
|
/* Compute big and little steps */
|
|
iLittle = FTOL(dxdyRight);
|
|
sh->dxRightFrac = FLT_FRACTION(dxdyRight - iLittle);
|
|
if (dxdyRight < 0) {
|
|
iBig = iLittle - 1;
|
|
} else {
|
|
iBig = iLittle + 1;
|
|
}
|
|
sh->dxRightLittle = iLittle;
|
|
sh->dxRightBig = iBig;
|
|
}
|
|
|
|
|
|
void InitLineParamsVan (__GLcontext *gc, __GLvertex *v0, __GLvertex *v1,
|
|
__GLfloat invDelta)
|
|
{
|
|
__GLcoord *n0 = &(v0->normal);
|
|
__GLcoord *n1 = &(v1->normal);
|
|
__GLphongShader *phong = &(gc->polygon.shader.phong);
|
|
GLuint msm_colorMaterialChange, flags=0;
|
|
GLuint modeFlags = gc->polygon.shader.modeFlags;
|
|
|
|
msm_colorMaterialChange = gc->light.front.colorMaterialChange;
|
|
phong->face = __GL_FRONTFACE;
|
|
|
|
if ((gc->state.enables.general & __GL_COLOR_MATERIAL_ENABLE) &&
|
|
msm_colorMaterialChange && (modeFlags & __GL_SHADE_RGB))
|
|
flags |= __GL_PHONG_NEED_COLOR_XPOLATE;
|
|
|
|
//Compute Invariant color if possible
|
|
if (((!(flags & __GL_PHONG_NEED_COLOR_XPOLATE) ||
|
|
!(msm_colorMaterialChange & (__GL_MATERIAL_AMBIENT |
|
|
__GL_MATERIAL_EMISSIVE))) &&
|
|
(modeFlags & __GL_SHADE_RGB)) &&
|
|
!(flags & __GL_PHONG_NEED_EYE_XPOLATE))
|
|
{
|
|
ComputePhongInvarientRGBColor (gc);
|
|
flags |= __GL_PHONG_INV_COLOR_VALID;
|
|
}
|
|
|
|
//Store the flags
|
|
gc->polygon.shader.phong.flags |= flags;
|
|
|
|
phong->dndx.x = (n1->x - n0->x) * invDelta;
|
|
phong->dndx.y = (n1->y - n0->y) * invDelta;
|
|
phong->dndx.z = (n1->z - n0->z) * invDelta;
|
|
|
|
phong->nTmp.x = n0->x;
|
|
phong->nTmp.y = n0->y;
|
|
phong->nTmp.z = n0->z;
|
|
|
|
if (gc->polygon.shader.phong.flags & __GL_PHONG_NEED_EYE_XPOLATE)
|
|
{
|
|
phong->dedx.x = (v1->eyeX - v0->eyeX) * invDelta;
|
|
phong->dedx.y = (v1->eyeY - v0->eyeY) * invDelta;
|
|
phong->dedx.z = (v1->eyeZ - v0->eyeZ) * invDelta;
|
|
|
|
phong->eTmp.x = v0->eyeX;
|
|
phong->eTmp.y = v0->eyeY;
|
|
phong->eTmp.z = v0->eyeZ;
|
|
}
|
|
}
|
|
|
|
|
|
void InitLineParamsAccel (__GLcontext *gc, __GLvertex *v0, __GLvertex *v1,
|
|
__GLfloat invDelta)
|
|
{
|
|
__GLcoord normal;
|
|
__GLcoord *n0 = &(v0->normal);
|
|
__GLcoord *n1 = &normal;
|
|
__GLcoord *n2 = &(v1->normal);
|
|
__GLlightSourceMachine *lsm;
|
|
GLuint msm_colorMaterialChange, flags = 0;
|
|
GLuint modeFlags = gc->polygon.shader.modeFlags;
|
|
__GLphongShader *phong = &gc->polygon.shader.phong;
|
|
GLint face = phong->face, curL, w;
|
|
|
|
msm_colorMaterialChange = gc->light.front.colorMaterialChange;
|
|
phong->face = __GL_FRONTFACE;
|
|
w = gc->line.options.numPixels;
|
|
|
|
if ((gc->state.enables.general & __GL_COLOR_MATERIAL_ENABLE) &&
|
|
msm_colorMaterialChange && (modeFlags & __GL_SHADE_RGB))
|
|
flags |= __GL_PHONG_NEED_COLOR_XPOLATE;
|
|
|
|
//Compute Invariant color if possible
|
|
if (((!(flags & __GL_PHONG_NEED_COLOR_XPOLATE) ||
|
|
!(msm_colorMaterialChange & (__GL_MATERIAL_AMBIENT |
|
|
__GL_MATERIAL_EMISSIVE))) &&
|
|
(modeFlags & __GL_SHADE_RGB)) &&
|
|
!(flags & __GL_PHONG_NEED_EYE_XPOLATE))
|
|
{
|
|
ComputePhongInvarientRGBColor (gc);
|
|
flags |= __GL_PHONG_INV_COLOR_VALID;
|
|
}
|
|
|
|
//Store the flags
|
|
gc->polygon.shader.phong.flags |= flags;
|
|
|
|
phong->dndx.x = (n2->x - n0->x) * invDelta;
|
|
phong->dndx.y = (n2->y - n0->y) * invDelta;
|
|
phong->dndx.x = (n2->z - n0->z) * invDelta;
|
|
|
|
|
|
normal.x = (n0->x + n2->x)/2.0f;
|
|
normal.y = (n0->y + n2->y)/2.0f;
|
|
normal.z = (n0->z + n2->z)/2.0f;
|
|
if (gc->state.enables.general & __GL_NORMALIZE_ENABLE)
|
|
__glNormalize(&normal.x, &normal.x);
|
|
|
|
for (lsm = gc->light.sources, curL = 0; lsm;
|
|
lsm = lsm->next, curL++)
|
|
{
|
|
__GLphongPerLightData *pld = &(phong->perLight[curL]);
|
|
__GLcoord *L = &(lsm->unitVPpli); // L is already normalized here
|
|
__GLcoord *H = &(lsm->hHat); // H is already normalized here
|
|
GLfloat d0, d1, d2;
|
|
|
|
/***** Diffuse *****/
|
|
DOT (d0,n0,L);
|
|
DOT (d1,n1,L);
|
|
DOT (d2,n2,L);
|
|
|
|
__glCalcForwardDifferences(w, d0, d1, d2, &pld->Ddel, &pld->Ddel2);
|
|
pld->Dcurr = d0;
|
|
|
|
/***** Specular ******/
|
|
DOT (d0,n0,H);
|
|
DOT (d1,n1,H);
|
|
DOT (d2,n2,H);
|
|
|
|
__glCalcForwardDifferences(w, d0, d1, d2, &pld->Sdel, &pld->Sdel2);
|
|
pld->Scurr = d0;
|
|
}
|
|
|
|
phong->numLights = curL;
|
|
}
|
|
|
|
|
|
void InitSpanNEInterpolationVan (__GLcontext *gc)
|
|
{
|
|
GLint i;
|
|
__GLphongShader *phong = &(gc->polygon.shader.phong);
|
|
|
|
phong->nTmp = phong->nCur;
|
|
phong->eTmp = phong->eCur;
|
|
}
|
|
|
|
|
|
void InitSpanNInterpolationVan (__GLcontext *gc)
|
|
{
|
|
GLint i;
|
|
__GLphongShader *phong = &(gc->polygon.shader.phong);
|
|
|
|
phong->nTmp = phong->nCur;
|
|
}
|
|
|
|
void InitSpanInterpolationAccel (__GLcontext *gc)
|
|
{
|
|
__GLphongShader *phong = &(gc->polygon.shader.phong);
|
|
GLint face = phong->face;
|
|
__GLlightSourceMachine *lsm;
|
|
__GLcoord n0, n1, n2, dndx;
|
|
__GLcoord *N0 = &n0;
|
|
__GLcoord *N1 = &n1;
|
|
__GLcoord *N2 = &n2;
|
|
|
|
GLint curL, w, w2;
|
|
|
|
w = gc->polygon.shader.length;
|
|
w2 = w / 2;
|
|
|
|
if (face == __GL_FRONTFACE)
|
|
{
|
|
//msm = &gc->light.front;
|
|
n0.x = phong->nCur.x;
|
|
n0.y = phong->nCur.y;
|
|
n0.z = phong->nCur.z;
|
|
|
|
dndx.x = phong->dndx.x;
|
|
dndx.y = phong->dndx.y;
|
|
dndx.z = phong->dndx.z;
|
|
}
|
|
else
|
|
{
|
|
//msm = &gc->light.back;
|
|
n0.x = -phong->nCur.x;
|
|
n0.y = -phong->nCur.y;
|
|
n0.z = -phong->nCur.z;
|
|
|
|
dndx.x = -phong->dndx.x;
|
|
dndx.y = -phong->dndx.y;
|
|
dndx.z = -phong->dndx.z;
|
|
}
|
|
|
|
if (w > 2)
|
|
{
|
|
n2.x = n0.x + w*dndx.x;
|
|
n2.y = n0.y + w*dndx.y;
|
|
n2.z = n0.z + w*dndx.z;
|
|
|
|
n1.x = n0.x + w2*dndx.x;
|
|
n1.y = n0.y + w2*dndx.y;
|
|
n1.z = n0.z + w2*dndx.z;
|
|
}
|
|
|
|
if (gc->state.enables.general & __GL_NORMALIZE_ENABLE)
|
|
{
|
|
__glNormalize(&n0.x, &n0.x);
|
|
if (w > 2)
|
|
{
|
|
__glNormalize(&n1.x, &n1.x);
|
|
__glNormalize(&n2.x, &n2.x);
|
|
}
|
|
}
|
|
|
|
for (lsm = gc->light.sources, curL=0; lsm; lsm = lsm->next, curL++)
|
|
{
|
|
__GLphongPerLightData *pld = &(phong->perLight[curL]);
|
|
__GLcoord *L = &(lsm->unitVPpli); // L is already normalized here
|
|
__GLcoord *H = &(lsm->hHat); // H is already normalized here
|
|
GLfloat d0, d1, d2;
|
|
|
|
if (w > 2)
|
|
{
|
|
/***** Diffuse *****/
|
|
DOT (d0,N0,L);
|
|
DOT (d1,N1,L);
|
|
DOT (d2,N2,L);
|
|
|
|
__glCalcForwardDifferences(w, d0, d1, d2, &pld->Ddel,
|
|
&pld->Ddel2);
|
|
pld->Dcurr = d0;
|
|
|
|
/***** Specular ******/
|
|
DOT (d0, N0, H);
|
|
DOT (d1, N1, H);
|
|
DOT (d2, N2, H);
|
|
|
|
__glCalcForwardDifferences(w, d0, d1, d2, &pld->Sdel,
|
|
&pld->Sdel2);
|
|
pld->Scurr = d0;
|
|
}
|
|
else
|
|
{
|
|
/***** Diffuse *****/
|
|
DOT (d0,(&n0),L);
|
|
pld->Dcurr = d0;
|
|
pld->Ddel = 0.0;
|
|
pld->Ddel2 = 0.0;
|
|
|
|
/***** Specular ******/
|
|
DOT (d0,(&n0),H);
|
|
pld->Scurr = d0;
|
|
pld->Sdel = 0.0;
|
|
pld->Sdel2 = 0.0;
|
|
}
|
|
}
|
|
phong->numLights = curL;
|
|
}
|
|
|
|
|
|
void UpdateParamsAlongSpanAccel (__GLcontext *gc)
|
|
{
|
|
GLint i;
|
|
__GLphongShader *phong = &(gc->polygon.shader.phong);
|
|
|
|
for (i=0; i<phong->numLights; i++)
|
|
{
|
|
__GLphongPerLightData *pld = &(phong->perLight[i]);
|
|
|
|
/* Diffuse */
|
|
pld->Dcurr += pld->Ddel;
|
|
pld->Ddel += pld->Ddel2;
|
|
|
|
/* Specular */
|
|
pld->Scurr += pld->Sdel;
|
|
pld->Sdel += pld->Sdel2;
|
|
}
|
|
}
|
|
|
|
|
|
void UpdateNAlongSpanVan (__GLcontext *gc)
|
|
{
|
|
GLint i;
|
|
__GLphongShader *phong = &(gc->polygon.shader.phong);
|
|
|
|
phong->nTmp.x += phong->dndx.x;
|
|
phong->nTmp.y += phong->dndx.y;
|
|
phong->nTmp.z += phong->dndx.z;
|
|
}
|
|
|
|
void UpdateNEAlongSpanVan (__GLcontext *gc)
|
|
{
|
|
GLint i;
|
|
__GLphongShader *phong = &(gc->polygon.shader.phong);
|
|
|
|
phong->nTmp.x += phong->dndx.x;
|
|
phong->nTmp.y += phong->dndx.y;
|
|
phong->nTmp.z += phong->dndx.z;
|
|
|
|
phong->eTmp.x += phong->dedx.x;
|
|
phong->eTmp.y += phong->dedx.y;
|
|
phong->eTmp.z += phong->dedx.z;
|
|
phong->eTmp.w += phong->dedx.w;
|
|
}
|
|
|
|
|
|
GLboolean FASTCALL __glPhongCISpan(__GLcontext *gc)
|
|
{
|
|
__GLcolor *cp, outColor;
|
|
__GLfloat r, drdx;
|
|
__GLcoord dndx;
|
|
GLint w;
|
|
__GLphongShader *phong = &(gc->polygon.shader.phong);
|
|
GLboolean needColor = (gc->polygon.shader.phong.flags &
|
|
__GL_PHONG_NEED_COLOR_XPOLATE);
|
|
|
|
w = gc->polygon.shader.length;
|
|
cp = gc->polygon.shader.colors;
|
|
|
|
if (needColor)
|
|
{
|
|
phong->tmpColor.r = gc->polygon.shader.frag.color.r;
|
|
drdx = gc->polygon.shader.drdx;
|
|
}
|
|
|
|
while (--w >= 0)
|
|
{
|
|
/* Compute color using appropriate parameters */
|
|
(*gc->procs.phong.ComputeCIColor) (gc, &outColor);
|
|
|
|
cp->r = outColor.r;
|
|
|
|
/* Update parameters */
|
|
(*gc->procs.phong.UpdateAlongSpan) (gc);
|
|
|
|
if (needColor)
|
|
phong->tmpColor.r += drdx;
|
|
|
|
cp++;
|
|
}
|
|
|
|
return GL_FALSE;
|
|
}
|
|
|
|
GLboolean FASTCALL __glPhongRGBASpan (__GLcontext *gc)
|
|
{
|
|
__GLcolor *cp, dcdx, outColor;
|
|
__GLcoord dndx;
|
|
GLint w;
|
|
__GLphongShader *phong = &(gc->polygon.shader.phong);
|
|
GLboolean needColor = (gc->polygon.shader.phong.flags &
|
|
__GL_PHONG_NEED_COLOR_XPOLATE);
|
|
|
|
w = gc->polygon.shader.length;
|
|
cp = gc->polygon.shader.colors;
|
|
|
|
if (needColor)
|
|
{
|
|
phong->tmpColor = gc->polygon.shader.frag.color;
|
|
dcdx.r = gc->polygon.shader.drdx;
|
|
dcdx.g = gc->polygon.shader.dgdx;
|
|
dcdx.b = gc->polygon.shader.dbdx;
|
|
dcdx.a = gc->polygon.shader.dadx;
|
|
}
|
|
|
|
while (--w >= 0)
|
|
{
|
|
/* Compute color using appropriate parameters */
|
|
(*gc->procs.phong.ComputeRGBColor) (gc, &outColor);
|
|
|
|
cp->r = outColor.r;
|
|
cp->g = outColor.g;
|
|
cp->b = outColor.b;
|
|
cp->a = outColor.a;
|
|
|
|
/* Update parameters */
|
|
(*gc->procs.phong.UpdateAlongSpan) (gc);
|
|
|
|
if (needColor)
|
|
{
|
|
phong->tmpColor.r += dcdx.r;
|
|
phong->tmpColor.g += dcdx.g;
|
|
phong->tmpColor.b += dcdx.b;
|
|
phong->tmpColor.a += dcdx.a;
|
|
}
|
|
cp++;
|
|
}
|
|
return GL_FALSE;
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
* RGB, Use Normal, Fast-lights, no ColorMaterial*
|
|
*******************************************************************/
|
|
void ComputeRGBColorVanZippy (__GLcontext *gc, __GLcolor *outColor)
|
|
{
|
|
GLint face = gc->polygon.shader.phong.face;
|
|
__GLcoord n;
|
|
__GLfloat nxi, nyi, nzi;
|
|
__GLlightSourcePerMaterialMachine *lspmm;
|
|
__GLlightSourceMachine *lsm;
|
|
__GLlightSourceState *lss;
|
|
__GLcolor baseEmissiveAmbient;
|
|
__GLmaterialMachine *msm;
|
|
__GLfloat msm_alpha, msm_threshold, msm_scale, *msm_specTable;
|
|
GLuint numLights;
|
|
__GLfloat rsi=0.0, gsi=0.0, bsi=0.0;
|
|
__GLphongShader *phong = &(gc->polygon.shader.phong);
|
|
|
|
ASSERTOPENGL (phong->flags & __GL_PHONG_INV_COLOR_VALID,
|
|
"Zippy, invarient color should have been computed\n");
|
|
ASSERTOPENGL (!(phong->flags & __GL_PHONG_NEED_COLOR_XPOLATE),
|
|
"Zippy, no need for color interpolation\n");
|
|
|
|
n = phong->nTmp;
|
|
if (gc->state.enables.general & __GL_NORMALIZE_ENABLE)
|
|
__glNormalize(&n.x, &n.x);
|
|
|
|
if (face == __GL_FRONTFACE)
|
|
{
|
|
msm = &gc->light.front;
|
|
nxi = n.x;
|
|
nyi = n.y;
|
|
nzi = n.z;
|
|
}
|
|
else
|
|
{
|
|
msm = &gc->light.back;
|
|
nxi = -n.x;
|
|
nyi = -n.y;
|
|
nzi = -n.z;
|
|
}
|
|
|
|
rsi = phong->invColor.r;
|
|
gsi = phong->invColor.g;
|
|
bsi = phong->invColor.b;
|
|
|
|
msm_alpha = msm->alpha;
|
|
msm_scale = msm->scale;
|
|
msm_threshold = msm->threshold;
|
|
msm_specTable = msm->specTable;
|
|
|
|
for (lsm = gc->light.sources; lsm; lsm = lsm->next)
|
|
{
|
|
__GLfloat n1, n2;
|
|
|
|
lspmm = &lsm->front + face;
|
|
|
|
/* Add in specular and diffuse effect of light, if any */
|
|
n1 = nxi * lsm->unitVPpli.x + nyi * lsm->unitVPpli.y +
|
|
nzi * lsm->unitVPpli.z;
|
|
|
|
if (__GL_FLOAT_GTZ(n1))
|
|
{
|
|
n2 = (nxi * lsm->hHat.x + nyi * lsm->hHat.y + nzi *
|
|
lsm->hHat.z) - msm_threshold;
|
|
if (__GL_FLOAT_GEZ(n2))
|
|
{
|
|
__GLfloat fx = n2 * msm_scale + __glHalf;
|
|
|
|
if( fx < (__GLfloat)__GL_SPEC_LOOKUP_TABLE_SIZE )
|
|
n2 = msm_specTable[(GLint)fx];
|
|
else
|
|
n2 = __glOne;
|
|
rsi += n2 * lspmm->specular.r;
|
|
gsi += n2 * lspmm->specular.g;
|
|
bsi += n2 * lspmm->specular.b;
|
|
}
|
|
rsi += n1 * lspmm->diffuse.r;
|
|
gsi += n1 * lspmm->diffuse.g;
|
|
bsi += n1 * lspmm->diffuse.b;
|
|
}
|
|
}
|
|
__GL_CLAMP_R(outColor->r, gc, rsi);
|
|
__GL_CLAMP_G(outColor->g, gc, gsi);
|
|
__GL_CLAMP_B(outColor->b, gc, bsi);
|
|
outColor->a = msm_alpha;
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
* RGB, Use Normal, Fast-lights, ColorMaterial *
|
|
*******************************************************************/
|
|
void ComputeRGBColorVanFast (__GLcontext *gc, __GLcolor *outColor)
|
|
{
|
|
GLint face = gc->polygon.shader.phong.face;
|
|
__GLfloat nxi, nyi, nzi;
|
|
__GLfloat zero;
|
|
__GLlightSourcePerMaterialMachine *lspmm;
|
|
__GLlightSourceMachine *lsm;
|
|
__GLlightSourceState *lss;
|
|
__GLfloat ri, gi, bi;
|
|
__GLfloat alpha;
|
|
__GLcolor emissiveAmbientI;
|
|
__GLcolor inColor;
|
|
__GLcolor diffuseSpecularI;
|
|
__GLcolor baseEmissiveAmbient;
|
|
__GLmaterialMachine *msm;
|
|
__GLcolor lm_ambient;
|
|
__GLfloat msm_alpha, msm_threshold, msm_scale, *msm_specTable;
|
|
GLuint msm_colorMaterialChange;
|
|
__GLphongShader *phong = &(gc->polygon.shader.phong);
|
|
__GLcoord n;
|
|
|
|
zero = __glZero;
|
|
|
|
|
|
// Optimization: If no colors have been interpolated
|
|
// Use the Zippy function
|
|
if (!(phong->flags & __GL_PHONG_NEED_COLOR_XPOLATE))
|
|
ComputeRGBColorVanZippy (gc, outColor);
|
|
|
|
inColor = phong->tmpColor;
|
|
|
|
n = phong->nTmp;
|
|
if (gc->state.enables.general & __GL_NORMALIZE_ENABLE)
|
|
__glNormalize(&n.x, &n.x);
|
|
|
|
if (face == __GL_FRONTFACE)
|
|
{
|
|
msm = &gc->light.front;
|
|
nxi = n.x;
|
|
nyi = n.y;
|
|
nzi = n.z;
|
|
}
|
|
else
|
|
{
|
|
msm = &gc->light.back;
|
|
nxi = -n.x;
|
|
nyi = -n.y;
|
|
nzi = -n.z;
|
|
}
|
|
|
|
msm_scale = msm->scale;
|
|
msm_threshold = msm->threshold;
|
|
msm_specTable = msm->specTable;
|
|
msm_alpha = msm->alpha;
|
|
msm_colorMaterialChange = msm->colorMaterialChange;
|
|
|
|
// Save latest colors normalized to 0..1
|
|
ri = inColor.r * gc->oneOverRedVertexScale;
|
|
gi = inColor.g * gc->oneOverGreenVertexScale;
|
|
bi = inColor.b * gc->oneOverBlueVertexScale;
|
|
alpha = inColor.a;
|
|
|
|
// Compute invarient emissive and ambient components for this vertex.
|
|
if (phong->flags & __GL_PHONG_INV_COLOR_VALID)
|
|
{
|
|
emissiveAmbientI.r = phong->invColor.r;
|
|
emissiveAmbientI.g = phong->invColor.g;
|
|
emissiveAmbientI.b = phong->invColor.b;
|
|
}
|
|
else
|
|
{
|
|
lm_ambient.r = gc->state.light.model.ambient.r;
|
|
lm_ambient.g = gc->state.light.model.ambient.g;
|
|
lm_ambient.b = gc->state.light.model.ambient.b;
|
|
|
|
baseEmissiveAmbient.r = msm->paSceneColor.r;
|
|
baseEmissiveAmbient.g = msm->paSceneColor.g;
|
|
baseEmissiveAmbient.b = msm->paSceneColor.b;
|
|
|
|
if (msm_colorMaterialChange & __GL_MATERIAL_AMBIENT)
|
|
{
|
|
emissiveAmbientI.r = baseEmissiveAmbient.r
|
|
+ ri * lm_ambient.r;
|
|
emissiveAmbientI.g = baseEmissiveAmbient.g
|
|
+ gi * lm_ambient.g;
|
|
emissiveAmbientI.b = baseEmissiveAmbient.b
|
|
+ bi * lm_ambient.b;
|
|
|
|
// Add per-light per-material ambient
|
|
for (lsm = gc->light.sources; lsm; lsm = lsm->next)
|
|
{
|
|
lss = lsm->state;
|
|
emissiveAmbientI.r += ri * lss->ambient.r;
|
|
emissiveAmbientI.g += gi * lss->ambient.g;
|
|
emissiveAmbientI.b += bi * lss->ambient.b;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (lsm = gc->light.sources; lsm; lsm = lsm->next)
|
|
{
|
|
lspmm = &lsm->front + face;
|
|
baseEmissiveAmbient.r += lspmm->ambient.r;
|
|
baseEmissiveAmbient.g += lspmm->ambient.g;
|
|
baseEmissiveAmbient.b += lspmm->ambient.b;
|
|
}
|
|
emissiveAmbientI.r = baseEmissiveAmbient.r + inColor.r;
|
|
emissiveAmbientI.g = baseEmissiveAmbient.g + inColor.g;
|
|
emissiveAmbientI.b = baseEmissiveAmbient.b + inColor.b;
|
|
}
|
|
}
|
|
|
|
// Compute the diffuse and specular components for this vertex.
|
|
|
|
diffuseSpecularI.r = zero;
|
|
diffuseSpecularI.g = zero;
|
|
diffuseSpecularI.b = zero;
|
|
|
|
for (lsm = gc->light.sources; lsm; lsm = lsm->next)
|
|
{
|
|
__GLfloat n1, n2;
|
|
|
|
lss = lsm->state;
|
|
lspmm = &lsm->front + face;
|
|
|
|
/* Add in specular and diffuse effect of light, if any */
|
|
n1 = nxi * lsm->unitVPpli.x + nyi * lsm->unitVPpli.y +
|
|
nzi * lsm->unitVPpli.z;
|
|
|
|
if (__GL_FLOAT_GTZ(n1))
|
|
{
|
|
n2 = nxi * lsm->hHat.x + nyi * lsm->hHat.y + nzi * lsm->hHat.z;
|
|
n2 -= msm_threshold;
|
|
if (__GL_FLOAT_GEZ(n2))
|
|
{
|
|
__GLfloat fx = n2 * msm_scale + __glHalf;
|
|
if( fx < (__GLfloat)__GL_SPEC_LOOKUP_TABLE_SIZE )
|
|
n2 = msm_specTable[(GLint)fx];
|
|
else
|
|
n2 = __glOne;
|
|
if (msm_colorMaterialChange & __GL_MATERIAL_SPECULAR)
|
|
{
|
|
/* Recompute per-light per-material cached specular */
|
|
diffuseSpecularI.r += n2 * ri * lss->specular.r;
|
|
diffuseSpecularI.g += n2 * gi * lss->specular.g;
|
|
diffuseSpecularI.b += n2 * bi * lss->specular.b;
|
|
}
|
|
else
|
|
{
|
|
diffuseSpecularI.r += n2 * lspmm->specular.r;
|
|
diffuseSpecularI.g += n2 * lspmm->specular.g;
|
|
diffuseSpecularI.b += n2 * lspmm->specular.b;
|
|
}
|
|
}
|
|
|
|
if (msm_colorMaterialChange & __GL_MATERIAL_DIFFUSE)
|
|
{
|
|
/* Recompute per-light per-material cached diffuse */
|
|
diffuseSpecularI.r += n1 * ri * lss->diffuse.r;
|
|
diffuseSpecularI.g += n1 * gi * lss->diffuse.g;
|
|
diffuseSpecularI.b += n1 * bi * lss->diffuse.b;
|
|
}
|
|
else
|
|
{
|
|
diffuseSpecularI.r += n1 * lspmm->diffuse.r;
|
|
diffuseSpecularI.g += n1 * lspmm->diffuse.g;
|
|
diffuseSpecularI.b += n1 * lspmm->diffuse.b;
|
|
}
|
|
}
|
|
}
|
|
|
|
__GL_CLAMP_R(outColor->r, gc, emissiveAmbientI.r + diffuseSpecularI.r);
|
|
__GL_CLAMP_G(outColor->g, gc, emissiveAmbientI.g + diffuseSpecularI.g);
|
|
__GL_CLAMP_B(outColor->b, gc, emissiveAmbientI.b + diffuseSpecularI.b);
|
|
|
|
if (msm_colorMaterialChange & __GL_MATERIAL_DIFFUSE)
|
|
{
|
|
__GL_CLAMP_A(outColor->a, gc, alpha);
|
|
}
|
|
else
|
|
outColor->a = msm_alpha;
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
* RGB, Use Normal, Slow-lights, ColorMaterial *
|
|
*******************************************************************/
|
|
void ComputeRGBColorVanSlow (__GLcontext *gc, __GLcolor *outColor)
|
|
{
|
|
GLint face = gc->polygon.shader.phong.face;
|
|
__GLfloat nxi, nyi, nzi;
|
|
__GLfloat zero;
|
|
__GLlightSourcePerMaterialMachine *lspmm;
|
|
__GLlightSourceMachine *lsm;
|
|
__GLlightSourceState *lss;
|
|
__GLfloat ri, gi, bi;
|
|
__GLfloat alpha;
|
|
__GLfloat rsi, gsi, bsi;
|
|
__GLcolor sceneColorI;
|
|
__GLmaterialMachine *msm;
|
|
__GLcolor inColor;
|
|
__GLcolor lm_ambient;
|
|
__GLfloat msm_alpha, msm_threshold, msm_scale, *msm_specTable;
|
|
__GLcolor msm_paSceneColor;
|
|
GLuint msm_colorMaterialChange;
|
|
GLboolean eyeWIsZero, localViewer;
|
|
static __GLcoord Pe = { 0, 0, 0, 1 };
|
|
__GLcoord n;
|
|
__GLphongShader *phong = &(gc->polygon.shader.phong);
|
|
|
|
zero = __glZero;
|
|
|
|
inColor = phong->tmpColor;
|
|
|
|
n = phong->nTmp;
|
|
if (gc->state.enables.general & __GL_NORMALIZE_ENABLE)
|
|
__glNormalize(&n.x, &n.x);
|
|
|
|
if (face == __GL_FRONTFACE)
|
|
{
|
|
msm = &gc->light.front;
|
|
nxi = n.x;
|
|
nyi = n.y;
|
|
nzi = n.z;
|
|
}
|
|
else
|
|
{
|
|
msm = &gc->light.back;
|
|
nxi = -n.x;
|
|
nyi = -n.y;
|
|
nzi = -n.z;
|
|
}
|
|
|
|
lm_ambient.r = gc->state.light.model.ambient.r;
|
|
lm_ambient.g = gc->state.light.model.ambient.g;
|
|
lm_ambient.b = gc->state.light.model.ambient.b;
|
|
|
|
msm_scale = msm->scale;
|
|
msm_threshold = msm->threshold;
|
|
msm_specTable = msm->specTable;
|
|
msm_alpha = msm->alpha;
|
|
msm_colorMaterialChange = msm->colorMaterialChange;
|
|
msm_paSceneColor = msm->paSceneColor;
|
|
|
|
localViewer = gc->state.light.model.localViewer;
|
|
|
|
// Get invarient scene color if there is no ambient or emissive color
|
|
// material.
|
|
|
|
sceneColorI.r = msm_paSceneColor.r;
|
|
sceneColorI.g = msm_paSceneColor.g;
|
|
sceneColorI.b = msm_paSceneColor.b;
|
|
|
|
if (phong->flags & __GL_PHONG_NEED_EYE_XPOLATE)
|
|
{
|
|
// Save latest colors normalized to 0..1
|
|
|
|
ri = inColor.r * gc->oneOverRedVertexScale;
|
|
gi = inColor.g * gc->oneOverGreenVertexScale;
|
|
bi = inColor.b * gc->oneOverBlueVertexScale;
|
|
alpha = inColor.a;
|
|
|
|
// Compute scene color.
|
|
// If color has not changed, the previous sceneColorI values are
|
|
// used!
|
|
|
|
if (msm_colorMaterialChange & (__GL_MATERIAL_AMBIENT |
|
|
__GL_MATERIAL_EMISSIVE))
|
|
{
|
|
if (msm_colorMaterialChange & __GL_MATERIAL_AMBIENT)
|
|
{
|
|
sceneColorI.r = msm_paSceneColor.r + ri * lm_ambient.r;
|
|
sceneColorI.g = msm_paSceneColor.g + gi * lm_ambient.g;
|
|
sceneColorI.b = msm_paSceneColor.b + bi * lm_ambient.b;
|
|
}
|
|
else
|
|
{
|
|
sceneColorI.r = msm_paSceneColor.r + inColor.r;
|
|
sceneColorI.g = msm_paSceneColor.g + inColor.g;
|
|
sceneColorI.b = msm_paSceneColor.b + inColor.b;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Compute the diffuse and specular components for this vertex.
|
|
rsi = sceneColorI.r;
|
|
gsi = sceneColorI.g;
|
|
bsi = sceneColorI.b;
|
|
|
|
eyeWIsZero = __GL_FLOAT_EQZ(phong->eTmp.w);
|
|
|
|
for (lsm = gc->light.sources; lsm; lsm = lsm->next)
|
|
{
|
|
__GLfloat n1, n2;
|
|
|
|
lss = lsm->state;
|
|
lspmm = &lsm->front + face;
|
|
|
|
if (lsm->slowPath || eyeWIsZero)
|
|
{
|
|
__GLcoord hHat, vPli, vPliHat, vPeHat;
|
|
__GLfloat att, attSpot;
|
|
__GLfloat hv[3];
|
|
|
|
/* Compute unit h[i] */
|
|
__glVecSub4(&vPli, &phong->eTmp, &lsm->position);
|
|
__glNormalize(&vPliHat.x, &vPli.x);
|
|
if (localViewer)
|
|
{
|
|
__glVecSub4(&vPeHat, &phong->eTmp, &Pe);
|
|
__glNormalize(&vPeHat.x, &vPeHat.x);
|
|
hv[0] = vPliHat.x + vPeHat.x;
|
|
hv[1] = vPliHat.y + vPeHat.y;
|
|
hv[2] = vPliHat.z + vPeHat.z;
|
|
}
|
|
else
|
|
{
|
|
hv[0] = vPliHat.x;
|
|
hv[1] = vPliHat.y;
|
|
hv[2] = vPliHat.z + __glOne;
|
|
}
|
|
__glNormalize(&hHat.x, hv);
|
|
|
|
/* Compute attenuation */
|
|
if (__GL_FLOAT_NEZ(lsm->position.w))
|
|
{
|
|
__GLfloat k0, k1, k2, dist;
|
|
|
|
k0 = lsm->constantAttenuation;
|
|
k1 = lsm->linearAttenuation;
|
|
k2 = lsm->quadraticAttenuation;
|
|
if (__GL_FLOAT_EQZ(k1) && __GL_FLOAT_EQZ(k2))
|
|
{
|
|
/* Use pre-computed 1/k0 */
|
|
att = lsm->attenuation;
|
|
}
|
|
else
|
|
{
|
|
__GLfloat den;
|
|
|
|
dist = __GL_SQRTF(vPli.x*vPli.x + vPli.y*vPli.y
|
|
+ vPli.z*vPli.z);
|
|
den = k0 + k1 * dist + k2 * dist * dist;
|
|
att = __GL_FLOAT_EQZ(den) ? __glOne : __glOne / den;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
att = __glOne;
|
|
}
|
|
|
|
/* Compute spot effect if light is a spot light */
|
|
attSpot = att;
|
|
if (lsm->isSpot)
|
|
{
|
|
__GLfloat dot, px, py, pz;
|
|
|
|
px = -vPliHat.x;
|
|
py = -vPliHat.y;
|
|
pz = -vPliHat.z;
|
|
dot = px * lsm->direction.x + py * lsm->direction.y
|
|
+ pz * lsm->direction.z;
|
|
if ((dot >= lsm->threshold) && (dot >= lsm->cosCutOffAngle))
|
|
{
|
|
GLint ix = (GLint)((dot - lsm->threshold) * lsm->scale
|
|
+ __glHalf);
|
|
if (ix < __GL_SPOT_LOOKUP_TABLE_SIZE)
|
|
attSpot = att * lsm->spotTable[ix];
|
|
}
|
|
else
|
|
{
|
|
attSpot = zero;
|
|
}
|
|
}
|
|
|
|
/* Add in remaining effect of light, if any */
|
|
if (attSpot)
|
|
{
|
|
__GLfloat n1, n2;
|
|
__GLcolor sum;
|
|
|
|
if (msm_colorMaterialChange & __GL_MATERIAL_AMBIENT)
|
|
{
|
|
sum.r = ri * lss->ambient.r;
|
|
sum.g = gi * lss->ambient.g;
|
|
sum.b = bi * lss->ambient.b;
|
|
}
|
|
else
|
|
{
|
|
sum.r = lspmm->ambient.r;
|
|
sum.g = lspmm->ambient.g;
|
|
sum.b = lspmm->ambient.b;
|
|
}
|
|
|
|
n1 = nxi * vPliHat.x + nyi * vPliHat.y + nzi * vPliHat.z;
|
|
if (__GL_FLOAT_GTZ(n1))
|
|
{
|
|
n2 = nxi * hHat.x + nyi * hHat.y + nzi * hHat.z;
|
|
n2 -= msm_threshold;
|
|
if (__GL_FLOAT_GEZ(n2))
|
|
{
|
|
__GLfloat fx = n2 * msm_scale + __glHalf;
|
|
if( fx < (__GLfloat)__GL_SPEC_LOOKUP_TABLE_SIZE )
|
|
n2 = msm_specTable[(GLint)fx];
|
|
else
|
|
n2 = __glOne;
|
|
if (msm_colorMaterialChange & __GL_MATERIAL_SPECULAR)
|
|
{
|
|
/* Recompute per-light per-material cached specular */
|
|
sum.r += n2 * ri * lss->specular.r;
|
|
sum.g += n2 * gi * lss->specular.g;
|
|
sum.b += n2 * bi * lss->specular.b;
|
|
}
|
|
else
|
|
{
|
|
sum.r += n2 * lspmm->specular.r;
|
|
sum.g += n2 * lspmm->specular.g;
|
|
sum.b += n2 * lspmm->specular.b;
|
|
}
|
|
}
|
|
if (msm_colorMaterialChange & __GL_MATERIAL_DIFFUSE)
|
|
{
|
|
/* Recompute per-light per-material cached diffuse */
|
|
sum.r += n1 * ri * lss->diffuse.r;
|
|
sum.g += n1 * gi * lss->diffuse.g;
|
|
sum.b += n1 * bi * lss->diffuse.b;
|
|
}
|
|
else
|
|
{
|
|
sum.r += n1 * lspmm->diffuse.r;
|
|
sum.g += n1 * lspmm->diffuse.g;
|
|
sum.b += n1 * lspmm->diffuse.b;
|
|
}
|
|
}
|
|
|
|
rsi += attSpot * sum.r;
|
|
gsi += attSpot * sum.g;
|
|
bsi += attSpot * sum.b;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
__GLfloat n1, n2;
|
|
|
|
if (msm_colorMaterialChange & __GL_MATERIAL_AMBIENT)
|
|
{
|
|
rsi += ri * lss->ambient.r;
|
|
gsi += gi * lss->ambient.g;
|
|
bsi += bi * lss->ambient.b;
|
|
}
|
|
else
|
|
{
|
|
rsi += lspmm->ambient.r;
|
|
gsi += lspmm->ambient.g;
|
|
bsi += lspmm->ambient.b;
|
|
}
|
|
|
|
/* Add in specular and diffuse effect of light, if any */
|
|
n1 = nxi * lsm->unitVPpli.x + nyi * lsm->unitVPpli.y +
|
|
nzi * lsm->unitVPpli.z;
|
|
if (__GL_FLOAT_GTZ(n1))
|
|
{
|
|
n2= nxi * lsm->hHat.x + nyi * lsm->hHat.y + nzi * lsm->hHat.z;
|
|
n2 -= msm_threshold;
|
|
if (__GL_FLOAT_GEZ(n2))
|
|
{
|
|
__GLfloat fx = n2 * msm_scale + __glHalf;
|
|
if( fx < (__GLfloat)__GL_SPEC_LOOKUP_TABLE_SIZE )
|
|
n2 = msm_specTable[(GLint)fx];
|
|
else
|
|
n2 = __glOne;
|
|
if (msm_colorMaterialChange & __GL_MATERIAL_SPECULAR)
|
|
{
|
|
/* Recompute per-light per-material cached specular */
|
|
rsi += n2 * ri * lss->specular.r;
|
|
gsi += n2 * gi * lss->specular.g;
|
|
bsi += n2 * bi * lss->specular.b;
|
|
}
|
|
else
|
|
{
|
|
rsi += n2 * lspmm->specular.r;
|
|
gsi += n2 * lspmm->specular.g;
|
|
bsi += n2 * lspmm->specular.b;
|
|
}
|
|
}
|
|
if (msm_colorMaterialChange & __GL_MATERIAL_DIFFUSE)
|
|
{
|
|
/* Recompute per-light per-material cached diffuse */
|
|
rsi += n1 * ri * lss->diffuse.r;
|
|
gsi += n1 * gi * lss->diffuse.g;
|
|
bsi += n1 * bi * lss->diffuse.b;
|
|
}
|
|
else
|
|
{
|
|
rsi += n1 * lspmm->diffuse.r;
|
|
gsi += n1 * lspmm->diffuse.g;
|
|
bsi += n1 * lspmm->diffuse.b;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
__GL_CLAMP_R(outColor->r, gc, rsi);
|
|
__GL_CLAMP_G(outColor->g, gc, gsi);
|
|
__GL_CLAMP_B(outColor->b, gc, bsi);
|
|
|
|
if (msm_colorMaterialChange & __GL_MATERIAL_DIFFUSE)
|
|
{
|
|
__GL_CLAMP_A(outColor->a, gc, alpha);
|
|
}
|
|
else
|
|
outColor->a = msm_alpha;
|
|
}
|
|
|
|
/*******************************************************************
|
|
* RGB, Use Dot, Fast-lights, no ColorMaterial *
|
|
*******************************************************************/
|
|
void ComputeRGBColorAccelZippy (__GLcontext *gc, __GLcolor *outColor)
|
|
{
|
|
GLint face = gc->polygon.shader.phong.face;
|
|
__GLlightSourcePerMaterialMachine *lspmm;
|
|
__GLlightSourceMachine *lsm;
|
|
__GLlightSourceState *lss;
|
|
__GLcolor baseEmissiveAmbient;
|
|
__GLmaterialMachine *msm;
|
|
__GLfloat msm_alpha, msm_threshold, msm_scale, *msm_specTable;
|
|
GLuint numLights;
|
|
__GLfloat rsi=0.0, gsi=0.0, bsi=0.0;
|
|
__GLphongShader *phong = &(gc->polygon.shader.phong);
|
|
GLint curL;
|
|
|
|
if (face == __GL_FRONTFACE)
|
|
msm = &gc->light.front;
|
|
else
|
|
msm = &gc->light.back;
|
|
|
|
ASSERTOPENGL (phong->flags & __GL_PHONG_INV_COLOR_VALID,
|
|
"Zippy, invarient color should have been computed\n");
|
|
ASSERTOPENGL (!(phong->flags & __GL_PHONG_NEED_COLOR_XPOLATE),
|
|
"Zippy, no need for color interpolation\n");
|
|
|
|
rsi = phong->invColor.r;
|
|
gsi = phong->invColor.g;
|
|
bsi = phong->invColor.b;
|
|
msm_alpha = msm->alpha;
|
|
|
|
msm_scale = msm->scale;
|
|
msm_threshold = msm->threshold;
|
|
msm_specTable = msm->specTable;
|
|
|
|
for (lsm = gc->light.sources, curL = 0; lsm; lsm = lsm->next, curL++)
|
|
{
|
|
__GLfloat n1, n2, x, y, x2, y2;
|
|
__GLphongPerLightData *pld = &(phong->perLight[curL]);
|
|
__GLfloat a, b, c, d, e, f, g, h, i;
|
|
|
|
/* Add in specular and diffuse effect of light, if any */
|
|
n1 = pld->Dcurr;
|
|
lspmm = &lsm->front + face;
|
|
if (__GL_FLOAT_GTZ(n1))
|
|
{
|
|
#ifdef __FASTEST
|
|
n2 = pld->Scurr - msm_threshold;
|
|
#endif //__FASTEST
|
|
#ifdef __SLOW
|
|
x = phong->tmp_pos.x; x2 = x*x;
|
|
y = phong->tmp_pos.y; y2 = y*y;
|
|
|
|
a = pld->A[0]; b = pld->A[1];
|
|
c = pld->A[2]; d = pld->A[3];
|
|
e = pld->A[4]; f = pld->A[5];
|
|
g = pld->A[6]; h = pld->A[7];
|
|
i = pld->A[8];
|
|
|
|
n2 = (a*x+b*y+c)/__GL_SQRTF(d*x2+e*x*y+f*y2+g*x+h*y+i);
|
|
#endif //__SLOW
|
|
#ifdef __FASTER
|
|
x = phong->tmp_pos.x; x2 = x*x;
|
|
y = phong->tmp_pos.y; y2 = y*y;
|
|
|
|
n2 = pld->S[5]*x2 + pld->S[4]*x*y + pld->S[3]*y2 + pld->S[2]*x +
|
|
pld->S[1]*y + pld->S[0];
|
|
#endif //__FASTER
|
|
|
|
//n2 -= msm_threshold;
|
|
if (__GL_FLOAT_GEZ(n2))
|
|
{
|
|
__GLfloat fx = n2 * msm_scale + __glHalf;
|
|
|
|
if( fx < (__GLfloat)__GL_SPEC_LOOKUP_TABLE_SIZE )
|
|
n2 = msm_specTable[(GLint)fx];
|
|
else
|
|
n2 = __glOne;
|
|
rsi += n2 * lspmm->specular.r;
|
|
gsi += n2 * lspmm->specular.g;
|
|
bsi += n2 * lspmm->specular.b;
|
|
|
|
}
|
|
rsi += n1 * lspmm->diffuse.r;
|
|
gsi += n1 * lspmm->diffuse.g;
|
|
bsi += n1 * lspmm->diffuse.b;
|
|
}
|
|
}
|
|
__GL_CLAMP_R(outColor->r, gc, rsi);
|
|
__GL_CLAMP_G(outColor->g, gc, gsi);
|
|
__GL_CLAMP_B(outColor->b, gc, bsi);
|
|
outColor->a = msm_alpha;
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
* RGB, Use Dot, Fast-lights, ColorMaterial *
|
|
*******************************************************************/
|
|
void ComputeRGBColorAccelFast (__GLcontext *gc, __GLcolor *outColor)
|
|
{
|
|
GLint face = gc->polygon.shader.phong.face;
|
|
__GLfloat zero;
|
|
__GLlightSourcePerMaterialMachine *lspmm;
|
|
__GLlightSourceMachine *lsm;
|
|
__GLlightSourceState *lss;
|
|
__GLfloat ri, gi, bi;
|
|
__GLfloat alpha;
|
|
__GLcolor emissiveAmbientI;
|
|
__GLcolor inColor;
|
|
__GLcolor diffuseSpecularI;
|
|
__GLcolor baseEmissiveAmbient;
|
|
__GLmaterialMachine *msm;
|
|
__GLcolor lm_ambient;
|
|
__GLfloat msm_alpha, msm_threshold, msm_scale, *msm_specTable;
|
|
GLuint msm_colorMaterialChange;
|
|
__GLphongShader *phong = &(gc->polygon.shader.phong);
|
|
GLint curL;
|
|
|
|
zero = __glZero;
|
|
|
|
if (face == __GL_FRONTFACE)
|
|
msm = &gc->light.front;
|
|
else
|
|
msm = &gc->light.back;
|
|
|
|
msm_colorMaterialChange = msm->colorMaterialChange;
|
|
|
|
ASSERTOPENGL (phong->flags & __GL_PHONG_NEED_COLOR_XPOLATE,
|
|
"Fast, need color interpolation\n");
|
|
#if 0
|
|
ASSERTOPENGL (!(gc->state.enables.general & __GL_NORMALIZE_ENABLE),
|
|
"Normalization should have been disabled\n");
|
|
#endif
|
|
|
|
inColor = phong->tmpColor;
|
|
|
|
msm_scale = msm->scale;
|
|
msm_threshold = msm->threshold;
|
|
msm_specTable = msm->specTable;
|
|
msm_alpha = msm->alpha;
|
|
|
|
// Save latest colors normalized to 0..1
|
|
ri = inColor.r * gc->oneOverRedVertexScale;
|
|
gi = inColor.g * gc->oneOverGreenVertexScale;
|
|
bi = inColor.b * gc->oneOverBlueVertexScale;
|
|
alpha = inColor.a;
|
|
|
|
// Compute invarient emissive and ambient components for this vertex.
|
|
if (phong->flags & __GL_PHONG_INV_COLOR_VALID)
|
|
{
|
|
emissiveAmbientI.r = phong->invColor.r;
|
|
emissiveAmbientI.g = phong->invColor.g;
|
|
emissiveAmbientI.b = phong->invColor.b;
|
|
}
|
|
else
|
|
{
|
|
lm_ambient.r = gc->state.light.model.ambient.r;
|
|
lm_ambient.g = gc->state.light.model.ambient.g;
|
|
lm_ambient.b = gc->state.light.model.ambient.b;
|
|
|
|
baseEmissiveAmbient.r = msm->paSceneColor.r;
|
|
baseEmissiveAmbient.g = msm->paSceneColor.g;
|
|
baseEmissiveAmbient.b = msm->paSceneColor.b;
|
|
|
|
if (msm_colorMaterialChange & __GL_MATERIAL_AMBIENT)
|
|
{
|
|
emissiveAmbientI.r = baseEmissiveAmbient.r
|
|
+ ri * lm_ambient.r;
|
|
emissiveAmbientI.g = baseEmissiveAmbient.g
|
|
+ gi * lm_ambient.g;
|
|
emissiveAmbientI.b = baseEmissiveAmbient.b
|
|
+ bi * lm_ambient.b;
|
|
|
|
// Add per-light per-material ambient
|
|
for (lsm = gc->light.sources; lsm; lsm = lsm->next)
|
|
{
|
|
lss = lsm->state;
|
|
emissiveAmbientI.r += ri * lss->ambient.r;
|
|
emissiveAmbientI.g += gi * lss->ambient.g;
|
|
emissiveAmbientI.b += bi * lss->ambient.b;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (lsm = gc->light.sources; lsm; lsm = lsm->next)
|
|
{
|
|
lspmm = &lsm->front + face;
|
|
baseEmissiveAmbient.r += lspmm->ambient.r;
|
|
baseEmissiveAmbient.g += lspmm->ambient.g;
|
|
baseEmissiveAmbient.b += lspmm->ambient.b;
|
|
}
|
|
emissiveAmbientI.r = baseEmissiveAmbient.r + inColor.r;
|
|
emissiveAmbientI.g = baseEmissiveAmbient.g + inColor.g;
|
|
emissiveAmbientI.b = baseEmissiveAmbient.b + inColor.b;
|
|
}
|
|
}
|
|
|
|
// Compute the diffuse and specular components for this vertex.
|
|
diffuseSpecularI.r = zero;
|
|
diffuseSpecularI.g = zero;
|
|
diffuseSpecularI.b = zero;
|
|
|
|
for (lsm = gc->light.sources, curL=0; lsm; lsm = lsm->next, curL++)
|
|
{
|
|
__GLfloat n1, n2;
|
|
__GLphongPerLightData *pld = &(phong->perLight[curL]);
|
|
|
|
lss = lsm->state;
|
|
lspmm = &lsm->front + face;
|
|
|
|
/* Add in specular and diffuse effect of light, if any */
|
|
n1 = pld->Dcurr;
|
|
|
|
if (__GL_FLOAT_GTZ(n1))
|
|
{
|
|
n2 = pld->Scurr - msm_threshold;
|
|
if (__GL_FLOAT_GEZ(n2))
|
|
{
|
|
__GLfloat fx = n2 * msm_scale + __glHalf;
|
|
if( fx < (__GLfloat)__GL_SPEC_LOOKUP_TABLE_SIZE )
|
|
n2 = msm_specTable[(GLint)fx];
|
|
else
|
|
n2 = __glOne;
|
|
if (msm_colorMaterialChange & __GL_MATERIAL_SPECULAR)
|
|
{
|
|
/* Recompute per-light per-material cached specular */
|
|
diffuseSpecularI.r += n2 * ri * lss->specular.r;
|
|
diffuseSpecularI.g += n2 * gi * lss->specular.g;
|
|
diffuseSpecularI.b += n2 * bi * lss->specular.b;
|
|
}
|
|
else
|
|
{
|
|
diffuseSpecularI.r += n2 * lspmm->specular.r;
|
|
diffuseSpecularI.g += n2 * lspmm->specular.g;
|
|
diffuseSpecularI.b += n2 * lspmm->specular.b;
|
|
}
|
|
}
|
|
|
|
if (msm_colorMaterialChange & __GL_MATERIAL_DIFFUSE)
|
|
{
|
|
/* Recompute per-light per-material cached diffuse */
|
|
diffuseSpecularI.r += n1 * ri * lss->diffuse.r;
|
|
diffuseSpecularI.g += n1 * gi * lss->diffuse.g;
|
|
diffuseSpecularI.b += n1 * bi * lss->diffuse.b;
|
|
}
|
|
else
|
|
{
|
|
diffuseSpecularI.r += n1 * lspmm->diffuse.r;
|
|
diffuseSpecularI.g += n1 * lspmm->diffuse.g;
|
|
diffuseSpecularI.b += n1 * lspmm->diffuse.b;
|
|
}
|
|
}
|
|
}
|
|
|
|
__GL_CLAMP_R(outColor->r, gc, emissiveAmbientI.r + diffuseSpecularI.r);
|
|
__GL_CLAMP_G(outColor->g, gc, emissiveAmbientI.g + diffuseSpecularI.g);
|
|
__GL_CLAMP_B(outColor->b, gc, emissiveAmbientI.b + diffuseSpecularI.b);
|
|
|
|
if (msm_colorMaterialChange & __GL_MATERIAL_DIFFUSE)
|
|
{
|
|
__GL_CLAMP_A(outColor->a, gc, alpha);
|
|
}
|
|
else
|
|
outColor->a = msm_alpha;
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
* CI, Vanilla, Fast-lights *
|
|
*******************************************************************/
|
|
void ComputeCIColorVanFast (__GLcontext *gc, __GLcolor *outColor)
|
|
{
|
|
GLint face = gc->polygon.shader.phong.face;
|
|
__GLfloat zero;
|
|
__GLcoord n;
|
|
__GLfloat nxi, nyi, nzi;
|
|
__GLlightSourcePerMaterialMachine *lspmm;
|
|
__GLlightSourceMachine *lsm;
|
|
__GLlightSourceState *lss;
|
|
__GLcolor baseEmissiveAmbient;
|
|
__GLmaterialMachine *msm;
|
|
__GLmaterialState *ms;
|
|
__GLfloat msm_threshold, msm_scale, *msm_specTable;
|
|
GLuint numLights;
|
|
__GLfloat ms_cmapa, ms_cmapd, ms_cmaps;
|
|
__GLfloat ci, si, di;
|
|
__GLphongShader *phong = &(gc->polygon.shader.phong);
|
|
GLfloat redMaxF;
|
|
GLint redMaxI;
|
|
|
|
zero = __glZero;
|
|
|
|
n = phong->nTmp;
|
|
if (gc->state.enables.general & __GL_NORMALIZE_ENABLE)
|
|
__glNormalize(&n.x, &n.x);
|
|
|
|
if (face == __GL_FRONTFACE)
|
|
{
|
|
ms = &gc->state.light.front;
|
|
msm = &gc->light.front;
|
|
nxi = n.x;
|
|
nyi = n.y;
|
|
nzi = n.z;
|
|
}
|
|
else
|
|
{
|
|
ms = &gc->state.light.back;
|
|
msm = &gc->light.back;
|
|
nxi = -n.x;
|
|
nyi = -n.y;
|
|
nzi = -n.z;
|
|
}
|
|
|
|
ASSERTOPENGL (!(phong->flags & __GL_PHONG_NEED_COLOR_XPOLATE),
|
|
"Zippy, no need for color interpolation\n");
|
|
|
|
msm_scale = msm->scale;
|
|
msm_threshold = msm->threshold;
|
|
msm_specTable = msm->specTable;
|
|
ms_cmapa = ms->cmapa;
|
|
ms_cmapd = ms->cmapd;
|
|
ms_cmaps = ms->cmaps;
|
|
redMaxF = (GLfloat) gc->frontBuffer.redMax;
|
|
redMaxI = (GLint) gc->frontBuffer.redMax;
|
|
|
|
si = zero;
|
|
di = zero;
|
|
|
|
for (lsm = gc->light.sources; lsm; lsm = lsm->next)
|
|
{
|
|
__GLfloat n1, n2;
|
|
|
|
lspmm = &lsm->front + face;
|
|
|
|
/* Add in specular and diffuse effect of light, if any */
|
|
n1 = nxi * lsm->unitVPpli.x + nyi * lsm->unitVPpli.y +
|
|
nzi * lsm->unitVPpli.z;
|
|
|
|
if (__GL_FLOAT_GTZ(n1))
|
|
{
|
|
n2 = (nxi * lsm->hHat.x + nyi * lsm->hHat.y + nzi *
|
|
lsm->hHat.z) - msm_threshold;
|
|
if (__GL_FLOAT_GEZ(n2))
|
|
{
|
|
__GLfloat fx = n2 * msm_scale + __glHalf;
|
|
|
|
if( fx < (__GLfloat)__GL_SPEC_LOOKUP_TABLE_SIZE )
|
|
n2 = msm_specTable[(GLint)fx];
|
|
else
|
|
n2 = __glOne;
|
|
si += n2 * lsm->sli;
|
|
}
|
|
di += n1 * lsm->dli;
|
|
}
|
|
}
|
|
|
|
/* Compute final color */
|
|
if (si > __glOne)
|
|
si = __glOne;
|
|
|
|
ci = ms_cmapa + (__glOne - si) * di * (ms_cmapd - ms_cmapa)
|
|
+ si * (ms_cmaps - ms_cmapa);
|
|
|
|
// need to mask color index before color clipping
|
|
if (ci > redMaxF)
|
|
{
|
|
GLfloat fraction;
|
|
GLint integer;
|
|
|
|
integer = (GLint) ci;
|
|
fraction = ci - (GLfloat) integer;
|
|
integer = integer & redMaxI;
|
|
ci = (GLfloat) integer + fraction;
|
|
}
|
|
else if (ci < 0)
|
|
{
|
|
GLfloat fraction;
|
|
GLint integer;
|
|
|
|
integer = (GLint) __GL_FLOORF(ci);
|
|
fraction = ci - (GLfloat) integer;
|
|
integer = integer & redMaxI;
|
|
ci = (GLfloat) integer + fraction;
|
|
}
|
|
|
|
outColor->r = ci;
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
* CI, Vanilla, Slow-lights *
|
|
*******************************************************************/
|
|
void ComputeCIColorVanSlow (__GLcontext *gc, __GLcolor *outColor)
|
|
{
|
|
GLint face = gc->polygon.shader.phong.face;
|
|
__GLfloat nxi, nyi, nzi;
|
|
__GLfloat zero;
|
|
__GLlightSourceMachine *lsm;
|
|
__GLmaterialState *ms;
|
|
__GLmaterialMachine *msm;
|
|
__GLfloat msm_threshold, msm_scale, *msm_specTable;
|
|
__GLfloat ms_cmapa, ms_cmapd, ms_cmaps;
|
|
__GLfloat ci, si, di;
|
|
GLfloat redMaxF;
|
|
GLint redMaxI;
|
|
GLboolean eyeWIsZero, localViewer;
|
|
static __GLcoord Pe = { 0, 0, 0, 1 };
|
|
__GLphongShader *phong = &(gc->polygon.shader.phong);
|
|
__GLcoord n;
|
|
|
|
|
|
zero = __glZero;
|
|
|
|
n = phong->nTmp;
|
|
if (gc->state.enables.general & __GL_NORMALIZE_ENABLE)
|
|
__glNormalize(&n.x, &n.x);
|
|
|
|
if (face == __GL_FRONTFACE)
|
|
{
|
|
ms = &gc->state.light.front;
|
|
msm = &gc->light.front;
|
|
nxi = n.x;
|
|
nyi = n.y;
|
|
nzi = n.z;
|
|
}
|
|
else
|
|
{
|
|
ms = &gc->state.light.back;
|
|
msm = &gc->light.back;
|
|
nxi = -n.x;
|
|
nyi = -n.y;
|
|
nzi = -n.z;
|
|
}
|
|
|
|
msm_scale = msm->scale;
|
|
msm_threshold = msm->threshold;
|
|
msm_specTable = msm->specTable;
|
|
ms_cmapa = ms->cmapa;
|
|
ms_cmapd = ms->cmapd;
|
|
ms_cmaps = ms->cmaps;
|
|
localViewer = gc->state.light.model.localViewer;
|
|
redMaxF = (GLfloat) gc->frontBuffer.redMax;
|
|
redMaxI = (GLint) gc->frontBuffer.redMax;
|
|
|
|
|
|
si = zero;
|
|
di = zero;
|
|
|
|
eyeWIsZero = __GL_FLOAT_EQZ(phong->eTmp.w);
|
|
|
|
for (lsm = gc->light.sources; lsm; lsm = lsm->next)
|
|
{
|
|
if (lsm->slowPath || eyeWIsZero)
|
|
{
|
|
__GLfloat n1, n2, att, attSpot;
|
|
__GLcoord vPliHat, vPli, hHat, vPeHat;
|
|
__GLfloat hv[3];
|
|
|
|
/* Compute vPli, hi (normalized) */
|
|
__glVecSub4(&vPli, &phong->eTmp, &lsm->position);
|
|
__glNormalize(&vPliHat.x, &vPli.x);
|
|
if (localViewer)
|
|
{
|
|
__glVecSub4(&vPeHat, &phong->eTmp, &Pe);
|
|
__glNormalize(&vPeHat.x, &vPeHat.x);
|
|
hv[0] = vPliHat.x + vPeHat.x;
|
|
hv[1] = vPliHat.y + vPeHat.y;
|
|
hv[2] = vPliHat.z + vPeHat.z;
|
|
}
|
|
else
|
|
{
|
|
hv[0] = vPliHat.x;
|
|
hv[1] = vPliHat.y;
|
|
hv[2] = vPliHat.z + __glOne;
|
|
}
|
|
__glNormalize(&hHat.x, hv);
|
|
|
|
/* Compute attenuation */
|
|
if (__GL_FLOAT_NEZ(lsm->position.w))
|
|
{
|
|
__GLfloat k0, k1, k2, dist;
|
|
|
|
k0 = lsm->constantAttenuation;
|
|
k1 = lsm->linearAttenuation;
|
|
k2 = lsm->quadraticAttenuation;
|
|
if (__GL_FLOAT_EQZ(k1) && __GL_FLOAT_EQZ(k2))
|
|
{
|
|
/* Use pre-computed 1/k0 */
|
|
att = lsm->attenuation;
|
|
}
|
|
else
|
|
{
|
|
__GLfloat den;
|
|
|
|
dist = __GL_SQRTF(vPli.x*vPli.x + vPli.y*vPli.y
|
|
+ vPli.z*vPli.z);
|
|
den = k0 + k1 * dist + k2 * dist * dist;
|
|
att = __GL_FLOAT_EQZ(den) ? __glOne : __glOne / den;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
att = __glOne;
|
|
}
|
|
|
|
/* Compute spot effect if light is a spot light */
|
|
attSpot = att;
|
|
if (lsm->isSpot)
|
|
{
|
|
__GLfloat dot, px, py, pz;
|
|
|
|
px = -vPliHat.x;
|
|
py = -vPliHat.y;
|
|
pz = -vPliHat.z;
|
|
dot = px * lsm->direction.x + py * lsm->direction.y
|
|
+ pz * lsm->direction.z;
|
|
if ((dot >= lsm->threshold) && (dot >= lsm->cosCutOffAngle))
|
|
{
|
|
GLint ix = (GLint)((dot - lsm->threshold) * lsm->scale
|
|
+ __glHalf);
|
|
if (ix < __GL_SPOT_LOOKUP_TABLE_SIZE)
|
|
attSpot = att * lsm->spotTable[ix];
|
|
}
|
|
else
|
|
{
|
|
attSpot = zero;
|
|
}
|
|
}
|
|
|
|
/* Add in remaining effect of light, if any */
|
|
if (attSpot)
|
|
{
|
|
n1 = nxi * vPliHat.x + nyi * vPliHat.y + nzi * vPliHat.z;
|
|
if (__GL_FLOAT_GTZ(n1))
|
|
{
|
|
n2 = nxi * hHat.x + nyi * hHat.y + nzi * hHat.z;
|
|
n2 -= msm_threshold;
|
|
if (__GL_FLOAT_GEZ(n2))
|
|
{
|
|
__GLfloat fx = n2 * msm_scale + __glHalf;
|
|
if( fx < (__GLfloat)__GL_SPEC_LOOKUP_TABLE_SIZE )
|
|
n2 = msm_specTable[(GLint)fx];
|
|
else
|
|
n2 = __glOne;
|
|
si += attSpot * n2 * lsm->sli;
|
|
}
|
|
di += attSpot * n1 * lsm->dli;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
__GLfloat n1, n2;
|
|
|
|
/* Compute specular contribution */
|
|
n1 = nxi * lsm->unitVPpli.x + nyi * lsm->unitVPpli.y +
|
|
nzi * lsm->unitVPpli.z;
|
|
if (__GL_FLOAT_GTZ(n1))
|
|
{
|
|
n2= nxi * lsm->hHat.x + nyi * lsm->hHat.y + nzi * lsm->hHat.z;
|
|
n2 -= msm_threshold;
|
|
if (__GL_FLOAT_GEZ(n2))
|
|
{
|
|
__GLfloat fx = n2 * msm_scale + __glHalf;
|
|
if( fx < (__GLfloat)__GL_SPEC_LOOKUP_TABLE_SIZE )
|
|
n2 = msm_specTable[(GLint)fx];
|
|
else
|
|
n2 = __glOne;
|
|
si += n2 * lsm->sli;
|
|
}
|
|
di += n1 * lsm->dli;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Compute final color */
|
|
if (si > __glOne)
|
|
si = __glOne;
|
|
|
|
ci = ms_cmapa + (__glOne - si) * di * (ms_cmapd - ms_cmapa)
|
|
+ si * (ms_cmaps - ms_cmapa);
|
|
if (ci > ms_cmaps)
|
|
ci = ms_cmaps;
|
|
|
|
// need to mask color index before color clipping
|
|
|
|
if (ci > redMaxF)
|
|
{
|
|
GLfloat fraction;
|
|
GLint integer;
|
|
|
|
integer = (GLint) ci;
|
|
fraction = ci - (GLfloat) integer;
|
|
integer = integer & redMaxI;
|
|
ci = (GLfloat) integer + fraction;
|
|
}
|
|
else if (ci < 0)
|
|
{
|
|
GLfloat fraction;
|
|
GLint integer;
|
|
|
|
integer = (GLint) __GL_FLOORF(ci);
|
|
fraction = ci - (GLfloat) integer;
|
|
integer = integer & redMaxI;
|
|
ci = (GLfloat) integer + fraction;
|
|
}
|
|
outColor->r = ci;
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************
|
|
* CI, Fast-lights, Fast-path *
|
|
*******************************************************************/
|
|
void ComputeCIColorAccelFast (__GLcontext *gc, __GLcolor *outColor)
|
|
{
|
|
__GLfloat zero;
|
|
GLint face = gc->polygon.shader.phong.face;
|
|
__GLlightSourcePerMaterialMachine *lspmm;
|
|
__GLlightSourceMachine *lsm;
|
|
__GLlightSourceState *lss;
|
|
__GLcolor baseEmissiveAmbient;
|
|
__GLmaterialMachine *msm;
|
|
__GLmaterialState *ms;
|
|
__GLfloat msm_threshold, msm_scale, *msm_specTable;
|
|
GLuint numLights;
|
|
__GLfloat ms_cmapa, ms_cmapd, ms_cmaps;
|
|
__GLfloat ci, si, di;
|
|
__GLphongShader *phong = &(gc->polygon.shader.phong);
|
|
GLfloat redMaxF;
|
|
GLint redMaxI;
|
|
GLint curL;
|
|
|
|
zero = __glZero;
|
|
|
|
if (face == __GL_FRONTFACE)
|
|
{
|
|
ms = &gc->state.light.front;
|
|
msm = &gc->light.front;
|
|
}
|
|
else
|
|
{
|
|
ms = &gc->state.light.back;
|
|
msm = &gc->light.back;
|
|
}
|
|
|
|
|
|
ASSERTOPENGL (!(phong->flags & __GL_PHONG_NEED_COLOR_XPOLATE),
|
|
"Zippy, no need for color interpolation\n");
|
|
|
|
msm_scale = msm->scale;
|
|
msm_threshold = msm->threshold;
|
|
msm_specTable = msm->specTable;
|
|
ms_cmapa = ms->cmapa;
|
|
ms_cmapd = ms->cmapd;
|
|
ms_cmaps = ms->cmaps;
|
|
redMaxF = (GLfloat) gc->frontBuffer.redMax;
|
|
redMaxI = (GLint) gc->frontBuffer.redMax;
|
|
|
|
si = zero;
|
|
di = zero;
|
|
|
|
for (lsm = gc->light.sources, curL=0; lsm; lsm = lsm->next, curL++)
|
|
{
|
|
__GLfloat n1, n2;
|
|
__GLphongPerLightData *pld = &(phong->perLight[curL]);
|
|
|
|
lspmm = &lsm->front + face;
|
|
|
|
/* Add in specular and diffuse effect of light, if any */
|
|
n1 = pld->Dcurr;
|
|
if (__GL_FLOAT_GTZ(n1))
|
|
{
|
|
n2 = pld->Scurr - msm_threshold;
|
|
if (__GL_FLOAT_GEZ(n2))
|
|
{
|
|
__GLfloat fx = n2 * msm_scale + __glHalf;
|
|
|
|
if( fx < (__GLfloat)__GL_SPEC_LOOKUP_TABLE_SIZE )
|
|
n2 = msm_specTable[(GLint)fx];
|
|
else
|
|
n2 = __glOne;
|
|
si += n2 * lsm->sli;
|
|
}
|
|
di += n1 * lsm->dli;
|
|
}
|
|
}
|
|
|
|
/* Compute final color */
|
|
if (si > __glOne)
|
|
si = __glOne;
|
|
|
|
ci = ms_cmapa + (__glOne - si) * di * (ms_cmapd - ms_cmapa)
|
|
+ si * (ms_cmaps - ms_cmapa);
|
|
|
|
// need to mask color index before color clipping
|
|
if (ci > redMaxF)
|
|
{
|
|
GLfloat fraction;
|
|
GLint integer;
|
|
|
|
integer = (GLint) ci;
|
|
fraction = ci - (GLfloat) integer;
|
|
integer = integer & redMaxI;
|
|
ci = (GLfloat) integer + fraction;
|
|
}
|
|
else if (ci < 0)
|
|
{
|
|
GLfloat fraction;
|
|
GLint integer;
|
|
|
|
integer = (GLint) __GL_FLOORF(ci);
|
|
fraction = ci - (GLfloat) integer;
|
|
integer = integer & redMaxI;
|
|
ci = (GLfloat) integer + fraction;
|
|
}
|
|
|
|
outColor->r = ci;
|
|
}
|
|
|
|
|
|
void ComputePhongInvarientRGBColor (__GLcontext *gc)
|
|
{
|
|
GLint face = gc->polygon.shader.phong.face;
|
|
__GLlightSourcePerMaterialMachine *lspmm;
|
|
__GLlightSourceMachine *lsm;
|
|
__GLlightSourceState *lss;
|
|
__GLmaterialMachine *msm;
|
|
__GLfloat msm_alpha;
|
|
__GLfloat rsi, gsi, bsi;
|
|
__GLphongShader *phong = &(gc->polygon.shader.phong);
|
|
|
|
if (face == __GL_FRONTFACE)
|
|
msm = &gc->light.front;
|
|
else
|
|
msm = &gc->light.back;
|
|
|
|
// Compute invarient emissive and ambient components for this vertex.
|
|
|
|
rsi = msm->paSceneColor.r;
|
|
gsi = msm->paSceneColor.g;
|
|
bsi = msm->paSceneColor.b;
|
|
|
|
// add invarient per-light per-material cached ambient
|
|
|
|
for (lsm = gc->light.sources; lsm; lsm = lsm->next)
|
|
{
|
|
lspmm = &lsm->front + face;
|
|
rsi += lspmm->ambient.r;
|
|
gsi += lspmm->ambient.g;
|
|
bsi += lspmm->ambient.b;
|
|
}
|
|
phong->invColor.r = rsi;
|
|
phong->invColor.g = gsi;
|
|
phong->invColor.b = bsi;
|
|
}
|
|
|
|
void FASTCALL __glGenericPickPhongProcs(__GLcontext *gc)
|
|
{
|
|
__GLlightSourceMachine *lsm;
|
|
GLboolean anySlow = GL_FALSE;
|
|
GLboolean colorMaterial = (gc->state.enables.general &
|
|
__GL_COLOR_MATERIAL_ENABLE);
|
|
GLboolean rgb_mode = (gc->polygon.shader.modeFlags & __GL_SHADE_RGB);
|
|
GLboolean normalize = (gc->state.enables.general & __GL_NORMALIZE_ENABLE);
|
|
GLboolean doVanilla = GL_FALSE;
|
|
|
|
gc->polygon.shader.phong.flags = 0;
|
|
for (lsm = gc->light.sources; lsm; lsm = lsm->next) {
|
|
if (lsm->slowPath) {
|
|
anySlow = GL_TRUE;
|
|
// Assuming here that anySlow means need Eye XPolate
|
|
gc->polygon.shader.phong.flags |= __GL_PHONG_NEED_EYE_XPOLATE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
doVanilla = (!(gc->state.enables.general & __GL_NORMALIZE_ENABLE)
|
|
|| (anySlow)
|
|
|| (gc->state.enables.general & __GL_POLYGON_SMOOTH_ENABLE)
|
|
|| (gc->state.enables.general & __GL_LINE_SMOOTH_ENABLE)
|
|
);
|
|
|
|
|
|
if ((gc->state.hints.phong == GL_NICEST) || doVanilla)
|
|
{
|
|
gc->procs.phong.InitLineParams = InitLineParamsVan;
|
|
|
|
if (anySlow)
|
|
{
|
|
gc->procs.phong.InitSpanInterpolation = InitSpanNEInterpolationVan;
|
|
gc->procs.phong.UpdateAlongSpan = UpdateNEAlongSpanVan;
|
|
gc->procs.phong.ComputeRGBColor = ComputeRGBColorVanSlow;
|
|
gc->procs.phong.ComputeCIColor = ComputeCIColorVanSlow;
|
|
}
|
|
else
|
|
{
|
|
gc->procs.phong.InitSpanInterpolation = InitSpanNInterpolationVan;
|
|
gc->procs.phong.UpdateAlongSpan = UpdateNAlongSpanVan;
|
|
gc->procs.phong.ComputeCIColor = ComputeCIColorVanFast;
|
|
if (colorMaterial)
|
|
{
|
|
gc->procs.phong.ComputeRGBColor = ComputeRGBColorVanFast;
|
|
}
|
|
else
|
|
{
|
|
gc->procs.phong.ComputeRGBColor = ComputeRGBColorVanZippy;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ASSERTOPENGL (!anySlow, "Slow lights currently turned off\n");
|
|
|
|
gc->procs.phong.InitSpanInterpolation = InitSpanInterpolationAccel;
|
|
gc->procs.phong.UpdateAlongSpan = UpdateParamsAlongSpanAccel;
|
|
gc->procs.phong.InitLineParams = InitLineParamsAccel;
|
|
gc->procs.phong.ComputeCIColor = ComputeCIColorAccelFast;
|
|
|
|
if (colorMaterial)
|
|
gc->procs.phong.ComputeRGBColor = ComputeRGBColorAccelFast;
|
|
else
|
|
gc->procs.phong.ComputeRGBColor = ComputeRGBColorAccelZippy;
|
|
|
|
}
|
|
}
|
|
|
|
void __glCalcForwardDifferences( GLint w, __GLfloat p0, __GLfloat p1,
|
|
__GLfloat p2, __GLfloat *d1, __GLfloat *d2 )
|
|
{
|
|
// Compute quadratic forward differences along a span of length w, from
|
|
// points p0, p1, p2
|
|
__GLfloat dx;
|
|
__GLfloat a0, a1, a2;
|
|
|
|
if( w < 2 ) {
|
|
*d1 = *d2 = 0.0f;
|
|
return;
|
|
}
|
|
|
|
dx = 1.0f / w; // normalization factor
|
|
|
|
// quadratic polynomial coefficients
|
|
a0 = p0;
|
|
a1 = ( -3.0f*p0 + 4.0f*p1 - p2) * dx;
|
|
a2 = 2.0f * (p0 - 2.0f*p1 + p2) * dx * dx;
|
|
|
|
#ifdef __DEBUG_PRINT
|
|
DbgPrint ("a2=%f, a1=%f, a0=%f\n", a2, a1, a0);
|
|
#endif
|
|
// forward difference parameters
|
|
*d1 = a1 + a2;
|
|
*d2 = 2.0f * a2;
|
|
}
|
|
|
|
|
|
|
|
#ifdef __JUNKED_CODE
|
|
void InitSpanInterpolationFast (__GLcontext *gc)
|
|
{
|
|
GLint i;
|
|
__GLphongShader *phong = &(gc->polygon.shader.phong);
|
|
|
|
phong->tmp_pos.x = phong->cur_pos.x;
|
|
phong->tmp_pos.y = phong->cur_pos.y;
|
|
|
|
for (i=0; i<phong->numLights; i++)
|
|
{
|
|
__GLphongPerLightData *pld = &(phong->perLight[i]);
|
|
|
|
/* Diffuse */
|
|
pld->D_tmp = pld->D_curr;
|
|
pld->Ddel_tmp = pld->DdelSpan;
|
|
|
|
/* Specular */
|
|
pld->S_tmp = pld->S_curr;
|
|
pld->Sdel_tmp = pld->SdelSpan;
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef __TWO
|
|
ASSERTOPENGL (!anySlow, "Slow lights currently turned off\n");
|
|
|
|
gc->procs.phong.InitInterpolation = InitializePhongInterpolationVan;
|
|
gc->procs.phong.SetInitParams = SetInitialPhongInterpolationVan;
|
|
gc->procs.phong.UpdateAlongEdge = UpdateParamsAlongEdgeVan;
|
|
|
|
gc->procs.phong.InitSpanInterpolation = InitSpanInterpolationTWO;
|
|
gc->procs.phong.UpdateAlongSpan = UpdateParamsAlongSpanFast;
|
|
|
|
//Line related
|
|
gc->procs.phong.InitLineParams = InitLineParamsFast;
|
|
|
|
if (colorMaterial)
|
|
gc->procs.phong.ComputeRGBColor = ComputeRGBColorAccelFast;
|
|
else
|
|
gc->procs.phong.ComputeRGBColor = ComputeRGBColorAccelZippy;
|
|
#else
|
|
gc->procs.phong.InitInterpolation = InitializePhongInterpolationFast;
|
|
gc->procs.phong.SetInitParams = SetInitialPhongInterpolationFast;
|
|
gc->procs.phong.UpdateAlongEdge = UpdateParamsAlongEdgeFast;
|
|
gc->procs.phong.InitSpanInterpolation = InitSpanInterpolationFast;
|
|
gc->procs.phong.UpdateAlongSpan = UpdateParamsAlongSpanFast;
|
|
gc->procs.phong.ComputeCIColor = ComputeCIColorAccelFast;
|
|
|
|
//Line related
|
|
gc->procs.phong.InitLineParams = InitLineParamsFast;
|
|
|
|
if (colorMaterial)
|
|
gc->procs.phong.ComputeRGBColor = ComputeRGBColorAccelFast;
|
|
else
|
|
gc->procs.phong.ComputeRGBColor = ComputeRGBColorAccelZippy;
|
|
#endif
|
|
|
|
void InitSpanInterpolationTWO (__GLcontext *gc)
|
|
{
|
|
__GLphongShader *phong = &(gc->polygon.shader.phong);
|
|
GLint face = phong->face;
|
|
__GLlightSourceMachine *lsm;
|
|
//__GLmaterialMachine *msm;
|
|
__GLcoord n, dndx;
|
|
__GLcoord *A = &dndx;
|
|
__GLcoord *C = &n;
|
|
__GLfloat a, b, c, d, e, f, g, h, i;
|
|
GLint curL;
|
|
|
|
|
|
if (face == __GL_FRONTFACE)
|
|
{
|
|
//msm = &gc->light.front;
|
|
n.x = phong->nCur.x;
|
|
n.y = phong->nCur.y;
|
|
n.z = phong->nCur.z;
|
|
|
|
dndx.x = phong->dndx.x;
|
|
dndx.y = phong->dndx.y;
|
|
dndx.z = phong->dndx.z;
|
|
}
|
|
else
|
|
{
|
|
//msm = &gc->light.back;
|
|
n.x = -phong->nCur.x;
|
|
n.y = -phong->nCur.y;
|
|
n.z = -phong->nCur.z;
|
|
|
|
dndx.x = -phong->dndx.x;
|
|
dndx.y = -phong->dndx.y;
|
|
dndx.z = -phong->dndx.z;
|
|
}
|
|
|
|
if (gc->state.enables.general & __GL_NORMALIZE_ENABLE)
|
|
__glNormalize(&n.x, &n.x);
|
|
|
|
MAGN2 (d,A); //d = A.A
|
|
DOT (g,A,C); g *= 2.0; //g = 2A.C
|
|
MAGN2 (i,C); //i = C.C
|
|
|
|
for (lsm = gc->light.sources, curL=0; lsm; lsm = lsm->next, curL++)
|
|
{
|
|
__GLfloat i2, iRt, tmp5, tmp2;
|
|
__GLphongPerLightData *pld = &(phong->perLight[curL]);
|
|
__GLcoord *L = &(lsm->unitVPpli); // L is already normalized here
|
|
__GLcoord *H = &(lsm->hHat); // H is already normalized here
|
|
|
|
i2 = (i*i);
|
|
iRt = __GL_SQRTF(i);
|
|
|
|
/***** Diffuse *****/
|
|
// Remaining Bishop parameters
|
|
DOT (a,L,A); //a = L.A/|L|
|
|
DOT (c,L,C); //c = L.C/|L|
|
|
|
|
tmp2 = (2.0*a*i - c*g)/(2.0*i*iRt);
|
|
tmp5 = (3.0*c*g*g - 4.0*c*d*i - 4.0*a*g*i)/(8.0*i2*iRt);
|
|
|
|
// Constant deltas
|
|
pld->Ddel2Span = 2*tmp5;
|
|
pld->Ddel_tmp = tmp2 + tmp5;
|
|
pld->D_tmp = c/iRt;
|
|
|
|
/***** Specular ******/
|
|
// Remaining Bishop parameters
|
|
DOT (a,H,A); //a = H.A/|H|
|
|
DOT (c,H,C); //c = H.C/|H|
|
|
|
|
// Polynomial coefficients
|
|
tmp2 = (2.0*a*i - c*g)/(2.0*i*iRt);
|
|
tmp5 = (3.0*c*g*g - 4.0*c*d*i - 4.0*a*g*i)/(8.0*i2*iRt);
|
|
|
|
// Constant deltas
|
|
pld->Sdel2Span = 2*tmp5;
|
|
pld->Sdel_tmp = tmp2 + tmp5;
|
|
pld->S_tmp = c/iRt;
|
|
}
|
|
phong->numLights = curL;
|
|
}
|
|
|
|
void SetInitialPhongInterpolationVan (__GLcontext *gc, __GLvertex *a,
|
|
__GLcoord *an, __GLfloat dx,
|
|
__GLfloat dy)
|
|
{
|
|
__GLshade *sh = &gc->polygon.shader;
|
|
__GLphongShader *phong = &gc->polygon.shader.phong;
|
|
__GLfloat little = sh->dxLeftLittle;
|
|
__GLfloat big = sh->dxLeftBig;
|
|
|
|
phong->nCur.x = an->x + dx*phong->dndx.x + dy*phong->dndy.x;
|
|
phong->nCur.y = an->y + dx*phong->dndx.y + dy*phong->dndy.y;
|
|
phong->nCur.z = an->z + dx*phong->dndx.z + dy*phong->dndy.z;
|
|
|
|
phong->nLittle.x = phong->dndy.x + little * phong->dndx.x;
|
|
phong->nLittle.y = phong->dndy.y + little * phong->dndx.y;
|
|
phong->nLittle.z = phong->dndy.z + little * phong->dndx.z;
|
|
|
|
if (big > little)
|
|
{
|
|
phong->nBig.x = phong->nLittle.x + phong->dndx.x;
|
|
phong->nBig.y = phong->nLittle.y + phong->dndx.y;
|
|
phong->nBig.z = phong->nLittle.z + phong->dndx.z;
|
|
}
|
|
else
|
|
{
|
|
phong->nBig.x = phong->nLittle.x - phong->dndx.x;
|
|
phong->nBig.y = phong->nLittle.y - phong->dndx.y;
|
|
phong->nBig.z = phong->nLittle.z - phong->dndx.z;
|
|
}
|
|
|
|
if (phong->flags & __GL_PHONG_NEED_EYE_XPOLATE)
|
|
{
|
|
phong->eCur.x = a->eyeX + dx*phong->dedx.x + dy*phong->dedy.x;
|
|
phong->eCur.y = a->eyeY + dx*phong->dedx.y + dy*phong->dedy.y;
|
|
phong->eCur.z = a->eyeZ + dx*phong->dedx.z + dy*phong->dedy.z;
|
|
phong->eCur.w = a->eyeW + dx*phong->dedx.w + dy*phong->dedy.w;
|
|
|
|
phong->eLittle.x = phong->dedy.x + little * phong->dedx.x;
|
|
phong->eLittle.y = phong->dedy.y + little * phong->dedx.y;
|
|
phong->eLittle.z = phong->dedy.z + little * phong->dedx.z;
|
|
phong->eLittle.w = phong->dedy.w + little * phong->dedx.w;
|
|
|
|
if (big > little)
|
|
{
|
|
phong->eBig.x = phong->eLittle.x + phong->dedx.x;
|
|
phong->eBig.y = phong->eLittle.y + phong->dedx.y;
|
|
phong->eBig.z = phong->eLittle.z + phong->dedx.z;
|
|
phong->eBig.w = phong->eLittle.w + phong->dedx.w;
|
|
}
|
|
else
|
|
{
|
|
phong->eBig.x = phong->eLittle.x - phong->dedx.x;
|
|
phong->eBig.y = phong->eLittle.y - phong->dedx.y;
|
|
phong->eBig.z = phong->eLittle.z - phong->dedx.z;
|
|
phong->eBig.w = phong->eLittle.w - phong->dedx.w;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Equivalent to SetInitialPhongParameters. Does for D and S */
|
|
void SetInitialPhongInterpolationFast (__GLcontext *gc, __GLvertex *a,
|
|
__GLcoord *an, __GLfloat dx,
|
|
__GLfloat dy)
|
|
{
|
|
__GLshade *sh = &gc->polygon.shader;
|
|
__GLphongShader *phong = &gc->polygon.shader.phong;
|
|
__GLfloat little = sh->dxLeftLittle;
|
|
__GLfloat little2 = little*little;
|
|
__GLfloat big = sh->dxLeftBig;
|
|
__GLfloat big2 = big*big;
|
|
__GLfloat dx2 = dx*dx;
|
|
__GLfloat dy2 = dy*dy;
|
|
__GLcoord pos;
|
|
int i;
|
|
GLfloat x, x2, y, y2;
|
|
GLfloat aa, b, c, d, e, f, g, h, ii;
|
|
|
|
phong->cur_pos.x += dx;
|
|
phong->cur_pos.y += dy;
|
|
pos = phong->cur_pos;
|
|
x = phong->cur_pos.x; x2 = x*x;
|
|
y = phong->cur_pos.y; y2 = y*y;
|
|
|
|
for (i = 0; i<phong->numLights; i++)
|
|
{
|
|
__GLphongPerLightData *pld = &phong->perLight[i];
|
|
__GLfloat tmp1, tmp2, tmp3;
|
|
|
|
/**** Diffuse Parameters *****/
|
|
pld->D_curr = pld->D[5]*x2 + pld->D[4]*x*y + pld->D[3]*y2 +
|
|
pld->D[2]*x + pld->D[1]*y + pld->D[0];
|
|
|
|
tmp1 = 2*pld->D[5]*x + pld->D[4]*y + pld->D[2];
|
|
tmp2 = 2*pld->D[3]*y + pld->D[4]*x + pld->D[1];
|
|
|
|
// Compute the along-edge del2 and del terms (Little)
|
|
tmp3 = pld->D[5]*little2 + pld->D[4]*little + pld->D[3];
|
|
pld->Ddel2EdgeLittle = 2*tmp3;
|
|
pld->DdelEdgeLittle = tmp1*little + tmp2 + tmp3;
|
|
|
|
// Compute the along-edge del2 and del terms (Big)
|
|
tmp3 = pld->D[5]*big2 + pld->D[4]*big + pld->D[3];
|
|
pld->Ddel2EdgeBig = 2*tmp3;
|
|
pld->DdelEdgeBig = tmp1*big + tmp2 + tmp3;
|
|
|
|
// Compute the along-span del terms
|
|
pld->DdelSpan = tmp1 + pld->D[5];
|
|
pld->DdelSpanEdgeBig = pld->D[4] + 2*pld->D[5]*big;
|
|
pld->DdelSpanEdgeLittle = pld->D[4] + 2*pld->D[5]*little;
|
|
|
|
/**** Specular Parameters ****/
|
|
#ifndef __SLOW
|
|
pld->S_curr = pld->S[5]*x2 + pld->S[4]*x*y + pld->S[3]*y2 +
|
|
pld->S[2]*x + pld->S[1]*y + pld->S[0];
|
|
#else
|
|
aa = pld->A[0]; b = pld->A[1];
|
|
c = pld->A[2]; d = pld->A[3];
|
|
e = pld->A[4]; f = pld->A[5];
|
|
g = pld->A[6]; h = pld->A[7];
|
|
ii = pld->A[8];
|
|
|
|
pld->S_curr = (aa*x+b*y+c)/__GL_SQRTF(d*x2+e*x*y+f*y2+g*x+h*y+ii);
|
|
|
|
#endif
|
|
|
|
tmp1 = 2*pld->S[5]*x + pld->S[4]*y + pld->S[2];
|
|
tmp2 = 2*pld->S[3]*y + pld->S[4]*x + pld->S[1];
|
|
|
|
// Compute the along-edge del2 and del terms (Little)
|
|
tmp3 = pld->S[5]*little2 + pld->S[4]*little + pld->S[3];
|
|
pld->Sdel2EdgeLittle = 2*tmp3;
|
|
pld->SdelEdgeLittle = tmp1*little + tmp2 + tmp3;
|
|
|
|
// Compute the along-edge del2 and del terms (Big)
|
|
tmp3 = pld->S[5]*big2 + pld->S[4]*big + pld->S[3];
|
|
pld->Sdel2EdgeBig = 2*tmp3;
|
|
pld->SdelEdgeBig = tmp1*big + tmp2 + tmp3;
|
|
|
|
// Compute the along-span del terms
|
|
pld->SdelSpan = tmp1 + pld->S[5];
|
|
pld->SdelSpanEdgeBig = pld->S[4] + 2*pld->S[5]*big;
|
|
pld->SdelSpanEdgeLittle = pld->S[4] + 2*pld->S[5]*little;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/* Called when: Normalization Enabled, FastLights */
|
|
/******************************************************
|
|
****Set up the Polynomial for diffuse illumination****
|
|
******************************************************
|
|
* *
|
|
* 2 2 *
|
|
* SD (x,y) = D_5x + D_4xy + D_3y + D_2x + D_1y + D_0 *
|
|
* *
|
|
* D_i are expressed in terms of: a,b,c,d,e,f,g,h,i *
|
|
* *
|
|
* D_0 = c/sqrt(i) *
|
|
* D_1 = (2bi - ch)/(2i*sqrt(i)) *
|
|
* D_2 = (2ai - cg)/(2i*sqrt(i)) *
|
|
* D_3 = (3ch^2 - 4cfi - 4bhi)/(4i^2*sqrt(i)) *
|
|
* D_4 = (3cgh - 2ci - 2bgi - 2ahi)/(8i^2*sqrt(i)) *
|
|
* D_5 = (3ig^2 - 4cdi - 4agi)/(4i^2*sqrt(i)) *
|
|
******************************************************/
|
|
void InitializePhongInterpolationFast (__GLcontext *gc, __GLvertex *v)
|
|
{
|
|
GLboolean colorMaterial = (gc->state.enables.general &
|
|
__GL_COLOR_MATERIAL_ENABLE);
|
|
GLint face = gc->polygon.shader.phong.face;
|
|
__GLlightSourcePerMaterialMachine *lspmm;
|
|
__GLlightSourceMachine *lsm;
|
|
__GLmaterialMachine *msm;
|
|
GLuint msm_colorMaterialChange;
|
|
__GLfloat msm_alpha;
|
|
__GLfloat rsi, gsi, bsi;
|
|
__GLcoord normal;
|
|
GLint curL;
|
|
__GLphongShader *phong = &gc->polygon.shader.phong;
|
|
__GLshade *sh = &gc->polygon.shader;
|
|
__GLfloat little = sh->dxLeftLittle;
|
|
__GLfloat big = sh->dxLeftBig;
|
|
__GLcoord *A = &(phong->dndx);
|
|
__GLcoord *B = &(phong->dndy);
|
|
__GLcoord *C;
|
|
//From Bishop's paper
|
|
__GLfloat a, b, c, d, e, f, g, h, i;
|
|
|
|
#ifdef __CENTER
|
|
normal.x = v->normal.x + (v->window.x - phong->center.x)*A->x
|
|
+ (v->window.y - phong->center.y)*B->x;
|
|
normal.y = v->normal.y + (v->window.x - phong->center.x)*A->y
|
|
+ (v->window.y - phong->center.y)*B->y;
|
|
normal.z = v->normal.z + (v->window.x - phong->center.x)*A->z
|
|
+ (v->window.y - phong->center.y)*B->z;
|
|
#else
|
|
normal.x = v->normal.x;
|
|
normal.y = v->normal.y;
|
|
normal.z = v->normal.z;
|
|
#endif
|
|
if (face == __GL_FRONTFACE)
|
|
{
|
|
msm = &gc->light.front;
|
|
}
|
|
else
|
|
{
|
|
msm = &gc->light.back;
|
|
normal.x = -normal.x;
|
|
normal.y = -normal.y;
|
|
normal.z = -normal.z;
|
|
}
|
|
|
|
C = &normal;
|
|
//msm_colorMaterialChange = msm->colorMaterialChange;
|
|
#ifdef __DBG_PRINT
|
|
DbgPrint ("A = (%f, %f, %f)\n", A->x, A->y, A->z);
|
|
DbgPrint ("B = (%f, %f, %f)\n", B->x, B->y, B->z);
|
|
DbgPrint ("C = (%f, %f, %f)\n", C->x, C->y, C->z);
|
|
#endif
|
|
|
|
//***********Diffuse Bishop Parameters*****************************
|
|
//a, b, c depend upon the light vector, so compute inside the loop
|
|
//d, e, f, g, h, i depend only upon the incoming normal
|
|
|
|
MAGN2 (d, A); //d = A.A
|
|
DOT (e,A,B); e *= 2.0; //e = 2A.B
|
|
MAGN2 (f, B); //f = B.B
|
|
DOT (g,A,C); g *= 2.0; //g = 2A.C
|
|
DOT (h,B,C); h *= 2.0; //h = 2B.C
|
|
MAGN2 (i,C); //i = C.C
|
|
|
|
// Normalization not needed since
|
|
// it was done (if needed) during normal propagation.
|
|
// Compute the per-light interpolation parameters
|
|
|
|
for (lsm = gc->light.sources, curL = 0; lsm;
|
|
lsm = lsm->next, curL++)
|
|
{
|
|
__GLphongPerLightData *pld = &(phong->perLight[curL]);
|
|
__GLcoord *L = &(lsm->unitVPpli); // L is already normalized here
|
|
__GLcoord *H = &(lsm->hHat); // H is already normalized here
|
|
GLfloat i2, iRt;
|
|
|
|
i2 = i*i;
|
|
iRt = __GL_SQRTF(i);
|
|
|
|
/***** Diffuse *****/
|
|
// Remaining Bishop parameters
|
|
DOT (a,L,A); //a = L.A/|L|
|
|
DOT (b,L,B); //b = L.B/|L|
|
|
DOT (c,L,C); //c = L.C/|L|
|
|
|
|
|
|
// Polynomial coefficients
|
|
//DOT (pld->D[0], &normal, L);
|
|
pld->D[0] = c/iRt;
|
|
pld->D[1] = (2.0*b*i - c*h)/(2.0*i*iRt);
|
|
pld->D[2] = (2.0*a*i - c*g)/(2.0*i*iRt);
|
|
pld->D[3] = (3.0*c*h*h - 4.0*c*f*i - 4.0*b*h*i)/(8.0*i2*iRt);
|
|
pld->D[4] = (3.0*c*g*h - 2.0*c*e*i - 2.0*b*g*i - 2.0*a*h*i)/
|
|
(4.0*i2*iRt);
|
|
pld->D[5] = (3.0*c*g*g - 4.0*c*d*i - 4.0*a*g*i)/(8.0*i2*iRt);
|
|
|
|
#ifdef __DBG_PRINT
|
|
DbgPrint ("D[0]= %f, D[1]=%f, D[2]=%f, D[3]=%f, D[4]=%f, D[5]=%f\n",
|
|
pld->D[0], pld->D[1], pld->D[2], pld->D[3], pld->D[4],
|
|
pld->D[5]);
|
|
#endif
|
|
// Constant deltas
|
|
pld->Ddel2Span = 2*pld->D[5];
|
|
pld->D_curr = pld->D[0];
|
|
#ifdef __DBG_PRINT
|
|
DbgPrint ("Ddel2Span= %f, D_curr=%f\n", pld->Ddel2Span, pld->D_curr);
|
|
#endif
|
|
|
|
/***** Specular ******/
|
|
// Remaining Bishop parameters
|
|
DOT (a,H,A); //a = H.A/|H|
|
|
DOT (b,H,B); //b = H.B/|H|
|
|
DOT (c,H,C); //c = H.C/|H|
|
|
|
|
// Polynomial coefficients
|
|
DOT (pld->S[0], &normal, H);
|
|
pld->S[1] = (2.0*b*i - c*h)/(2.0*i*iRt);
|
|
pld->S[2] = (2.0*a*i - c*g)/(2.0*i*iRt);
|
|
pld->S[3] = (3.0*c*h*h - 4.0*c*f*i - 4.0*b*h*i)/(8.0*i2*iRt);
|
|
pld->S[4] = (3.0*c*g*h - 2.0*c*e*i - 2.0*b*g*i - 2.0*a*h*i)/
|
|
(4.0*i2*iRt);
|
|
pld->S[5] = (3.0*c*g*g - 4.0*c*d*i - 4.0*a*g*i)/(8.0*i2*iRt);
|
|
|
|
// Constant deltas
|
|
pld->Sdel2Span = 2*pld->S[5];
|
|
pld->S_curr = pld->S[0];
|
|
|
|
#ifdef __SLOW
|
|
pld->A[0] = a; pld->A[1] = b;
|
|
pld->A[2] = c; pld->A[3] = d;
|
|
pld->A[4] = e; pld->A[5] = f;
|
|
pld->A[6] = g; pld->A[7] = h;
|
|
pld->A[8] = i;
|
|
#endif
|
|
#ifdef __DBG_PRINT
|
|
DbgPrint ("L = (%f, %f, %f)\n", L->x, L->y, L->z);
|
|
DbgPrint ("H = (%f, %f, %f)\n", H->x, H->y, H->z);
|
|
DbgPrint ("a= %f, b=%f, c=%f, d=%f, e=%f, f=%f, g=%f, h=%f, i=%f\n",
|
|
a, b, c, d, e, f, g, h, i);
|
|
#endif
|
|
}
|
|
|
|
phong->numLights = curL;
|
|
#ifdef __CENTER
|
|
phong->cur_pos.x = v->window.x - phong->center.x;
|
|
phong->cur_pos.y = v->window.y - phong->center.y;
|
|
#else
|
|
phong->cur_pos.x = 0.0;
|
|
phong->cur_pos.y = 0.0;
|
|
#endif
|
|
}
|
|
|
|
|
|
void InitializePhongInterpolationSlow (__GLcontext *gc, __GLvertex *v)
|
|
{
|
|
}
|
|
|
|
/* Do nothing */
|
|
void InitializePhongInterpolationVan (__GLcontext *gc, __GLvertex *v)
|
|
{
|
|
__GLphongShader *phong = &gc->polygon.shader.phong;
|
|
|
|
#ifdef __DBG_PRINT
|
|
DbgPrint ("dndx = (%f, %f, %f)\n", phong->dndx.x, phong->dndx.y,
|
|
phong->dndx.z);
|
|
DbgPrint ("dndy = (%f, %f, %f)\n", phong->dndy.x, phong->dndy.y,
|
|
phong->dndy.z);
|
|
DbgPrint ("normal = (%f, %f, %f)\n", v->normal.x, v->normal.y,
|
|
v->normal.z);
|
|
#endif
|
|
}
|
|
|
|
void UpdateParamsAlongEdgeFast (__GLcontext *gc, __GLfloat dxLeft,
|
|
GLboolean useBigStep)
|
|
{
|
|
__GLphongShader *phong = &(gc->polygon.shader.phong);
|
|
__GLphongPerLightData *pld;
|
|
GLint i;
|
|
|
|
if (useBigStep)
|
|
{
|
|
for (i=0; i<phong->numLights; i++)
|
|
{
|
|
pld = &(phong->perLight[i]);
|
|
|
|
/** Diffuse Parameters **/
|
|
pld->D_curr += pld->DdelEdgeBig;
|
|
pld->DdelEdgeBig += pld->Ddel2EdgeBig;
|
|
pld->DdelEdgeLittle += pld->Ddel2EdgeBig;
|
|
pld->DdelSpan += pld->DdelSpanEdgeBig;
|
|
|
|
/** Specular Parameters **/
|
|
pld->S_curr += pld->SdelEdgeBig;
|
|
pld->SdelEdgeBig += pld->Sdel2EdgeBig;
|
|
pld->SdelEdgeLittle += pld->Sdel2EdgeBig;
|
|
pld->SdelSpan += pld->SdelSpanEdgeBig;
|
|
}
|
|
}
|
|
else //Use small step
|
|
{
|
|
for (i=0; i<phong->numLights; i++)
|
|
{
|
|
pld = &(phong->perLight[i]);
|
|
|
|
/** Diffuse Parameters **/
|
|
pld->D_curr += pld->DdelEdgeLittle;
|
|
pld->DdelEdgeBig += pld->Ddel2EdgeLittle;
|
|
pld->DdelEdgeLittle += pld->Ddel2EdgeLittle;
|
|
pld->DdelSpan += pld->DdelSpanEdgeLittle;
|
|
|
|
/** Specular Parameters **/
|
|
pld->S_curr += pld->SdelEdgeLittle;
|
|
pld->SdelEdgeBig += pld->Sdel2EdgeLittle;
|
|
pld->SdelEdgeLittle += pld->Sdel2EdgeLittle;
|
|
pld->SdelSpan += pld->SdelSpanEdgeLittle;
|
|
}
|
|
}
|
|
|
|
phong->cur_pos.x += dxLeft;
|
|
phong->cur_pos.y += 1.0;
|
|
}
|
|
|
|
|
|
|
|
void UpdateParamsAlongEdgeVan (__GLcontext *gc, __GLfloat dxLeft,
|
|
GLboolean useBigStep)
|
|
{
|
|
__GLphongShader *phong = &(gc->polygon.shader.phong);
|
|
|
|
if (useBigStep)
|
|
{
|
|
phong->nCur.x += phong->nBig.x;
|
|
phong->nCur.y += phong->nBig.y;
|
|
phong->nCur.z += phong->nBig.z;
|
|
}
|
|
else
|
|
{
|
|
phong->nCur.x += phong->nLittle.x;
|
|
phong->nCur.y += phong->nLittle.y;
|
|
phong->nCur.z += phong->nLittle.z;
|
|
}
|
|
|
|
if (phong->flags & __GL_PHONG_NEED_EYE_XPOLATE)
|
|
{
|
|
if (useBigStep)
|
|
{
|
|
phong->eCur.x += phong->eBig.x;
|
|
phong->eCur.y += phong->eBig.y;
|
|
phong->eCur.z += phong->eBig.z;
|
|
phong->eCur.w += phong->eBig.w;
|
|
}
|
|
else
|
|
{
|
|
phong->eCur.x += phong->eLittle.x;
|
|
phong->eCur.y += phong->eLittle.y;
|
|
phong->eCur.z += phong->eLittle.z;
|
|
phong->eCur.w += phong->eLittle.w;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#endif //__JUNKED_CODE
|
|
|
|
#endif // GL_WIN_phong_shading
|