1 /* $Id: fog.c,v 1.9 1997/07/24 01:25:01 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 2.4
6 * Copyright (C) 1995-1996 Brian Paul
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the Free
20 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23
24 /*
25 * $Log: fog.c,v $
26 * Revision 1.9 1997/07/24 01:25:01 brianp
27 * changed precompiled header symbol from PCH to PC_HEADER
28 *
29 * Revision 1.8 1997/06/20 04:14:47 brianp
30 * changed color components from GLfixed to GLubyte
31 *
32 * Revision 1.7 1997/05/28 03:24:54 brianp
33 * added precompiled header (PCH) support
34 *
35 * Revision 1.6 1997/05/22 03:03:47 brianp
36 * don't apply fog to alpha values
37 *
38 * Revision 1.5 1997/04/20 20:28:49 brianp
39 * replaced abort() with gl_problem()
40 *
41 * Revision 1.4 1996/11/04 02:30:15 brianp
42 * optimized gl_fog_color_pixels() and gl_fog_index_pixels()
43 *
44 * Revision 1.3 1996/09/27 01:26:52 brianp
45 * added missing default cases to switches
46 *
47 * Revision 1.2 1996/09/15 14:17:30 brianp
48 * now use GLframebuffer and GLvisual
49 *
50 * Revision 1.1 1996/09/13 01:38:16 brianp
51 * Initial revision
52 *
53 */
54
55
56 #ifdef PC_HEADER
57 #include "all.h"
58 #else
59 #include <math.h>
60 #include <stdlib.h>
61 #include "context.h"
62 #include "fog.h"
63 #include "dlist.h"
64 #include "macros.h"
65 #include "types.h"
66 #endif
67
68
69
gl_Fogfv(GLcontext * ctx,GLenum pname,const GLfloat * params)70 void gl_Fogfv( GLcontext *ctx, GLenum pname, const GLfloat *params )
71 {
72 GLenum m;
73
74 switch (pname) {
75 case GL_FOG_MODE:
76 m = (GLenum) (GLint) *params;
77 if (m==GL_LINEAR || m==GL_EXP || m==GL_EXP2) {
78 ctx->Fog.Mode = m;
79 }
80 else {
81 gl_error( ctx, GL_INVALID_ENUM, "glFog" );
82 }
83 break;
84 case GL_FOG_DENSITY:
85 if (*params<0.0) {
86 gl_error( ctx, GL_INVALID_VALUE, "glFog" );
87 }
88 else {
89 ctx->Fog.Density = *params;
90 }
91 break;
92 case GL_FOG_START:
93 #ifndef GL_VERSION_1_1
94 if (*params<0.0F) {
95 gl_error( ctx, GL_INVALID_VALUE, "glFog(GL_FOG_START)" );
96 return;
97 }
98 #endif
99 ctx->Fog.Start = *params;
100 break;
101 case GL_FOG_END:
102 #ifndef GL_VERSION_1_1
103 if (*params<0.0F) {
104 gl_error( ctx, GL_INVALID_VALUE, "glFog(GL_FOG_END)" );
105 return;
106 }
107 #endif
108 ctx->Fog.End = *params;
109 break;
110 case GL_FOG_INDEX:
111 ctx->Fog.Index = *params;
112 break;
113 case GL_FOG_COLOR:
114 ctx->Fog.Color[0] = params[0];
115 ctx->Fog.Color[1] = params[1];
116 ctx->Fog.Color[2] = params[2];
117 ctx->Fog.Color[3] = params[3];
118 break;
119 default:
120 gl_error( ctx, GL_INVALID_ENUM, "glFog" );
121 }
122 }
123
124
125
126
127 /*
128 * Compute the fogged color for an array of vertices.
129 * Input: n - number of vertices
130 * v - array of vertices
131 * color - the original vertex colors
132 * Output: color - the fogged colors
133 */
gl_fog_color_vertices(GLcontext * ctx,GLuint n,GLfloat v[][4],GLubyte color[][4])134 void gl_fog_color_vertices( GLcontext *ctx,
135 GLuint n, GLfloat v[][4], GLubyte color[][4] )
136 {
137 GLuint i;
138 GLfloat d;
139 GLfloat fogr = ctx->Fog.Color[0] * ctx->Visual->RedScale;
140 GLfloat fogg = ctx->Fog.Color[1] * ctx->Visual->GreenScale;
141 GLfloat fogb = ctx->Fog.Color[2] * ctx->Visual->BlueScale;
142 GLfloat end = ctx->Fog.End;
143
144 switch (ctx->Fog.Mode) {
145 case GL_LINEAR:
146 d = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
147 for (i=0;i<n;i++) {
148 GLfloat f = (end - ABSF(v[i][2])) * d;
149 f = CLAMP( f, 0.0F, 1.0F );
150 color[i][0] = f * color[i][0] + (1.0F-f) * fogr;
151 color[i][1] = f * color[i][1] + (1.0F-f) * fogg;
152 color[i][2] = f * color[i][2] + (1.0F-f) * fogb;
153 }
154 break;
155 case GL_EXP:
156 d = -ctx->Fog.Density;
157 for (i=0;i<n;i++) {
158 GLfloat f = exp( d * ABSF(v[i][2]) );
159 f = CLAMP( f, 0.0F, 1.0F );
160 color[i][0] = f * color[i][0] + (1.0F-f) * fogr;
161 color[i][1] = f * color[i][1] + (1.0F-f) * fogg;
162 color[i][2] = f * color[i][2] + (1.0F-f) * fogb;
163 }
164 break;
165 case GL_EXP2:
166 d = -(ctx->Fog.Density*ctx->Fog.Density);
167 for (i=0;i<n;i++) {
168 GLfloat z = ABSF(v[i][2]);
169 GLfloat f = exp( d * z*z );
170 f = CLAMP( f, 0.0F, 1.0F );
171 color[i][0] = f * color[i][0] + (1.0F-f) * fogr;
172 color[i][1] = f * color[i][1] + (1.0F-f) * fogg;
173 color[i][2] = f * color[i][2] + (1.0F-f) * fogb;
174 }
175 break;
176 default:
177 gl_problem(ctx, "Bad fog mode in gl_fog_color_vertices");
178 return;
179 }
180 }
181
182
183
184 /*
185 * Compute the fogged color indexes for an array of vertices.
186 * Input: n - number of vertices
187 * v - array of vertices
188 * In/Out: indx - array of vertex color indexes
189 */
gl_fog_index_vertices(GLcontext * ctx,GLuint n,GLfloat v[][4],GLuint indx[])190 void gl_fog_index_vertices( GLcontext *ctx,
191 GLuint n, GLfloat v[][4], GLuint indx[] )
192 {
193 /* NOTE: the extensive use of casts generates better/faster code for MIPS */
194 switch (ctx->Fog.Mode) {
195 case GL_LINEAR:
196 {
197 GLfloat d = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
198 GLfloat fogindex = ctx->Fog.Index;
199 GLfloat fogend = ctx->Fog.End;
200 GLuint i;
201 for (i=0;i<n;i++) {
202 GLfloat f = (fogend - ABSF(v[i][2])) * d;
203 f = CLAMP( f, 0.0F, 1.0F );
204 indx[i] = (GLint)
205 ((GLfloat) (GLint) indx[i] + (1.0F-f) * fogindex);
206 }
207 }
208 break;
209 case GL_EXP:
210 {
211 GLfloat d = -ctx->Fog.Density;
212 GLfloat fogindex = ctx->Fog.Index;
213 GLuint i;
214 for (i=0;i<n;i++) {
215 GLfloat f = exp( d * ABSF(v[i][2]) );
216 f = CLAMP( f, 0.0F, 1.0F );
217 indx[i] = (GLint)
218 ((GLfloat) (GLint) indx[i] + (1.0F-f) * fogindex);
219 }
220 }
221 break;
222 case GL_EXP2:
223 {
224 GLfloat d = -(ctx->Fog.Density*ctx->Fog.Density);
225 GLfloat fogindex = ctx->Fog.Index;
226 GLuint i;
227 for (i=0;i<n;i++) {
228 GLfloat z = ABSF(v[i][2]);
229 GLfloat f = exp( -d * z*z );
230 f = CLAMP( f, 0.0F, 1.0F );
231 indx[i] = (GLint)
232 ((GLfloat) (GLint) indx[i] + (1.0F-f) * fogindex);
233 }
234 }
235 break;
236 default:
237 gl_problem(ctx, "Bad fog mode in gl_fog_index_vertices");
238 return;
239 }
240 }
241
242
243
244
245 /*
246 * Apply fog to an array of RGBA pixels.
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
251 */
gl_fog_color_pixels(GLcontext * ctx,GLuint n,const GLdepth z[],GLubyte red[],GLubyte green[],GLubyte blue[],GLubyte alpha[])252 void gl_fog_color_pixels( GLcontext *ctx,
253 GLuint n, const GLdepth z[], GLubyte red[],
254 GLubyte green[], GLubyte blue[], GLubyte alpha[] )
255 {
256 GLfloat c = ctx->ProjectionMatrix[10];
257 GLfloat d = ctx->ProjectionMatrix[14];
258 GLuint i;
259
260 GLfloat fog_red = ctx->Fog.Color[0] * ctx->Visual->RedScale;
261 GLfloat fog_green = ctx->Fog.Color[1] * ctx->Visual->GreenScale;
262 GLfloat fog_blue = ctx->Fog.Color[2] * ctx->Visual->BlueScale;
263
264 GLfloat tz = ctx->Viewport.Tz;
265 GLfloat szInv = 1.0F / ctx->Viewport.Sz;
266
267 switch (ctx->Fog.Mode) {
268 case GL_LINEAR:
269 {
270 GLfloat fogEnd = ctx->Fog.End;
271 GLfloat fogScale = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
272 for (i=0;i<n;i++) {
273 GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
274 GLfloat eyez = -d / (c+ndcz);
275 GLfloat f, g;
276 if (eyez < 0.0) eyez = -eyez;
277 f = (fogEnd - eyez) * fogScale;
278 f = CLAMP( f, 0.0F, 1.0F );
279 g = 1.0F - f;
280 red[i] = (GLint) (f * (GLfloat) red[i] + g * fog_red);
281 green[i] = (GLint) (f * (GLfloat) green[i] + g * fog_green);
282 blue[i] = (GLint) (f * (GLfloat) blue[i] + g * fog_blue);
283 }
284 }
285 break;
286 case GL_EXP:
287 for (i=0;i<n;i++) {
288 GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
289 GLfloat eyez = -d / (c+ndcz);
290 GLfloat f, g;
291 if (eyez < 0.0) eyez = -eyez;
292 f = exp( -ctx->Fog.Density * eyez );
293 f = CLAMP( f, 0.0F, 1.0F );
294 g = 1.0F - f;
295 red[i] = (GLint) (f * (GLfloat) red[i] + g * fog_red);
296 green[i] = (GLint) (f * (GLfloat) green[i] + g * fog_green);
297 blue[i] = (GLint) (f * (GLfloat) blue[i] + g * fog_blue);
298 }
299 break;
300 case GL_EXP2:
301 {
302 GLfloat negDensitySquared = -ctx->Fog.Density * ctx->Fog.Density;
303 for (i=0;i<n;i++) {
304 GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
305 GLfloat eyez = -d / (c+ndcz);
306 GLfloat f, g;
307 if (eyez < 0.0) eyez = -eyez;
308 f = exp( negDensitySquared * eyez*eyez );
309 f = CLAMP( f, 0.0F, 1.0F );
310 g = 1.0F - f;
311 red[i] = (GLint) (f * (GLfloat) red[i] + g * fog_red);
312 green[i] = (GLint) (f * (GLfloat) green[i] + g * fog_green);
313 blue[i] = (GLint) (f * (GLfloat) blue[i] + g * fog_blue);
314 }
315 }
316 break;
317 default:
318 gl_problem(ctx, "Bad fog mode in gl_fog_color_pixels");
319 return;
320 }
321 }
322
323
324
325
326 /*
327 * Apply fog to an array of color index pixels.
328 * Input: n - number of pixels
329 * z - array of integer depth values
330 * index - pixel color indexes
331 * Output: index - fogged pixel color indexes
332 */
gl_fog_index_pixels(GLcontext * ctx,GLuint n,const GLdepth z[],GLuint index[])333 void gl_fog_index_pixels( GLcontext *ctx,
334 GLuint n, const GLdepth z[], GLuint index[] )
335 {
336 GLfloat c = ctx->ProjectionMatrix[10];
337 GLfloat d = ctx->ProjectionMatrix[14];
338 GLuint i;
339
340 GLfloat tz = ctx->Viewport.Tz;
341 GLfloat szInv = 1.0F / ctx->Viewport.Sz;
342
343 switch (ctx->Fog.Mode) {
344 case GL_LINEAR:
345 {
346 GLfloat fogEnd = ctx->Fog.End;
347 GLfloat fogScale = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
348 for (i=0;i<n;i++) {
349 GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
350 GLfloat eyez = -d / (c+ndcz);
351 GLfloat f;
352 if (eyez < 0.0) eyez = -eyez;
353 f = (fogEnd - eyez) * fogScale;
354 f = CLAMP( f, 0.0F, 1.0F );
355 index[i] = (GLuint) ((GLfloat) index[i] + (1.0F-f) * ctx->Fog.Index);
356 }
357 }
358 break;
359 case GL_EXP:
360 for (i=0;i<n;i++) {
361 GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
362 GLfloat eyez = -d / (c+ndcz);
363 GLfloat f;
364 if (eyez < 0.0) eyez = -eyez;
365 f = exp( -ctx->Fog.Density * eyez );
366 f = CLAMP( f, 0.0F, 1.0F );
367 index[i] = (GLuint) ((GLfloat) index[i] + (1.0F-f) * ctx->Fog.Index);
368 }
369 break;
370 case GL_EXP2:
371 {
372 GLfloat negDensitySquared = -ctx->Fog.Density * ctx->Fog.Density;
373 for (i=0;i<n;i++) {
374 GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
375 GLfloat eyez = -d / (c+ndcz);
376 GLfloat f;
377 if (eyez < 0.0) eyez = -eyez;
378 f = exp( negDensitySquared * eyez*eyez );
379 f = CLAMP( f, 0.0F, 1.0F );
380 index[i] = (GLuint) ((GLfloat) index[i] + (1.0F-f) * ctx->Fog.Index);
381 }
382 }
383 break;
384 default:
385 gl_problem(ctx, "Bad fog mode in gl_fog_index_pixels");
386 return;
387 }
388 }
389
390