Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Mesa 3-D graphics library
  3.  * Version:  6.5
  4.  *
  5.  * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
  6.  *
  7.  * Permission is hereby granted, free of charge, to any person obtaining a
  8.  * copy of this software and associated documentation files (the "Software"),
  9.  * to deal in the Software without restriction, including without limitation
  10.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11.  * and/or sell copies of the Software, and to permit persons to whom the
  12.  * Software is furnished to do so, subject to the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice shall be included
  15.  * in all copies or substantial portions of the Software.
  16.  *
  17.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  18.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  20.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  21.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  22.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23.  *
  24.  * Authors:
  25.  *    Keith Whitwell <keith@tungstengraphics.com>
  26.  */
  27.  
  28.  
  29. #include "main/glheader.h"
  30. #include "main/colormac.h"
  31. #include "main/macros.h"
  32. #include "main/imports.h"
  33. #include "main/mtypes.h"
  34.  
  35. #include "math/m_xform.h"
  36.  
  37. #include "t_context.h"
  38. #include "t_pipeline.h"
  39.  
  40.  
  41. struct fog_stage_data {
  42.    GLvector4f fogcoord;         /* has actual storage allocated */
  43. };
  44.  
  45. #define FOG_STAGE_DATA(stage) ((struct fog_stage_data *)stage->privatePtr)
  46.  
  47. #define FOG_EXP_TABLE_SIZE 256
  48. #define FOG_MAX (10.0)
  49. #define EXP_FOG_MAX .0006595
  50. #define FOG_INCR (FOG_MAX/FOG_EXP_TABLE_SIZE)
  51. static GLfloat exp_table[FOG_EXP_TABLE_SIZE];
  52. static GLfloat inited = 0;
  53.  
  54. #if 1
  55. #define NEG_EXP( result, narg )                                         \
  56. do {                                                                    \
  57.    GLfloat f = (GLfloat) (narg * (1.0/FOG_INCR));                       \
  58.    GLint k = (GLint) f;                                                 \
  59.    if (k > FOG_EXP_TABLE_SIZE-2)                                        \
  60.       result = (GLfloat) EXP_FOG_MAX;                                   \
  61.    else                                                                 \
  62.       result = exp_table[k] + (f-k)*(exp_table[k+1]-exp_table[k]);      \
  63. } while (0)
  64. #else
  65. #define NEG_EXP( result, narg )                                 \
  66. do {                                                            \
  67.    result = exp(-narg);                                         \
  68. } while (0)
  69. #endif
  70.  
  71.  
  72. /**
  73.  * Initialize the exp_table[] lookup table for approximating exp().
  74.  */
  75. static void
  76. init_static_data( void )
  77. {
  78.    GLfloat f = 0.0F;
  79.    GLint i = 0;
  80.    for ( ; i < FOG_EXP_TABLE_SIZE ; i++, f += FOG_INCR) {
  81.       exp_table[i] = EXPF(-f);
  82.    }
  83.    inited = 1;
  84. }
  85.  
  86.  
  87. /**
  88.  * Compute per-vertex fog blend factors from fog coordinates by
  89.  * evaluating the GL_LINEAR, GL_EXP or GL_EXP2 fog function.
  90.  * Fog coordinates are distances from the eye (typically between the
  91.  * near and far clip plane distances).
  92.  * Note that fogcoords may be negative, if eye z is source absolute
  93.  * value must be taken earlier.
  94.  * Fog blend factors are in the range [0,1].
  95.  */
  96. static void
  97. compute_fog_blend_factors(struct gl_context *ctx, GLvector4f *out, const GLvector4f *in)
  98. {
  99.    GLfloat end  = ctx->Fog.End;
  100.    GLfloat *v = in->start;
  101.    GLuint stride = in->stride;
  102.    GLuint n = in->count;
  103.    GLfloat (*data)[4] = out->data;
  104.    GLfloat d;
  105.    GLuint i;
  106.  
  107.    out->count = in->count;
  108.  
  109.    switch (ctx->Fog.Mode) {
  110.    case GL_LINEAR:
  111.       if (ctx->Fog.Start == ctx->Fog.End)
  112.          d = 1.0F;
  113.       else
  114.          d = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
  115.       for ( i = 0 ; i < n ; i++, STRIDE_F(v, stride)) {
  116.          const GLfloat z = *v;
  117.          GLfloat f = (end - z) * d;
  118.          data[i][0] = CLAMP(f, 0.0F, 1.0F);
  119.       }
  120.       break;
  121.    case GL_EXP:
  122.       d = ctx->Fog.Density;
  123.       for ( i = 0 ; i < n ; i++, STRIDE_F(v,stride)) {
  124.          const GLfloat z = *v;
  125.          NEG_EXP( data[i][0], d * z );
  126.       }
  127.       break;
  128.    case GL_EXP2:
  129.       d = ctx->Fog.Density*ctx->Fog.Density;
  130.       for ( i = 0 ; i < n ; i++, STRIDE_F(v, stride)) {
  131.          const GLfloat z = *v;
  132.          NEG_EXP( data[i][0], d * z * z );
  133.       }
  134.       break;
  135.    default:
  136.       _mesa_problem(ctx, "Bad fog mode in make_fog_coord");
  137.       return;
  138.    }
  139. }
  140.  
  141.  
  142. static GLboolean
  143. run_fog_stage(struct gl_context *ctx, struct tnl_pipeline_stage *stage)
  144. {
  145.    TNLcontext *tnl = TNL_CONTEXT(ctx);
  146.    struct vertex_buffer *VB = &tnl->vb;
  147.    struct fog_stage_data *store = FOG_STAGE_DATA(stage);
  148.    GLvector4f *input;
  149.  
  150.  
  151.    if (!ctx->Fog.Enabled)
  152.       return GL_TRUE;
  153.  
  154.    if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT && !ctx->VertexProgram._Current) {
  155.       GLuint i;
  156.       GLfloat *coord;
  157.       /* Fog is computed from vertex or fragment Z values */
  158.       /* source = VB->AttribPtr[_TNL_ATTRIB_POS] or VB->EyePtr coords */
  159.       /* dest = VB->AttribPtr[_TNL_ATTRIB_FOG] = fog stage private storage */
  160.       VB->AttribPtr[_TNL_ATTRIB_FOG] = &store->fogcoord;
  161.  
  162.       if (!ctx->_NeedEyeCoords) {
  163.          /* compute fog coords from object coords */
  164.          const GLfloat *m = ctx->ModelviewMatrixStack.Top->m;
  165.          GLfloat plane[4];
  166.  
  167.          /* Use this to store calculated eye z values:
  168.           */
  169.          input = &store->fogcoord;
  170.  
  171.          plane[0] = m[2];
  172.          plane[1] = m[6];
  173.          plane[2] = m[10];
  174.          plane[3] = m[14];
  175.          /* Full eye coords weren't required, just calculate the
  176.           * eye Z values.
  177.           */
  178.          _mesa_dotprod_tab[VB->AttribPtr[_TNL_ATTRIB_POS]->size]
  179.             ( (GLfloat *) input->data,
  180.               4 * sizeof(GLfloat),
  181.               VB->AttribPtr[_TNL_ATTRIB_POS], plane );
  182.  
  183.          input->count = VB->AttribPtr[_TNL_ATTRIB_POS]->count;
  184.  
  185.          /* make sure coords are really positive
  186.             NOTE should avoid going through array twice */
  187.          coord = input->start;
  188.          for (i = 0; i < input->count; i++) {
  189.             *coord = FABSF(*coord);
  190.             STRIDE_F(coord, input->stride);
  191.          }
  192.       }
  193.       else {
  194.          /* fog coordinates = eye Z coordinates - need to copy for ABS */
  195.          input = &store->fogcoord;
  196.  
  197.          if (VB->EyePtr->size < 2)
  198.             _mesa_vector4f_clean_elem( VB->EyePtr, VB->Count, 2 );
  199.  
  200.          input->stride = 4 * sizeof(GLfloat);
  201.          input->count = VB->EyePtr->count;
  202.          coord = VB->EyePtr->start;
  203.          for (i = 0 ; i < VB->EyePtr->count; i++) {
  204.             input->data[i][0] = FABSF(coord[2]);
  205.             STRIDE_F(coord, VB->EyePtr->stride);
  206.          }
  207.       }
  208.    }
  209.    else {
  210.       /* use glFogCoord() coordinates */
  211.       input = VB->AttribPtr[_TNL_ATTRIB_FOG];  /* source data */
  212.  
  213.       /* input->count may be one if glFogCoord was only called once
  214.        * before glBegin.  But we need to compute fog for all vertices.
  215.        */
  216.       input->count = VB->AttribPtr[_TNL_ATTRIB_POS]->count;
  217.  
  218.       VB->AttribPtr[_TNL_ATTRIB_FOG] = &store->fogcoord;  /* dest data */
  219.    }
  220.  
  221.    if (tnl->_DoVertexFog) {
  222.       /* compute blend factors from fog coordinates */
  223.       compute_fog_blend_factors( ctx, VB->AttribPtr[_TNL_ATTRIB_FOG], input );
  224.    }
  225.    else {
  226.       /* results = incoming fog coords (compute fog per-fragment later) */
  227.       VB->AttribPtr[_TNL_ATTRIB_FOG] = input;
  228.    }
  229.  
  230.    return GL_TRUE;
  231. }
  232.  
  233.  
  234.  
  235. /* Called the first time stage->run() is invoked.
  236.  */
  237. static GLboolean
  238. alloc_fog_data(struct gl_context *ctx, struct tnl_pipeline_stage *stage)
  239. {
  240.    TNLcontext *tnl = TNL_CONTEXT(ctx);
  241.    struct fog_stage_data *store;
  242.    stage->privatePtr = MALLOC(sizeof(*store));
  243.    store = FOG_STAGE_DATA(stage);
  244.    if (!store)
  245.       return GL_FALSE;
  246.  
  247.    _mesa_vector4f_alloc( &store->fogcoord, 0, tnl->vb.Size, 32 );
  248.  
  249.    if (!inited)
  250.       init_static_data();
  251.  
  252.    return GL_TRUE;
  253. }
  254.  
  255.  
  256. static void
  257. free_fog_data(struct tnl_pipeline_stage *stage)
  258. {
  259.    struct fog_stage_data *store = FOG_STAGE_DATA(stage);
  260.    if (store) {
  261.       _mesa_vector4f_free( &store->fogcoord );
  262.       FREE( store );
  263.       stage->privatePtr = NULL;
  264.    }
  265. }
  266.  
  267.  
  268. const struct tnl_pipeline_stage _tnl_fog_coordinate_stage =
  269. {
  270.    "build fog coordinates",     /* name */
  271.    NULL,                        /* private_data */
  272.    alloc_fog_data,              /* dtr */
  273.    free_fog_data,               /* dtr */
  274.    NULL,                /* check */
  275.    run_fog_stage                /* run -- initially set to init. */
  276. };
  277.