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

Last change on this file since 2977 was 2962, checked in by jeroen, 25 years ago

* empty log message *

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