2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
31 #include "s_context.h"
37 * Used to convert current raster distance to a fog factor in [0,1].
40 _swrast_z_to_fogfactor(GLcontext
*ctx
, GLfloat z
)
44 switch (ctx
->Fog
.Mode
) {
46 if (ctx
->Fog
.Start
== ctx
->Fog
.End
)
49 d
= 1.0F
/ (ctx
->Fog
.End
- ctx
->Fog
.Start
);
50 f
= (ctx
->Fog
.End
- z
) * d
;
51 return CLAMP(f
, 0.0F
, 1.0F
);
54 f
= (GLfloat
) exp(-d
* z
);
55 f
= CLAMP(f
, 0.0F
, 1.0F
);
59 f
= (GLfloat
) exp(-(d
* d
* z
* z
));
60 f
= CLAMP(f
, 0.0F
, 1.0F
);
63 _mesa_problem(ctx
, "Bad fog mode in _swrast_z_to_fogfactor");
70 * Apply fog to a span of RGBA pixels.
71 * The fog value are either in the span->array->fog array or interpolated from
72 * the fog/fogStep values.
73 * They fog values are either fog coordinates (Z) or fog blend factors.
74 * _PreferPixelFog should be in sync with that state!
77 _swrast_fog_rgba_span( const GLcontext
*ctx
, struct sw_span
*span
)
79 const SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
80 const GLchan rFog
= swrast
->_FogColor
[RCOMP
];
81 const GLchan gFog
= swrast
->_FogColor
[GCOMP
];
82 const GLchan bFog
= swrast
->_FogColor
[BCOMP
];
83 const GLuint haveW
= (span
->interpMask
& SPAN_W
);
84 GLchan (*rgba
)[4] = (GLchan (*)[4]) span
->array
->rgba
;
86 ASSERT(swrast
->_FogEnabled
);
87 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_FOG
);
88 ASSERT(span
->arrayMask
& SPAN_RGBA
);
90 /* NOTE: if haveW is true, that means the fog start/step values are
91 * perspective-corrected and we have to divide each fog coord by W.
94 /* we need to compute fog blend factors */
95 if (swrast
->_PreferPixelFog
) {
96 /* The span's fog values are fog coordinates, now compute blend factors
97 * and blend the fragment colors with the fog color.
99 switch (swrast
->_FogMode
) {
102 const GLfloat fogEnd
= ctx
->Fog
.End
;
103 const GLfloat fogScale
= (ctx
->Fog
.Start
== ctx
->Fog
.End
)
104 ? 1.0F
: 1.0F
/ (ctx
->Fog
.End
- ctx
->Fog
.Start
);
105 const GLfloat fogStep
= span
->fogStep
;
106 GLfloat fogCoord
= span
->fog
;
107 const GLfloat wStep
= haveW
? span
->dwdx
: 0.0F
;
108 GLfloat w
= haveW
? span
->w
: 1.0F
;
110 for (i
= 0; i
< span
->end
; i
++) {
111 GLfloat f
, oneMinusF
;
112 f
= (fogEnd
- FABSF(fogCoord
) / w
) * fogScale
;
113 f
= CLAMP(f
, 0.0F
, 1.0F
);
114 oneMinusF
= 1.0F
- f
;
115 rgba
[i
][RCOMP
] = (GLchan
) (f
* rgba
[i
][RCOMP
] + oneMinusF
* rFog
);
116 rgba
[i
][GCOMP
] = (GLchan
) (f
* rgba
[i
][GCOMP
] + oneMinusF
* gFog
);
117 rgba
[i
][BCOMP
] = (GLchan
) (f
* rgba
[i
][BCOMP
] + oneMinusF
* bFog
);
125 const GLfloat density
= -ctx
->Fog
.Density
;
126 const GLfloat fogStep
= span
->fogStep
;
127 GLfloat fogCoord
= span
->fog
;
128 const GLfloat wStep
= haveW
? span
->dwdx
: 0.0F
;
129 GLfloat w
= haveW
? span
->w
: 1.0F
;
131 for (i
= 0; i
< span
->end
; i
++) {
132 GLfloat f
, oneMinusF
;
133 f
= (GLfloat
) exp(density
* FABSF(fogCoord
) / w
);
134 f
= CLAMP(f
, 0.0F
, 1.0F
);
135 oneMinusF
= 1.0F
- f
;
136 rgba
[i
][RCOMP
] = (GLchan
) (f
* rgba
[i
][RCOMP
] + oneMinusF
* rFog
);
137 rgba
[i
][GCOMP
] = (GLchan
) (f
* rgba
[i
][GCOMP
] + oneMinusF
* gFog
);
138 rgba
[i
][BCOMP
] = (GLchan
) (f
* rgba
[i
][BCOMP
] + oneMinusF
* bFog
);
146 const GLfloat negDensitySquared
= -ctx
->Fog
.Density
* ctx
->Fog
.Density
;
147 const GLfloat fogStep
= span
->fogStep
;
148 GLfloat fogCoord
= span
->fog
;
149 const GLfloat wStep
= haveW
? span
->dwdx
: 0.0F
;
150 GLfloat w
= haveW
? span
->w
: 1.0F
;
152 for (i
= 0; i
< span
->end
; i
++) {
153 const GLfloat coord
= fogCoord
/ w
;
154 GLfloat tmp
= negDensitySquared
* coord
* coord
;
155 GLfloat f
, oneMinusF
;
156 #if defined(__alpha__) || defined(__alpha)
157 /* XXX this underflow check may be needed for other systems*/
158 if (tmp
< FLT_MIN_10_EXP
)
159 tmp
= FLT_MIN_10_EXP
;
161 f
= (GLfloat
) exp(tmp
);
162 f
= CLAMP(f
, 0.0F
, 1.0F
);
163 oneMinusF
= 1.0F
- f
;
164 rgba
[i
][RCOMP
] = (GLchan
) (f
* rgba
[i
][RCOMP
] + oneMinusF
* rFog
);
165 rgba
[i
][GCOMP
] = (GLchan
) (f
* rgba
[i
][GCOMP
] + oneMinusF
* gFog
);
166 rgba
[i
][BCOMP
] = (GLchan
) (f
* rgba
[i
][BCOMP
] + oneMinusF
* bFog
);
173 _mesa_problem(ctx
, "Bad fog mode in _swrast_fog_rgba_span");
177 else if (span
->arrayMask
& SPAN_FOG
) {
178 /* The span's fog array values are blend factors.
179 * They were previously computed per-vertex.
182 for (i
= 0; i
< span
->end
; i
++) {
183 const GLfloat f
= span
->array
->fog
[i
];
184 const GLfloat oneMinusF
= 1.0F
- f
;
185 rgba
[i
][RCOMP
] = (GLchan
) (f
* rgba
[i
][RCOMP
] + oneMinusF
* rFog
);
186 rgba
[i
][GCOMP
] = (GLchan
) (f
* rgba
[i
][GCOMP
] + oneMinusF
* gFog
);
187 rgba
[i
][BCOMP
] = (GLchan
) (f
* rgba
[i
][BCOMP
] + oneMinusF
* bFog
);
191 /* The span's fog start/step values are blend factors.
192 * They were previously computed per-vertex.
194 const GLfloat fogStep
= span
->fogStep
;
195 GLfloat fog
= span
->fog
;
196 const GLfloat wStep
= haveW
? span
->dwdx
: 0.0F
;
197 GLfloat w
= haveW
? span
->w
: 1.0F
;
199 ASSERT(span
->interpMask
& SPAN_FOG
);
200 for (i
= 0; i
< span
->end
; i
++) {
201 const GLfloat fact
= fog
/ w
;
202 const GLfloat oneMinusF
= 1.0F
- fact
;
203 rgba
[i
][RCOMP
] = (GLchan
) (fact
* rgba
[i
][RCOMP
] + oneMinusF
* rFog
);
204 rgba
[i
][GCOMP
] = (GLchan
) (fact
* rgba
[i
][GCOMP
] + oneMinusF
* gFog
);
205 rgba
[i
][BCOMP
] = (GLchan
) (fact
* rgba
[i
][BCOMP
] + oneMinusF
* bFog
);
214 * As above, but color index mode.
217 _swrast_fog_ci_span( const GLcontext
*ctx
, struct sw_span
*span
)
219 const SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
220 const GLuint haveW
= (span
->interpMask
& SPAN_W
);
221 const GLuint fogIndex
= (GLuint
) ctx
->Fog
.Index
;
222 GLuint
*index
= span
->array
->index
;
224 ASSERT(swrast
->_FogEnabled
);
225 ASSERT(span
->arrayMask
& SPAN_INDEX
);
226 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_FOG
);
228 /* we need to compute fog blend factors */
229 if (swrast
->_PreferPixelFog
) {
230 /* The span's fog values are fog coordinates, now compute blend factors
231 * and blend the fragment colors with the fog color.
233 switch (ctx
->Fog
.Mode
) {
236 const GLfloat fogEnd
= ctx
->Fog
.End
;
237 const GLfloat fogScale
= (ctx
->Fog
.Start
== ctx
->Fog
.End
)
238 ? 1.0F
: 1.0F
/ (ctx
->Fog
.End
- ctx
->Fog
.Start
);
239 const GLfloat fogStep
= span
->fogStep
;
240 GLfloat fogCoord
= span
->fog
;
241 const GLfloat wStep
= haveW
? span
->dwdx
: 0.0F
;
242 GLfloat w
= haveW
? span
->w
: 1.0F
;
244 for (i
= 0; i
< span
->end
; i
++) {
245 GLfloat f
= (fogEnd
- fogCoord
/ w
) * fogScale
;
246 f
= CLAMP(f
, 0.0F
, 1.0F
);
247 index
[i
] = (GLuint
) ((GLfloat
) index
[i
] + (1.0F
- f
) * fogIndex
);
255 const GLfloat density
= -ctx
->Fog
.Density
;
256 const GLfloat fogStep
= span
->fogStep
;
257 GLfloat fogCoord
= span
->fog
;
258 const GLfloat wStep
= haveW
? span
->dwdx
: 0.0F
;
259 GLfloat w
= haveW
? span
->w
: 1.0F
;
261 for (i
= 0; i
< span
->end
; i
++) {
262 GLfloat f
= (GLfloat
) exp(density
* fogCoord
/ w
);
263 f
= CLAMP(f
, 0.0F
, 1.0F
);
264 index
[i
] = (GLuint
) ((GLfloat
) index
[i
] + (1.0F
- f
) * fogIndex
);
272 const GLfloat negDensitySquared
= -ctx
->Fog
.Density
* ctx
->Fog
.Density
;
273 const GLfloat fogStep
= span
->fogStep
;
274 GLfloat fogCoord
= span
->fog
;
275 const GLfloat wStep
= haveW
? span
->dwdx
: 0.0F
;
276 GLfloat w
= haveW
? span
->w
: 1.0F
;
278 for (i
= 0; i
< span
->end
; i
++) {
279 const GLfloat coord
= fogCoord
/ w
;
280 GLfloat tmp
= negDensitySquared
* coord
* coord
;
282 #if defined(__alpha__) || defined(__alpha)
283 /* XXX this underflow check may be needed for other systems*/
284 if (tmp
< FLT_MIN_10_EXP
)
285 tmp
= FLT_MIN_10_EXP
;
287 f
= (GLfloat
) exp(tmp
);
288 f
= CLAMP(f
, 0.0F
, 1.0F
);
289 index
[i
] = (GLuint
) ((GLfloat
) index
[i
] + (1.0F
- f
) * fogIndex
);
296 _mesa_problem(ctx
, "Bad fog mode in _swrast_fog_ci_span");
300 else if (span
->arrayMask
& SPAN_FOG
) {
301 /* The span's fog array values are blend factors.
302 * They were previously computed per-vertex.
305 for (i
= 0; i
< span
->end
; i
++) {
306 const GLfloat f
= span
->array
->fog
[i
];
307 index
[i
] = (GLuint
) ((GLfloat
) index
[i
] + (1.0F
- f
) * fogIndex
);
311 /* The span's fog start/step values are blend factors.
312 * They were previously computed per-vertex.
314 const GLfloat fogStep
= span
->fogStep
;
315 GLfloat fog
= span
->fog
;
316 const GLfloat wStep
= haveW
? span
->dwdx
: 0.0F
;
317 GLfloat w
= haveW
? span
->w
: 1.0F
;
319 ASSERT(span
->interpMask
& SPAN_FOG
);
320 for (i
= 0; i
< span
->end
; i
++) {
321 const GLfloat f
= fog
/ w
;
322 index
[i
] = (GLuint
) ((GLfloat
) index
[i
] + (1.0F
- f
) * fogIndex
);