home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / coders / mesa-1.2.8 / src / fog.c < prev    next >
C/C++ Source or Header  |  1996-05-27  |  12KB  |  434 lines

  1. /* fog.c */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  1.2
  6.  * Copyright (C) 1995  Brian Paul  (brianp@ssec.wisc.edu)
  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. $Id: fog.c,v 1.13 1996/02/14 16:57:22 brianp Exp $
  26.  
  27. $Log: fog.c,v $
  28.  * Revision 1.13  1996/02/14  16:57:22  brianp
  29.  * optimized gl_fog_color|index_vertices() functions
  30.  *
  31.  * Revision 1.12  1995/12/30  17:16:17  brianp
  32.  * gl_fog_color_vertices now takes integer colors instead of floats
  33.  *
  34.  * Revision 1.11  1995/12/20  15:26:39  brianp
  35.  * changed color index array arguments to GLuint
  36.  *
  37.  * Revision 1.10  1995/12/18  17:25:35  brianp
  38.  * use new GLdepth datatype, replace MAX_DEPTH with DEPTH_SCALE
  39.  *
  40.  * Revision 1.9  1995/11/03  22:35:35  brianp
  41.  * replaced gl_fog_color_vertex with gl_fog_color_vertices
  42.  * replaced gl_fog_index_vertex with gl_fog_index_vertices
  43.  *
  44.  * Revision 1.8  1995/07/20  15:35:11  brianp
  45.  * added type casts to stop warnings with Sun's cc
  46.  *
  47.  * Revision 1.7  1995/06/12  15:41:04  brianp
  48.  * removed debugging printf's
  49.  *
  50.  * Revision 1.6  1995/06/12  15:33:54  brianp
  51.  * changed color arrays to GLubyte
  52.  * check for -eyez in gl_fog_index_pixels
  53.  *
  54.  * Revision 1.5  1995/05/22  21:02:41  brianp
  55.  * Release 1.2
  56.  *
  57.  * Revision 1.4  1995/03/04  19:29:44  brianp
  58.  * 1.1 beta revision
  59.  *
  60.  * Revision 1.3  1995/02/27  22:48:50  brianp
  61.  * modified for PB
  62.  *
  63.  * Revision 1.2  1995/02/26  22:58:24  brianp
  64.  * fixed glFogi
  65.  *
  66.  * Revision 1.1  1995/02/24  14:23:03  brianp
  67.  * Initial revision
  68.  *
  69.  */
  70.  
  71.  
  72. #include <math.h>
  73. #include <stdlib.h>
  74. #include "context.h"
  75. #include "list.h"
  76. #include "macros.h"
  77.  
  78.  
  79.  
  80. void gl_fog( GLenum pname, const GLfloat *params )
  81. {
  82.    GLenum m;
  83.  
  84.    switch (pname) {
  85.       case GL_FOG_MODE:
  86.          m = (GLenum) (GLint) *params;
  87.      if (m==GL_LINEAR || m==GL_EXP || m==GL_EXP2) {
  88.         CC.Fog.Mode = m;
  89.      }
  90.      else {
  91.         gl_error( GL_INVALID_ENUM, "glFog" );
  92.      }
  93.      break;
  94.       case GL_FOG_DENSITY:
  95.      if (*params<0.0) {
  96.         gl_error( GL_INVALID_VALUE, "glFog" );
  97.      }
  98.      else {
  99.         CC.Fog.Density = *params;
  100.      }
  101.      break;
  102.       case GL_FOG_START:
  103.      CC.Fog.Start = *params;
  104.      break;
  105.       case GL_FOG_END:
  106.      CC.Fog.End = *params;
  107.      break;
  108.       case GL_FOG_INDEX:
  109.      CC.Fog.Index = *params;
  110.      break;
  111.       case GL_FOG_COLOR:
  112.      CC.Fog.Color[0] = params[0];
  113.      CC.Fog.Color[1] = params[1];
  114.      CC.Fog.Color[2] = params[2];
  115.      CC.Fog.Color[3] = params[3];
  116.          break;
  117.       default:
  118.          gl_error( GL_INVALID_ENUM, "glFog" );
  119.    }
  120. }
  121.  
  122.  
  123.  
  124. void glFogf( GLenum pname, GLfloat param )
  125. {
  126.    if (CC.ExecuteFlag) {
  127.       gl_fog( pname, ¶m );
  128.    }
  129.    if (CC.CompileFlag) {
  130.       gl_save_fog( pname, ¶m );
  131.    }
  132. }
  133.  
  134.  
  135.  
  136. void glFogi( GLenum pname, GLint param )
  137. {
  138.    GLfloat p;
  139.  
  140.    p = (GLfloat) param;
  141.  
  142.    if (CC.ExecuteFlag) {
  143.       gl_fog( pname, &p );
  144.    }
  145.    if (CC.CompileFlag) {
  146.       gl_save_fog( pname, &p );
  147.    }
  148. }
  149.  
  150.  
  151.  
  152. void glFogfv( GLenum pname, const GLfloat *params )
  153. {
  154.    if (CC.ExecuteFlag) {
  155.       gl_fog( pname, params );
  156.    }
  157.    if (CC.CompileFlag) {
  158.       gl_save_fog( pname, params );
  159.    }
  160. }
  161.  
  162.  
  163.  
  164. void glFogiv( GLenum pname, const GLint *params )
  165. {
  166.    GLfloat p[4];
  167.  
  168.    switch (pname) {
  169.       case GL_FOG_MODE:
  170.       case GL_FOG_DENSITY:
  171.       case GL_FOG_START:
  172.       case GL_FOG_END:
  173.       case GL_FOG_INDEX:
  174.          p[0] = (GLfloat) *params;
  175.      break;
  176.       case GL_FOG_COLOR:
  177.      p[0] = INT_TO_FLOAT( params[0] );
  178.      p[1] = INT_TO_FLOAT( params[1] );
  179.      p[2] = INT_TO_FLOAT( params[2] );
  180.      p[3] = INT_TO_FLOAT( params[3] );
  181.      break;
  182.       default:
  183.      gl_error( GL_INVALID_ENUM, "glFogi" );
  184.      return;
  185.    }
  186.    if (CC.ExecuteFlag) {
  187.       gl_fog( pname, p );
  188.    }
  189.    if (CC.CompileFlag) {
  190.       gl_save_fog( pname, p );
  191.    }
  192. }
  193.  
  194.  
  195.  
  196. /*
  197.  * Compute the fogged color for an array of vertices.
  198.  * Input:  n - number of vertices
  199.  *         v - array of vertices
  200.  *         color - the original vertex colors
  201.  * Output:  color - the fogged colors
  202.  */
  203. void gl_fog_color_vertices( GLuint n, GLfloat v[][4], GLfixed color[][4] )
  204. {
  205.    GLuint i;
  206.    GLfloat d;
  207.    GLfloat shift = (GLfloat) (1 << CC.ColorShift);
  208.    GLfloat fogr = CC.Fog.Color[0] * CC.RedScale   * shift;
  209.    GLfloat fogg = CC.Fog.Color[1] * CC.GreenScale * shift;
  210.    GLfloat fogb = CC.Fog.Color[2] * CC.BlueScale  * shift;
  211.    GLfloat foga = CC.Fog.Color[3] * CC.AlphaScale * shift;
  212.  
  213.    switch (CC.Fog.Mode) {
  214.       case GL_LINEAR:
  215.          d = 1.0F / (CC.Fog.End - CC.Fog.Start);
  216.          for (i=0;i<n;i++) {
  217.             GLfloat f = (CC.Fog.End - ABSF(v[i][2])) * d;
  218.             f = CLAMP( f, 0.0F, 1.0F );
  219.             color[i][0] = f * color[i][0] + (1.0F-f) * fogr;
  220.             color[i][1] = f * color[i][1] + (1.0F-f) * fogg;
  221.             color[i][2] = f * color[i][2] + (1.0F-f) * fogb;
  222.             color[i][3] = f * color[i][3] + (1.0F-f) * foga;
  223.          }
  224.      break;
  225.       case GL_EXP:
  226.          d = -CC.Fog.Density;
  227.          for (i=0;i<n;i++) {
  228.             GLfloat f = exp( d * ABSF(v[i][2]) );
  229.             f = CLAMP( f, 0.0F, 1.0F );
  230.             color[i][0] = f * color[i][0] + (1.0F-f) * fogr;
  231.             color[i][1] = f * color[i][1] + (1.0F-f) * fogg;
  232.             color[i][2] = f * color[i][2] + (1.0F-f) * fogb;
  233.             color[i][3] = f * color[i][3] + (1.0F-f) * foga;
  234.          }
  235.      break;
  236.       case GL_EXP2:
  237.          d = -(CC.Fog.Density*CC.Fog.Density);
  238.          for (i=0;i<n;i++) {
  239.             GLfloat z = ABSF(v[i][2]);
  240.             GLfloat f = exp( d * z*z );
  241.             f = CLAMP( f, 0.0F, 1.0F );
  242.             color[i][0] = f * color[i][0] + (1.0F-f) * fogr;
  243.             color[i][1] = f * color[i][1] + (1.0F-f) * fogg;
  244.             color[i][2] = f * color[i][2] + (1.0F-f) * fogb;
  245.             color[i][3] = f * color[i][3] + (1.0F-f) * foga;
  246.          }
  247.      break;
  248.       default:
  249.          abort();
  250.    }
  251. }
  252.  
  253.  
  254.  
  255. /*
  256.  * Compute the fogged color indexes for an array of vertices.
  257.  * Input:  n - number of vertices
  258.  *         v - array of vertices
  259.  * In/Out: indx - array of vertex color indexes
  260.  */
  261. void gl_fog_index_vertices( GLuint n, GLfloat v[][4], GLuint indx[] )
  262. {
  263.    /* NOTE: the extensive use of casts generates better/faster code for MIPS */
  264.    switch (CC.Fog.Mode) {
  265.       case GL_LINEAR:
  266.          {
  267.             GLfloat d = 1.0F / (CC.Fog.End - CC.Fog.Start);
  268.             GLfloat fogindex = CC.Fog.Index;
  269.             GLfloat fogend = CC.Fog.End;
  270.             GLuint i;
  271.             for (i=0;i<n;i++) {
  272.                GLfloat f = (fogend - ABSF(v[i][2])) * d;
  273.                f = CLAMP( f, 0.0F, 1.0F );
  274.                indx[i] = (GLint) ((GLfloat) (GLint) indx[i] + (1.0F-f) * fogindex);
  275.             }
  276.          }
  277.      break;
  278.       case GL_EXP:
  279.          {
  280.             GLfloat d = -CC.Fog.Density;
  281.             GLfloat fogindex = CC.Fog.Index;
  282.             GLuint i;
  283.             for (i=0;i<n;i++) {
  284.                GLfloat f = exp( d * ABSF(v[i][2]) );
  285.                f = CLAMP( f, 0.0F, 1.0F );
  286.                indx[i] = (GLint) ((GLfloat) (GLint) indx[i] + (1.0F-f) * fogindex);
  287.             }
  288.          }
  289.      break;
  290.       case GL_EXP2:
  291.          {
  292.             GLfloat d = -(CC.Fog.Density*CC.Fog.Density);
  293.             GLfloat fogindex = CC.Fog.Index;
  294.             GLuint i;
  295.             for (i=0;i<n;i++) {
  296.                GLfloat z = ABSF(v[i][2]);
  297.                GLfloat f = exp( -d * z*z );
  298.                f = CLAMP( f, 0.0F, 1.0F );
  299.                indx[i] = (GLint) ((GLfloat) (GLint) indx[i] + (1.0F-f) * fogindex);
  300.             }
  301.          }
  302.      break;
  303.       default:
  304.          abort();
  305.    }
  306. }
  307.  
  308.  
  309.  
  310.  
  311. /*
  312.  * Apply fog to an array of RGBA pixels.
  313.  * Input:  n - number of pixels
  314.  *         z - array of integer depth values
  315.  *         red, green, blue, alpha - pixel colors
  316.  * Output:  red, green, blue, alpha - fogged pixel colors
  317.  */
  318. void gl_fog_color_pixels( GLuint n, const GLdepth z[], GLubyte red[],
  319.               GLubyte green[], GLubyte blue[], GLubyte alpha[] )
  320. {
  321.    /* TODO: optimize case when c = 1.0 and d = 0.0 */
  322.    GLfloat d = CC.ProjectionMatrix[14];
  323.    GLfloat c = CC.ProjectionMatrix[10];
  324.    GLfloat winz, ndcz, eyez, f;
  325.    GLuint i;
  326.  
  327.    GLint fog_red   = (GLint) (CC.Fog.Color[0] * CC.RedScale);
  328.    GLint fog_green = (GLint) (CC.Fog.Color[1] * CC.GreenScale);
  329.    GLint fog_blue  = (GLint) (CC.Fog.Color[2] * CC.BlueScale);
  330.    GLint fog_alpha = (GLint) (CC.Fog.Color[3] * CC.AlphaScale);
  331.  
  332.    switch (CC.Fog.Mode) {
  333.       case GL_LINEAR:
  334.          for (i=0;i<n;i++) {
  335.         winz = (GLfloat) z[i] / DEPTH_SCALE;
  336.         ndcz = (winz - CC.Viewport.Tz) / CC.Viewport.Sz;
  337.         eyez = -d / (c+ndcz);
  338.         if (eyez < 0.0)  eyez = -eyez;
  339.         f = (CC.Fog.End - eyez) / (CC.Fog.End - CC.Fog.Start);
  340.         f = CLAMP( f, 0.0F, 1.0F );
  341.         red[i]   = (GLint) (f * (GLfloat) red[i]   + (1.0F-f) * fog_red);
  342.         green[i] = (GLint) (f * (GLfloat) green[i] + (1.0F-f) * fog_green);
  343.         blue[i]  = (GLint) (f * (GLfloat) blue[i]  + (1.0F-f) * fog_blue);
  344.         alpha[i] = (GLint) (f * (GLfloat) alpha[i] + (1.0F-f) * fog_alpha);
  345.      }
  346.      break;
  347.       case GL_EXP:
  348.      for (i=0;i<n;i++) {
  349.         winz = (GLfloat) z[i] / DEPTH_SCALE;
  350.         ndcz = (winz - CC.Viewport.Tz) / CC.Viewport.Sz;
  351.         eyez = -d / (c+ndcz);
  352.         if (eyez < 0.0)  eyez = -eyez;
  353.         f = exp( -CC.Fog.Density * eyez );
  354.         f = CLAMP( f, 0.0F, 1.0F );
  355.         red[i]   = (GLint) (f * (GLfloat) red[i]   + (1.0F-f) * fog_red);
  356.         green[i] = (GLint) (f * (GLfloat) green[i] + (1.0F-f) * fog_green);
  357.         blue[i]  = (GLint) (f * (GLfloat) blue[i]  + (1.0F-f) * fog_blue);
  358.         alpha[i] = (GLint) (f * (GLfloat) alpha[i] + (1.0F-f) * fog_alpha);
  359.      }
  360.      break;
  361.       case GL_EXP2:
  362.      for (i=0;i<n;i++) {
  363.         winz = (GLfloat) z[i] / DEPTH_SCALE;
  364.         ndcz = (winz - CC.Viewport.Tz) / CC.Viewport.Sz;
  365.         eyez = -d / (c+ndcz);
  366.         if (eyez < 0.0)  eyez = -eyez;
  367.         f = exp( -(CC.Fog.Density*CC.Fog.Density * eyez*eyez) );
  368.         f = CLAMP( f, 0.0F, 1.0F );
  369.         red[i]   = (GLint) (f * (GLfloat) red[i]   + (1.0F-f) * fog_red);
  370.         green[i] = (GLint) (f * (GLfloat) green[i] + (1.0F-f) * fog_green);
  371.         blue[i]  = (GLint) (f * (GLfloat) blue[i]  + (1.0F-f) * fog_blue);
  372.         alpha[i] = (GLint) (f * (GLfloat) alpha[i] + (1.0F-f) * fog_alpha);
  373.      }
  374.      break;
  375.    }
  376. }
  377.  
  378.  
  379.  
  380.  
  381. /*
  382.  * Apply fog to an array of color index pixels.
  383.  * Input:  n - number of pixels
  384.  *         z - array of integer depth values
  385.  *         index - pixel color indexes
  386.  * Output:  index - fogged pixel color indexes
  387.  */
  388. void gl_fog_index_pixels( GLuint n, const GLdepth z[], GLuint index[] )
  389. {
  390.    /* TODO: optimize case when c = 1.0 and d = 0.0 */
  391.    GLfloat d = CC.ProjectionMatrix[14];
  392.    GLfloat c = CC.ProjectionMatrix[10];
  393.    GLfloat winz, ndcz, eyez, f;
  394.    GLuint i;
  395.  
  396.    switch (CC.Fog.Mode) {
  397.       case GL_LINEAR:
  398.          for (i=0;i<n;i++) {
  399.         winz = (GLfloat) z[i] / DEPTH_SCALE;
  400.         ndcz = (winz - CC.Viewport.Tz) / CC.Viewport.Sz;
  401.         eyez = -d / (c+ndcz);
  402.         if (eyez < 0.0)  eyez = -eyez;
  403.         f = (CC.Fog.End - eyez) / (CC.Fog.End - CC.Fog.Start);
  404.         f = CLAMP( f, 0.0F, 1.0F );
  405.         index[i] = (GLuint) ((GLfloat) index[i] + (1.0F-f) * CC.Fog.Index);
  406.      }
  407.      break;
  408.       case GL_EXP:
  409.          for (i=0;i<n;i++) {
  410.         winz = (GLfloat) z[i] / DEPTH_SCALE;
  411.         ndcz = (winz - CC.Viewport.Tz) / CC.Viewport.Sz;
  412.         eyez = -d / (c+ndcz);
  413.         if (eyez < 0.0)  eyez = -eyez;
  414.         f = exp( -CC.Fog.Density * eyez );
  415.         f = CLAMP( f, 0.0F, 1.0F );
  416.         index[i] = (GLuint) ((GLfloat) index[i] + (1.0F-f) * CC.Fog.Index);
  417.      }
  418.      break;
  419.       case GL_EXP2:
  420.          for (i=0;i<n;i++) {
  421.         winz = (GLfloat) z[i] / DEPTH_SCALE;
  422.         ndcz = (winz - CC.Viewport.Tz) / CC.Viewport.Sz;
  423.         eyez = -d / (c+ndcz);
  424.         if (eyez < 0.0)  eyez = -eyez;
  425.         f = exp( -(CC.Fog.Density*CC.Fog.Density * eyez*eyez) );
  426.         f = CLAMP( f, 0.0F, 1.0F );
  427.         index[i] = (GLuint) ((GLfloat) index[i] + (1.0F-f) * CC.Fog.Index);
  428.      }
  429.      break;
  430.    }
  431.  
  432. }
  433.  
  434.