1 /* $Id: fog.c,v 1.23 2000/10/28 11:42:12 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.
43 _mesa_Fogf(GLenum pname
, GLfloat param
)
45 _mesa_Fogfv(pname
, ¶m
);
50 _mesa_Fogi(GLenum pname
, GLint param
)
52 GLfloat fparam
= (GLfloat
) param
;
53 _mesa_Fogfv(pname
, &fparam
);
58 _mesa_Fogiv(GLenum pname
, const GLint
*params
)
67 case GL_FOG_COORDINATE_SOURCE_EXT
:
68 p
[0] = (GLfloat
) *params
;
71 p
[0] = INT_TO_FLOAT( params
[0] );
72 p
[1] = INT_TO_FLOAT( params
[1] );
73 p
[2] = INT_TO_FLOAT( params
[2] );
74 p
[3] = INT_TO_FLOAT( params
[3] );
77 /* Error will be caught later in _mesa_Fogfv */
80 _mesa_Fogfv(pname
, p
);
85 _mesa_Fogfv( GLenum pname
, const GLfloat
*params
)
87 GET_CURRENT_CONTEXT(ctx
);
90 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glFog");
94 m
= (GLenum
) (GLint
) *params
;
95 if (m
==GL_LINEAR
|| m
==GL_EXP
|| m
==GL_EXP2
) {
99 gl_error( ctx
, GL_INVALID_ENUM
, "glFog" );
105 gl_error( ctx
, GL_INVALID_VALUE
, "glFog" );
109 ctx
->Fog
.Density
= *params
;
113 ctx
->Fog
.Start
= *params
;
116 ctx
->Fog
.End
= *params
;
119 ctx
->Fog
.Index
= *params
;
122 ctx
->Fog
.Color
[0] = params
[0];
123 ctx
->Fog
.Color
[1] = params
[1];
124 ctx
->Fog
.Color
[2] = params
[2];
125 ctx
->Fog
.Color
[3] = params
[3];
127 case GL_FOG_COORDINATE_SOURCE_EXT
: {
128 GLenum p
= (GLenum
)(GLint
) *params
;
129 if (p
== GL_FOG_COORDINATE_EXT
|| p
== GL_FRAGMENT_DEPTH_EXT
)
130 ctx
->Fog
.FogCoordinateSource
= p
;
132 gl_error( ctx
, GL_INVALID_ENUM
, "glFog" );
136 gl_error( ctx
, GL_INVALID_ENUM
, "glFog" );
140 if (ctx
->Driver
.Fogfv
) {
141 (*ctx
->Driver
.Fogfv
)( ctx
, pname
, params
);
144 ctx
->NewState
|= NEW_FOG
;
151 _mesa_init_fog( void )
155 static GLvector1f
*get_fogcoord_ptr( GLcontext
*ctx
, GLvector1f
*tmp
)
157 struct vertex_buffer
*VB
= ctx
->VB
;
159 if (ctx
->Fog
.FogCoordinateSource
== GL_FRAGMENT_DEPTH_EXT
) {
160 if (!ctx
->NeedEyeCoords
) {
161 GLfloat
*m
= ctx
->ModelView
.m
;
169 /* Full eye coords weren't required, just calculate the
172 gl_dotprod_tab
[0][VB
->ObjPtr
->size
](&VB
->Eye
, 2,
173 VB
->ObjPtr
, plane
, 0 );
175 tmp
->data
= &(VB
->Eye
.data
[0][2]);
176 tmp
->start
= VB
->Eye
.start
+2;
177 tmp
->stride
= VB
->Eye
.stride
;
182 if (VB
->EyePtr
->size
< 2)
183 gl_vector4f_clean_elem( &VB
->Eye
, VB
->Count
, 2 );
185 tmp
->data
= &(VB
->EyePtr
->data
[0][2]);
186 tmp
->start
= VB
->EyePtr
->start
+2;
187 tmp
->stride
= VB
->EyePtr
->stride
;
191 return VB
->FogCoordPtr
;
195 /* Use lookup table & interpolation?
198 make_win_fog_coords( struct vertex_buffer
*VB
,
199 GLvector1f
*fogcoord
)
201 const GLcontext
*ctx
= VB
->ctx
;
202 GLfloat end
= ctx
->Fog
.End
;
203 GLfloat
*v
= fogcoord
->start
;
204 GLuint stride
= fogcoord
->stride
;
205 GLuint n
= VB
->Count
- VB
->Start
;
210 VB
->FogCoordPtr
= VB
->store
.FogCoord
;
211 out
= VB
->FogCoordPtr
->data
+ VB
->Start
;
213 switch (ctx
->Fog
.Mode
) {
215 d
= 1.0F
/ (ctx
->Fog
.End
- ctx
->Fog
.Start
);
216 for ( i
= 0 ; i
< n
; i
++, STRIDE_F(v
, stride
)) {
217 out
[i
] = (end
- ABSF(*v
)) * d
;
218 if (0) fprintf(stderr
, "z %f out %f\n", *v
, out
[i
]);
222 d
= -ctx
->Fog
.Density
;
223 for ( i
= 0 ; i
< n
; i
++, STRIDE_F(v
,stride
)) {
224 out
[i
] = exp( d
*ABSF(*v
) );
225 if (0) fprintf(stderr
, "z %f out %f\n", *v
, out
[i
]);
229 d
= -(ctx
->Fog
.Density
*ctx
->Fog
.Density
);
230 for ( i
= 0 ; i
< n
; i
++, STRIDE_F(v
, stride
)) {
232 out
[i
] = exp( d
*z
*z
);
233 if (0) fprintf(stderr
, "z %f out %f\n", *v
, out
[i
]);
237 gl_problem(ctx
, "Bad fog mode in make_fog_coord");
244 _mesa_make_win_fog_coords( struct vertex_buffer
*VB
)
248 make_win_fog_coords( VB
, get_fogcoord_ptr( VB
->ctx
, &tmp
) );
254 * Apply fog to an array of RGBA pixels.
255 * Input: n - number of pixels
256 * fog - array of interpolated screen-space fog coordinates in [0..1]
257 * red, green, blue, alpha - pixel colors
258 * Output: red, green, blue, alpha - fogged pixel colors
261 _mesa_fog_rgba_pixels( const GLcontext
*ctx
,
266 GLfixed rFog
= ctx
->Fog
.Color
[0] * 255.0;
267 GLfixed gFog
= ctx
->Fog
.Color
[1] * 255.0;
268 GLfixed bFog
= ctx
->Fog
.Color
[2] * 255.0;
272 GLfixed f
= CLAMP(fog
[i
], 0, FIXED_ONE
);
273 GLfixed g
= FIXED_ONE
- f
;
274 rgba
[i
][0] = (f
*rgba
[i
][0] + g
*rFog
) >> FIXED_SHIFT
;
275 rgba
[i
][1] = (f
*rgba
[i
][1] + g
*gFog
) >> FIXED_SHIFT
;
276 rgba
[i
][2] = (f
*rgba
[i
][2] + g
*bFog
) >> FIXED_SHIFT
;
284 * Apply fog to an array of color index pixels.
285 * Input: n - number of pixels
286 * z - array of integer depth values
287 * index - pixel color indexes
288 * Output: index - fogged pixel color indexes
291 _mesa_fog_ci_pixels( const GLcontext
*ctx
,
292 GLuint n
, const GLfixed fog
[], GLuint index
[] )
294 GLuint idx
= ctx
->Fog
.Index
;
298 GLfixed f
= FixedToFloat(CLAMP(fog
[i
], 0, FIXED_ONE
));
299 index
[i
] = (GLuint
) ((GLfloat
) index
[i
] + (1.0F
-f
) * idx
);
306 * Calculate fog coords from window z values
307 * Input: n - number of pixels
308 * z - array of integer depth values
309 * red, green, blue, alpha - pixel colors
310 * Output: red, green, blue, alpha - fogged pixel colors
312 * Use lookup table & interpolation?
315 _mesa_win_fog_coords_from_z( const GLcontext
*ctx
,
320 GLfloat c
= ctx
->ProjectionMatrix
.m
[10];
321 GLfloat d
= ctx
->ProjectionMatrix
.m
[14];
324 GLfloat tz
= ctx
->Viewport
.WindowMap
.m
[MAT_TZ
];
325 GLfloat szInv
= 1.0F
/ ctx
->Viewport
.WindowMap
.m
[MAT_SZ
];
327 switch (ctx
->Fog
.Mode
) {
330 GLfloat fogEnd
= ctx
->Fog
.End
;
331 GLfloat fogScale
= (GLfloat
) FIXED_ONE
/ (ctx
->Fog
.End
-
334 GLfloat ndcz
= ((GLfloat
) z
[i
] - tz
) * szInv
;
335 GLfloat eyez
= -d
/ (c
+ndcz
);
336 if (eyez
< 0.0) eyez
= -eyez
;
337 fogcoord
[i
] = (GLint
)(fogEnd
- eyez
) * fogScale
;
343 GLfloat ndcz
= ((GLfloat
) z
[i
] - tz
) * szInv
;
344 GLfloat eyez
= d
/ (c
+ndcz
);
345 if (eyez
< 0.0) eyez
= -eyez
;
346 fogcoord
[i
] = FloatToFixed(exp( -ctx
->Fog
.Density
* eyez
));
351 GLfloat negDensitySquared
= -ctx
->Fog
.Density
* ctx
->Fog
.Density
;
353 GLfloat ndcz
= ((GLfloat
) z
[i
] - tz
) * szInv
;
354 GLfloat eyez
= d
/ (c
+ndcz
);
355 GLfloat tmp
= negDensitySquared
* eyez
* eyez
;
356 #if defined(__alpha__) || defined(__alpha)
357 /* XXX this underflow check may be needed for other systems */
358 if (tmp
< FLT_MIN_10_EXP
)
359 tmp
= FLT_MIN_10_EXP
;
361 fogcoord
[i
] = FloatToFixed(exp( tmp
));
366 gl_problem(ctx
, "Bad fog mode in _mesa_win_fog_coords_from_z");
373 * Apply fog to an array of RGBA pixels.
374 * Input: n - number of pixels
375 * z - array of integer depth values
376 * red, green, blue, alpha - pixel colors
377 * Output: red, green, blue, alpha - fogged pixel colors
380 _mesa_depth_fog_rgba_pixels( const GLcontext
*ctx
,
381 GLuint n
, const GLdepth z
[], GLubyte rgba
[][4] )
383 GLfixed fog
[MAX_WIDTH
];
384 _mesa_win_fog_coords_from_z( ctx
, n
, z
, fog
);
385 _mesa_fog_rgba_pixels( ctx
, n
, fog
, rgba
);
390 * Apply fog to an array of color index pixels.
391 * Input: n - number of pixels
392 * z - array of integer depth values
393 * index - pixel color indexes
394 * Output: index - fogged pixel color indexes
397 _mesa_depth_fog_ci_pixels( const GLcontext
*ctx
,
398 GLuint n
, const GLdepth z
[], GLuint index
[] )
400 GLfixed fog
[MAX_WIDTH
];
401 _mesa_win_fog_coords_from_z( ctx
, n
, z
, fog
);
402 _mesa_fog_ci_pixels( ctx
, n
, fog
, index
);