X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fswrast%2Fs_fog.c;h=0988ebb1a7d2e96af773d366b2d2495111824cac;hb=612fc012934d9ec61972c3cfd914923937339611;hp=dfdc1821f26e60182a10c914f7e5fd065965c0db;hpb=30971cd098d147a4363df0dec0c338587dc1478f;p=mesa.git diff --git a/src/mesa/swrast/s_fog.c b/src/mesa/swrast/s_fog.c index dfdc1821f26..0988ebb1a7d 100644 --- a/src/mesa/swrast/s_fog.c +++ b/src/mesa/swrast/s_fog.c @@ -1,21 +1,21 @@ -/* $Id: s_fog.c,v 1.3 2000/11/15 00:26:01 brianp Exp $ */ +/* $Id: s_fog.c,v 1.22 2002/02/17 17:30:58 brianp Exp $ */ /* * Mesa 3-D graphics library - * Version: 3.5 - * - * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. - * + * Version: 4.1 + * + * Copyright (C) 1999-2002 Brian Paul All Rights Reserved. + * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL @@ -33,82 +33,71 @@ #include "s_context.h" #include "s_fog.h" +#include "s_span.h" -/* - * Apply fog to an array of RGBA pixels. - * Input: n - number of pixels - * fog - array of interpolated screen-space fog coordinates in [0..1] - * red, green, blue, alpha - pixel colors - * Output: red, green, blue, alpha - fogged pixel colors - */ -void -_mesa_fog_rgba_pixels( const GLcontext *ctx, - GLuint n, - const GLfixed fog[], - GLchan rgba[][4] ) -{ - GLfixed rFog = ctx->Fog.Color[0] * CHAN_MAXF; - GLfixed gFog = ctx->Fog.Color[1] * CHAN_MAXF; - GLfixed bFog = ctx->Fog.Color[2] * CHAN_MAXF; - GLuint i; - - for (i=0;i> FIXED_SHIFT; - rgba[i][1] = (f*rgba[i][1] + g*gFog) >> FIXED_SHIFT; - rgba[i][2] = (f*rgba[i][2] + g*bFog) >> FIXED_SHIFT; - } -} - - -/* - * Apply fog to an array of color index pixels. - * Input: n - number of pixels - * z - array of integer depth values - * index - pixel color indexes - * Output: index - fogged pixel color indexes +/** + * Used to convert current raster distance to a fog factor in [0,1]. */ -void -_mesa_fog_ci_pixels( const GLcontext *ctx, - GLuint n, const GLfixed fog[], GLuint index[] ) +GLfloat +_mesa_z_to_fogfactor(GLcontext *ctx, GLfloat z) { - GLuint idx = ctx->Fog.Index; - GLuint i; + GLfloat d, f; - for (i=0;iFog.Mode) { + case GL_LINEAR: + if (ctx->Fog.Start == ctx->Fog.End) + d = 1.0F; + else + d = 1.0F / (ctx->Fog.End - ctx->Fog.Start); + f = (ctx->Fog.End - z) * d; + return CLAMP(f, 0.0F, 1.0F); + case GL_EXP: + d = ctx->Fog.Density; + f = (GLfloat) exp(-d * z); + return f; + case GL_EXP2: + d = ctx->Fog.Density; + f = (GLfloat) exp(-(d * d * z * z)); + return f; + default: + _mesa_problem(ctx, "Bad fog mode in _mesa_z_to_fogfactor"); + return 0.0; } } -/* - * Calculate fog coords from window z values +/** + * Calculate fog factors (in [0,1]) from window z values * Input: n - number of pixels * z - array of integer depth values * red, green, blue, alpha - pixel colors * Output: red, green, blue, alpha - fogged pixel colors * - * Use lookup table & interpolation? + * Use lookup table & interpolation? */ -void -_mesa_win_fog_coords_from_z( const GLcontext *ctx, - GLuint n, - const GLdepth z[], - GLfixed fogcoord[] ) +static void +compute_fog_factors_from_z( const GLcontext *ctx, + GLuint n, + const GLdepth z[], + GLfloat fogFact[] ) { - const GLboolean ortho = (ctx->ProjectionMatrix.m[15] != 0.0F); - const GLfloat p10 = ctx->ProjectionMatrix.m[10]; - const GLfloat p14 = ctx->ProjectionMatrix.m[14]; + const GLfloat *proj = ctx->ProjectionMatrixStack.Top->m; + const GLboolean ortho = (proj[15] != 0.0F); + const GLfloat p10 = proj[10]; + const GLfloat p14 = proj[14]; const GLfloat tz = ctx->Viewport._WindowMap.m[MAT_TZ]; - const GLfloat szInv = 1.0F / ctx->Viewport._WindowMap.m[MAT_SZ]; + GLfloat szInv; GLuint i; + if (ctx->Viewport._WindowMap.m[MAT_SZ] == 0.0) + szInv = 1.0F; + else + szInv = 1.0F / ctx->Viewport._WindowMap.m[MAT_SZ]; + /* * Note: to compute eyeZ from the ndcZ we have to solve the following: * @@ -136,14 +125,18 @@ _mesa_win_fog_coords_from_z( const GLcontext *ctx, case GL_LINEAR: { GLfloat fogEnd = ctx->Fog.End; - GLfloat fogScale = (GLfloat) FIXED_ONE / (ctx->Fog.End - - ctx->Fog.Start); + GLfloat fogScale; + if (ctx->Fog.Start == ctx->Fog.End) + fogScale = 1.0; + else + fogScale = 1.0F / (ctx->Fog.End - ctx->Fog.Start); if (ortho) { for (i=0;iFog.Density * eyez )); + if (eyez < 0.0) + eyez = -eyez; + fogFact[i] = (GLfloat) exp( -ctx->Fog.Density * eyez ); } } else { @@ -171,8 +166,9 @@ _mesa_win_fog_coords_from_z( const GLcontext *ctx, for (i=0;iFog.Density * eyez )); + if (eyez < 0.0) + eyez = -eyez; + fogFact[i] = (GLfloat) exp( -ctx->Fog.Density * eyez ); } } break; @@ -189,7 +185,7 @@ _mesa_win_fog_coords_from_z( const GLcontext *ctx, if (tmp < FLT_MIN_10_EXP) tmp = FLT_MIN_10_EXP; #endif - fogcoord[i] = FloatToFixed(exp( tmp )); + fogFact[i] = (GLfloat) exp( tmp ); } } else { @@ -203,48 +199,111 @@ _mesa_win_fog_coords_from_z( const GLcontext *ctx, if (tmp < FLT_MIN_10_EXP) tmp = FLT_MIN_10_EXP; #endif - fogcoord[i] = FloatToFixed(exp( tmp )); + fogFact[i] = (GLfloat) exp( tmp ); } } } break; default: - gl_problem(ctx, "Bad fog mode in _mesa_win_fog_coords_from_z"); + _mesa_problem(ctx, "Bad fog mode in compute_fog_factors_from_z"); return; } } -/* - * Apply fog to an array of RGBA pixels. - * Input: n - number of pixels - * z - array of integer depth values - * red, green, blue, alpha - pixel colors - * Output: red, green, blue, alpha - fogged pixel colors + +/** + * Apply fog to a span of RGBA pixels. + * The fog factors are either in the span->fogArray or stored as base/step. + * These are fog _factors_, not fog coords. Fog coords were converted to + * fog factors per vertex. */ void -_mesa_depth_fog_rgba_pixels( const GLcontext *ctx, - GLuint n, const GLdepth z[], GLchan rgba[][4] ) +_mesa_fog_rgba_span( const GLcontext *ctx, struct sw_span *span ) { - GLfixed fog[MAX_WIDTH]; - _mesa_win_fog_coords_from_z( ctx, n, z, fog ); - _mesa_fog_rgba_pixels( ctx, n, fog, rgba ); + const SWcontext *swrast = SWRAST_CONTEXT(ctx); + const GLuint n = span->end; + GLchan (*rgba)[4] = (GLchan (*)[4]) span->color.rgba; + GLchan rFog, gFog, bFog; + + ASSERT(ctx->Fog.Enabled); + ASSERT((span->interpMask | span->arrayMask) & SPAN_FOG); + ASSERT(span->arrayMask & SPAN_RGBA); + + UNCLAMPED_FLOAT_TO_CHAN(rFog, ctx->Fog.Color[RCOMP]); + UNCLAMPED_FLOAT_TO_CHAN(gFog, ctx->Fog.Color[GCOMP]); + UNCLAMPED_FLOAT_TO_CHAN(bFog, ctx->Fog.Color[BCOMP]); + + if (swrast->_PreferPixelFog) { + /* compute fog factor from each fragment's Z value */ + if ((span->interpMask & SPAN_Z) && (span->arrayMask & SPAN_Z) == 0) + _mesa_span_interpolate_z(ctx, span); + compute_fog_factors_from_z(ctx, n, span->zArray, span->fogArray); + span->arrayMask |= SPAN_FOG; + } + + if (span->arrayMask & SPAN_FOG) { + GLuint i; + for (i = 0; i < n; i++) { + const GLfloat fog = span->fogArray[i]; + const GLfloat oneMinusFog = 1.0F - fog; + rgba[i][RCOMP] = (GLchan) (fog * rgba[i][RCOMP] + oneMinusFog * rFog); + rgba[i][GCOMP] = (GLchan) (fog * rgba[i][GCOMP] + oneMinusFog * gFog); + rgba[i][BCOMP] = (GLchan) (fog * rgba[i][BCOMP] + oneMinusFog * bFog); + } + } + else { + GLfloat fog = span->fog, dFog = span->fogStep; + GLuint i; + for (i = 0; i < n; i++) { + const GLfloat oneMinusFog = 1.0F - fog; + rgba[i][RCOMP] = (GLchan) (fog * rgba[i][RCOMP] + oneMinusFog * rFog); + rgba[i][GCOMP] = (GLchan) (fog * rgba[i][GCOMP] + oneMinusFog * gFog); + rgba[i][BCOMP] = (GLchan) (fog * rgba[i][BCOMP] + oneMinusFog * bFog); + fog += dFog; + } + } } -/* - * Apply fog to an array of color index pixels. - * Input: n - number of pixels - * z - array of integer depth values - * index - pixel color indexes - * Output: index - fogged pixel color indexes +/** + * As above, but color index mode. */ void -_mesa_depth_fog_ci_pixels( const GLcontext *ctx, - GLuint n, const GLdepth z[], GLuint index[] ) +_mesa_fog_ci_span( const GLcontext *ctx, struct sw_span *span ) { - GLfixed fog[MAX_WIDTH]; - _mesa_win_fog_coords_from_z( ctx, n, z, fog ); - _mesa_fog_ci_pixels( ctx, n, fog, index ); -} + const SWcontext *swrast = SWRAST_CONTEXT(ctx); + const GLuint n = span->end; + GLuint *index = span->color.index; + ASSERT(ctx->Fog.Enabled); + ASSERT(span->arrayMask & SPAN_INDEX); + ASSERT((span->interpMask | span->arrayMask) & SPAN_FOG); + + if (swrast->_PreferPixelFog) { + /* compute fog factor from each fragment's Z value */ + if ((span->interpMask & SPAN_Z) && (span->arrayMask & SPAN_Z) == 0) + _mesa_span_interpolate_z(ctx, span); + compute_fog_factors_from_z(ctx, n, span->zArray, span->fogArray); + span->arrayMask |= SPAN_FOG; + } + + if (span->arrayMask & SPAN_FOG) { + const GLuint idx = (GLuint) ctx->Fog.Index; + GLuint i; + for (i = 0; i < n; i++) { + const GLfloat f = CLAMP(span->fogArray[i], 0.0F, 1.0F); + index[i] = (GLuint) ((GLfloat) index[i] + (1.0F - f) * idx); + } + } + else { + GLfloat fog = span->fog, dFog = span->fogStep; + const GLuint idx = (GLuint) ctx->Fog.Index; + GLuint i; + for (i = 0; i < n; i++) { + const GLfloat f = CLAMP(fog, 0.0F, 1.0F); + index[i] = (GLuint) ((GLfloat) index[i] + (1.0F - f) * idx); + fog += dFog; + } + } +}