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