source: trunk/src/opengl/mesa/fog.c@ 3721

Last change on this file since 3721 was 3598, checked in by jeroen, 25 years ago

* empty log message *

File size: 11.8 KB
Line 
1/* $Id: fog.c,v 1.3 2000-05-23 20:40:33 jeroen 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/* $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#include "glheader.h"
34#include "types.h"
35#include "context.h"
36#include "fog.h"
37#include "macros.h"
38#include "mmath.h"
39#include "xform.h"
40#endif
41
42
43
44void
45_mesa_Fogf(GLenum pname, GLfloat param)
46{
47 _mesa_Fogfv(pname, &param);
48}
49
50
51void
52_mesa_Fogi(GLenum pname, GLint param )
53{
54 GLfloat fparam = (GLfloat) param;
55 _mesa_Fogfv(pname, &fparam);
56}
57
58
59void
60_mesa_Fogiv(GLenum pname, const GLint *params )
61{
62 GLfloat p[4];
63 switch (pname) {
64 case GL_FOG_MODE:
65 case GL_FOG_DENSITY:
66 case GL_FOG_START:
67 case GL_FOG_END:
68 case GL_FOG_INDEX:
69 p[0] = (GLfloat) *params;
70 break;
71 case GL_FOG_COLOR:
72 p[0] = INT_TO_FLOAT( params[0] );
73 p[1] = INT_TO_FLOAT( params[1] );
74 p[2] = INT_TO_FLOAT( params[2] );
75 p[3] = INT_TO_FLOAT( params[3] );
76 break;
77 default:
78 /* Error will be caught later in _mesa_Fogfv */
79 ;
80 }
81 _mesa_Fogfv(pname, p);
82}
83
84
85void
86_mesa_Fogfv( GLenum pname, const GLfloat *params )
87{
88 GET_CURRENT_CONTEXT(ctx);
89 GLenum m;
90
91 switch (pname) {
92 case GL_FOG_MODE:
93 m = (GLenum) (GLint) *params;
94 if (m==GL_LINEAR || m==GL_EXP || m==GL_EXP2) {
95 ctx->Fog.Mode = m;
96 }
97 else {
98 gl_error( ctx, GL_INVALID_ENUM, "glFog" );
99 return;
100 }
101 break;
102 case GL_FOG_DENSITY:
103 if (*params<0.0) {
104 gl_error( ctx, GL_INVALID_VALUE, "glFog" );
105 return;
106 }
107 else {
108 ctx->Fog.Density = *params;
109 }
110 break;
111 case GL_FOG_START:
112 ctx->Fog.Start = *params;
113 break;
114 case GL_FOG_END:
115 ctx->Fog.End = *params;
116 break;
117 case GL_FOG_INDEX:
118 ctx->Fog.Index = *params;
119 break;
120 case GL_FOG_COLOR:
121 ctx->Fog.Color[0] = params[0];
122 ctx->Fog.Color[1] = params[1];
123 ctx->Fog.Color[2] = params[2];
124 ctx->Fog.Color[3] = params[3];
125 break;
126 default:
127 gl_error( ctx, GL_INVALID_ENUM, "glFog" );
128 return;
129 }
130
131 if (ctx->Driver.Fogfv) {
132 (*ctx->Driver.Fogfv)( ctx, pname, params );
133 }
134
135 ctx->NewState |= NEW_FOG;
136}
137
138
139typedef void (*fog_func)( struct vertex_buffer *VB, GLuint side,
140 GLubyte flag );
141
142typedef void (*fog_coord_func)( struct vertex_buffer *VB,
143 const GLvector4f *from,
144 GLubyte flag );
145
146static fog_func fog_ci_tab[2];
147static fog_func fog_rgba_tab[2];
148static fog_coord_func make_fog_coord_tab[2];
149
150/*
151 * Compute the fogged color for an array of vertices.
152 * Input: n - number of vertices
153 * v - array of vertices
154 * color - the original vertex colors
155 * Output: color - the fogged colors
156 *
157 */
158#define TAG(x) x##_raw
159#define CULLCHECK
160#define IDX 0
161#include "fog_tmp.h"
162
163#define TAG(x) x##_masked
164#define CULLCHECK if (cullmask[i]&flag)
165#define IDX 1
166#include "fog_tmp.h"
167
168
169void
170_mesa_init_fog( void )
171{
172 init_fog_tab_masked();
173 init_fog_tab_raw();
174}
175
176
177/*
178 * Compute fog for the vertices in the vertex buffer.
179 */
180void
181_mesa_fog_vertices( struct vertex_buffer *VB )
182{
183 GLcontext *ctx = VB->ctx;
184 GLuint i = VB->CullMode & 1;
185
186 if (ctx->Visual->RGBAflag) {
187 /* Fog RGB colors */
188 if (ctx->TriangleCaps & DD_TRI_LIGHT_TWOSIDE) {
189 fog_rgba_tab[i]( VB, 0, VERT_FACE_FRONT );
190 fog_rgba_tab[i]( VB, 1, VERT_FACE_REAR );
191 } else {
192 fog_rgba_tab[i]( VB, 0, VERT_FACE_FRONT|VERT_FACE_REAR );
193 }
194 }
195 else {
196 /* Fog color indexes */
197 if (ctx->TriangleCaps & DD_TRI_LIGHT_TWOSIDE) {
198 fog_ci_tab[i]( VB, 0, VERT_FACE_FRONT );
199 fog_ci_tab[i]( VB, 1, VERT_FACE_REAR );
200 } else {
201 fog_ci_tab[i]( VB, 0, VERT_FACE_FRONT|VERT_FACE_REAR );
202 }
203 }
204}
205
206
207static void check_fog_coords( GLcontext *ctx, struct gl_pipeline_stage *d )
208{
209 d->type = 0;
210
211 if (ctx->FogMode==FOG_FRAGMENT)
212 {
213 d->type = PIPE_IMMEDIATE|PIPE_PRECALC;
214 d->inputs = VERT_OBJ_ANY;
215 d->outputs = VERT_FOG_COORD;
216 }
217}
218
219
220static void gl_make_fog_coords( struct vertex_buffer *VB )
221{
222 GLcontext *ctx = VB->ctx;
223
224 /* If full eye coords weren't required, just calculate the eye Z
225 * values.
226 */
227 if (!ctx->NeedEyeCoords) {
228 GLfloat *m = ctx->ModelView.m;
229 GLfloat plane[4];
230
231 plane[0] = m[2];
232 plane[1] = m[6];
233 plane[2] = m[10];
234 plane[3] = m[14];
235
236 gl_dotprod_tab[0][VB->ObjPtr->size](&VB->Eye,
237 2, /* fill z coordinates */
238 VB->ObjPtr,
239 plane,
240 0 );
241
242 make_fog_coord_tab[0]( VB, &VB->Eye, 0 );
243 }
244 else
245 {
246 make_fog_coord_tab[0]( VB, VB->EyePtr, 0 );
247 }
248}
249
250
251/* Drivers that want fog coordinates in VB->Spec[0] alpha, can substitute this
252 * stage for the default PIPE_OP_FOG pipeline stage.
253 */
254struct gl_pipeline_stage gl_fog_coord_stage = {
255 "build fog coordinates",
256 PIPE_OP_FOG,
257 PIPE_PRECALC|PIPE_IMMEDIATE,
258 0,
259 NEW_FOG,
260 NEW_LIGHTING|NEW_RASTER_OPS|NEW_FOG|NEW_MODELVIEW,
261 0, 0,
262 0, 0, 0,
263 check_fog_coords,
264 gl_make_fog_coords
265};
266
267
268
269
270
271/*
272 * Apply fog to an array of RGBA pixels.
273 * Input: n - number of pixels
274 * z - array of integer depth values
275 * red, green, blue, alpha - pixel colors
276 * Output: red, green, blue, alpha - fogged pixel colors
277 */
278void
279_mesa_fog_rgba_pixels( const GLcontext *ctx,
280 GLuint n, const GLdepth z[], GLubyte rgba[][4] )
281{
282 GLfloat c = ctx->ProjectionMatrix.m[10];
283 GLfloat d = ctx->ProjectionMatrix.m[14];
284 GLuint i;
285
286 GLfloat rFog = ctx->Fog.Color[0] * 255.0F;
287 GLfloat gFog = ctx->Fog.Color[1] * 255.0F;
288 GLfloat bFog = ctx->Fog.Color[2] * 255.0F;
289
290 GLfloat tz = ctx->Viewport.WindowMap.m[MAT_TZ];
291 GLfloat szInv = 1.0F / ctx->Viewport.WindowMap.m[MAT_SZ];
292
293 switch (ctx->Fog.Mode) {
294 case GL_LINEAR:
295 {
296 GLfloat fogEnd = ctx->Fog.End;
297 GLfloat fogScale = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
298 for (i=0;i<n;i++) {
299 GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
300 GLfloat eyez = -d / (c+ndcz);
301 GLfloat f, g;
302 if (eyez < 0.0) eyez = -eyez;
303 f = (fogEnd - eyez) * fogScale;
304 f = CLAMP( f, 0.0F, 1.0F );
305 g = 1.0F - f;
306 rgba[i][RCOMP] = (GLint) (f * rgba[i][RCOMP] + g * rFog);
307 rgba[i][GCOMP] = (GLint) (f * rgba[i][GCOMP] + g * gFog);
308 rgba[i][BCOMP] = (GLint) (f * rgba[i][BCOMP] + g * bFog);
309 }
310 }
311 break;
312 case GL_EXP:
313 for (i=0;i<n;i++) {
314 GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
315 GLfloat eyez = d / (c+ndcz);
316 GLfloat f, g;
317 if (eyez < 0.0)
318 eyez = -eyez;
319 f = exp( -ctx->Fog.Density * eyez );
320 g = 1.0F - f;
321 rgba[i][RCOMP] = (GLint) (f * rgba[i][RCOMP] + g * rFog);
322 rgba[i][GCOMP] = (GLint) (f * rgba[i][GCOMP] + g * gFog);
323 rgba[i][BCOMP] = (GLint) (f * rgba[i][BCOMP] + g * bFog);
324 }
325 break;
326 case GL_EXP2:
327 {
328 GLfloat negDensitySquared = -ctx->Fog.Density * ctx->Fog.Density;
329 for (i=0;i<n;i++) {
330 GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
331 GLfloat eyez = d / (c+ndcz);
332 GLfloat f, g;
333 GLfloat tmp = negDensitySquared * eyez * eyez;
334#ifdef __alpha__
335 /* XXX this underflow check may be needed for other systems */
336 if (tmp < FLT_MIN_10_EXP)
337 f = exp( FLT_MIN_10_EXP );
338 else
339#endif
340 f = exp( tmp );
341 g = 1.0F - f;
342 rgba[i][RCOMP] = (GLint) (f * rgba[i][RCOMP] + g * rFog);
343 rgba[i][GCOMP] = (GLint) (f * rgba[i][GCOMP] + g * gFog);
344 rgba[i][BCOMP] = (GLint) (f * rgba[i][BCOMP] + g * bFog);
345 }
346 }
347 break;
348 default:
349 gl_problem(ctx, "Bad fog mode in _mesa_fog_rgba_pixels");
350 return;
351 }
352}
353
354
355
356
357/*
358 * Apply fog to an array of color index pixels.
359 * Input: n - number of pixels
360 * z - array of integer depth values
361 * index - pixel color indexes
362 * Output: index - fogged pixel color indexes
363 */
364void
365_mesa_fog_ci_pixels( const GLcontext *ctx,
366 GLuint n, const GLdepth z[], GLuint index[] )
367{
368 GLfloat c = ctx->ProjectionMatrix.m[10];
369 GLfloat d = ctx->ProjectionMatrix.m[14];
370 GLuint i;
371
372 GLfloat tz = ctx->Viewport.WindowMap.m[MAT_TZ];
373 GLfloat szInv = 1.0F / ctx->Viewport.WindowMap.m[MAT_SZ];
374
375 switch (ctx->Fog.Mode) {
376 case GL_LINEAR:
377 {
378 GLfloat fogEnd = ctx->Fog.End;
379 GLfloat fogScale = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
380 for (i=0;i<n;i++) {
381 GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
382 GLfloat eyez = -d / (c+ndcz);
383 GLfloat f;
384 if (eyez < 0.0) eyez = -eyez;
385 f = (fogEnd - eyez) * fogScale;
386 f = CLAMP( f, 0.0F, 1.0F );
387 index[i] = (GLuint) ((GLfloat) index[i] + (1.0F-f) * ctx->Fog.Index);
388 }
389 }
390 break;
391 case GL_EXP:
392 for (i=0;i<n;i++) {
393 GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
394 GLfloat eyez = -d / (c+ndcz);
395 GLfloat f;
396 if (eyez < 0.0)
397 eyez = -eyez;
398 f = exp( -ctx->Fog.Density * eyez );
399 f = CLAMP( f, 0.0F, 1.0F );
400 index[i] = (GLuint) ((GLfloat) index[i] + (1.0F-f) * ctx->Fog.Index);
401 }
402 break;
403 case GL_EXP2:
404 {
405 GLfloat negDensitySquared = -ctx->Fog.Density * ctx->Fog.Density;
406 for (i=0;i<n;i++) {
407 GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
408 GLfloat eyez = -d / (c+ndcz);
409 GLfloat tmp, f;
410 if (eyez < 0.0)
411 eyez = -eyez;
412 tmp = negDensitySquared * eyez * eyez;
413#ifdef __alpha__
414 /* XXX this underflow check may be needed for other systems */
415 if (tmp < FLT_MIN_10_EXP)
416 f = exp( FLT_MIN_10_EXP );
417 else
418#endif
419 f = exp( tmp );
420 f = CLAMP( f, 0.0F, 1.0F );
421 index[i] = (GLuint) ((GLfloat) index[i] + (1.0F-f) * ctx->Fog.Index);
422 }
423 }
424 break;
425 default:
426 gl_problem(ctx, "Bad fog mode in _mesa_fog_ci_pixels");
427 return;
428 }
429}
430
Note: See TracBrowser for help on using the repository browser.