added memory macros
[mesa.git] / src / mesa / main / fog.c
1 /* $Id: fog.c,v 1.2 1999/10/08 09:27:10 keithw 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 #ifdef XFree86Server
45 #include "GL/xf86glx.h"
46 #endif
47 #endif
48
49
50
51 void gl_Fogfv( GLcontext *ctx, GLenum pname, const GLfloat *params )
52 {
53 GLenum m;
54
55 switch (pname) {
56 case GL_FOG_MODE:
57 m = (GLenum) (GLint) *params;
58 if (m==GL_LINEAR || m==GL_EXP || m==GL_EXP2) {
59 ctx->Fog.Mode = m;
60 }
61 else {
62 gl_error( ctx, GL_INVALID_ENUM, "glFog" );
63 return;
64 }
65 break;
66 case GL_FOG_DENSITY:
67 if (*params<0.0) {
68 gl_error( ctx, GL_INVALID_VALUE, "glFog" );
69 return;
70 }
71 else {
72 ctx->Fog.Density = *params;
73 }
74 break;
75 case GL_FOG_START:
76 #if 0
77 /* Prior to OpenGL 1.1, this was an error */
78 if (*params<0.0F) {
79 gl_error( ctx, GL_INVALID_VALUE, "glFog(GL_FOG_START)" );
80 return;
81 }
82 #endif
83 ctx->Fog.Start = *params;
84 break;
85 case GL_FOG_END:
86 #if 0
87 /* Prior to OpenGL 1.1, this was an error */
88 if (*params<0.0F) {
89 gl_error( ctx, GL_INVALID_VALUE, "glFog(GL_FOG_END)" );
90 return;
91 }
92 #endif
93 ctx->Fog.End = *params;
94 break;
95 case GL_FOG_INDEX:
96 ctx->Fog.Index = *params;
97 break;
98 case GL_FOG_COLOR:
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];
103 break;
104 default:
105 gl_error( ctx, GL_INVALID_ENUM, "glFog" );
106 return;
107 }
108
109 if (ctx->Driver.Fogfv) {
110 (*ctx->Driver.Fogfv)( ctx, pname, params );
111 }
112
113 ctx->NewState |= NEW_FOG;
114 }
115
116
117 typedef void (*fog_func)( struct vertex_buffer *VB, GLuint side,
118 GLubyte flag );
119
120
121 static fog_func fog_ci_tab[2];
122 static fog_func fog_rgba_tab[2];
123
124 /*
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
130 *
131 */
132 #define TAG(x) x##_raw
133 #define CULLCHECK
134 #define IDX 0
135 #include "fog_tmp.h"
136
137 #define TAG(x) x##_masked
138 #define CULLCHECK if (cullmask[i]&flag)
139 #define IDX 1
140 #include "fog_tmp.h"
141
142 void gl_init_fog( void )
143 {
144 init_fog_tab_masked();
145 init_fog_tab_raw();
146 }
147
148 /*
149 * Compute fog for the vertices in the vertex buffer.
150 */
151 void gl_fog_vertices( struct vertex_buffer *VB )
152 {
153 GLcontext *ctx = VB->ctx;
154 GLuint i = VB->CullMode & 1;
155
156 if (ctx->Visual->RGBAflag) {
157 /* Fog RGB colors */
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 );
161 } else {
162 fog_rgba_tab[i]( VB, 0, VERT_FACE_FRONT|VERT_FACE_REAR );
163 }
164 }
165 else {
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 );
170 } else {
171 fog_ci_tab[i]( VB, 0, VERT_FACE_FRONT|VERT_FACE_REAR );
172 }
173 }
174 }
175
176 /*
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
182 */
183 void gl_fog_rgba_pixels( const GLcontext *ctx,
184 GLuint n, const GLdepth z[], GLubyte rgba[][4] )
185 {
186 GLfloat c = ctx->ProjectionMatrix.m[10];
187 GLfloat d = ctx->ProjectionMatrix.m[14];
188 GLuint i;
189
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;
193
194 GLfloat tz = ctx->Viewport.WindowMap.m[MAT_TZ];
195 GLfloat szInv = 1.0F / ctx->Viewport.WindowMap.m[MAT_SZ];
196
197 switch (ctx->Fog.Mode) {
198 case GL_LINEAR:
199 {
200 GLfloat fogEnd = ctx->Fog.End;
201 GLfloat fogScale = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
202 for (i=0;i<n;i++) {
203 GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
204 GLfloat eyez = -d / (c+ndcz);
205 GLfloat f, g;
206 if (eyez < 0.0) eyez = -eyez;
207 f = (fogEnd - eyez) * fogScale;
208 f = CLAMP( f, 0.0F, 1.0F );
209 g = 1.0F - f;
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);
213 }
214 }
215 break;
216 case GL_EXP:
217 for (i=0;i<n;i++) {
218 GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
219 GLfloat eyez = d / (c+ndcz);
220 GLfloat f, g;
221 if (eyez < 0.0)
222 eyez = -eyez;
223 f = exp( -ctx->Fog.Density * eyez );
224 g = 1.0F - f;
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);
228 }
229 break;
230 case GL_EXP2:
231 {
232 GLfloat negDensitySquared = -ctx->Fog.Density * ctx->Fog.Density;
233 for (i=0;i<n;i++) {
234 GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
235 GLfloat eyez = d / (c+ndcz);
236 GLfloat f, g;
237 GLfloat tmp = negDensitySquared * eyez * eyez;
238 #ifdef __alpha__
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 );
242 else
243 #endif
244 f = exp( tmp );
245 g = 1.0F - f;
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);
249 }
250 }
251 break;
252 default:
253 gl_problem(ctx, "Bad fog mode in gl_fog_rgba_pixels");
254 return;
255 }
256 }
257
258
259
260
261 /*
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
267 */
268 void gl_fog_ci_pixels( const GLcontext *ctx,
269 GLuint n, const GLdepth z[], GLuint index[] )
270 {
271 GLfloat c = ctx->ProjectionMatrix.m[10];
272 GLfloat d = ctx->ProjectionMatrix.m[14];
273 GLuint i;
274
275 GLfloat tz = ctx->Viewport.WindowMap.m[MAT_TZ];
276 GLfloat szInv = 1.0F / ctx->Viewport.WindowMap.m[MAT_SZ];
277
278 switch (ctx->Fog.Mode) {
279 case GL_LINEAR:
280 {
281 GLfloat fogEnd = ctx->Fog.End;
282 GLfloat fogScale = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
283 for (i=0;i<n;i++) {
284 GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
285 GLfloat eyez = -d / (c+ndcz);
286 GLfloat f;
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);
291 }
292 }
293 break;
294 case GL_EXP:
295 for (i=0;i<n;i++) {
296 GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
297 GLfloat eyez = -d / (c+ndcz);
298 GLfloat f;
299 if (eyez < 0.0)
300 eyez = -eyez;
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);
304 }
305 break;
306 case GL_EXP2:
307 {
308 GLfloat negDensitySquared = -ctx->Fog.Density * ctx->Fog.Density;
309 for (i=0;i<n;i++) {
310 GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
311 GLfloat eyez = -d / (c+ndcz);
312 GLfloat tmp, f;
313 if (eyez < 0.0)
314 eyez = -eyez;
315 tmp = negDensitySquared * eyez * eyez;
316 #ifdef __alpha__
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 );
320 else
321 #endif
322 f = exp( tmp );
323 f = CLAMP( f, 0.0F, 1.0F );
324 index[i] = (GLuint) ((GLfloat) index[i] + (1.0F-f) * ctx->Fog.Index);
325 }
326 }
327 break;
328 default:
329 gl_problem(ctx, "Bad fog mode in gl_fog_ci_pixels");
330 return;
331 }
332 }
333