home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mesa5.zip / mesa5src.zip / tnl / t_vb_fog.cpp < prev    next >
C/C++ Source or Header  |  2002-10-29  |  7KB  |  255 lines

  1. /* $Id: t_vb_fog.c,v 1.19 2002/10/29 20:29:03 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  4.1
  6.  *
  7.  * Copyright (C) 1999-2002  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.  * Authors:
  27.  *    Keith Whitwell <keith@tungstengraphics.com>
  28.  */
  29.  
  30.  
  31. #include "glheader.h"
  32. #include "colormac.h"
  33. #include "context.h"
  34. #include "macros.h"
  35. #include "imports.h"
  36. #include "mmath.h"
  37. #include "mtypes.h"
  38.  
  39. #include "math/m_xform.h"
  40.  
  41. #include "t_context.h"
  42. #include "t_pipeline.h"
  43.  
  44.  
  45. struct fog_stage_data {
  46.    GLvector4f fogcoord;        /* has actual storage allocated */
  47.    GLvector4f input;        /* points into VB->EyePtr Z values */
  48. };
  49.  
  50. #define FOG_STAGE_DATA(stage) ((struct fog_stage_data *)stage->privatePtr)
  51.  
  52. #define FOG_EXP_TABLE_SIZE 256
  53. #define FOG_MAX (10.0)
  54. #define EXP_FOG_MAX .0006595
  55. #define FOG_INCR (FOG_MAX/FOG_EXP_TABLE_SIZE)
  56. static GLfloat exp_table[FOG_EXP_TABLE_SIZE];
  57. static GLfloat inited = 0;
  58.  
  59. #if 1
  60. #define NEG_EXP( result, narg )                        \
  61. do {                                    \
  62.    GLfloat f = (GLfloat) (narg * (1.0/FOG_INCR));            \
  63.    GLint k = (GLint) f;                            \
  64.    if (k > FOG_EXP_TABLE_SIZE-2)                     \
  65.       result = (GLfloat) EXP_FOG_MAX;                    \
  66.    else                                    \
  67.       result = exp_table[k] + (f-k)*(exp_table[k+1]-exp_table[k]);    \
  68. } while (0)
  69. #else
  70. #define NEG_EXP( result, narg )                    \
  71. do {                                \
  72.    result = exp(-narg);                        \
  73. } while (0)
  74. #endif
  75.  
  76.  
  77. static void init_static_data( void )
  78. {
  79.    GLfloat f = 0.0F;
  80.    GLint i = 0;
  81.    for ( ; i < FOG_EXP_TABLE_SIZE ; i++, f += FOG_INCR) {
  82.       exp_table[i] = (GLfloat) exp(-f);
  83.    }
  84.    inited = 1;
  85. }
  86.  
  87.  
  88. static void make_win_fog_coords( GLcontext *ctx, GLvector4f *out,
  89.                  const GLvector4f *in )
  90. {
  91.    GLfloat end  = ctx->Fog.End;
  92.    GLfloat *v = in->start;
  93.    GLuint stride = in->stride;
  94.    GLuint n = in->count;
  95.    GLfloat (*data)[4] = out->data;
  96.    GLfloat d;
  97.    GLuint i;
  98.  
  99.    out->count = in->count;
  100.  
  101.    switch (ctx->Fog.Mode) {
  102.    case GL_LINEAR:
  103.       if (ctx->Fog.Start == ctx->Fog.End)
  104.          d = 1.0F;
  105.       else
  106.          d = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
  107.       for ( i = 0 ; i < n ; i++, STRIDE_F(v, stride)) {
  108.          GLfloat f = (end - ABSF(*v)) * d;
  109.      data[i][0] = CLAMP(f, 0.0F, 1.0F);
  110.       }
  111.       break;
  112.    case GL_EXP:
  113.       d = ctx->Fog.Density;
  114.       for ( i = 0 ; i < n ; i++, STRIDE_F(v,stride))
  115.          NEG_EXP( data[i][0], d * ABSF(*v) );
  116.       break;
  117.    case GL_EXP2:
  118.       d = ctx->Fog.Density*ctx->Fog.Density;
  119.       for ( i = 0 ; i < n ; i++, STRIDE_F(v, stride)) {
  120.          GLfloat z = *v;
  121.          NEG_EXP( data[i][0], d * z * z );
  122.       }
  123.       break;
  124.    default:
  125.       _mesa_problem(ctx, "Bad fog mode in make_fog_coord");
  126.       return;
  127.    }
  128. }
  129.  
  130.  
  131. static GLboolean run_fog_stage( GLcontext *ctx,
  132.                 struct gl_pipeline_stage *stage )
  133. {
  134.    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
  135.    struct fog_stage_data *store = FOG_STAGE_DATA(stage);
  136.    GLvector4f *input;
  137.  
  138.    if (stage->changed_inputs == 0)
  139.       return GL_TRUE;
  140.  
  141.    if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT) {
  142.       /* fog computed from Z depth */
  143.       /* source = VB->ObjPtr or VB->EyePtr coords */
  144.       /* dest = VB->FogCoordPtr = fog stage private storage */
  145.       VB->FogCoordPtr = &store->fogcoord;
  146.  
  147.       if (!ctx->_NeedEyeCoords) {
  148.      const GLfloat *m = ctx->ModelviewMatrixStack.Top->m;
  149.      GLfloat plane[4];
  150.  
  151.      /* Use this to store calculated eye z values:
  152.       */
  153.      input = &store->fogcoord;
  154.  
  155.      plane[0] = m[2];
  156.      plane[1] = m[6];
  157.      plane[2] = m[10];
  158.      plane[3] = m[14];
  159.  
  160.      /* Full eye coords weren't required, just calculate the
  161.       * eye Z values.
  162.       */
  163.      _mesa_dotprod_tab[VB->ObjPtr->size]( (GLfloat *) input->data,
  164.                           4 * sizeof(GLfloat),
  165.                           VB->ObjPtr, plane );
  166.  
  167.      input->count = VB->ObjPtr->count;
  168.       }
  169.       else {
  170.      input = &store->input;
  171.  
  172.      if (VB->EyePtr->size < 2)
  173.         _mesa_vector4f_clean_elem( VB->EyePtr, VB->Count, 2 );
  174.  
  175.      input->data = (GLfloat (*)[4]) &(VB->EyePtr->data[0][2]);
  176.      input->start = VB->EyePtr->start+2;
  177.      input->stride = VB->EyePtr->stride;
  178.      input->count = VB->EyePtr->count;
  179.       }
  180.    }
  181.    else {
  182.       /* use glFogCoord() coordinates */
  183.       /* source = VB->FogCoordPtr */
  184.       input = VB->FogCoordPtr;
  185.       /* dest = fog stage private storage */
  186.       VB->FogCoordPtr = &store->fogcoord;
  187.    }
  188.  
  189.    make_win_fog_coords( ctx, VB->FogCoordPtr, input );
  190.    return GL_TRUE;
  191. }
  192.  
  193.  
  194. static void check_fog_stage( GLcontext *ctx, struct gl_pipeline_stage *stage )
  195. {
  196.    stage->active = ctx->Fog.Enabled && !ctx->VertexProgram.Enabled;
  197.  
  198.    if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT)
  199.       stage->inputs = VERT_BIT_EYE;
  200.    else
  201.       stage->inputs = VERT_BIT_FOG;
  202. }
  203.  
  204.  
  205. /* Called the first time stage->run() is invoked.
  206.  */
  207. static GLboolean alloc_fog_data( GLcontext *ctx,
  208.                  struct gl_pipeline_stage *stage )
  209. {
  210.    TNLcontext *tnl = TNL_CONTEXT(ctx);
  211.    struct fog_stage_data *store;
  212.    stage->privatePtr = MALLOC(sizeof(*store));
  213.    store = FOG_STAGE_DATA(stage);
  214.    if (!store)
  215.       return GL_FALSE;
  216.  
  217.    _mesa_vector4f_alloc( &store->fogcoord, 0, tnl->vb.Size, 32 );
  218.    _mesa_vector4f_init( &store->input, 0, 0 );
  219.  
  220.    if (!inited)
  221.       init_static_data();
  222.  
  223.    /* Now run the stage.
  224.     */
  225.    stage->run = run_fog_stage;
  226.    return stage->run( ctx, stage );
  227. }
  228.  
  229.  
  230. static void free_fog_data( struct gl_pipeline_stage *stage )
  231. {
  232.    struct fog_stage_data *store = FOG_STAGE_DATA(stage);
  233.    if (store) {
  234.       _mesa_vector4f_free( &store->fogcoord );
  235.       FREE( store );
  236.       stage->privatePtr = NULL;
  237.    }
  238. }
  239.  
  240.  
  241. const struct gl_pipeline_stage _tnl_fog_coordinate_stage =
  242. {
  243.    "build fog coordinates",    /* name */
  244.    _NEW_FOG,            /* check_state */
  245.    _NEW_FOG,            /* run_state */
  246.    GL_FALSE,            /* active? */
  247.    0,                /* inputs */
  248.    VERT_BIT_FOG,        /* outputs */
  249.    0,                /* changed_inputs */
  250.    NULL,            /* private_data */
  251.    free_fog_data,        /* dtr */
  252.    check_fog_stage,        /* check */
  253.    alloc_fog_data        /* run -- initially set to init. */
  254. };
  255.