1 /* $Id: fog.c,v 1.26 2000/10/30 13:32:00 keithw Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2000 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.
44 _mesa_Fogf(GLenum pname
, GLfloat param
)
46 _mesa_Fogfv(pname
, ¶m
);
51 _mesa_Fogi(GLenum pname
, GLint param
)
53 GLfloat fparam
= (GLfloat
) param
;
54 _mesa_Fogfv(pname
, &fparam
);
59 _mesa_Fogiv(GLenum pname
, const GLint
*params
)
68 case GL_FOG_COORDINATE_SOURCE_EXT
:
69 p
[0] = (GLfloat
) *params
;
72 p
[0] = INT_TO_FLOAT( params
[0] );
73 p
[1] = INT_TO_FLOAT( params
[1] );
74 p
[2] = INT_TO_FLOAT( params
[2] );
75 p
[3] = INT_TO_FLOAT( params
[3] );
78 /* Error will be caught later in _mesa_Fogfv */
81 _mesa_Fogfv(pname
, p
);
86 _mesa_Fogfv( GLenum pname
, const GLfloat
*params
)
88 GET_CURRENT_CONTEXT(ctx
);
91 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glFog");
95 m
= (GLenum
) (GLint
) *params
;
96 if (m
==GL_LINEAR
|| m
==GL_EXP
|| m
==GL_EXP2
) {
100 gl_error( ctx
, GL_INVALID_ENUM
, "glFog" );
106 gl_error( ctx
, GL_INVALID_VALUE
, "glFog" );
110 ctx
->Fog
.Density
= *params
;
114 ctx
->Fog
.Start
= *params
;
117 ctx
->Fog
.End
= *params
;
120 ctx
->Fog
.Index
= *params
;
123 ctx
->Fog
.Color
[0] = params
[0];
124 ctx
->Fog
.Color
[1] = params
[1];
125 ctx
->Fog
.Color
[2] = params
[2];
126 ctx
->Fog
.Color
[3] = params
[3];
128 case GL_FOG_COORDINATE_SOURCE_EXT
: {
129 GLenum p
= (GLenum
)(GLint
) *params
;
130 if (p
== GL_FOG_COORDINATE_EXT
|| p
== GL_FRAGMENT_DEPTH_EXT
)
131 ctx
->Fog
.FogCoordinateSource
= p
;
133 gl_error( ctx
, GL_INVALID_ENUM
, "glFog" );
137 gl_error( ctx
, GL_INVALID_ENUM
, "glFog" );
141 if (ctx
->Driver
.Fogfv
) {
142 (*ctx
->Driver
.Fogfv
)( ctx
, pname
, params
);
145 ctx
->NewState
|= _NEW_FOG
;
152 _mesa_init_fog( void )
156 static GLvector1f
*get_fogcoord_ptr( GLcontext
*ctx
, GLvector1f
*tmp
)
158 struct vertex_buffer
*VB
= ctx
->VB
;
160 if (ctx
->Fog
.FogCoordinateSource
== GL_FRAGMENT_DEPTH_EXT
) {
161 if (!ctx
->NeedEyeCoords
) {
162 GLfloat
*m
= ctx
->ModelView
.m
;
170 /* Full eye coords weren't required, just calculate the
173 gl_dotprod_tab
[0][VB
->ObjPtr
->size
](&VB
->Eye
, 2,
174 VB
->ObjPtr
, plane
, 0 );
176 tmp
->data
= &(VB
->Eye
.data
[0][2]);
177 tmp
->start
= VB
->Eye
.start
+2;
178 tmp
->stride
= VB
->Eye
.stride
;
183 if (VB
->EyePtr
->size
< 2)
184 gl_vector4f_clean_elem( &VB
->Eye
, VB
->Count
, 2 );
186 tmp
->data
= &(VB
->EyePtr
->data
[0][2]);
187 tmp
->start
= VB
->EyePtr
->start
+2;
188 tmp
->stride
= VB
->EyePtr
->stride
;
192 return VB
->FogCoordPtr
;
196 /* Use lookup table & interpolation?
199 make_win_fog_coords( struct vertex_buffer
*VB
,
200 GLvector1f
*fogcoord
)
202 const GLcontext
*ctx
= VB
->ctx
;
203 GLfloat end
= ctx
->Fog
.End
;
204 GLfloat
*v
= fogcoord
->start
;
205 GLuint stride
= fogcoord
->stride
;
206 GLuint n
= VB
->Count
- VB
->Start
;
211 VB
->FogCoordPtr
= VB
->store
.FogCoord
;
212 out
= VB
->FogCoordPtr
->data
+ VB
->Start
;
214 switch (ctx
->Fog
.Mode
) {
216 d
= 1.0F
/ (ctx
->Fog
.End
- ctx
->Fog
.Start
);
217 for ( i
= 0 ; i
< n
; i
++, STRIDE_F(v
, stride
)) {
218 out
[i
] = (end
- ABSF(*v
)) * d
;
219 if (0) fprintf(stderr
, "z %f out %f\n", *v
, out
[i
]);
223 d
= -ctx
->Fog
.Density
;
224 for ( i
= 0 ; i
< n
; i
++, STRIDE_F(v
,stride
)) {
225 out
[i
] = exp( d
*ABSF(*v
) );
226 if (0) fprintf(stderr
, "z %f out %f\n", *v
, out
[i
]);
230 d
= -(ctx
->Fog
.Density
*ctx
->Fog
.Density
);
231 for ( i
= 0 ; i
< n
; i
++, STRIDE_F(v
, stride
)) {
233 out
[i
] = exp( d
*z
*z
);
234 if (0) fprintf(stderr
, "z %f out %f\n", *v
, out
[i
]);
238 gl_problem(ctx
, "Bad fog mode in make_fog_coord");
245 _mesa_make_win_fog_coords( struct vertex_buffer
*VB
)
249 make_win_fog_coords( VB
, get_fogcoord_ptr( VB
->ctx
, &tmp
) );
255 * Apply fog to an array of RGBA pixels.
256 * Input: n - number of pixels
257 * fog - array of interpolated screen-space fog coordinates in [0..1]
258 * red, green, blue, alpha - pixel colors
259 * Output: red, green, blue, alpha - fogged pixel colors
262 _mesa_fog_rgba_pixels( const GLcontext
*ctx
,
267 GLfixed rFog
= ctx
->Fog
.Color
[0] * CHAN_MAXF
;
268 GLfixed gFog
= ctx
->Fog
.Color
[1] * CHAN_MAXF
;
269 GLfixed bFog
= ctx
->Fog
.Color
[2] * CHAN_MAXF
;
273 GLfixed f
= CLAMP(fog
[i
], 0, FIXED_ONE
);
274 GLfixed g
= FIXED_ONE
- f
;
275 rgba
[i
][0] = (f
*rgba
[i
][0] + g
*rFog
) >> FIXED_SHIFT
;
276 rgba
[i
][1] = (f
*rgba
[i
][1] + g
*gFog
) >> FIXED_SHIFT
;
277 rgba
[i
][2] = (f
*rgba
[i
][2] + g
*bFog
) >> FIXED_SHIFT
;
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_fog_ci_pixels( const GLcontext
*ctx
,
293 GLuint n
, const GLfixed fog
[], GLuint index
[] )
295 GLuint idx
= ctx
->Fog
.Index
;
299 GLfixed f
= FixedToFloat(CLAMP(fog
[i
], 0, FIXED_ONE
));
300 index
[i
] = (GLuint
) ((GLfloat
) index
[i
] + (1.0F
-f
) * idx
);
307 * Calculate fog coords from window z values
308 * Input: n - number of pixels
309 * z - array of integer depth values
310 * red, green, blue, alpha - pixel colors
311 * Output: red, green, blue, alpha - fogged pixel colors
313 * Use lookup table & interpolation?
316 _mesa_win_fog_coords_from_z( const GLcontext
*ctx
,
321 GLfloat c
= ctx
->ProjectionMatrix
.m
[10];
322 GLfloat d
= ctx
->ProjectionMatrix
.m
[14];
325 GLfloat tz
= ctx
->Viewport
.WindowMap
.m
[MAT_TZ
];
326 GLfloat szInv
= 1.0F
/ ctx
->Viewport
.WindowMap
.m
[MAT_SZ
];
328 switch (ctx
->Fog
.Mode
) {
331 GLfloat fogEnd
= ctx
->Fog
.End
;
332 GLfloat fogScale
= (GLfloat
) FIXED_ONE
/ (ctx
->Fog
.End
-
335 GLfloat ndcz
= ((GLfloat
) z
[i
] - tz
) * szInv
;
336 GLfloat eyez
= -d
/ (c
+ndcz
);
337 if (eyez
< 0.0) eyez
= -eyez
;
338 fogcoord
[i
] = (GLint
)(fogEnd
- eyez
) * fogScale
;
344 GLfloat ndcz
= ((GLfloat
) z
[i
] - tz
) * szInv
;
345 GLfloat eyez
= d
/ (c
+ndcz
);
346 if (eyez
< 0.0) eyez
= -eyez
;
347 fogcoord
[i
] = FloatToFixed(exp( -ctx
->Fog
.Density
* eyez
));
352 GLfloat negDensitySquared
= -ctx
->Fog
.Density
* ctx
->Fog
.Density
;
354 GLfloat ndcz
= ((GLfloat
) z
[i
] - tz
) * szInv
;
355 GLfloat eyez
= d
/ (c
+ndcz
);
356 GLfloat tmp
= negDensitySquared
* eyez
* eyez
;
357 #if defined(__alpha__) || defined(__alpha)
358 /* XXX this underflow check may be needed for other systems */
359 if (tmp
< FLT_MIN_10_EXP
)
360 tmp
= FLT_MIN_10_EXP
;
362 fogcoord
[i
] = FloatToFixed(exp( tmp
));
367 gl_problem(ctx
, "Bad fog mode in _mesa_win_fog_coords_from_z");
374 * Apply fog to an array of RGBA pixels.
375 * Input: n - number of pixels
376 * z - array of integer depth values
377 * red, green, blue, alpha - pixel colors
378 * Output: red, green, blue, alpha - fogged pixel colors
381 _mesa_depth_fog_rgba_pixels( const GLcontext
*ctx
,
382 GLuint n
, const GLdepth z
[], GLchan rgba
[][4] )
384 GLfixed fog
[MAX_WIDTH
];
385 _mesa_win_fog_coords_from_z( ctx
, n
, z
, fog
);
386 _mesa_fog_rgba_pixels( ctx
, n
, fog
, rgba
);
391 * Apply fog to an array of color index pixels.
392 * Input: n - number of pixels
393 * z - array of integer depth values
394 * index - pixel color indexes
395 * Output: index - fogged pixel color indexes
398 _mesa_depth_fog_ci_pixels( const GLcontext
*ctx
,
399 GLuint n
, const GLdepth z
[], GLuint index
[] )
401 GLfixed fog
[MAX_WIDTH
];
402 _mesa_win_fog_coords_from_z( ctx
, n
, z
, fog
);
403 _mesa_fog_ci_pixels( ctx
, n
, fog
, index
);