3 * Mesa 3-D graphics library
6 * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 #include "s_context.h"
40 * Used to convert current raster distance to a fog factor in [0,1].
43 _swrast_z_to_fogfactor(GLcontext
*ctx
, GLfloat z
)
47 switch (ctx
->Fog
.Mode
) {
49 if (ctx
->Fog
.Start
== ctx
->Fog
.End
)
52 d
= 1.0F
/ (ctx
->Fog
.End
- ctx
->Fog
.Start
);
53 f
= (ctx
->Fog
.End
- z
) * d
;
54 return CLAMP(f
, 0.0F
, 1.0F
);
57 f
= (GLfloat
) exp(-d
* z
);
58 f
= CLAMP(f
, 0.0F
, 1.0F
);
62 f
= (GLfloat
) exp(-(d
* d
* z
* z
));
63 f
= CLAMP(f
, 0.0F
, 1.0F
);
66 _mesa_problem(ctx
, "Bad fog mode in _swrast_z_to_fogfactor");
73 * Apply fog to a span of RGBA pixels.
74 * The fog value are either in the span->array->fog array or interpolated from
75 * the fog/fogStep values.
76 * They fog values are either fog coordinates (Z) or fog blend factors.
77 * _PreferPixelFog should be in sync with that state!
80 _swrast_fog_rgba_span( const GLcontext
*ctx
, struct sw_span
*span
)
82 const SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
83 const GLchan rFog
= swrast
->_FogColor
[RCOMP
];
84 const GLchan gFog
= swrast
->_FogColor
[GCOMP
];
85 const GLchan bFog
= swrast
->_FogColor
[BCOMP
];
86 const GLuint haveW
= (span
->interpMask
& SPAN_W
);
87 GLchan (*rgba
)[4] = (GLchan (*)[4]) span
->array
->rgba
;
89 ASSERT(swrast
->_FogEnabled
);
90 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_FOG
);
91 ASSERT(span
->arrayMask
& SPAN_RGBA
);
93 /* NOTE: if haveW is true, that means the fog start/step values are
94 * perspective-corrected and we have to divide each fog coord by W.
97 /* we need to compute fog blend factors */
98 if (swrast
->_PreferPixelFog
) {
99 /* The span's fog values are fog coordinates, now compute blend factors
100 * and blend the fragment colors with the fog color.
102 switch (ctx
->Fog
.Mode
) {
105 const GLfloat fogEnd
= ctx
->Fog
.End
;
106 const GLfloat fogScale
= (ctx
->Fog
.Start
== ctx
->Fog
.End
)
107 ? 1.0F
: 1.0F
/ (ctx
->Fog
.End
- ctx
->Fog
.Start
);
108 const GLfloat fogStep
= span
->fogStep
;
109 GLfloat fogCoord
= span
->fog
;
110 const GLfloat wStep
= haveW
? span
->dwdx
: 0.0F
;
111 GLfloat w
= haveW
? span
->w
: 1.0F
;
113 for (i
= 0; i
< span
->end
; i
++) {
114 GLfloat f
, oneMinusF
;
115 f
= (fogEnd
- fogCoord
/ w
) * fogScale
;
116 f
= CLAMP(f
, 0.0F
, 1.0F
);
117 oneMinusF
= 1.0F
- f
;
118 rgba
[i
][RCOMP
] = (GLchan
) (f
* rgba
[i
][RCOMP
] + oneMinusF
* rFog
);
119 rgba
[i
][GCOMP
] = (GLchan
) (f
* rgba
[i
][GCOMP
] + oneMinusF
* gFog
);
120 rgba
[i
][BCOMP
] = (GLchan
) (f
* rgba
[i
][BCOMP
] + oneMinusF
* bFog
);
128 const GLfloat density
= -ctx
->Fog
.Density
;
129 const GLfloat fogStep
= span
->fogStep
;
130 GLfloat fogCoord
= span
->fog
;
131 const GLfloat wStep
= haveW
? span
->dwdx
: 0.0F
;
132 GLfloat w
= haveW
? span
->w
: 1.0F
;
134 for (i
= 0; i
< span
->end
; i
++) {
135 GLfloat f
, oneMinusF
;
136 f
= (GLfloat
) exp(density
* fogCoord
/ w
);
137 f
= CLAMP(f
, 0.0F
, 1.0F
);
138 oneMinusF
= 1.0F
- f
;
139 rgba
[i
][RCOMP
] = (GLchan
) (f
* rgba
[i
][RCOMP
] + oneMinusF
* rFog
);
140 rgba
[i
][GCOMP
] = (GLchan
) (f
* rgba
[i
][GCOMP
] + oneMinusF
* gFog
);
141 rgba
[i
][BCOMP
] = (GLchan
) (f
* rgba
[i
][BCOMP
] + oneMinusF
* bFog
);
149 const GLfloat negDensitySquared
= -ctx
->Fog
.Density
* ctx
->Fog
.Density
;
150 const GLfloat fogStep
= span
->fogStep
;
151 GLfloat fogCoord
= span
->fog
;
152 const GLfloat wStep
= haveW
? span
->dwdx
: 0.0F
;
153 GLfloat w
= haveW
? span
->w
: 1.0F
;
155 for (i
= 0; i
< span
->end
; i
++) {
156 const GLfloat coord
= fogCoord
/ w
;
157 GLfloat tmp
= negDensitySquared
* coord
* coord
;
158 GLfloat f
, oneMinusF
;
159 #if defined(__alpha__) || defined(__alpha)
160 /* XXX this underflow check may be needed for other systems*/
161 if (tmp
< FLT_MIN_10_EXP
)
162 tmp
= FLT_MIN_10_EXP
;
164 f
= (GLfloat
) exp(tmp
);
165 f
= CLAMP(f
, 0.0F
, 1.0F
);
166 oneMinusF
= 1.0F
- f
;
167 rgba
[i
][RCOMP
] = (GLchan
) (f
* rgba
[i
][RCOMP
] + oneMinusF
* rFog
);
168 rgba
[i
][GCOMP
] = (GLchan
) (f
* rgba
[i
][GCOMP
] + oneMinusF
* gFog
);
169 rgba
[i
][BCOMP
] = (GLchan
) (f
* rgba
[i
][BCOMP
] + oneMinusF
* bFog
);
176 _mesa_problem(ctx
, "Bad fog mode in _swrast_fog_rgba_span");
180 else if (span
->arrayMask
& SPAN_FOG
) {
181 /* The span's fog array values are blend factors.
182 * They were previously computed per-vertex.
185 for (i
= 0; i
< span
->end
; i
++) {
186 const GLfloat f
= span
->array
->fog
[i
];
187 const GLfloat oneMinusF
= 1.0F
- f
;
188 rgba
[i
][RCOMP
] = (GLchan
) (f
* rgba
[i
][RCOMP
] + oneMinusF
* rFog
);
189 rgba
[i
][GCOMP
] = (GLchan
) (f
* rgba
[i
][GCOMP
] + oneMinusF
* gFog
);
190 rgba
[i
][BCOMP
] = (GLchan
) (f
* rgba
[i
][BCOMP
] + oneMinusF
* bFog
);
194 /* The span's fog start/step values are blend factors.
195 * They were previously computed per-vertex.
197 const GLfloat fogStep
= span
->fogStep
;
198 GLfloat fog
= span
->fog
;
199 const GLfloat wStep
= haveW
? span
->dwdx
: 0.0F
;
200 GLfloat w
= haveW
? span
->w
: 1.0F
;
202 ASSERT(span
->interpMask
& SPAN_FOG
);
203 for (i
= 0; i
< span
->end
; i
++) {
204 const GLfloat fact
= fog
/ w
;
205 const GLfloat oneMinusF
= 1.0F
- fact
;
206 rgba
[i
][RCOMP
] = (GLchan
) (fact
* rgba
[i
][RCOMP
] + oneMinusF
* rFog
);
207 rgba
[i
][GCOMP
] = (GLchan
) (fact
* rgba
[i
][GCOMP
] + oneMinusF
* gFog
);
208 rgba
[i
][BCOMP
] = (GLchan
) (fact
* rgba
[i
][BCOMP
] + oneMinusF
* bFog
);
217 * As above, but color index mode.
220 _swrast_fog_ci_span( const GLcontext
*ctx
, struct sw_span
*span
)
222 const SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
223 const GLuint haveW
= (span
->interpMask
& SPAN_W
);
224 const GLuint fogIndex
= (GLuint
) ctx
->Fog
.Index
;
225 GLuint
*index
= span
->array
->index
;
227 ASSERT(swrast
->_FogEnabled
);
228 ASSERT(span
->arrayMask
& SPAN_INDEX
);
229 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_FOG
);
231 /* we need to compute fog blend factors */
232 if (swrast
->_PreferPixelFog
) {
233 /* The span's fog values are fog coordinates, now compute blend factors
234 * and blend the fragment colors with the fog color.
236 switch (ctx
->Fog
.Mode
) {
239 const GLfloat fogEnd
= ctx
->Fog
.End
;
240 const GLfloat fogScale
= (ctx
->Fog
.Start
== ctx
->Fog
.End
)
241 ? 1.0F
: 1.0F
/ (ctx
->Fog
.End
- ctx
->Fog
.Start
);
242 const GLfloat fogStep
= span
->fogStep
;
243 GLfloat fogCoord
= span
->fog
;
244 const GLfloat wStep
= haveW
? span
->dwdx
: 0.0F
;
245 GLfloat w
= haveW
? span
->w
: 1.0F
;
247 for (i
= 0; i
< span
->end
; i
++) {
248 GLfloat f
= (fogEnd
- fogCoord
/ w
) * fogScale
;
249 f
= CLAMP(f
, 0.0F
, 1.0F
);
250 index
[i
] = (GLuint
) ((GLfloat
) index
[i
] + (1.0F
- f
) * fogIndex
);
258 const GLfloat density
= -ctx
->Fog
.Density
;
259 const GLfloat fogStep
= span
->fogStep
;
260 GLfloat fogCoord
= span
->fog
;
261 const GLfloat wStep
= haveW
? span
->dwdx
: 0.0F
;
262 GLfloat w
= haveW
? span
->w
: 1.0F
;
264 for (i
= 0; i
< span
->end
; i
++) {
265 GLfloat f
= (GLfloat
) exp(density
* fogCoord
/ w
);
266 f
= CLAMP(f
, 0.0F
, 1.0F
);
267 index
[i
] = (GLuint
) ((GLfloat
) index
[i
] + (1.0F
- f
) * fogIndex
);
275 const GLfloat negDensitySquared
= -ctx
->Fog
.Density
* ctx
->Fog
.Density
;
276 const GLfloat fogStep
= span
->fogStep
;
277 GLfloat fogCoord
= span
->fog
;
278 const GLfloat wStep
= haveW
? span
->dwdx
: 0.0F
;
279 GLfloat w
= haveW
? span
->w
: 1.0F
;
281 for (i
= 0; i
< span
->end
; i
++) {
282 const GLfloat coord
= fogCoord
/ w
;
283 GLfloat tmp
= negDensitySquared
* coord
* coord
;
285 #if defined(__alpha__) || defined(__alpha)
286 /* XXX this underflow check may be needed for other systems*/
287 if (tmp
< FLT_MIN_10_EXP
)
288 tmp
= FLT_MIN_10_EXP
;
290 f
= (GLfloat
) exp(tmp
);
291 f
= CLAMP(f
, 0.0F
, 1.0F
);
292 index
[i
] = (GLuint
) ((GLfloat
) index
[i
] + (1.0F
- f
) * fogIndex
);
299 _mesa_problem(ctx
, "Bad fog mode in _swrast_fog_ci_span");
303 else if (span
->arrayMask
& SPAN_FOG
) {
304 /* The span's fog array values are blend factors.
305 * They were previously computed per-vertex.
308 for (i
= 0; i
< span
->end
; i
++) {
309 const GLfloat f
= span
->array
->fog
[i
];
310 index
[i
] = (GLuint
) ((GLfloat
) index
[i
] + (1.0F
- f
) * fogIndex
);
314 /* The span's fog start/step values are blend factors.
315 * They were previously computed per-vertex.
317 const GLfloat fogStep
= span
->fogStep
;
318 GLfloat fog
= span
->fog
;
319 const GLfloat wStep
= haveW
? span
->dwdx
: 0.0F
;
320 GLfloat w
= haveW
? span
->w
: 1.0F
;
322 ASSERT(span
->interpMask
& SPAN_FOG
);
323 for (i
= 0; i
< span
->end
; i
++) {
324 const GLfloat f
= fog
/ w
;
325 index
[i
] = (GLuint
) ((GLfloat
) index
[i
] + (1.0F
- f
) * fogIndex
);