1 /* $Id: s_fog.c,v 1.13 2001/06/18 23:55:18 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
);
63 f
= exp(-(d
* d
* z
* z
));
66 _mesa_problem(ctx
, "Bad fog mode in make_fog_coord");
74 * Apply fog to an array of RGBA pixels.
75 * Input: n - number of pixels
76 * fog - array of fog factors in [0,1]
77 * red, green, blue, alpha - pixel colors
78 * Output: red, green, blue, alpha - fogged pixel colors
81 _mesa_fog_rgba_pixels( const GLcontext
*ctx
,
87 GLchan rFog
, gFog
, bFog
;
89 UNCLAMPED_FLOAT_TO_CHAN(rFog
, ctx
->Fog
.Color
[RCOMP
]);
90 UNCLAMPED_FLOAT_TO_CHAN(gFog
, ctx
->Fog
.Color
[GCOMP
]);
91 UNCLAMPED_FLOAT_TO_CHAN(bFog
, ctx
->Fog
.Color
[BCOMP
]);
93 for (i
= 0; i
< n
; i
++) {
94 const GLfloat f
= fog
[i
];
95 const GLfloat g
= 1.0 - f
;
96 rgba
[i
][RCOMP
] = f
* rgba
[i
][RCOMP
] + g
* rFog
;
97 rgba
[i
][GCOMP
] = f
* rgba
[i
][GCOMP
] + g
* gFog
;
98 rgba
[i
][BCOMP
] = f
* rgba
[i
][BCOMP
] + g
* bFog
;
105 * Apply fog to an array of color index pixels.
106 * Input: n - number of pixels
107 * fog - array of fog factors in [0,1]
108 * index - pixel color indexes
109 * Output: index - fogged pixel color indexes
112 _mesa_fog_ci_pixels( const GLcontext
*ctx
,
113 GLuint n
, const GLfloat fog
[], GLuint index
[] )
115 GLuint idx
= (GLuint
) ctx
->Fog
.Index
;
118 for (i
= 0; i
< n
; i
++) {
119 const GLfloat f
= CLAMP(fog
[i
], 0.0, 1.0);
120 index
[i
] = (GLuint
) ((GLfloat
) index
[i
] + (1.0F
- f
) * idx
);
127 * Calculate fog factors (in [0,1]) from window z values
128 * Input: n - number of pixels
129 * z - array of integer depth values
130 * red, green, blue, alpha - pixel colors
131 * Output: red, green, blue, alpha - fogged pixel colors
133 * Use lookup table & interpolation?
136 compute_fog_factors_from_z( const GLcontext
*ctx
,
141 const GLboolean ortho
= (ctx
->ProjectionMatrix
.m
[15] != 0.0F
);
142 const GLfloat p10
= ctx
->ProjectionMatrix
.m
[10];
143 const GLfloat p14
= ctx
->ProjectionMatrix
.m
[14];
144 const GLfloat tz
= ctx
->Viewport
._WindowMap
.m
[MAT_TZ
];
148 if (ctx
->Viewport
._WindowMap
.m
[MAT_SZ
] == 0.0)
151 szInv
= 1.0F
/ ctx
->Viewport
._WindowMap
.m
[MAT_SZ
];
154 * Note: to compute eyeZ from the ndcZ we have to solve the following:
156 * p[10] * eyeZ + p[14] * eyeW
157 * ndcZ = ---------------------------
158 * p[11] * eyeZ + p[15] * eyeW
162 * p[14] * eyeW - p[15] * eyeW * ndcZ
163 * eyeZ = ----------------------------------
164 * p[11] * ndcZ - p[10]
167 * a) if using an orthographic projection, p[11] = 0 and p[15] = 1.
168 * b) if using a perspective projection, p[11] = -1 and p[15] = 0.
169 * c) we assume eyeW = 1 (not always true- glVertex4)
171 * Then we can simplify the calculation of eyeZ quite a bit. We do
172 * separate calculations for the orthographic and perspective cases below.
173 * Note that we drop a negative sign or two since they don't matter.
176 switch (ctx
->Fog
.Mode
) {
179 GLfloat fogEnd
= ctx
->Fog
.End
;
181 if (ctx
->Fog
.Start
== ctx
->Fog
.End
)
184 fogScale
= 1.0F
/ (ctx
->Fog
.End
- ctx
->Fog
.Start
);
187 GLfloat ndcz
= ((GLfloat
) z
[i
] - tz
) * szInv
;
188 GLfloat eyez
= (ndcz
- p14
) / p10
;
191 fogFact
[i
] = (fogEnd
- eyez
) * fogScale
;
197 GLfloat ndcz
= ((GLfloat
) z
[i
] - tz
) * szInv
;
198 GLfloat eyez
= p14
/ (ndcz
+ p10
);
201 fogFact
[i
] = (fogEnd
- eyez
) * fogScale
;
209 GLfloat ndcz
= ((GLfloat
) z
[i
] - tz
) * szInv
;
210 GLfloat eyez
= (ndcz
- p14
) / p10
;
213 fogFact
[i
] = exp( -ctx
->Fog
.Density
* eyez
);
219 GLfloat ndcz
= ((GLfloat
) z
[i
] - tz
) * szInv
;
220 GLfloat eyez
= p14
/ (ndcz
+ p10
);
223 fogFact
[i
] = exp( -ctx
->Fog
.Density
* eyez
);
229 GLfloat negDensitySquared
= -ctx
->Fog
.Density
* ctx
->Fog
.Density
;
232 GLfloat ndcz
= ((GLfloat
) z
[i
] - tz
) * szInv
;
233 GLfloat eyez
= (ndcz
- p14
) / p10
;
234 GLfloat tmp
= negDensitySquared
* eyez
* eyez
;
235 #if defined(__alpha__) || defined(__alpha)
236 /* XXX this underflow check may be needed for other systems*/
237 if (tmp
< FLT_MIN_10_EXP
)
238 tmp
= FLT_MIN_10_EXP
;
240 fogFact
[i
] = exp( tmp
);
246 GLfloat ndcz
= ((GLfloat
) z
[i
] - tz
) * szInv
;
247 GLfloat eyez
= p14
/ (ndcz
+ p10
);
248 GLfloat tmp
= negDensitySquared
* eyez
* eyez
;
249 #if defined(__alpha__) || defined(__alpha)
250 /* XXX this underflow check may be needed for other systems*/
251 if (tmp
< FLT_MIN_10_EXP
)
252 tmp
= FLT_MIN_10_EXP
;
254 fogFact
[i
] = exp( tmp
);
260 _mesa_problem(ctx
, "Bad fog mode in compute_fog_factors_from_z");
267 * Apply fog to an array of RGBA pixels.
268 * Input: n - number of pixels
269 * z - array of integer depth values
270 * red, green, blue, alpha - pixel colors
271 * Output: red, green, blue, alpha - fogged pixel colors
274 _mesa_depth_fog_rgba_pixels( const GLcontext
*ctx
,
275 GLuint n
, const GLdepth z
[], GLchan rgba
[][4] )
277 GLfloat fogFact
[PB_SIZE
];
278 ASSERT(n
<= PB_SIZE
);
279 compute_fog_factors_from_z( ctx
, n
, z
, fogFact
);
280 _mesa_fog_rgba_pixels( ctx
, n
, fogFact
, rgba
);
285 * Apply fog to an array of color index pixels.
286 * Input: n - number of pixels
287 * z - array of integer depth values
288 * index - pixel color indexes
289 * Output: index - fogged pixel color indexes
292 _mesa_depth_fog_ci_pixels( const GLcontext
*ctx
,
293 GLuint n
, const GLdepth z
[], GLuint index
[] )
295 GLfloat fogFact
[PB_SIZE
];
296 ASSERT(n
<= PB_SIZE
);
297 compute_fog_factors_from_z( ctx
, n
, z
, fogFact
);
298 _mesa_fog_ci_pixels( ctx
, n
, fogFact
, index
);