1 /* $Id: fog.c,v 1.2 1999/10/08 09:27:10 keithw Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999 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.
28 /* $XFree86: xc/lib/GL/mesa/src/fog.c,v 1.4 1999/04/04 00:20:24 dawes Exp $ */
37 #include "GL/xf86glx.h"
45 #include "GL/xf86glx.h"
51 void gl_Fogfv( GLcontext
*ctx
, GLenum pname
, const GLfloat
*params
)
57 m
= (GLenum
) (GLint
) *params
;
58 if (m
==GL_LINEAR
|| m
==GL_EXP
|| m
==GL_EXP2
) {
62 gl_error( ctx
, GL_INVALID_ENUM
, "glFog" );
68 gl_error( ctx
, GL_INVALID_VALUE
, "glFog" );
72 ctx
->Fog
.Density
= *params
;
77 /* Prior to OpenGL 1.1, this was an error */
79 gl_error( ctx
, GL_INVALID_VALUE
, "glFog(GL_FOG_START)" );
83 ctx
->Fog
.Start
= *params
;
87 /* Prior to OpenGL 1.1, this was an error */
89 gl_error( ctx
, GL_INVALID_VALUE
, "glFog(GL_FOG_END)" );
93 ctx
->Fog
.End
= *params
;
96 ctx
->Fog
.Index
= *params
;
99 ctx
->Fog
.Color
[0] = params
[0];
100 ctx
->Fog
.Color
[1] = params
[1];
101 ctx
->Fog
.Color
[2] = params
[2];
102 ctx
->Fog
.Color
[3] = params
[3];
105 gl_error( ctx
, GL_INVALID_ENUM
, "glFog" );
109 if (ctx
->Driver
.Fogfv
) {
110 (*ctx
->Driver
.Fogfv
)( ctx
, pname
, params
);
113 ctx
->NewState
|= NEW_FOG
;
117 typedef void (*fog_func
)( struct vertex_buffer
*VB
, GLuint side
,
121 static fog_func fog_ci_tab
[2];
122 static fog_func fog_rgba_tab
[2];
125 * Compute the fogged color for an array of vertices.
126 * Input: n - number of vertices
127 * v - array of vertices
128 * color - the original vertex colors
129 * Output: color - the fogged colors
132 #define TAG(x) x##_raw
137 #define TAG(x) x##_masked
138 #define CULLCHECK if (cullmask[i]&flag)
142 void gl_init_fog( void )
144 init_fog_tab_masked();
149 * Compute fog for the vertices in the vertex buffer.
151 void gl_fog_vertices( struct vertex_buffer
*VB
)
153 GLcontext
*ctx
= VB
->ctx
;
154 GLuint i
= VB
->CullMode
& 1;
156 if (ctx
->Visual
->RGBAflag
) {
158 if (ctx
->TriangleCaps
& DD_TRI_LIGHT_TWOSIDE
) {
159 fog_rgba_tab
[i
]( VB
, 0, VERT_FACE_FRONT
);
160 fog_rgba_tab
[i
]( VB
, 1, VERT_FACE_REAR
);
162 fog_rgba_tab
[i
]( VB
, 0, VERT_FACE_FRONT
|VERT_FACE_REAR
);
166 /* Fog color indexes */
167 if (ctx
->TriangleCaps
& DD_TRI_LIGHT_TWOSIDE
) {
168 fog_ci_tab
[i
]( VB
, 0, VERT_FACE_FRONT
);
169 fog_ci_tab
[i
]( VB
, 1, VERT_FACE_REAR
);
171 fog_ci_tab
[i
]( VB
, 0, VERT_FACE_FRONT
|VERT_FACE_REAR
);
177 * Apply fog to an array of RGBA pixels.
178 * Input: n - number of pixels
179 * z - array of integer depth values
180 * red, green, blue, alpha - pixel colors
181 * Output: red, green, blue, alpha - fogged pixel colors
183 void gl_fog_rgba_pixels( const GLcontext
*ctx
,
184 GLuint n
, const GLdepth z
[], GLubyte rgba
[][4] )
186 GLfloat c
= ctx
->ProjectionMatrix
.m
[10];
187 GLfloat d
= ctx
->ProjectionMatrix
.m
[14];
190 GLfloat rFog
= ctx
->Fog
.Color
[0] * 255.0F
;
191 GLfloat gFog
= ctx
->Fog
.Color
[1] * 255.0F
;
192 GLfloat bFog
= ctx
->Fog
.Color
[2] * 255.0F
;
194 GLfloat tz
= ctx
->Viewport
.WindowMap
.m
[MAT_TZ
];
195 GLfloat szInv
= 1.0F
/ ctx
->Viewport
.WindowMap
.m
[MAT_SZ
];
197 switch (ctx
->Fog
.Mode
) {
200 GLfloat fogEnd
= ctx
->Fog
.End
;
201 GLfloat fogScale
= 1.0F
/ (ctx
->Fog
.End
- ctx
->Fog
.Start
);
203 GLfloat ndcz
= ((GLfloat
) z
[i
] - tz
) * szInv
;
204 GLfloat eyez
= -d
/ (c
+ndcz
);
206 if (eyez
< 0.0) eyez
= -eyez
;
207 f
= (fogEnd
- eyez
) * fogScale
;
208 f
= CLAMP( f
, 0.0F
, 1.0F
);
210 rgba
[i
][RCOMP
] = (GLint
) (f
* rgba
[i
][RCOMP
] + g
* rFog
);
211 rgba
[i
][GCOMP
] = (GLint
) (f
* rgba
[i
][GCOMP
] + g
* gFog
);
212 rgba
[i
][BCOMP
] = (GLint
) (f
* rgba
[i
][BCOMP
] + g
* bFog
);
218 GLfloat ndcz
= ((GLfloat
) z
[i
] - tz
) * szInv
;
219 GLfloat eyez
= d
/ (c
+ndcz
);
223 f
= exp( -ctx
->Fog
.Density
* eyez
);
225 rgba
[i
][RCOMP
] = (GLint
) (f
* rgba
[i
][RCOMP
] + g
* rFog
);
226 rgba
[i
][GCOMP
] = (GLint
) (f
* rgba
[i
][GCOMP
] + g
* gFog
);
227 rgba
[i
][BCOMP
] = (GLint
) (f
* rgba
[i
][BCOMP
] + g
* bFog
);
232 GLfloat negDensitySquared
= -ctx
->Fog
.Density
* ctx
->Fog
.Density
;
234 GLfloat ndcz
= ((GLfloat
) z
[i
] - tz
) * szInv
;
235 GLfloat eyez
= d
/ (c
+ndcz
);
237 GLfloat tmp
= negDensitySquared
* eyez
* eyez
;
239 /* XXX this underflow check may be needed for other systems */
240 if (tmp
< FLT_MIN_10_EXP
)
241 f
= exp( FLT_MIN_10_EXP
);
246 rgba
[i
][RCOMP
] = (GLint
) (f
* rgba
[i
][RCOMP
] + g
* rFog
);
247 rgba
[i
][GCOMP
] = (GLint
) (f
* rgba
[i
][GCOMP
] + g
* gFog
);
248 rgba
[i
][BCOMP
] = (GLint
) (f
* rgba
[i
][BCOMP
] + g
* bFog
);
253 gl_problem(ctx
, "Bad fog mode in gl_fog_rgba_pixels");
262 * Apply fog to an array of color index pixels.
263 * Input: n - number of pixels
264 * z - array of integer depth values
265 * index - pixel color indexes
266 * Output: index - fogged pixel color indexes
268 void gl_fog_ci_pixels( const GLcontext
*ctx
,
269 GLuint n
, const GLdepth z
[], GLuint index
[] )
271 GLfloat c
= ctx
->ProjectionMatrix
.m
[10];
272 GLfloat d
= ctx
->ProjectionMatrix
.m
[14];
275 GLfloat tz
= ctx
->Viewport
.WindowMap
.m
[MAT_TZ
];
276 GLfloat szInv
= 1.0F
/ ctx
->Viewport
.WindowMap
.m
[MAT_SZ
];
278 switch (ctx
->Fog
.Mode
) {
281 GLfloat fogEnd
= ctx
->Fog
.End
;
282 GLfloat fogScale
= 1.0F
/ (ctx
->Fog
.End
- ctx
->Fog
.Start
);
284 GLfloat ndcz
= ((GLfloat
) z
[i
] - tz
) * szInv
;
285 GLfloat eyez
= -d
/ (c
+ndcz
);
287 if (eyez
< 0.0) eyez
= -eyez
;
288 f
= (fogEnd
- eyez
) * fogScale
;
289 f
= CLAMP( f
, 0.0F
, 1.0F
);
290 index
[i
] = (GLuint
) ((GLfloat
) index
[i
] + (1.0F
-f
) * ctx
->Fog
.Index
);
296 GLfloat ndcz
= ((GLfloat
) z
[i
] - tz
) * szInv
;
297 GLfloat eyez
= -d
/ (c
+ndcz
);
301 f
= exp( -ctx
->Fog
.Density
* eyez
);
302 f
= CLAMP( f
, 0.0F
, 1.0F
);
303 index
[i
] = (GLuint
) ((GLfloat
) index
[i
] + (1.0F
-f
) * ctx
->Fog
.Index
);
308 GLfloat negDensitySquared
= -ctx
->Fog
.Density
* ctx
->Fog
.Density
;
310 GLfloat ndcz
= ((GLfloat
) z
[i
] - tz
) * szInv
;
311 GLfloat eyez
= -d
/ (c
+ndcz
);
315 tmp
= negDensitySquared
* eyez
* eyez
;
317 /* XXX this underflow check may be needed for other systems */
318 if (tmp
< FLT_MIN_10_EXP
)
319 f
= exp( FLT_MIN_10_EXP
);
323 f
= CLAMP( f
, 0.0F
, 1.0F
);
324 index
[i
] = (GLuint
) ((GLfloat
) index
[i
] + (1.0F
-f
) * ctx
->Fog
.Index
);
329 gl_problem(ctx
, "Bad fog mode in gl_fog_ci_pixels");