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 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 */ 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 */ 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 */ 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 */ 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