home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 5 / MA_Cover_5.iso / ppc / mesa / src / fog.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-01-31  |  11.6 KB  |  390 lines

  1. /* $Id: fog.c,v 1.9 1997/07/24 01:25:01 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  2.4
  6.  * Copyright (C) 1995-1996  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: fog.c,v $
  26.  * Revision 1.9  1997/07/24 01:25:01  brianp
  27.  * changed precompiled header symbol from PCH to PC_HEADER
  28.  *
  29.  * Revision 1.8  1997/06/20 04:14:47  brianp
  30.  * changed color components from GLfixed to GLubyte
  31.  *
  32.  * Revision 1.7  1997/05/28 03:24:54  brianp
  33.  * added precompiled header (PCH) support
  34.  *
  35.  * Revision 1.6  1997/05/22 03:03:47  brianp
  36.  * don't apply fog to alpha values
  37.  *
  38.  * Revision 1.5  1997/04/20 20:28:49  brianp
  39.  * replaced abort() with gl_problem()
  40.  *
  41.  * Revision 1.4  1996/11/04 02:30:15  brianp
  42.  * optimized gl_fog_color_pixels() and gl_fog_index_pixels()
  43.  *
  44.  * Revision 1.3  1996/09/27 01:26:52  brianp
  45.  * added missing default cases to switches
  46.  *
  47.  * Revision 1.2  1996/09/15 14:17:30  brianp
  48.  * now use GLframebuffer and GLvisual
  49.  *
  50.  * Revision 1.1  1996/09/13 01:38:16  brianp
  51.  * Initial revision
  52.  *
  53.  */
  54.  
  55.  
  56. #ifdef PC_HEADER
  57. #include "all.h"
  58. #else
  59. #include <math.h>
  60. #include <stdlib.h>
  61. #include "context.h"
  62. #include "fog.h"
  63. #include "dlist.h"
  64. #include "macros.h"
  65. #include "types.h"
  66. #endif
  67.  
  68.  
  69.  
  70. void gl_Fogfv( GLcontext *ctx, GLenum pname, const GLfloat *params )
  71. {
  72.    GLenum m;
  73.  
  74.    switch (pname) {
  75.       case GL_FOG_MODE:
  76.          m = (GLenum) (GLint) *params;
  77.      if (m==GL_LINEAR || m==GL_EXP || m==GL_EXP2) {
  78.         ctx->Fog.Mode = m;
  79.      }
  80.      else {
  81.         gl_error( ctx, GL_INVALID_ENUM, "glFog" );
  82.      }
  83.      break;
  84.       case GL_FOG_DENSITY:
  85.      if (*params<0.0) {
  86.         gl_error( ctx, GL_INVALID_VALUE, "glFog" );
  87.      }
  88.      else {
  89.         ctx->Fog.Density = *params;
  90.      }
  91.      break;
  92.       case GL_FOG_START:
  93. #ifndef GL_VERSION_1_1
  94.          if (*params<0.0F) {
  95.             gl_error( ctx, GL_INVALID_VALUE, "glFog(GL_FOG_START)" );
  96.             return;
  97.          }
  98. #endif
  99.      ctx->Fog.Start = *params;
  100.      break;
  101.       case GL_FOG_END:
  102. #ifndef GL_VERSION_1_1
  103.          if (*params<0.0F) {
  104.             gl_error( ctx, GL_INVALID_VALUE, "glFog(GL_FOG_END)" );
  105.             return;
  106.          }
  107. #endif
  108.      ctx->Fog.End = *params;
  109.      break;
  110.       case GL_FOG_INDEX:
  111.      ctx->Fog.Index = *params;
  112.      break;
  113.       case GL_FOG_COLOR:
  114.      ctx->Fog.Color[0] = params[0];
  115.      ctx->Fog.Color[1] = params[1];
  116.      ctx->Fog.Color[2] = params[2];
  117.      ctx->Fog.Color[3] = params[3];
  118.          break;
  119.       default:
  120.          gl_error( ctx, GL_INVALID_ENUM, "glFog" );
  121.    }
  122. }
  123.  
  124.  
  125.  
  126.  
  127. /*
  128.  * Compute the fogged color for an array of vertices.
  129.  * Input:  n - number of vertices
  130.  *         v - array of vertices
  131.  *         color - the original vertex colors
  132.  * Output:  color - the fogged colors
  133.  */
  134. void gl_fog_color_vertices( GLcontext *ctx,
  135.                             GLuint n, GLfloat v[][4], GLubyte color[][4] )
  136. {
  137.    GLuint i;
  138.    GLfloat d;
  139.    GLfloat fogr = ctx->Fog.Color[0] * ctx->Visual->RedScale;
  140.    GLfloat fogg = ctx->Fog.Color[1] * ctx->Visual->GreenScale;
  141.    GLfloat fogb = ctx->Fog.Color[2] * ctx->Visual->BlueScale;
  142.    GLfloat end = ctx->Fog.End;
  143.  
  144.    switch (ctx->Fog.Mode) {
  145.       case GL_LINEAR:
  146.          d = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
  147.          for (i=0;i<n;i++) {
  148.             GLfloat f = (end - ABSF(v[i][2])) * d;
  149.             f = CLAMP( f, 0.0F, 1.0F );
  150.             color[i][0] = f * color[i][0] + (1.0F-f) * fogr;
  151.             color[i][1] = f * color[i][1] + (1.0F-f) * fogg;
  152.             color[i][2] = f * color[i][2] + (1.0F-f) * fogb;
  153.          }
  154.      break;
  155.       case GL_EXP:
  156.          d = -ctx->Fog.Density;
  157.          for (i=0;i<n;i++) {
  158.             GLfloat f = exp( d * ABSF(v[i][2]) );
  159.             f = CLAMP( f, 0.0F, 1.0F );
  160.             color[i][0] = f * color[i][0] + (1.0F-f) * fogr;
  161.             color[i][1] = f * color[i][1] + (1.0F-f) * fogg;
  162.             color[i][2] = f * color[i][2] + (1.0F-f) * fogb;
  163.          }
  164.      break;
  165.       case GL_EXP2:
  166.          d = -(ctx->Fog.Density*ctx->Fog.Density);
  167.          for (i=0;i<n;i++) {
  168.             GLfloat z = ABSF(v[i][2]);
  169.             GLfloat f = exp( d * z*z );
  170.             f = CLAMP( f, 0.0F, 1.0F );
  171.             color[i][0] = f * color[i][0] + (1.0F-f) * fogr;
  172.             color[i][1] = f * color[i][1] + (1.0F-f) * fogg;
  173.             color[i][2] = f * color[i][2] + (1.0F-f) * fogb;
  174.          }
  175.      break;
  176.       default:
  177.          gl_problem(ctx, "Bad fog mode in gl_fog_color_vertices");
  178.          return;
  179.    }
  180. }
  181.  
  182.  
  183.  
  184. /*
  185.  * Compute the fogged color indexes for an array of vertices.
  186.  * Input:  n - number of vertices
  187.  *         v - array of vertices
  188.  * In/Out: indx - array of vertex color indexes
  189.  */
  190. void gl_fog_index_vertices( GLcontext *ctx,
  191.                             GLuint n, GLfloat v[][4], GLuint indx[] )
  192. {
  193.    /* NOTE: the extensive use of casts generates better/faster code for MIPS */
  194.    switch (ctx->Fog.Mode) {
  195.       case GL_LINEAR:
  196.          {
  197.             GLfloat d = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
  198.             GLfloat fogindex = ctx->Fog.Index;
  199.             GLfloat fogend = ctx->Fog.End;
  200.             GLuint i;
  201.             for (i=0;i<n;i++) {
  202.                GLfloat f = (fogend - ABSF(v[i][2])) * d;
  203.                f = CLAMP( f, 0.0F, 1.0F );
  204.                indx[i] = (GLint)
  205.                          ((GLfloat) (GLint) indx[i] + (1.0F-f) * fogindex);
  206.             }
  207.          }
  208.      break;
  209.       case GL_EXP:
  210.          {
  211.             GLfloat d = -ctx->Fog.Density;
  212.             GLfloat fogindex = ctx->Fog.Index;
  213.             GLuint i;
  214.             for (i=0;i<n;i++) {
  215.                GLfloat f = exp( d * ABSF(v[i][2]) );
  216.                f = CLAMP( f, 0.0F, 1.0F );
  217.                indx[i] = (GLint)
  218.                          ((GLfloat) (GLint) indx[i] + (1.0F-f) * fogindex);
  219.             }
  220.          }
  221.      break;
  222.       case GL_EXP2:
  223.          {
  224.             GLfloat d = -(ctx->Fog.Density*ctx->Fog.Density);
  225.             GLfloat fogindex = ctx->Fog.Index;
  226.             GLuint i;
  227.             for (i=0;i<n;i++) {
  228.                GLfloat z = ABSF(v[i][2]);
  229.                GLfloat f = exp( -d * z*z );
  230.                f = CLAMP( f, 0.0F, 1.0F );
  231.                indx[i] = (GLint)
  232.                          ((GLfloat) (GLint) indx[i] + (1.0F-f) * fogindex);
  233.             }
  234.          }
  235.      break;
  236.       default:
  237.          gl_problem(ctx, "Bad fog mode in gl_fog_index_vertices");
  238.          return;
  239.    }
  240. }
  241.  
  242.  
  243.  
  244.  
  245. /*
  246.  * Apply fog to an array of RGBA pixels.
  247.  * Input:  n - number of pixels
  248.  *         z - array of integer depth values
  249.  *         red, green, blue, alpha - pixel colors
  250.  * Output:  red, green, blue, alpha - fogged pixel colors
  251.  */
  252. void gl_fog_color_pixels( GLcontext *ctx,
  253.                           GLuint n, const GLdepth z[], GLubyte red[],
  254.               GLubyte green[], GLubyte blue[], GLubyte alpha[] )
  255. {
  256.    GLfloat c = ctx->ProjectionMatrix[10];
  257.    GLfloat d = ctx->ProjectionMatrix[14];
  258.    GLuint i;
  259.  
  260.    GLfloat fog_red   = ctx->Fog.Color[0] * ctx->Visual->RedScale;
  261.    GLfloat fog_green = ctx->Fog.Color[1] * ctx->Visual->GreenScale;
  262.    GLfloat fog_blue  = ctx->Fog.Color[2] * ctx->Visual->BlueScale;
  263.  
  264.    GLfloat tz = ctx->Viewport.Tz;
  265.    GLfloat szInv = 1.0F / ctx->Viewport.Sz;
  266.  
  267.    switch (ctx->Fog.Mode) {
  268.       case GL_LINEAR:
  269.          {
  270.             GLfloat fogEnd = ctx->Fog.End;
  271.             GLfloat fogScale = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
  272.             for (i=0;i<n;i++) {
  273.                GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
  274.                GLfloat eyez = -d / (c+ndcz);
  275.                GLfloat f, g;
  276.                if (eyez < 0.0)  eyez = -eyez;
  277.                f = (fogEnd - eyez) * fogScale;
  278.                f = CLAMP( f, 0.0F, 1.0F );
  279.                g = 1.0F - f;
  280.                red[i]   = (GLint) (f * (GLfloat) red[i]   + g * fog_red);
  281.                green[i] = (GLint) (f * (GLfloat) green[i] + g * fog_green);
  282.                blue[i]  = (GLint) (f * (GLfloat) blue[i]  + g * fog_blue);
  283.             }
  284.          }
  285.      break;
  286.       case GL_EXP:
  287.      for (i=0;i<n;i++) {
  288.         GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
  289.         GLfloat eyez = -d / (c+ndcz);
  290.             GLfloat f, g;
  291.         if (eyez < 0.0)  eyez = -eyez;
  292.         f = exp( -ctx->Fog.Density * eyez );
  293.         f = CLAMP( f, 0.0F, 1.0F );
  294.             g = 1.0F - f;
  295.             red[i]   = (GLint) (f * (GLfloat) red[i]   + g * fog_red);
  296.             green[i] = (GLint) (f * (GLfloat) green[i] + g * fog_green);
  297.             blue[i]  = (GLint) (f * (GLfloat) blue[i]  + g * fog_blue);
  298.      }
  299.      break;
  300.       case GL_EXP2:
  301.          {
  302.             GLfloat negDensitySquared = -ctx->Fog.Density * ctx->Fog.Density;
  303.             for (i=0;i<n;i++) {
  304.                GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
  305.                GLfloat eyez = -d / (c+ndcz);
  306.                GLfloat f, g;
  307.                if (eyez < 0.0)  eyez = -eyez;
  308.                f = exp( negDensitySquared * eyez*eyez );
  309.                f = CLAMP( f, 0.0F, 1.0F );
  310.                g = 1.0F - f;
  311.                red[i]   = (GLint) (f * (GLfloat) red[i]   + g * fog_red);
  312.                green[i] = (GLint) (f * (GLfloat) green[i] + g * fog_green);
  313.                blue[i]  = (GLint) (f * (GLfloat) blue[i]  + g * fog_blue);
  314.             }
  315.          }
  316.      break;
  317.       default:
  318.          gl_problem(ctx, "Bad fog mode in gl_fog_color_pixels");
  319.          return;
  320.    }
  321. }
  322.  
  323.  
  324.  
  325.  
  326. /*
  327.  * Apply fog to an array of color index pixels.
  328.  * Input:  n - number of pixels
  329.  *         z - array of integer depth values
  330.  *         index - pixel color indexes
  331.  * Output:  index - fogged pixel color indexes
  332.  */
  333. void gl_fog_index_pixels( GLcontext *ctx,
  334.                           GLuint n, const GLdepth z[], GLuint index[] )
  335. {
  336.    GLfloat c = ctx->ProjectionMatrix[10];
  337.    GLfloat d = ctx->ProjectionMatrix[14];
  338.    GLuint i;
  339.  
  340.    GLfloat tz = ctx->Viewport.Tz;
  341.    GLfloat szInv = 1.0F / ctx->Viewport.Sz;
  342.  
  343.    switch (ctx->Fog.Mode) {
  344.       case GL_LINEAR:
  345.          {
  346.             GLfloat fogEnd = ctx->Fog.End;
  347.             GLfloat fogScale = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
  348.             for (i=0;i<n;i++) {
  349.                GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
  350.                GLfloat eyez = -d / (c+ndcz);
  351.                GLfloat f;
  352.                if (eyez < 0.0)  eyez = -eyez;
  353.                f = (fogEnd - eyez) * fogScale;
  354.                f = CLAMP( f, 0.0F, 1.0F );
  355.                index[i] = (GLuint) ((GLfloat) index[i] + (1.0F-f) * ctx->Fog.Index);
  356.             }
  357.      }
  358.      break;
  359.       case GL_EXP:
  360.          for (i=0;i<n;i++) {
  361.         GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
  362.         GLfloat eyez = -d / (c+ndcz);
  363.             GLfloat f;
  364.         if (eyez < 0.0)  eyez = -eyez;
  365.         f = exp( -ctx->Fog.Density * eyez );
  366.         f = CLAMP( f, 0.0F, 1.0F );
  367.         index[i] = (GLuint) ((GLfloat) index[i] + (1.0F-f) * ctx->Fog.Index);
  368.      }
  369.      break;
  370.       case GL_EXP2:
  371.          {
  372.             GLfloat negDensitySquared = -ctx->Fog.Density * ctx->Fog.Density;
  373.             for (i=0;i<n;i++) {
  374.                GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
  375.                GLfloat eyez = -d / (c+ndcz);
  376.                GLfloat f;
  377.                if (eyez < 0.0)  eyez = -eyez;
  378.                f = exp( negDensitySquared * eyez*eyez );
  379.                f = CLAMP( f, 0.0F, 1.0F );
  380.                index[i] = (GLuint) ((GLfloat) index[i] + (1.0F-f) * ctx->Fog.Index);
  381.             }
  382.      }
  383.      break;
  384.       default:
  385.          gl_problem(ctx, "Bad fog mode in gl_fog_index_pixels");
  386.          return;
  387.    }
  388. }
  389.  
  390.