1 /* $Id: s_fog.c,v 1.18 2002/01/27 18:32:03 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 #include "s_context.h"
42 * Used to convert current raster distance to a fog factor in [0,1].
45 _mesa_z_to_fogfactor(GLcontext
*ctx
, GLfloat z
)
49 switch (ctx
->Fog
.Mode
) {
51 if (ctx
->Fog
.Start
== ctx
->Fog
.End
)
54 d
= 1.0F
/ (ctx
->Fog
.End
- ctx
->Fog
.Start
);
55 f
= (ctx
->Fog
.End
- z
) * d
;
56 return CLAMP(f
, 0.0F
, 1.0F
);
59 f
= (GLfloat
) exp(-d
* z
);
63 f
= (GLfloat
) exp(-(d
* d
* z
* z
));
66 _mesa_problem(ctx
, "Bad fog mode in make_fog_coord");
74 * Apply fog to a span of RGBA pixels.
76 * span - where span->fog and span->fogStep have to be set.
77 * red, green, blue, alpha - pixel colors
78 * Output: red, green, blue, alpha - fogged pixel colors
81 _mesa_fog_rgba_pixels( const GLcontext
*ctx
, struct sw_span
*span
,
85 GLfloat fog
= span
->fog
, Dfog
= span
->fogStep
;
86 GLchan rFog
, gFog
, bFog
;
88 /* printf("%s\n", __FUNCTION__);*/
89 ASSERT(ctx
->Fog
.Enabled
);
90 ASSERT(span
->interpMask
& SPAN_FOG
);
91 ASSERT(span
->filledColor
== GL_TRUE
|| (span
->arrayMask
& SPAN_RGBA
));
93 UNCLAMPED_FLOAT_TO_CHAN(rFog
, ctx
->Fog
.Color
[RCOMP
]);
94 UNCLAMPED_FLOAT_TO_CHAN(gFog
, ctx
->Fog
.Color
[GCOMP
]);
95 UNCLAMPED_FLOAT_TO_CHAN(bFog
, ctx
->Fog
.Color
[BCOMP
]);
97 for (i
= 0; i
< span
->end
; i
++) {
98 const GLfloat one_min_fog
= 1.0F
- fog
;
99 rgba
[i
][RCOMP
] = (GLchan
) (fog
* rgba
[i
][RCOMP
] + one_min_fog
* rFog
);
100 rgba
[i
][GCOMP
] = (GLchan
) (fog
* rgba
[i
][GCOMP
] + one_min_fog
* gFog
);
101 rgba
[i
][BCOMP
] = (GLchan
) (fog
* rgba
[i
][BCOMP
] + one_min_fog
* bFog
);
108 * Apply fog given in an array to RGBA pixels.
111 * fog - array of fog factors in [0,1]
112 * red, green, blue, alpha - pixel colors
113 * Output: red, green, blue, alpha - fogged pixel colors
116 _mesa_fog_rgba_pixels_with_array( const GLcontext
*ctx
, struct sw_span
*span
,
117 const GLfloat fog
[], GLchan rgba
[][4] )
120 GLchan rFog
, gFog
, bFog
;
122 /* printf("%s\n", __FUNCTION__);*/
124 ASSERT(ctx
->Fog
.Enabled
);
125 ASSERT(span
->filledColor
== GL_TRUE
|| (span
->arrayMask
& SPAN_RGBA
));
127 UNCLAMPED_FLOAT_TO_CHAN(rFog
, ctx
->Fog
.Color
[RCOMP
]);
128 UNCLAMPED_FLOAT_TO_CHAN(gFog
, ctx
->Fog
.Color
[GCOMP
]);
129 UNCLAMPED_FLOAT_TO_CHAN(bFog
, ctx
->Fog
.Color
[BCOMP
]);
131 for (i
= span
->start
; i
< span
->end
; i
++) {
132 const GLfloat f
= fog
[i
];
133 const GLfloat g
= 1.0F
- f
;
134 rgba
[i
][RCOMP
] = (GLchan
) (f
* rgba
[i
][RCOMP
] + g
* rFog
);
135 rgba
[i
][GCOMP
] = (GLchan
) (f
* rgba
[i
][GCOMP
] + g
* gFog
);
136 rgba
[i
][BCOMP
] = (GLchan
) (f
* rgba
[i
][BCOMP
] + g
* bFog
);
141 * Apply fog to an array of RGBA pixels.
142 * Input: n - number of pixels
143 * fog - array of fog factors in [0,1]
144 * red, green, blue, alpha - pixel colors
145 * Output: red, green, blue, alpha - fogged pixel colors
148 _old_fog_rgba_pixels( const GLcontext
*ctx
,
154 GLchan rFog
, gFog
, bFog
;
156 /* printf("%s\n", __FUNCTION__);*/
157 UNCLAMPED_FLOAT_TO_CHAN(rFog
, ctx
->Fog
.Color
[RCOMP
]);
158 UNCLAMPED_FLOAT_TO_CHAN(gFog
, ctx
->Fog
.Color
[GCOMP
]);
159 UNCLAMPED_FLOAT_TO_CHAN(bFog
, ctx
->Fog
.Color
[BCOMP
]);
161 for (i
= 0; i
< n
; i
++) {
162 const GLfloat f
= fog
[i
];
163 const GLfloat g
= 1.0F
- f
;
164 rgba
[i
][RCOMP
] = (GLchan
) (f
* rgba
[i
][RCOMP
] + g
* rFog
);
165 rgba
[i
][GCOMP
] = (GLchan
) (f
* rgba
[i
][GCOMP
] + g
* gFog
);
166 rgba
[i
][BCOMP
] = (GLchan
) (f
* rgba
[i
][BCOMP
] + g
* bFog
);
172 * Apply fog to a span of color index pixels.
174 * span - where span->fog and span->fogStep have to be set.
175 * index - pixel color indexes
176 * Output: index - fogged pixel color indexes
179 _mesa_fog_ci_pixels( const GLcontext
*ctx
, struct sw_span
*span
,
182 GLuint idx
= (GLuint
) ctx
->Fog
.Index
;
184 GLfloat fog
= span
->fog
, Dfog
= span
->fogStep
;
186 ASSERT(ctx
->Fog
.Enabled
);
187 ASSERT(span
->interpMask
& SPAN_FOG
);
188 ASSERT(span
->interpMask
& SPAN_INDEX
);
190 for (i
= 0; i
< span
->end
; i
++) {
191 const GLfloat f
= CLAMP(fog
, 0.0F
, 1.0F
);
192 index
[i
] = (GLuint
) ((GLfloat
) index
[i
] + (1.0F
- f
) * idx
);
199 * Apply fog given in an array to a span of color index pixels.
202 * fog - array of fog factors in [0,1]
203 * index - pixel color indexes
204 * Output: index - fogged pixel color indexes
207 _mesa_fog_ci_pixels_with_array( const GLcontext
*ctx
, struct sw_span
*span
,
208 const GLfloat fog
[], GLuint index
[] )
210 GLuint idx
= (GLuint
) ctx
->Fog
.Index
;
214 ASSERT(ctx
->Fog
.Enabled
);
215 ASSERT((span
->filledColor
== GL_TRUE
) || (span
->arrayMask
& SPAN_INDEX
));
217 for (i
= span
->start
; i
< span
->end
; i
++) {
218 const GLfloat f
= CLAMP(fog
[i
], 0.0F
, 1.0F
);
219 index
[i
] = (GLuint
) ((GLfloat
) index
[i
] + (1.0F
- f
) * idx
);
224 * Apply fog to an array of color index pixels.
225 * Input: n - number of pixels
226 * fog - array of fog factors in [0,1]
227 * index - pixel color indexes
228 * Output: index - fogged pixel color indexes
231 _old_fog_ci_pixels( const GLcontext
*ctx
,
232 GLuint n
, const GLfloat fog
[], GLuint index
[] )
234 GLuint idx
= (GLuint
) ctx
->Fog
.Index
;
237 for (i
= 0; i
< n
; i
++) {
238 const GLfloat f
= CLAMP(fog
[i
], 0.0F
, 1.0F
);
239 index
[i
] = (GLuint
) ((GLfloat
) index
[i
] + (1.0F
- f
) * idx
);
246 * Calculate fog factors (in [0,1]) from window z values
247 * Input: n - number of pixels
248 * z - array of integer depth values
249 * red, green, blue, alpha - pixel colors
250 * Output: red, green, blue, alpha - fogged pixel colors
252 * Use lookup table & interpolation?
255 compute_fog_factors_from_z( const GLcontext
*ctx
,
260 const GLfloat
*proj
= ctx
->ProjectionMatrixStack
.Top
->m
;
261 const GLboolean ortho
= (proj
[15] != 0.0F
);
262 const GLfloat p10
= proj
[10];
263 const GLfloat p14
= proj
[14];
264 const GLfloat tz
= ctx
->Viewport
._WindowMap
.m
[MAT_TZ
];
268 if (ctx
->Viewport
._WindowMap
.m
[MAT_SZ
] == 0.0)
271 szInv
= 1.0F
/ ctx
->Viewport
._WindowMap
.m
[MAT_SZ
];
274 * Note: to compute eyeZ from the ndcZ we have to solve the following:
276 * p[10] * eyeZ + p[14] * eyeW
277 * ndcZ = ---------------------------
278 * p[11] * eyeZ + p[15] * eyeW
282 * p[14] * eyeW - p[15] * eyeW * ndcZ
283 * eyeZ = ----------------------------------
284 * p[11] * ndcZ - p[10]
287 * a) if using an orthographic projection, p[11] = 0 and p[15] = 1.
288 * b) if using a perspective projection, p[11] = -1 and p[15] = 0.
289 * c) we assume eyeW = 1 (not always true- glVertex4)
291 * Then we can simplify the calculation of eyeZ quite a bit. We do
292 * separate calculations for the orthographic and perspective cases below.
293 * Note that we drop a negative sign or two since they don't matter.
296 switch (ctx
->Fog
.Mode
) {
299 GLfloat fogEnd
= ctx
->Fog
.End
;
301 if (ctx
->Fog
.Start
== ctx
->Fog
.End
)
304 fogScale
= 1.0F
/ (ctx
->Fog
.End
- ctx
->Fog
.Start
);
307 GLfloat ndcz
= ((GLfloat
) z
[i
] - tz
) * szInv
;
308 GLfloat eyez
= (ndcz
- p14
) / p10
;
311 fogFact
[i
] = (fogEnd
- eyez
) * fogScale
;
317 GLfloat ndcz
= ((GLfloat
) z
[i
] - tz
) * szInv
;
318 GLfloat eyez
= p14
/ (ndcz
+ p10
);
321 fogFact
[i
] = (fogEnd
- eyez
) * fogScale
;
329 GLfloat ndcz
= ((GLfloat
) z
[i
] - tz
) * szInv
;
330 GLfloat eyez
= (ndcz
- p14
) / p10
;
333 fogFact
[i
] = (GLfloat
) exp( -ctx
->Fog
.Density
* eyez
);
339 GLfloat ndcz
= ((GLfloat
) z
[i
] - tz
) * szInv
;
340 GLfloat eyez
= p14
/ (ndcz
+ p10
);
343 fogFact
[i
] = (GLfloat
) exp( -ctx
->Fog
.Density
* eyez
);
349 GLfloat negDensitySquared
= -ctx
->Fog
.Density
* ctx
->Fog
.Density
;
352 GLfloat ndcz
= ((GLfloat
) z
[i
] - tz
) * szInv
;
353 GLfloat eyez
= (ndcz
- p14
) / p10
;
354 GLfloat tmp
= negDensitySquared
* eyez
* eyez
;
355 #if defined(__alpha__) || defined(__alpha)
356 /* XXX this underflow check may be needed for other systems*/
357 if (tmp
< FLT_MIN_10_EXP
)
358 tmp
= FLT_MIN_10_EXP
;
360 fogFact
[i
] = (GLfloat
) exp( tmp
);
366 GLfloat ndcz
= ((GLfloat
) z
[i
] - tz
) * szInv
;
367 GLfloat eyez
= p14
/ (ndcz
+ p10
);
368 GLfloat tmp
= negDensitySquared
* eyez
* eyez
;
369 #if defined(__alpha__) || defined(__alpha)
370 /* XXX this underflow check may be needed for other systems*/
371 if (tmp
< FLT_MIN_10_EXP
)
372 tmp
= FLT_MIN_10_EXP
;
374 fogFact
[i
] = (GLfloat
) exp( tmp
);
380 _mesa_problem(ctx
, "Bad fog mode in compute_fog_factors_from_z");
387 * Apply fog to a span of RGBA pixels.
389 * span - where span->zArray has to be filled.
390 * red, green, blue, alpha - pixel colors
391 * Output: red, green, blue, alpha - fogged pixel colors
394 _mesa_depth_fog_rgba_pixels(const GLcontext
*ctx
, struct sw_span
*span
,
397 GLfloat fogFact
[PB_SIZE
];
399 /* printf("%s\n", __FUNCTION__);*/
400 ASSERT(ctx
->Fog
.Enabled
);
401 ASSERT(span
->arrayMask
& SPAN_Z
);
402 ASSERT(span
->end
<= PB_SIZE
);
403 ASSERT((span
->filledDepth
) == GL_TRUE
|| (span
->arrayMask
& SPAN_Z
));
405 compute_fog_factors_from_z(ctx
, span
->end
, span
->zArray
, fogFact
);
406 _mesa_fog_rgba_pixels_with_array( ctx
, span
, fogFact
, rgba
);
411 * Apply fog to an array of RGBA pixels.
412 * Input: n - number of pixels
413 * z - array of integer depth values
414 * red, green, blue, alpha - pixel colors
415 * Output: red, green, blue, alpha - fogged pixel colors
418 _old_depth_fog_rgba_pixels( const GLcontext
*ctx
,
419 GLuint n
, const GLdepth z
[], GLchan rgba
[][4] )
421 GLfloat fogFact
[PB_SIZE
];
422 ASSERT(n
<= PB_SIZE
);
423 /* printf("%s\n", __FUNCTION__);*/
424 compute_fog_factors_from_z( ctx
, n
, z
, fogFact
);
425 _old_fog_rgba_pixels( ctx
, n
, fogFact
, rgba
);
430 * Apply fog to a span of color index pixels.
432 * span - where span->zArray has to be filled.
433 * index - pixel color indexes
434 * Output: index - fogged pixel color indexes
437 _mesa_depth_fog_ci_pixels( const GLcontext
*ctx
, struct sw_span
*span
,
440 GLfloat fogFact
[PB_SIZE
];
442 ASSERT(ctx
->Fog
.Enabled
);
443 ASSERT(span
->arrayMask
& SPAN_Z
);
444 ASSERT(span
->end
<= PB_SIZE
);
445 ASSERT((span
->filledDepth
== GL_TRUE
) || (span
->arrayMask
& SPAN_Z
));
447 compute_fog_factors_from_z(ctx
, span
->end
, span
->zArray
, fogFact
);
448 _mesa_fog_ci_pixels_with_array( ctx
, span
, fogFact
, index
);
453 * Apply fog to an array of color index pixels.
454 * Input: n - number of pixels
455 * z - array of integer depth values
456 * index - pixel color indexes
457 * Output: index - fogged pixel color indexes
460 _old_depth_fog_ci_pixels( const GLcontext
*ctx
,
461 GLuint n
, const GLdepth z
[], GLuint index
[] )
463 GLfloat fogFact
[PB_SIZE
];
464 ASSERT(n
<= PB_SIZE
);
465 compute_fog_factors_from_z( ctx
, n
, z
, fogFact
);
466 _old_fog_ci_pixels( ctx
, n
, fogFact
, index
);