Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4358 Serge 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 "main/glheader.h"
27
#include "main/colormac.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
}