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
);
61 f
= (GLfloat
) exp(-(d
* d
* z
* z
));
64 _mesa_problem(ctx
, "Bad fog mode in _swrast_z_to_fogfactor");
71 * Apply fog to a span of RGBA pixels.
72 * The fog value are either in the span->array->fog array or interpolated from
73 * the fog/fogStep values.
74 * They fog values are either fog coordinates (Z) or fog blend factors.
75 * _PreferPixelFog should be in sync with that state!
78 _swrast_fog_rgba_span( const GLcontext
*ctx
, struct sw_span
*span
)
80 const SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
81 const GLchan rFog
= swrast
->_FogColor
[RCOMP
];
82 const GLchan gFog
= swrast
->_FogColor
[GCOMP
];
83 const GLchan bFog
= swrast
->_FogColor
[BCOMP
];
84 const GLuint haveW
= (span
->interpMask
& SPAN_W
);
85 GLchan (*rgba
)[4] = (GLchan (*)[4]) span
->array
->rgba
;
87 ASSERT(swrast
->_FogEnabled
);
88 ASSERT((span
->interpMask
| span
->arrayMask
) & SPAN_FOG
);
89 ASSERT(span
->arrayMask
& SPAN_RGBA
);
91 /* NOTE: if haveW is true, that means the fog start/step values are
92 * perspective-corrected and we have to divide each fog coord by W.
95 /* we need to compute fog blend factors */
96 if (swrast
->_PreferPixelFog
) {
97 /* The span's fog values are fog coordinates, now compute blend factors
98 * and blend the fragment colors with the fog color.
100 switch (ctx
->Fog
.Mode
) {
103 const GLfloat fogEnd
= ctx
->Fog
.End
;
104 const GLfloat fogScale
= (ctx
->Fog
.Start
== ctx
->Fog
.End
)
105 ? 1.0F
: 1.0F
/ (ctx
->Fog
.End
- ctx
->Fog
.Start
);
106 const GLfloat fogStep
= span
->fogStep
;
107 GLfloat fogCoord
= span
->fog
;
108 const GLfloat wStep
= haveW
? span
->dwdx
: 0.0F
;
109 GLfloat w
= haveW
? span
->w
: 1.0F
;
111 for (i
= 0; i
< span
->end
; i
++) {
112 GLfloat f
, oneMinusF
;
113 f
= (fogEnd
- FABSF(fogCoord
/w
)) * fogScale
;
114 f
= CLAMP(f
, 0.0F
, 1.0F
);
115 oneMinusF
= 1.0F
- f
;
116 rgba
[i
][RCOMP
] = (GLchan
) (f
* rgba
[i
][RCOMP
] + oneMinusF
* rFog
);
117 rgba
[i
][GCOMP
] = (GLchan
) (f
* rgba
[i
][GCOMP
] + oneMinusF
* gFog
);
118 rgba
[i
][BCOMP
] = (GLchan
) (f
* rgba
[i
][BCOMP
] + oneMinusF
* bFog
);
126 const GLfloat density
= -ctx
->Fog
.Density
;
127 const GLfloat fogStep
= span
->fogStep
;
128 GLfloat fogCoord
= span
->fog
;
129 const GLfloat wStep
= haveW
? span
->dwdx
: 0.0F
;
130 GLfloat w
= haveW
? span
->w
: 1.0F
;
132 for (i
= 0; i
< span
->end
; i
++) {
133 GLfloat f
, oneMinusF
;
134 f
= (GLfloat
) exp(density
* FABSF(fogCoord
/w
));
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
- FABSF(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
* FABSF(fogCoord
/w
));
263 index
[i
] = (GLuint
) ((GLfloat
) index
[i
] + (1.0F
- f
) * fogIndex
);
271 const GLfloat negDensitySquared
= -ctx
->Fog
.Density
* ctx
->Fog
.Density
;
272 const GLfloat fogStep
= span
->fogStep
;
273 GLfloat fogCoord
= span
->fog
;
274 const GLfloat wStep
= haveW
? span
->dwdx
: 0.0F
;
275 GLfloat w
= haveW
? span
->w
: 1.0F
;
277 for (i
= 0; i
< span
->end
; i
++) {
278 const GLfloat coord
= fogCoord
/ w
;
279 GLfloat tmp
= negDensitySquared
* coord
* coord
;
281 #if defined(__alpha__) || defined(__alpha)
282 /* XXX this underflow check may be needed for other systems*/
283 if (tmp
< FLT_MIN_10_EXP
)
284 tmp
= FLT_MIN_10_EXP
;
286 f
= (GLfloat
) exp(tmp
);
287 f
= CLAMP(f
, 0.0F
, 1.0F
);
288 index
[i
] = (GLuint
) ((GLfloat
) index
[i
] + (1.0F
- f
) * fogIndex
);
295 _mesa_problem(ctx
, "Bad fog mode in _swrast_fog_ci_span");
299 else if (span
->arrayMask
& SPAN_FOG
) {
300 /* The span's fog array values are blend factors.
301 * They were previously computed per-vertex.
304 for (i
= 0; i
< span
->end
; i
++) {
305 const GLfloat f
= span
->array
->fog
[i
];
306 index
[i
] = (GLuint
) ((GLfloat
) index
[i
] + (1.0F
- f
) * fogIndex
);
310 /* The span's fog start/step values are blend factors.
311 * They were previously computed per-vertex.
313 const GLfloat fogStep
= span
->fogStep
;
314 GLfloat fog
= span
->fog
;
315 const GLfloat wStep
= haveW
? span
->dwdx
: 0.0F
;
316 GLfloat w
= haveW
? span
->w
: 1.0F
;
318 ASSERT(span
->interpMask
& SPAN_FOG
);
319 for (i
= 0; i
< span
->end
; i
++) {
320 const GLfloat f
= fog
/ w
;
321 index
[i
] = (GLuint
) ((GLfloat
) index
[i
] + (1.0F
- f
) * fogIndex
);