This is fog.c in view mode; [Download] [Up]
/* $Id: fog.c,v 1.3 1996/09/27 01:26:52 brianp Exp $ */
/*
* Mesa 3-D graphics library
* Version: 2.0
* Copyright (C) 1995-1996 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* $Log: fog.c,v $
* Revision 1.3 1996/09/27 01:26:52 brianp
* added missing default cases to switches
*
* Revision 1.2 1996/09/15 14:17:30 brianp
* now use GLframebuffer and GLvisual
*
* Revision 1.1 1996/09/13 01:38:16 brianp
* Initial revision
*
*/
#include <math.h>
#include <stdlib.h>
#include "context.h"
#include "fog.h"
#include "dlist.h"
#include "macros.h"
#include "types.h"
void gl_Fogfv( GLcontext *ctx, GLenum pname, const GLfloat *params )
{
GLenum m;
switch (pname) {
case GL_FOG_MODE:
m = (GLenum) (GLint) *params;
if (m==GL_LINEAR || m==GL_EXP || m==GL_EXP2) {
ctx->Fog.Mode = m;
}
else {
gl_error( ctx, GL_INVALID_ENUM, "glFog" );
}
break;
case GL_FOG_DENSITY:
if (*params<0.0) {
gl_error( ctx, GL_INVALID_VALUE, "glFog" );
}
else {
ctx->Fog.Density = *params;
}
break;
case GL_FOG_START:
#ifndef GL_VERSION_1_1
if (*params<0.0F) {
gl_error( ctx, GL_INVALID_VALUE, "glFog(GL_FOG_START)" );
return;
}
#endif
ctx->Fog.Start = *params;
break;
case GL_FOG_END:
#ifndef GL_VERSION_1_1
if (*params<0.0F) {
gl_error( ctx, GL_INVALID_VALUE, "glFog(GL_FOG_END)" );
return;
}
#endif
ctx->Fog.End = *params;
break;
case GL_FOG_INDEX:
ctx->Fog.Index = *params;
break;
case GL_FOG_COLOR:
ctx->Fog.Color[0] = params[0];
ctx->Fog.Color[1] = params[1];
ctx->Fog.Color[2] = params[2];
ctx->Fog.Color[3] = params[3];
break;
default:
gl_error( ctx, GL_INVALID_ENUM, "glFog" );
}
}
/*
* Compute the fogged color for an array of vertices.
* Input: n - number of vertices
* v - array of vertices
* color - the original vertex colors
* Output: color - the fogged colors
*/
void gl_fog_color_vertices( GLcontext *ctx,
GLuint n, GLfloat v[][4], GLfixed color[][4] )
{
GLuint i;
GLfloat d;
GLfloat shift = (GLfloat) (1 << ctx->ColorShift);
GLfloat fogr = ctx->Fog.Color[0] * ctx->Visual->RedScale * shift;
GLfloat fogg = ctx->Fog.Color[1] * ctx->Visual->GreenScale * shift;
GLfloat fogb = ctx->Fog.Color[2] * ctx->Visual->BlueScale * shift;
GLfloat foga = ctx->Fog.Color[3] * ctx->Visual->AlphaScale * shift;
GLfloat end = ctx->Fog.End;
switch (ctx->Fog.Mode) {
case GL_LINEAR:
d = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
for (i=0;i<n;i++) {
GLfloat f = (end - ABSF(v[i][2])) * d;
f = CLAMP( f, 0.0F, 1.0F );
color[i][0] = f * color[i][0] + (1.0F-f) * fogr;
color[i][1] = f * color[i][1] + (1.0F-f) * fogg;
color[i][2] = f * color[i][2] + (1.0F-f) * fogb;
color[i][3] = f * color[i][3] + (1.0F-f) * foga;
}
break;
case GL_EXP:
d = -ctx->Fog.Density;
for (i=0;i<n;i++) {
GLfloat f = exp( d * ABSF(v[i][2]) );
f = CLAMP( f, 0.0F, 1.0F );
color[i][0] = f * color[i][0] + (1.0F-f) * fogr;
color[i][1] = f * color[i][1] + (1.0F-f) * fogg;
color[i][2] = f * color[i][2] + (1.0F-f) * fogb;
color[i][3] = f * color[i][3] + (1.0F-f) * foga;
}
break;
case GL_EXP2:
d = -(ctx->Fog.Density*ctx->Fog.Density);
for (i=0;i<n;i++) {
GLfloat z = ABSF(v[i][2]);
GLfloat f = exp( d * z*z );
f = CLAMP( f, 0.0F, 1.0F );
color[i][0] = f * color[i][0] + (1.0F-f) * fogr;
color[i][1] = f * color[i][1] + (1.0F-f) * fogg;
color[i][2] = f * color[i][2] + (1.0F-f) * fogb;
color[i][3] = f * color[i][3] + (1.0F-f) * foga;
}
break;
default:
abort();
}
}
/*
* Compute the fogged color indexes for an array of vertices.
* Input: n - number of vertices
* v - array of vertices
* In/Out: indx - array of vertex color indexes
*/
void gl_fog_index_vertices( GLcontext *ctx,
GLuint n, GLfloat v[][4], GLuint indx[] )
{
/* NOTE: the extensive use of casts generates better/faster code for MIPS */
switch (ctx->Fog.Mode) {
case GL_LINEAR:
{
GLfloat d = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
GLfloat fogindex = ctx->Fog.Index;
GLfloat fogend = ctx->Fog.End;
GLuint i;
for (i=0;i<n;i++) {
GLfloat f = (fogend - ABSF(v[i][2])) * d;
f = CLAMP( f, 0.0F, 1.0F );
indx[i] = (GLint)
((GLfloat) (GLint) indx[i] + (1.0F-f) * fogindex);
}
}
break;
case GL_EXP:
{
GLfloat d = -ctx->Fog.Density;
GLfloat fogindex = ctx->Fog.Index;
GLuint i;
for (i=0;i<n;i++) {
GLfloat f = exp( d * ABSF(v[i][2]) );
f = CLAMP( f, 0.0F, 1.0F );
indx[i] = (GLint)
((GLfloat) (GLint) indx[i] + (1.0F-f) * fogindex);
}
}
break;
case GL_EXP2:
{
GLfloat d = -(ctx->Fog.Density*ctx->Fog.Density);
GLfloat fogindex = ctx->Fog.Index;
GLuint i;
for (i=0;i<n;i++) {
GLfloat z = ABSF(v[i][2]);
GLfloat f = exp( -d * z*z );
f = CLAMP( f, 0.0F, 1.0F );
indx[i] = (GLint)
((GLfloat) (GLint) indx[i] + (1.0F-f) * fogindex);
}
}
break;
default:
abort();
}
}
/*
* Apply fog to an array of RGBA pixels.
* Input: n - number of pixels
* z - array of integer depth values
* red, green, blue, alpha - pixel colors
* Output: red, green, blue, alpha - fogged pixel colors
*/
void gl_fog_color_pixels( GLcontext *ctx,
GLuint n, const GLdepth z[], GLubyte red[],
GLubyte green[], GLubyte blue[], GLubyte alpha[] )
{
/* TODO: optimize case when c = 1.0 and d = 0.0 */
GLfloat d = ctx->ProjectionMatrix[14];
GLfloat c = ctx->ProjectionMatrix[10];
GLfloat winz, ndcz, eyez, f;
GLuint i;
GLint fog_red = (GLint) (ctx->Fog.Color[0] * ctx->Visual->RedScale);
GLint fog_green = (GLint) (ctx->Fog.Color[1] * ctx->Visual->GreenScale);
GLint fog_blue = (GLint) (ctx->Fog.Color[2] * ctx->Visual->BlueScale);
GLint fog_alpha = (GLint) (ctx->Fog.Color[3] * ctx->Visual->AlphaScale);
switch (ctx->Fog.Mode) {
case GL_LINEAR:
for (i=0;i<n;i++) {
winz = (GLfloat) z[i] / DEPTH_SCALE;
ndcz = (winz - ctx->Viewport.Tz) / ctx->Viewport.Sz;
eyez = -d / (c+ndcz);
if (eyez < 0.0) eyez = -eyez;
f = (ctx->Fog.End - eyez) / (ctx->Fog.End - ctx->Fog.Start);
f = CLAMP( f, 0.0F, 1.0F );
red[i] = (GLint) (f * (GLfloat) red[i] + (1.0F-f) * fog_red);
green[i] = (GLint) (f * (GLfloat) green[i] + (1.0F-f) * fog_green);
blue[i] = (GLint) (f * (GLfloat) blue[i] + (1.0F-f) * fog_blue);
alpha[i] = (GLint) (f * (GLfloat) alpha[i] + (1.0F-f) * fog_alpha);
}
break;
case GL_EXP:
for (i=0;i<n;i++) {
winz = (GLfloat) z[i] / DEPTH_SCALE;
ndcz = (winz - ctx->Viewport.Tz) / ctx->Viewport.Sz;
eyez = -d / (c+ndcz);
if (eyez < 0.0) eyez = -eyez;
f = exp( -ctx->Fog.Density * eyez );
f = CLAMP( f, 0.0F, 1.0F );
red[i] = (GLint) (f * (GLfloat) red[i] + (1.0F-f) * fog_red);
green[i] = (GLint) (f * (GLfloat) green[i] + (1.0F-f) * fog_green);
blue[i] = (GLint) (f * (GLfloat) blue[i] + (1.0F-f) * fog_blue);
alpha[i] = (GLint) (f * (GLfloat) alpha[i] + (1.0F-f) * fog_alpha);
}
break;
case GL_EXP2:
for (i=0;i<n;i++) {
winz = (GLfloat) z[i] / DEPTH_SCALE;
ndcz = (winz - ctx->Viewport.Tz) / ctx->Viewport.Sz;
eyez = -d / (c+ndcz);
if (eyez < 0.0) eyez = -eyez;
f = exp( -(ctx->Fog.Density*ctx->Fog.Density * eyez*eyez) );
f = CLAMP( f, 0.0F, 1.0F );
red[i] = (GLint) (f * (GLfloat) red[i] + (1.0F-f) * fog_red);
green[i] = (GLint) (f * (GLfloat) green[i] + (1.0F-f) * fog_green);
blue[i] = (GLint) (f * (GLfloat) blue[i] + (1.0F-f) * fog_blue);
alpha[i] = (GLint) (f * (GLfloat) alpha[i] + (1.0F-f) * fog_alpha);
}
break;
default:
abort();
}
}
/*
* Apply fog to an array of color index pixels.
* Input: n - number of pixels
* z - array of integer depth values
* index - pixel color indexes
* Output: index - fogged pixel color indexes
*/
void gl_fog_index_pixels( GLcontext *ctx,
GLuint n, const GLdepth z[], GLuint index[] )
{
/* TODO: optimize case when c = 1.0 and d = 0.0 */
GLfloat d = ctx->ProjectionMatrix[14];
GLfloat c = ctx->ProjectionMatrix[10];
GLfloat winz, ndcz, eyez, f;
GLuint i;
switch (ctx->Fog.Mode) {
case GL_LINEAR:
for (i=0;i<n;i++) {
winz = (GLfloat) z[i] / DEPTH_SCALE;
ndcz = (winz - ctx->Viewport.Tz) / ctx->Viewport.Sz;
eyez = -d / (c+ndcz);
if (eyez < 0.0) eyez = -eyez;
f = (ctx->Fog.End - eyez) / (ctx->Fog.End - ctx->Fog.Start);
f = CLAMP( f, 0.0F, 1.0F );
index[i] = (GLuint) ((GLfloat) index[i] + (1.0F-f) * ctx->Fog.Index);
}
break;
case GL_EXP:
for (i=0;i<n;i++) {
winz = (GLfloat) z[i] / DEPTH_SCALE;
ndcz = (winz - ctx->Viewport.Tz) / ctx->Viewport.Sz;
eyez = -d / (c+ndcz);
if (eyez < 0.0) eyez = -eyez;
f = exp( -ctx->Fog.Density * eyez );
f = CLAMP( f, 0.0F, 1.0F );
index[i] = (GLuint) ((GLfloat) index[i] + (1.0F-f) * ctx->Fog.Index);
}
break;
case GL_EXP2:
for (i=0;i<n;i++) {
winz = (GLfloat) z[i] / DEPTH_SCALE;
ndcz = (winz - ctx->Viewport.Tz) / ctx->Viewport.Sz;
eyez = -d / (c+ndcz);
if (eyez < 0.0) eyez = -eyez;
f = exp( -(ctx->Fog.Density*ctx->Fog.Density * eyez*eyez) );
f = CLAMP( f, 0.0F, 1.0F );
index[i] = (GLuint) ((GLfloat) index[i] + (1.0F-f) * ctx->Fog.Index);
}
break;
default:
abort();
}
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.