windows-nt/Source/XPSP1/NT/multimedia/opengl/server/soft/so_fog.c
2020-09-26 16:20:57 +08:00

620 lines
15 KiB
C

/*
** Copyright 1991, Silicon Graphics, Inc.
** All Rights Reserved.
**
** This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
** the contents of this file may not be disclosed to third parties, copied or
** duplicated in any form, in whole or in part, without the prior written
** permission of Silicon Graphics, Inc.
**
** RESTRICTED RIGHTS LEGEND:
** Use, duplication or disclosure by the Government is subject to restrictions
** as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
** and Computer Software clause at DFARS 252.227-7013, and/or in similar or
** successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
** rights reserved under the Copyright Laws of the United States.
**
** $Revision: 1.15 $
** $Date: 1993/10/07 18:46:43 $
*/
#include "precomp.h"
#pragma hdrstop
GLboolean FASTCALL __glFogSpan(__GLcontext *gc)
{
__GLcolor *cp, *fogColor;
__GLfloat f, oneMinusFog, fog;
GLint w;
GLboolean bGrayFog;
w = gc->polygon.shader.length;
f = gc->polygon.shader.frag.f;
cp = gc->polygon.shader.colors;
fogColor = &gc->state.fog.color;
#ifdef NT
bGrayFog = !gc->modes.colorIndexMode
&& (gc->state.fog.flags & __GL_FOG_GRAY_RGB);
if (bGrayFog)
{
while (--w >= 0)
{
__GLfloat delta;
/* clamp fog value */
fog = f;
if (fog < __glZero) fog = __glZero;
else if (fog > __glOne) fog = __glOne;
oneMinusFog = __glOne - fog;
delta = oneMinusFog * fogColor->r;
/* Blend incoming color against the fog color */
cp->r = fog * cp->r + delta;
cp->g = fog * cp->g + delta;
cp->b = fog * cp->b + delta;
f += gc->polygon.shader.dfdx;
cp++;
}
}
else
#endif
while (--w >= 0) {
/* clamp fog value */
fog = f;
if (fog < __glZero) fog = __glZero;
else if (fog > __glOne) fog = __glOne;
oneMinusFog = __glOne - fog;
/* Blend incoming color against the fog color */
if (gc->modes.colorIndexMode) {
cp->r = cp->r + oneMinusFog * gc->state.fog.index;
} else {
cp->r = fog * cp->r + oneMinusFog * fogColor->r;
cp->g = fog * cp->g + oneMinusFog * fogColor->g;
cp->b = fog * cp->b + oneMinusFog * fogColor->b;
}
f += gc->polygon.shader.dfdx;
cp++;
}
return GL_FALSE;
}
GLboolean FASTCALL __glFogStippledSpan(__GLcontext *gc)
{
__GLstippleWord bit, inMask, *sp;
__GLcolor *cp, *fogColor;
__GLfloat f, oneMinusFog, fog;
GLint count;
GLint w;
GLboolean bGrayFog;
w = gc->polygon.shader.length;
sp = gc->polygon.shader.stipplePat;
f = gc->polygon.shader.frag.f;
cp = gc->polygon.shader.colors;
fogColor = &gc->state.fog.color;
#ifdef NT
bGrayFog = (gc->state.fog.flags & __GL_FOG_GRAY_RGB) ? GL_TRUE : GL_FALSE;
#endif
while (w) {
count = w;
if (count > __GL_STIPPLE_BITS) {
count = __GL_STIPPLE_BITS;
}
w -= count;
inMask = *sp++;
bit = (__GLstippleWord) __GL_STIPPLE_SHIFT(0);
while (--count >= 0) {
if (inMask & bit) {
/* clamp fog value */
fog = f;
if (fog < __glZero) fog = __glZero;
else if (fog > __glOne) fog = __glOne;
oneMinusFog = __glOne - fog;
/* Blend incoming color against the fog color */
if (gc->modes.colorIndexMode) {
cp->r = cp->r + oneMinusFog * gc->state.fog.index;
} else {
#ifdef NT
if (bGrayFog)
{
__GLfloat delta = oneMinusFog * fogColor->r;
cp->r = fog * cp->r + delta;
cp->g = fog * cp->g + delta;
cp->b = fog * cp->b + delta;
}
else
#endif
{
cp->r = fog * cp->r + oneMinusFog * fogColor->r;
cp->g = fog * cp->g + oneMinusFog * fogColor->g;
cp->b = fog * cp->b + oneMinusFog * fogColor->b;
}
}
}
f += gc->polygon.shader.dfdx;
cp++;
#ifdef __GL_STIPPLE_MSB
bit >>= 1;
#else
bit <<= 1;
#endif
}
}
return GL_FALSE;
}
/************************************************************************/
GLboolean FASTCALL __glFogSpanSlow(__GLcontext *gc)
{
__GLcolor *cp, *fogColor;
__GLfloat f, oneMinusFog, fog, eyeZ;
__GLfloat density, density2neg, end;
GLint w;
GLboolean bGrayFog;
w = gc->polygon.shader.length;
f = gc->polygon.shader.frag.f;
cp = gc->polygon.shader.colors;
fogColor = &gc->state.fog.color;
density = gc->state.fog.density;
#ifdef NT
bGrayFog = (gc->state.fog.flags & __GL_FOG_GRAY_RGB) ? GL_TRUE : GL_FALSE;
density2neg = gc->state.fog.density2neg;
#else
density2 = density * density;
start = gc->state.fog.start;
#endif
end = gc->state.fog.end;
while (--w >= 0) {
#ifdef NT
/* Compute fog value */
eyeZ = f;
switch (gc->state.fog.mode) {
case GL_EXP:
if (eyeZ < __glZero)
fog = __GL_POWF(__glE, density * eyeZ);
else
fog = __GL_POWF(__glE, -density * eyeZ);
/* clamp fog value */
if (fog > __glOne) fog = __glOne;
break;
case GL_EXP2:
fog = __GL_POWF(__glE, density2neg * eyeZ * eyeZ);
/* clamp fog value */
if (fog > __glOne) fog = __glOne;
break;
case GL_LINEAR:
if (eyeZ < __glZero)
fog = (end + eyeZ) * gc->state.fog.oneOverEMinusS;
else
fog = (end - eyeZ) * gc->state.fog.oneOverEMinusS;
/* clamp fog value */
if (fog < __glZero) fog = __glZero;
else if (fog > __glOne) fog = __glOne;
break;
}
#else
/* Compute fog value */
eyeZ = f;
if (eyeZ < __glZero) eyeZ = -eyeZ;
switch (gc->state.fog.mode) {
case GL_EXP:
fog = __GL_POWF(__glE, -density * eyeZ);
break;
case GL_EXP2:
fog = __GL_POWF(__glE, -(density2 * eyeZ * eyeZ));
break;
case GL_LINEAR:
fog = (end - eyeZ) * gc->state.fog.oneOverEMinusS;
break;
}
/* clamp fog value */
if (fog < __glZero) fog = __glZero;
else if (fog > __glOne) fog = __glOne;
#endif
oneMinusFog = __glOne - fog;
/* Blend incoming color against the fog color */
if (gc->modes.colorIndexMode) {
cp->r = cp->r + oneMinusFog * gc->state.fog.index;
} else {
#ifdef NT
if (bGrayFog)
{
__GLfloat delta = oneMinusFog * fogColor->r;
cp->r = fog * cp->r + delta;
cp->g = fog * cp->g + delta;
cp->b = fog * cp->b + delta;
}
else
#endif
{
cp->r = fog * cp->r + oneMinusFog * fogColor->r;
cp->g = fog * cp->g + oneMinusFog * fogColor->g;
cp->b = fog * cp->b + oneMinusFog * fogColor->b;
}
}
f += gc->polygon.shader.dfdx;
cp++;
}
return GL_FALSE;
}
GLboolean FASTCALL __glFogStippledSpanSlow(__GLcontext *gc)
{
__GLstippleWord bit, inMask, *sp;
__GLcolor *cp, *fogColor;
__GLfloat f, oneMinusFog, fog, eyeZ;
__GLfloat density, density2neg, end;
GLint count;
GLint w;
GLboolean bGrayFog;
w = gc->polygon.shader.length;
sp = gc->polygon.shader.stipplePat;
f = gc->polygon.shader.frag.f;
cp = gc->polygon.shader.colors;
fogColor = &gc->state.fog.color;
#ifdef NT
bGrayFog = (gc->state.fog.flags & __GL_FOG_GRAY_RGB) ? GL_TRUE : GL_FALSE;
#endif
density = gc->state.fog.density;
#ifdef NT
density2neg = gc->state.fog.density2neg;
#else
density2 = density * density;
start = gc->state.fog.start;
#endif
end = gc->state.fog.end;
while (w) {
count = w;
if (count > __GL_STIPPLE_BITS) {
count = __GL_STIPPLE_BITS;
}
w -= count;
inMask = *sp++;
bit = (__GLstippleWord) __GL_STIPPLE_SHIFT(0);
while (--count >= 0) {
if (inMask & bit) {
#ifdef NT
/* Compute fog value */
eyeZ = f;
switch (gc->state.fog.mode) {
case GL_EXP:
if (eyeZ < __glZero)
fog = __GL_POWF(__glE, density * eyeZ);
else
fog = __GL_POWF(__glE, -density * eyeZ);
/* Clamp resulting fog value */
if (fog > __glOne) fog = __glOne;
break;
case GL_EXP2:
fog = __GL_POWF(__glE, density2neg * eyeZ * eyeZ);
/* Clamp resulting fog value */
if (fog > __glOne) fog = __glOne;
break;
case GL_LINEAR:
if (eyeZ < __glZero)
fog = (end + eyeZ) * gc->state.fog.oneOverEMinusS;
else
fog = (end - eyeZ) * gc->state.fog.oneOverEMinusS;
/* Clamp resulting fog value */
if (fog < __glZero) fog = __glZero;
else if (fog > __glOne) fog = __glOne;
break;
}
#else
/* Compute fog value */
eyeZ = f;
if (eyeZ < __glZero) eyeZ = -eyeZ;
switch (gc->state.fog.mode) {
case GL_EXP:
fog = __GL_POWF(__glE, -density * eyeZ);
break;
case GL_EXP2:
fog = __GL_POWF(__glE, -(density2 * eyeZ * eyeZ));
break;
case GL_LINEAR:
fog = (end - eyeZ) * gc->state.fog.oneOverEMinusS;
break;
}
/* Clamp resulting fog value */
if (fog < __glZero) fog = __glZero;
else if (fog > __glOne) fog = __glOne;
#endif
oneMinusFog = __glOne - fog;
/* Blend incoming color against the fog color */
if (gc->modes.colorIndexMode) {
cp->r = cp->r + oneMinusFog * gc->state.fog.index;
} else {
#ifdef NT
if (bGrayFog)
{
__GLfloat delta = oneMinusFog * fogColor->r;
cp->r = fog * cp->r + delta;
cp->g = fog * cp->g + delta;
cp->b = fog * cp->b + delta;
}
else
#endif
{
cp->r = fog * cp->r + oneMinusFog * fogColor->r;
cp->g = fog * cp->g + oneMinusFog * fogColor->g;
cp->b = fog * cp->b + oneMinusFog * fogColor->b;
}
}
}
f += gc->polygon.shader.dfdx;
cp++;
#ifdef __GL_STIPPLE_MSB
bit >>= 1;
#else
bit <<= 1;
#endif
}
}
return GL_FALSE;
}
/************************************************************************/
/*
** Compute the fog value given an eyeZ. Then blend into fragment.
** This is used when fragment fogging is done (GL_FOG_HINT == GL_NICEST)
** or by the point rendering routines.
** NOTE: the code below has the -eyeZ factored out.
*/
void __glFogFragmentSlow(__GLcontext *gc, __GLfragment *frag, __GLfloat eyeZ)
{
__GLfloat fog, oneMinusFog, density, density2neg, end;
__GLcolor *fogColor;
#ifdef NT
switch (gc->state.fog.mode) {
case GL_EXP:
density = gc->state.fog.density;
if (eyeZ < __glZero)
fog = __GL_POWF(__glE, density * eyeZ);
else
fog = __GL_POWF(__glE, -density * eyeZ);
/* clamp fog value */
if (fog > __glOne) fog = __glOne;
break;
case GL_EXP2:
density2neg = gc->state.fog.density2neg;
fog = __GL_POWF(__glE, density2neg * eyeZ * eyeZ);
/* clamp fog value */
if (fog > __glOne) fog = __glOne;
break;
case GL_LINEAR:
end = gc->state.fog.end;
if (eyeZ < __glZero)
fog = (end + eyeZ) * gc->state.fog.oneOverEMinusS;
else
fog = (end - eyeZ) * gc->state.fog.oneOverEMinusS;
/* clamp fog value */
if (fog < __glZero) fog = __glZero;
else if (fog > __glOne) fog = __glOne;
break;
}
#else
if (eyeZ < __glZero) eyeZ = -eyeZ;
switch (gc->state.fog.mode) {
case GL_EXP:
density = gc->state.fog.density;
fog = __GL_POWF(__glE, -density * eyeZ);
break;
case GL_EXP2:
density = gc->state.fog.density;
fog = __GL_POWF(__glE, -(density * eyeZ * density * eyeZ));
break;
case GL_LINEAR:
end = gc->state.fog.end;
fog = (end - eyeZ) * gc->state.fog.oneOverEMinusS;
break;
}
/*
** clamp fog value
*/
if (fog < __glZero)
fog = __glZero;
else if (fog > __glOne)
fog = __glOne;
#endif
oneMinusFog = __glOne - fog;
/*
** Blend incoming color against the fog color
*/
fogColor = &gc->state.fog.color;
if (gc->modes.colorIndexMode) {
frag->color.r = frag->color.r + oneMinusFog * gc->state.fog.index;
} else {
#ifdef NT
if (gc->state.fog.flags & __GL_FOG_GRAY_RGB)
{
__GLfloat delta = oneMinusFog * fogColor->r;
frag->color.r = fog * frag->color.r + delta;
frag->color.g = fog * frag->color.g + delta;
frag->color.b = fog * frag->color.b + delta;
}
else
#endif
{
frag->color.r = fog * frag->color.r + oneMinusFog * fogColor->r;
frag->color.g = fog * frag->color.g + oneMinusFog * fogColor->g;
frag->color.b = fog * frag->color.b + oneMinusFog * fogColor->b;
}
}
}
/*
** Compute generic fog value for vertex.
*/
__GLfloat FASTCALL __glFogVertex(__GLcontext *gc, __GLvertex *vx)
{
__GLfloat eyeZ, fog, density, density2neg, end;
eyeZ = vx->eyeZ;
#ifdef NT
switch (gc->state.fog.mode) {
case GL_EXP:
density = gc->state.fog.density;
if (eyeZ < __glZero)
fog = __GL_POWF(__glE, density * eyeZ);
else
fog = __GL_POWF(__glE, -density * eyeZ);
/* clamp fog value */
if (fog > __glOne) fog = __glOne;
break;
case GL_EXP2:
density2neg = gc->state.fog.density2neg;
fog = __GL_POWF(__glE, density2neg * eyeZ * eyeZ);
/* clamp fog value */
if (fog > __glOne) fog = __glOne;
break;
case GL_LINEAR:
end = gc->state.fog.end;
if (eyeZ < __glZero)
fog = (end + eyeZ) * gc->state.fog.oneOverEMinusS;
else
fog = (end - eyeZ) * gc->state.fog.oneOverEMinusS;
/* clamp fog value */
if (fog < __glZero) fog = __glZero;
else if (fog > __glOne) fog = __glOne;
break;
}
#else
if (eyeZ < __glZero) eyeZ = -eyeZ;
switch (gc->state.fog.mode) {
case GL_EXP:
density = gc->state.fog.density;
fog = __GL_POWF(__glE, -density * eyeZ);
break;
case GL_EXP2:
density = gc->state.fog.density;
fog = __GL_POWF(__glE, -(density * eyeZ * density * eyeZ));
break;
case GL_LINEAR:
end = gc->state.fog.end;
fog = (end - eyeZ) * gc->state.fog.oneOverEMinusS;
break;
}
/*
** Since this routine is called when we are doing slow fog, we can
** safely clamp the fog value here.
*/
if (fog < __glZero)
fog = __glZero;
else if (fog > __glOne)
fog = __glOne;
#endif
return fog;
}
/*
** Compute linear fog value for vertex
*/
__GLfloat FASTCALL __glFogVertexLinear(__GLcontext *gc, __GLvertex *vx)
{
__GLfloat eyeZ, fog, end;
eyeZ = vx->eyeZ;
#ifdef NT
end = gc->state.fog.end;
if (eyeZ < __glZero)
fog = (end + eyeZ) * gc->state.fog.oneOverEMinusS;
else
fog = (end - eyeZ) * gc->state.fog.oneOverEMinusS;
#else
if (eyeZ < __glZero) eyeZ = -eyeZ;
end = gc->state.fog.end;
fog = (end - eyeZ) * gc->state.fog.oneOverEMinusS;
#endif
if (fog < __glZero)
fog = __glZero;
else if (fog > __glOne)
fog = __glOne;
return fog;
}
/*
** Compute the fogged color given an incoming color and a fog value.
*/
void __glFogColorSlow(__GLcontext *gc, __GLcolor *out, __GLcolor *in,
__GLfloat fog)
{
__GLcolor *fogColor;
__GLfloat oneMinusFog;
__GLfloat r, g, b;
oneMinusFog = __glOne - fog;
/*
** Blend incoming color against the fog color
*/
fogColor = &gc->state.fog.color;
if (gc->modes.colorIndexMode) {
out->r = in->r + oneMinusFog * gc->state.fog.index;
} else {
#ifdef NT
if (gc->state.fog.flags & __GL_FOG_GRAY_RGB)
{
__GLfloat delta = oneMinusFog * fogColor->r;
out->r = fog * in->r + delta;
out->g = fog * in->g + delta;
out->b = fog * in->b + delta;
}
else
#endif
{
/*
** The following is coded like this to give the instruction scheduler
** a hand.
*/
r = fog * in->r;
g = fog * in->g;
b = fog * in->b;
r += oneMinusFog * fogColor->r;
g += oneMinusFog * fogColor->g;
b += oneMinusFog * fogColor->b;
out->r = r;
out->g = g;
out->b = b;
}
out->a = in->a;
}
}