home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / System / Mesa-3.1 / src / fog.c < prev    next >
C/C++ Source or Header  |  2000-01-07  |  11KB  |  386 lines

  1. /* $Id: fog.c,v 1.3.2.1 1999/11/25 16:51:24 keithw Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  3.1
  6.  * 
  7.  * Copyright (C) 1999  Brian Paul   All Rights Reserved.
  8.  * 
  9.  * Permission is hereby granted, free of charge, to any person obtaining a
  10.  * copy of this software and associated documentation files (the "Software"),
  11.  * to deal in the Software without restriction, including without limitation
  12.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  13.  * and/or sell copies of the Software, and to permit persons to whom the
  14.  * Software is furnished to do so, subject to the following conditions:
  15.  * 
  16.  * The above copyright notice and this permission notice shall be included
  17.  * in all copies or substantial portions of the Software.
  18.  * 
  19.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  20.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  22.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  23.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  24.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  */
  26.  
  27.  
  28. /* $XFree86: xc/lib/GL/mesa/src/fog.c,v 1.4 1999/04/04 00:20:24 dawes Exp $ */
  29.  
  30. #ifdef PC_HEADER
  31. #include "all.h"
  32. #else
  33. #ifndef XFree86Server
  34. #include <math.h>
  35. #include <stdlib.h>
  36. #else
  37. #include "GL/xf86glx.h"
  38. #endif
  39. #include "context.h"
  40. #include "fog.h"
  41. #include "macros.h"
  42. #include "mmath.h"
  43. #include "types.h"
  44. #include "xform.h"
  45. #endif
  46.  
  47.  
  48.  
  49. void gl_Fogfv( GLcontext *ctx, GLenum pname, const GLfloat *params )
  50. {
  51.    GLenum m;
  52.  
  53.    switch (pname) {
  54.       case GL_FOG_MODE:
  55.          m = (GLenum) (GLint) *params;
  56.      if (m==GL_LINEAR || m==GL_EXP || m==GL_EXP2) {
  57.         ctx->Fog.Mode = m;
  58.      }
  59.      else {
  60.         gl_error( ctx, GL_INVALID_ENUM, "glFog" );
  61.             return;
  62.      }
  63.      break;
  64.       case GL_FOG_DENSITY:
  65.      if (*params<0.0) {
  66.         gl_error( ctx, GL_INVALID_VALUE, "glFog" );
  67.             return;
  68.      }
  69.      else {
  70.         ctx->Fog.Density = *params;
  71.      }
  72.      break;
  73.       case GL_FOG_START:
  74.      ctx->Fog.Start = *params;
  75.      break;
  76.       case GL_FOG_END:
  77.      ctx->Fog.End = *params;
  78.      break;
  79.       case GL_FOG_INDEX:
  80.      ctx->Fog.Index = *params;
  81.      break;
  82.       case GL_FOG_COLOR:
  83.      ctx->Fog.Color[0] = params[0];
  84.      ctx->Fog.Color[1] = params[1];
  85.      ctx->Fog.Color[2] = params[2];
  86.      ctx->Fog.Color[3] = params[3];
  87.          break;
  88.       default:
  89.          gl_error( ctx, GL_INVALID_ENUM, "glFog" );
  90.          return;
  91.    }
  92.  
  93.    if (ctx->Driver.Fogfv) {
  94.       (*ctx->Driver.Fogfv)( ctx, pname, params );
  95.    }
  96.  
  97.    ctx->NewState |= NEW_FOG;
  98. }
  99.  
  100.  
  101. typedef void (*fog_func)( struct vertex_buffer *VB, GLuint side, 
  102.               GLubyte flag );
  103.  
  104. typedef void (*fog_coord_func)( struct vertex_buffer *VB, 
  105.                 const GLvector4f *from,
  106.                 GLubyte flag );
  107.  
  108. static fog_func fog_ci_tab[2];
  109. static fog_func fog_rgba_tab[2];
  110. static fog_coord_func make_fog_coord_tab[2];
  111.  
  112. /*
  113.  * Compute the fogged color for an array of vertices.
  114.  * Input:  n - number of vertices
  115.  *         v - array of vertices
  116.  *         color - the original vertex colors
  117.  * Output:  color - the fogged colors
  118.  * 
  119.  */
  120. #define TAG(x) x##_raw
  121. #define CULLCHECK
  122. #define IDX 0
  123. #include "fog_tmp.h"
  124.  
  125. #define TAG(x) x##_masked
  126. #define CULLCHECK if (cullmask[i]&flag)
  127. #define IDX 1
  128. #include "fog_tmp.h"
  129.  
  130. void gl_init_fog( void )
  131. {
  132.    init_fog_tab_masked();
  133.    init_fog_tab_raw();
  134. }
  135.  
  136. /*
  137.  * Compute fog for the vertices in the vertex buffer.
  138.  */
  139. void gl_fog_vertices( struct vertex_buffer *VB )
  140. {
  141.    GLcontext *ctx = VB->ctx;
  142.    GLuint i = VB->CullMode & 1;
  143.  
  144.    if (ctx->Visual->RGBAflag) {
  145.       /* Fog RGB colors */
  146.       if (ctx->TriangleCaps & DD_TRI_LIGHT_TWOSIDE) {
  147.      fog_rgba_tab[i]( VB, 0, VERT_FACE_FRONT );
  148.      fog_rgba_tab[i]( VB, 1, VERT_FACE_REAR );
  149.       } else {
  150.      fog_rgba_tab[i]( VB, 0, VERT_FACE_FRONT|VERT_FACE_REAR );
  151.       }
  152.    }
  153.    else {
  154.       /* Fog color indexes */
  155.       if (ctx->TriangleCaps & DD_TRI_LIGHT_TWOSIDE) {
  156.      fog_ci_tab[i]( VB, 0, VERT_FACE_FRONT );
  157.          fog_ci_tab[i]( VB, 1, VERT_FACE_REAR );
  158.       } else {
  159.      fog_ci_tab[i]( VB, 0, VERT_FACE_FRONT|VERT_FACE_REAR );
  160.       }
  161.    }
  162. }
  163.  
  164.  
  165. static void check_fog_coords( GLcontext *ctx, struct gl_pipeline_stage *d )
  166. {
  167.    d->type = 0;
  168.  
  169.    if (ctx->FogMode==FOG_FRAGMENT)
  170.    {
  171.       d->type = PIPE_IMMEDIATE|PIPE_PRECALC;
  172.       d->inputs = VERT_OBJ_ANY;
  173.       d->outputs = VERT_FOG_COORD;
  174.    }
  175. }
  176.  
  177. void gl_make_fog_coords( struct vertex_buffer *VB )
  178. {
  179.    GLcontext *ctx = VB->ctx;
  180.  
  181.    /* If full eye coords weren't required, just calculate the eye Z
  182.     * values.  
  183.     */
  184.    if (!ctx->NeedEyeCoords) {
  185.       GLfloat *m = ctx->ModelView.m;
  186.       GLfloat plane[4];
  187.  
  188.       plane[0] = m[2];
  189.       plane[1] = m[6];
  190.       plane[2] = m[10];
  191.       plane[3] = m[14];
  192.  
  193.       gl_dotprod_tab[0][VB->ObjPtr->size](&VB->Eye,
  194.                       2, /* fill z coordinates */
  195.                       VB->ObjPtr,
  196.                       plane,
  197.                       0 );
  198.  
  199.       make_fog_coord_tab[0]( VB, &VB->Eye, 0 );
  200.    }
  201.    else
  202.    {
  203.       make_fog_coord_tab[0]( VB, VB->EyePtr, 0 );
  204.    }
  205. }
  206.  
  207.  
  208. /* Drivers that want fog coordinates in VB->Spec[0] alpha, can substitute this
  209.  * stage for the default PIPE_OP_FOG pipeline stage.
  210.  */
  211. struct gl_pipeline_stage gl_fog_coord_stage = {
  212.    "build fog coordinates",
  213.    PIPE_OP_FOG,
  214.    PIPE_PRECALC|PIPE_IMMEDIATE,
  215.    0,
  216.    NEW_FOG,
  217.    NEW_LIGHTING|NEW_RASTER_OPS|NEW_FOG|NEW_MODELVIEW,
  218.    0, 0,
  219.    0, 0, 0,
  220.    check_fog_coords,
  221.    gl_make_fog_coords 
  222. };
  223.  
  224.  
  225.  
  226.  
  227.  
  228. /*
  229.  * Apply fog to an array of RGBA pixels.
  230.  * Input:  n - number of pixels
  231.  *         z - array of integer depth values
  232.  *         red, green, blue, alpha - pixel colors
  233.  * Output:  red, green, blue, alpha - fogged pixel colors
  234.  */
  235. void gl_fog_rgba_pixels( const GLcontext *ctx,
  236.                          GLuint n, const GLdepth z[], GLubyte rgba[][4] )
  237. {
  238.    GLfloat c = ctx->ProjectionMatrix.m[10];
  239.    GLfloat d = ctx->ProjectionMatrix.m[14];
  240.    GLuint i;
  241.  
  242.    GLfloat rFog = ctx->Fog.Color[0] * 255.0F;
  243.    GLfloat gFog = ctx->Fog.Color[1] * 255.0F;
  244.    GLfloat bFog = ctx->Fog.Color[2] * 255.0F;
  245.  
  246.    GLfloat tz = ctx->Viewport.WindowMap.m[MAT_TZ];
  247.    GLfloat szInv = 1.0F / ctx->Viewport.WindowMap.m[MAT_SZ];
  248.  
  249.    switch (ctx->Fog.Mode) {
  250.       case GL_LINEAR:
  251.          {
  252.             GLfloat fogEnd = ctx->Fog.End;
  253.             GLfloat fogScale = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
  254.             for (i=0;i<n;i++) {
  255.                GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
  256.                GLfloat eyez = -d / (c+ndcz);
  257.                GLfloat f, g;
  258.                if (eyez < 0.0)  eyez = -eyez;
  259.                f = (fogEnd - eyez) * fogScale;
  260.                f = CLAMP( f, 0.0F, 1.0F );
  261.                g = 1.0F - f;
  262.                rgba[i][RCOMP] = (GLint) (f * rgba[i][RCOMP] + g * rFog);
  263.                rgba[i][GCOMP] = (GLint) (f * rgba[i][GCOMP] + g * gFog);
  264.                rgba[i][BCOMP] = (GLint) (f * rgba[i][BCOMP] + g * bFog);
  265.             }
  266.          }
  267.      break;
  268.       case GL_EXP:
  269.      for (i=0;i<n;i++) {
  270.         GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
  271.         GLfloat eyez = d / (c+ndcz);
  272.             GLfloat f, g;
  273.         if (eyez < 0.0)
  274.                eyez = -eyez;
  275.         f = exp( -ctx->Fog.Density * eyez );
  276.             g = 1.0F - f;
  277.             rgba[i][RCOMP] = (GLint) (f * rgba[i][RCOMP] + g * rFog);
  278.             rgba[i][GCOMP] = (GLint) (f * rgba[i][GCOMP] + g * gFog);
  279.             rgba[i][BCOMP] = (GLint) (f * rgba[i][BCOMP] + g * bFog);
  280.      }
  281.      break;
  282.       case GL_EXP2:
  283.          {
  284.             GLfloat negDensitySquared = -ctx->Fog.Density * ctx->Fog.Density;
  285.             for (i=0;i<n;i++) {
  286.                GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
  287.                GLfloat eyez = d / (c+ndcz);
  288.                GLfloat f, g;
  289.                GLfloat tmp = negDensitySquared * eyez * eyez;
  290. #ifdef __alpha__
  291.                /* XXX this underflow check may be needed for other systems */
  292.                if (tmp < FLT_MIN_10_EXP)
  293.                   f = exp( FLT_MIN_10_EXP );
  294.                else
  295. #endif
  296.                   f = exp( tmp );
  297.                g = 1.0F - f;
  298.                rgba[i][RCOMP] = (GLint) (f * rgba[i][RCOMP] + g * rFog);
  299.                rgba[i][GCOMP] = (GLint) (f * rgba[i][GCOMP] + g * gFog);
  300.                rgba[i][BCOMP] = (GLint) (f * rgba[i][BCOMP] + g * bFog);
  301.             }
  302.          }
  303.      break;
  304.       default:
  305.          gl_problem(ctx, "Bad fog mode in gl_fog_rgba_pixels");
  306.          return;
  307.    }
  308. }
  309.  
  310.  
  311.  
  312.  
  313. /*
  314.  * Apply fog to an array of color index pixels.
  315.  * Input:  n - number of pixels
  316.  *         z - array of integer depth values
  317.  *         index - pixel color indexes
  318.  * Output:  index - fogged pixel color indexes
  319.  */
  320. void gl_fog_ci_pixels( const GLcontext *ctx,
  321.                        GLuint n, const GLdepth z[], GLuint index[] )
  322. {
  323.    GLfloat c = ctx->ProjectionMatrix.m[10];
  324.    GLfloat d = ctx->ProjectionMatrix.m[14];
  325.    GLuint i;
  326.  
  327.    GLfloat tz = ctx->Viewport.WindowMap.m[MAT_TZ];
  328.    GLfloat szInv = 1.0F / ctx->Viewport.WindowMap.m[MAT_SZ];
  329.  
  330.    switch (ctx->Fog.Mode) {
  331.       case GL_LINEAR:
  332.          {
  333.             GLfloat fogEnd = ctx->Fog.End;
  334.             GLfloat fogScale = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
  335.             for (i=0;i<n;i++) {
  336.                GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
  337.                GLfloat eyez = -d / (c+ndcz);
  338.                GLfloat f;
  339.                if (eyez < 0.0)  eyez = -eyez;
  340.                f = (fogEnd - eyez) * fogScale;
  341.                f = CLAMP( f, 0.0F, 1.0F );
  342.                index[i] = (GLuint) ((GLfloat) index[i] + (1.0F-f) * ctx->Fog.Index);
  343.             }
  344.      }
  345.      break;
  346.       case GL_EXP:
  347.          for (i=0;i<n;i++) {
  348.         GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
  349.         GLfloat eyez = -d / (c+ndcz);
  350.             GLfloat f;
  351.         if (eyez < 0.0)
  352.                eyez = -eyez;
  353.         f = exp( -ctx->Fog.Density * eyez );
  354.         f = CLAMP( f, 0.0F, 1.0F );
  355.         index[i] = (GLuint) ((GLfloat) index[i] + (1.0F-f) * ctx->Fog.Index);
  356.      }
  357.      break;
  358.       case GL_EXP2:
  359.          {
  360.             GLfloat negDensitySquared = -ctx->Fog.Density * ctx->Fog.Density;
  361.             for (i=0;i<n;i++) {
  362.                GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
  363.                GLfloat eyez = -d / (c+ndcz);
  364.                GLfloat tmp, f;
  365.                if (eyez < 0.0)
  366.                   eyez = -eyez;
  367.                tmp = negDensitySquared * eyez * eyez;
  368. #ifdef __alpha__
  369.                /* XXX this underflow check may be needed for other systems */
  370.                if (tmp < FLT_MIN_10_EXP)
  371.                   f = exp( FLT_MIN_10_EXP );
  372.                else
  373. #endif
  374.                f = exp( tmp );
  375.                f = CLAMP( f, 0.0F, 1.0F );
  376.                index[i] = (GLuint) ((GLfloat) index[i] + (1.0F-f) * ctx->Fog.Index);
  377.             }
  378.      }
  379.      break;
  380.       default:
  381.          gl_problem(ctx, "Bad fog mode in gl_fog_ci_pixels");
  382.          return;
  383.    }
  384. }
  385.  
  386.