clean-up of header includes (Daryll)
[mesa.git] / src / mesa / main / fog.c
1 /* $Id: fog.c,v 1.3 1999/11/08 07:36:44 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.1
6 *
7 * Copyright (C) 1999 Brian Paul All Rights Reserved.
8 *
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:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
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.
25 */
26
27
28 /* $XFree86: xc/lib/GL/mesa/src/fog.c,v 1.4 1999/04/04 00:20:24 dawes Exp $ */
29
30 #ifdef PC_HEADER
31 #include "all.h"
32 #else
33 #ifndef XFree86Server
34 #include <math.h>
35 #include <stdlib.h>
36 #else
37 #include "GL/xf86glx.h"
38 #endif
39 #include "context.h"
40 #include "fog.h"
41 #include "macros.h"
42 #include "mmath.h"
43 #include "types.h"
44 #endif
45
46
47
48 void gl_Fogfv( GLcontext *ctx, GLenum pname, const GLfloat *params )
49 {
50 GLenum m;
51
52 switch (pname) {
53 case GL_FOG_MODE:
54 m = (GLenum) (GLint) *params;
55 if (m==GL_LINEAR || m==GL_EXP || m==GL_EXP2) {
56 ctx->Fog.Mode = m;
57 }
58 else {
59 gl_error( ctx, GL_INVALID_ENUM, "glFog" );
60 return;
61 }
62 break;
63 case GL_FOG_DENSITY:
64 if (*params<0.0) {
65 gl_error( ctx, GL_INVALID_VALUE, "glFog" );
66 return;
67 }
68 else {
69 ctx->Fog.Density = *params;
70 }
71 break;
72 case GL_FOG_START:
73 #if 0
74 /* Prior to OpenGL 1.1, this was an error */
75 if (*params<0.0F) {
76 gl_error( ctx, GL_INVALID_VALUE, "glFog(GL_FOG_START)" );
77 return;
78 }
79 #endif
80 ctx->Fog.Start = *params;
81 break;
82 case GL_FOG_END:
83 #if 0
84 /* Prior to OpenGL 1.1, this was an error */
85 if (*params<0.0F) {
86 gl_error( ctx, GL_INVALID_VALUE, "glFog(GL_FOG_END)" );
87 return;
88 }
89 #endif
90 ctx->Fog.End = *params;
91 break;
92 case GL_FOG_INDEX:
93 ctx->Fog.Index = *params;
94 break;
95 case GL_FOG_COLOR:
96 ctx->Fog.Color[0] = params[0];
97 ctx->Fog.Color[1] = params[1];
98 ctx->Fog.Color[2] = params[2];
99 ctx->Fog.Color[3] = params[3];
100 break;
101 default:
102 gl_error( ctx, GL_INVALID_ENUM, "glFog" );
103 return;
104 }
105
106 if (ctx->Driver.Fogfv) {
107 (*ctx->Driver.Fogfv)( ctx, pname, params );
108 }
109
110 ctx->NewState |= NEW_FOG;
111 }
112
113
114 typedef void (*fog_func)( struct vertex_buffer *VB, GLuint side,
115 GLubyte flag );
116
117
118 static fog_func fog_ci_tab[2];
119 static fog_func fog_rgba_tab[2];
120
121 /*
122 * Compute the fogged color for an array of vertices.
123 * Input: n - number of vertices
124 * v - array of vertices
125 * color - the original vertex colors
126 * Output: color - the fogged colors
127 *
128 */
129 #define TAG(x) x##_raw
130 #define CULLCHECK
131 #define IDX 0
132 #include "fog_tmp.h"
133
134 #define TAG(x) x##_masked
135 #define CULLCHECK if (cullmask[i]&flag)
136 #define IDX 1
137 #include "fog_tmp.h"
138
139 void gl_init_fog( void )
140 {
141 init_fog_tab_masked();
142 init_fog_tab_raw();
143 }
144
145 /*
146 * Compute fog for the vertices in the vertex buffer.
147 */
148 void gl_fog_vertices( struct vertex_buffer *VB )
149 {
150 GLcontext *ctx = VB->ctx;
151 GLuint i = VB->CullMode & 1;
152
153 if (ctx->Visual->RGBAflag) {
154 /* Fog RGB colors */
155 if (ctx->TriangleCaps & DD_TRI_LIGHT_TWOSIDE) {
156 fog_rgba_tab[i]( VB, 0, VERT_FACE_FRONT );
157 fog_rgba_tab[i]( VB, 1, VERT_FACE_REAR );
158 } else {
159 fog_rgba_tab[i]( VB, 0, VERT_FACE_FRONT|VERT_FACE_REAR );
160 }
161 }
162 else {
163 /* Fog color indexes */
164 if (ctx->TriangleCaps & DD_TRI_LIGHT_TWOSIDE) {
165 fog_ci_tab[i]( VB, 0, VERT_FACE_FRONT );
166 fog_ci_tab[i]( VB, 1, VERT_FACE_REAR );
167 } else {
168 fog_ci_tab[i]( VB, 0, VERT_FACE_FRONT|VERT_FACE_REAR );
169 }
170 }
171 }
172
173 /*
174 * Apply fog to an array of RGBA pixels.
175 * Input: n - number of pixels
176 * z - array of integer depth values
177 * red, green, blue, alpha - pixel colors
178 * Output: red, green, blue, alpha - fogged pixel colors
179 */
180 void gl_fog_rgba_pixels( const GLcontext *ctx,
181 GLuint n, const GLdepth z[], GLubyte rgba[][4] )
182 {
183 GLfloat c = ctx->ProjectionMatrix.m[10];
184 GLfloat d = ctx->ProjectionMatrix.m[14];
185 GLuint i;
186
187 GLfloat rFog = ctx->Fog.Color[0] * 255.0F;
188 GLfloat gFog = ctx->Fog.Color[1] * 255.0F;
189 GLfloat bFog = ctx->Fog.Color[2] * 255.0F;
190
191 GLfloat tz = ctx->Viewport.WindowMap.m[MAT_TZ];
192 GLfloat szInv = 1.0F / ctx->Viewport.WindowMap.m[MAT_SZ];
193
194 switch (ctx->Fog.Mode) {
195 case GL_LINEAR:
196 {
197 GLfloat fogEnd = ctx->Fog.End;
198 GLfloat fogScale = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
199 for (i=0;i<n;i++) {
200 GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
201 GLfloat eyez = -d / (c+ndcz);
202 GLfloat f, g;
203 if (eyez < 0.0) eyez = -eyez;
204 f = (fogEnd - eyez) * fogScale;
205 f = CLAMP( f, 0.0F, 1.0F );
206 g = 1.0F - f;
207 rgba[i][RCOMP] = (GLint) (f * rgba[i][RCOMP] + g * rFog);
208 rgba[i][GCOMP] = (GLint) (f * rgba[i][GCOMP] + g * gFog);
209 rgba[i][BCOMP] = (GLint) (f * rgba[i][BCOMP] + g * bFog);
210 }
211 }
212 break;
213 case GL_EXP:
214 for (i=0;i<n;i++) {
215 GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
216 GLfloat eyez = d / (c+ndcz);
217 GLfloat f, g;
218 if (eyez < 0.0)
219 eyez = -eyez;
220 f = exp( -ctx->Fog.Density * eyez );
221 g = 1.0F - f;
222 rgba[i][RCOMP] = (GLint) (f * rgba[i][RCOMP] + g * rFog);
223 rgba[i][GCOMP] = (GLint) (f * rgba[i][GCOMP] + g * gFog);
224 rgba[i][BCOMP] = (GLint) (f * rgba[i][BCOMP] + g * bFog);
225 }
226 break;
227 case GL_EXP2:
228 {
229 GLfloat negDensitySquared = -ctx->Fog.Density * ctx->Fog.Density;
230 for (i=0;i<n;i++) {
231 GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
232 GLfloat eyez = d / (c+ndcz);
233 GLfloat f, g;
234 GLfloat tmp = negDensitySquared * eyez * eyez;
235 #ifdef __alpha__
236 /* XXX this underflow check may be needed for other systems */
237 if (tmp < FLT_MIN_10_EXP)
238 f = exp( FLT_MIN_10_EXP );
239 else
240 #endif
241 f = exp( tmp );
242 g = 1.0F - f;
243 rgba[i][RCOMP] = (GLint) (f * rgba[i][RCOMP] + g * rFog);
244 rgba[i][GCOMP] = (GLint) (f * rgba[i][GCOMP] + g * gFog);
245 rgba[i][BCOMP] = (GLint) (f * rgba[i][BCOMP] + g * bFog);
246 }
247 }
248 break;
249 default:
250 gl_problem(ctx, "Bad fog mode in gl_fog_rgba_pixels");
251 return;
252 }
253 }
254
255
256
257
258 /*
259 * Apply fog to an array of color index pixels.
260 * Input: n - number of pixels
261 * z - array of integer depth values
262 * index - pixel color indexes
263 * Output: index - fogged pixel color indexes
264 */
265 void gl_fog_ci_pixels( const GLcontext *ctx,
266 GLuint n, const GLdepth z[], GLuint index[] )
267 {
268 GLfloat c = ctx->ProjectionMatrix.m[10];
269 GLfloat d = ctx->ProjectionMatrix.m[14];
270 GLuint i;
271
272 GLfloat tz = ctx->Viewport.WindowMap.m[MAT_TZ];
273 GLfloat szInv = 1.0F / ctx->Viewport.WindowMap.m[MAT_SZ];
274
275 switch (ctx->Fog.Mode) {
276 case GL_LINEAR:
277 {
278 GLfloat fogEnd = ctx->Fog.End;
279 GLfloat fogScale = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
280 for (i=0;i<n;i++) {
281 GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
282 GLfloat eyez = -d / (c+ndcz);
283 GLfloat f;
284 if (eyez < 0.0) eyez = -eyez;
285 f = (fogEnd - eyez) * fogScale;
286 f = CLAMP( f, 0.0F, 1.0F );
287 index[i] = (GLuint) ((GLfloat) index[i] + (1.0F-f) * ctx->Fog.Index);
288 }
289 }
290 break;
291 case GL_EXP:
292 for (i=0;i<n;i++) {
293 GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
294 GLfloat eyez = -d / (c+ndcz);
295 GLfloat f;
296 if (eyez < 0.0)
297 eyez = -eyez;
298 f = exp( -ctx->Fog.Density * eyez );
299 f = CLAMP( f, 0.0F, 1.0F );
300 index[i] = (GLuint) ((GLfloat) index[i] + (1.0F-f) * ctx->Fog.Index);
301 }
302 break;
303 case GL_EXP2:
304 {
305 GLfloat negDensitySquared = -ctx->Fog.Density * ctx->Fog.Density;
306 for (i=0;i<n;i++) {
307 GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
308 GLfloat eyez = -d / (c+ndcz);
309 GLfloat tmp, f;
310 if (eyez < 0.0)
311 eyez = -eyez;
312 tmp = negDensitySquared * eyez * eyez;
313 #ifdef __alpha__
314 /* XXX this underflow check may be needed for other systems */
315 if (tmp < FLT_MIN_10_EXP)
316 f = exp( FLT_MIN_10_EXP );
317 else
318 #endif
319 f = exp( tmp );
320 f = CLAMP( f, 0.0F, 1.0F );
321 index[i] = (GLuint) ((GLfloat) index[i] + (1.0F-f) * ctx->Fog.Index);
322 }
323 }
324 break;
325 default:
326 gl_problem(ctx, "Bad fog mode in gl_fog_ci_pixels");
327 return;
328 }
329 }
330