xref: /reactos/dll/opengl/mesa/fog.c (revision 5f2bebf7)
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