ftp.nice.ch/pub/next/developer/resources/libraries/Mesa.2.0.s.tar.gz#/Mesa-2.0/src/fog.c

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.