Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Mesa 3-D graphics library
  3.  *
  4.  * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the "Software"),
  8.  * to deal in the Software without restriction, including without limitation
  9.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  10.  * and/or sell copies of the Software, and to permit persons to whom the
  11.  * Software is furnished to do so, subject to the following conditions:
  12.  *
  13.  * The above copyright notice and this permission notice shall be included
  14.  * in all copies or substantial portions of the Software.
  15.  *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  17.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  19.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  20.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  21.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  22.  * OTHER DEALINGS IN THE SOFTWARE.
  23.  */
  24.  
  25.  
  26. #include "c99_math.h"
  27. #include "main/glheader.h"
  28. #include "main/macros.h"
  29.  
  30. #include "s_context.h"
  31. #include "s_fog.h"
  32.  
  33.  
  34. /**
  35.  * Used to convert current raster distance to a fog factor in [0,1].
  36.  */
  37. GLfloat
  38. _swrast_z_to_fogfactor(struct gl_context *ctx, GLfloat z)
  39. {
  40.    GLfloat d, f;
  41.  
  42.    switch (ctx->Fog.Mode) {
  43.    case GL_LINEAR:
  44.       if (ctx->Fog.Start == ctx->Fog.End)
  45.          d = 1.0F;
  46.       else
  47.          d = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
  48.       f = (ctx->Fog.End - z) * d;
  49.       return CLAMP(f, 0.0F, 1.0F);
  50.    case GL_EXP:
  51.       d = ctx->Fog.Density;
  52.       f = expf(-d * z);
  53.       f = CLAMP(f, 0.0F, 1.0F);
  54.       return f;
  55.    case GL_EXP2:
  56.       d = ctx->Fog.Density;
  57.       f = expf(-(d * d * z * z));
  58.       f = CLAMP(f, 0.0F, 1.0F);
  59.       return f;
  60.    default:
  61.       _mesa_problem(ctx, "Bad fog mode in _swrast_z_to_fogfactor");
  62.       return 0.0;
  63.    }
  64. }
  65.  
  66.  
  67. #define LINEAR_FOG(f, coord)  f = (fogEnd - coord) * fogScale
  68.  
  69. #define EXP_FOG(f, coord)  f = expf(density * coord)
  70.  
  71. #define EXP2_FOG(f, coord)                              \
  72. do {                                                    \
  73.    GLfloat tmp = negDensitySquared * coord * coord;     \
  74.    if (tmp < FLT_MIN_10_EXP)                            \
  75.       tmp = FLT_MIN_10_EXP;                             \
  76.    f = expf(tmp);                                       \
  77.  } while(0)
  78.  
  79.  
  80. #define BLEND_FOG(f, coord)  f = coord
  81.  
  82.  
  83.  
  84. /**
  85.  * Template code for computing fog blend factor and applying it to colors.
  86.  * \param TYPE  either GLubyte, GLushort or GLfloat.
  87.  * \param COMPUTE_F  code to compute the fog blend factor, f.
  88.  */
  89. #define FOG_LOOP(TYPE, FOG_FUNC)                                                \
  90. if (span->arrayAttribs & VARYING_BIT_FOGC) {                                    \
  91.    GLuint i;                                                                    \
  92.    for (i = 0; i < span->end; i++) {                                            \
  93.       const GLfloat fogCoord = span->array->attribs[VARYING_SLOT_FOGC][i][0];   \
  94.       const GLfloat c = fabsf(fogCoord);                                        \
  95.       GLfloat f, oneMinusF;                                                     \
  96.       FOG_FUNC(f, c);                                                           \
  97.       f = CLAMP(f, 0.0F, 1.0F);                                                 \
  98.       oneMinusF = 1.0F - f;                                                     \
  99.       rgba[i][RCOMP] = (TYPE) (f * rgba[i][RCOMP] + oneMinusF * rFog);          \
  100.       rgba[i][GCOMP] = (TYPE) (f * rgba[i][GCOMP] + oneMinusF * gFog);          \
  101.       rgba[i][BCOMP] = (TYPE) (f * rgba[i][BCOMP] + oneMinusF * bFog);          \
  102.    }                                                                            \
  103. }                                                                               \
  104. else {                                                                          \
  105.    const GLfloat fogStep = span->attrStepX[VARYING_SLOT_FOGC][0];               \
  106.    GLfloat fogCoord = span->attrStart[VARYING_SLOT_FOGC][0];                    \
  107.    const GLfloat wStep = span->attrStepX[VARYING_SLOT_POS][3];                  \
  108.    GLfloat w = span->attrStart[VARYING_SLOT_POS][3];                            \
  109.    GLuint i;                                                                    \
  110.    for (i = 0; i < span->end; i++) {                                            \
  111.       const GLfloat c = fabsf(fogCoord) / w;                                    \
  112.       GLfloat f, oneMinusF;                                                     \
  113.       FOG_FUNC(f, c);                                                           \
  114.       f = CLAMP(f, 0.0F, 1.0F);                                                 \
  115.       oneMinusF = 1.0F - f;                                                     \
  116.       rgba[i][RCOMP] = (TYPE) (f * rgba[i][RCOMP] + oneMinusF * rFog);          \
  117.       rgba[i][GCOMP] = (TYPE) (f * rgba[i][GCOMP] + oneMinusF * gFog);          \
  118.       rgba[i][BCOMP] = (TYPE) (f * rgba[i][BCOMP] + oneMinusF * bFog);          \
  119.       fogCoord += fogStep;                                                      \
  120.       w += wStep;                                                               \
  121.    }                                                                            \
  122. }
  123.  
  124. /**
  125.  * Apply fog to a span of RGBA pixels.
  126.  * The fog value are either in the span->array->fog array or interpolated from
  127.  * the fog/fogStep values.
  128.  * They fog values are either fog coordinates (Z) or fog blend factors.
  129.  * _PreferPixelFog should be in sync with that state!
  130.  */
  131. void
  132. _swrast_fog_rgba_span( const struct gl_context *ctx, SWspan *span )
  133. {
  134.    const SWcontext *swrast = CONST_SWRAST_CONTEXT(ctx);
  135.    GLfloat rFog, gFog, bFog;
  136.  
  137.    assert(swrast->_FogEnabled);
  138.    assert(span->arrayMask & SPAN_RGBA);
  139.  
  140.    /* compute (scaled) fog color */
  141.    if (span->array->ChanType == GL_UNSIGNED_BYTE) {
  142.       rFog = ctx->Fog.Color[RCOMP] * 255.0F;
  143.       gFog = ctx->Fog.Color[GCOMP] * 255.0F;
  144.       bFog = ctx->Fog.Color[BCOMP] * 255.0F;
  145.    }
  146.    else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
  147.       rFog = ctx->Fog.Color[RCOMP] * 65535.0F;
  148.       gFog = ctx->Fog.Color[GCOMP] * 65535.0F;
  149.       bFog = ctx->Fog.Color[BCOMP] * 65535.0F;
  150.    }
  151.    else {
  152.       rFog = ctx->Fog.Color[RCOMP];
  153.       gFog = ctx->Fog.Color[GCOMP];
  154.       bFog = ctx->Fog.Color[BCOMP];
  155.    }
  156.  
  157.    if (swrast->_PreferPixelFog) {
  158.       /* The span's fog values are fog coordinates, now compute blend factors
  159.        * and blend the fragment colors with the fog color.
  160.        */
  161.       switch (ctx->Fog.Mode) {
  162.       case GL_LINEAR:
  163.          {
  164.             const GLfloat fogEnd = ctx->Fog.End;
  165.             const GLfloat fogScale = (ctx->Fog.Start == ctx->Fog.End)
  166.                ? 1.0F : 1.0F / (ctx->Fog.End - ctx->Fog.Start);
  167.             if (span->array->ChanType == GL_UNSIGNED_BYTE) {
  168.                GLubyte (*rgba)[4] = span->array->rgba8;
  169.                FOG_LOOP(GLubyte, LINEAR_FOG);
  170.             }
  171.             else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
  172.                GLushort (*rgba)[4] = span->array->rgba16;
  173.                FOG_LOOP(GLushort, LINEAR_FOG);
  174.             }
  175.             else {
  176.                GLfloat (*rgba)[4] = span->array->attribs[VARYING_SLOT_COL0];
  177.                assert(span->array->ChanType == GL_FLOAT);
  178.                FOG_LOOP(GLfloat, LINEAR_FOG);
  179.             }
  180.          }
  181.          break;
  182.  
  183.       case GL_EXP:
  184.          {
  185.             const GLfloat density = -ctx->Fog.Density;
  186.             if (span->array->ChanType == GL_UNSIGNED_BYTE) {
  187.                GLubyte (*rgba)[4] = span->array->rgba8;
  188.                FOG_LOOP(GLubyte, EXP_FOG);
  189.             }
  190.             else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
  191.                GLushort (*rgba)[4] = span->array->rgba16;
  192.                FOG_LOOP(GLushort, EXP_FOG);
  193.             }
  194.             else {
  195.                GLfloat (*rgba)[4] = span->array->attribs[VARYING_SLOT_COL0];
  196.                assert(span->array->ChanType == GL_FLOAT);
  197.                FOG_LOOP(GLfloat, EXP_FOG);
  198.             }
  199.          }
  200.          break;
  201.  
  202.       case GL_EXP2:
  203.          {
  204.             const GLfloat negDensitySquared = -ctx->Fog.Density * ctx->Fog.Density;
  205.             if (span->array->ChanType == GL_UNSIGNED_BYTE) {
  206.                GLubyte (*rgba)[4] = span->array->rgba8;
  207.                FOG_LOOP(GLubyte, EXP2_FOG);
  208.             }
  209.             else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
  210.                GLushort (*rgba)[4] = span->array->rgba16;
  211.                FOG_LOOP(GLushort, EXP2_FOG);
  212.             }
  213.             else {
  214.                GLfloat (*rgba)[4] = span->array->attribs[VARYING_SLOT_COL0];
  215.                assert(span->array->ChanType == GL_FLOAT);
  216.                FOG_LOOP(GLfloat, EXP2_FOG);
  217.             }
  218.          }
  219.          break;
  220.  
  221.       default:
  222.          _mesa_problem(ctx, "Bad fog mode in _swrast_fog_rgba_span");
  223.          return;
  224.       }
  225.    }
  226.    else {
  227.       /* The span's fog start/step/array values are blend factors in [0,1].
  228.        * They were previously computed per-vertex.
  229.        */
  230.       if (span->array->ChanType == GL_UNSIGNED_BYTE) {
  231.          GLubyte (*rgba)[4] = span->array->rgba8;
  232.          FOG_LOOP(GLubyte, BLEND_FOG);
  233.       }
  234.       else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
  235.          GLushort (*rgba)[4] = span->array->rgba16;
  236.          FOG_LOOP(GLushort, BLEND_FOG);
  237.       }
  238.       else {
  239.          GLfloat (*rgba)[4] = span->array->attribs[VARYING_SLOT_COL0];
  240.          assert(span->array->ChanType == GL_FLOAT);
  241.          FOG_LOOP(GLfloat, BLEND_FOG);
  242.       }
  243.    }
  244. }
  245.