diff options
author | Brian Paul <brian.paul@tungstengraphics.com> | 2004-02-17 21:03:03 +0000 |
---|---|---|
committer | Brian Paul <brian.paul@tungstengraphics.com> | 2004-02-17 21:03:03 +0000 |
commit | 09da0b8e6621a831e3eeb9381430f2bed18a22ad (patch) | |
tree | e7e307c3a5ddd773b469cf17d0331822388b466e /src/mesa | |
parent | 9a389d4bdb8026063034767e1599be975cb4e2f2 (diff) |
A bit of an overhaul of the fog code.
glFogCoord didn't always work reliably.
ARB fragment program fog options work now.
Per-fragment fog computations are now perspective corrected.
Diffstat (limited to 'src/mesa')
-rw-r--r-- | src/mesa/swrast/s_context.c | 47 | ||||
-rw-r--r-- | src/mesa/swrast/s_context.h | 8 | ||||
-rw-r--r-- | src/mesa/swrast/s_fog.c | 391 | ||||
-rw-r--r-- | src/mesa/swrast/s_span.c | 4 | ||||
-rw-r--r-- | src/mesa/swrast/s_triangle.c | 1 | ||||
-rw-r--r-- | src/mesa/swrast/s_tritemp.h | 10 | ||||
-rw-r--r-- | src/mesa/tnl/t_context.c | 13 | ||||
-rw-r--r-- | src/mesa/tnl/t_context.h | 37 | ||||
-rw-r--r-- | src/mesa/tnl/t_vb_fog.c | 58 | ||||
-rw-r--r-- | src/mesa/tnl/tnl.h | 6 |
10 files changed, 336 insertions, 239 deletions
diff --git a/src/mesa/swrast/s_context.c b/src/mesa/swrast/s_context.c index c69d4cfd5d..800f79080f 100644 --- a/src/mesa/swrast/s_context.c +++ b/src/mesa/swrast/s_context.c @@ -1,8 +1,8 @@ /* * Mesa 3-D graphics library - * Version: 5.1 + * Version: 6.1 * - * Copyright (C) 1999-2003 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2004 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"), @@ -28,6 +28,7 @@ #include "imports.h" #include "context.h" +#include "colormac.h" #include "mtypes.h" #include "texobj.h" #include "nvfragprog.h" @@ -141,15 +142,17 @@ _swrast_update_polygon( GLcontext *ctx ) static void -_swrast_update_hint( GLcontext *ctx ) +_swrast_update_fog_hint( GLcontext *ctx ) { SWcontext *swrast = SWRAST_CONTEXT(ctx); swrast->_PreferPixelFog = (!swrast->AllowVertexFog || + ctx->FragmentProgram.Enabled || (ctx->Hint.Fog == GL_NICEST && swrast->AllowPixelFog)); } + /* * Update the swrast->_AnyTextureCombine flag. */ @@ -169,6 +172,36 @@ _swrast_update_texture_env( GLcontext *ctx ) } +/* + * Update swrast->_FogColor and swrast->_FogEnable values. + */ +static void +_swrast_update_fog_state( GLcontext *ctx ) +{ + SWcontext *swrast = SWRAST_CONTEXT(ctx); + + /* convert fog color to GLchan values */ + CLAMPED_FLOAT_TO_CHAN(swrast->_FogColor[RCOMP], ctx->Fog.Color[RCOMP]); + CLAMPED_FLOAT_TO_CHAN(swrast->_FogColor[GCOMP], ctx->Fog.Color[GCOMP]); + CLAMPED_FLOAT_TO_CHAN(swrast->_FogColor[BCOMP], ctx->Fog.Color[BCOMP]); + + /* determine if fog is needed */ + swrast->_FogEnabled = GL_FALSE; + if (ctx->Fog.Enabled) { + swrast->_FogEnabled = GL_TRUE; + } + else if (ctx->FragmentProgram.Enabled && + ctx->FragmentProgram.Current->Base.Target == GL_FRAGMENT_PROGRAM_ARB) { + const struct fragment_program *p; + p = (struct fragment_program *) ctx->FragmentProgram.Current; + if (p->FogOption != GL_NONE) { + swrast->_FogEnabled = GL_TRUE; + } + } +} + + + #define _SWRAST_NEW_DERIVED (_SWRAST_NEW_RASTERMASK | \ _NEW_TEXTURE | \ _NEW_HINT | \ @@ -393,12 +426,16 @@ _swrast_validate_derived( GLcontext *ctx ) if (swrast->NewState & _NEW_POLYGON) _swrast_update_polygon( ctx ); - if (swrast->NewState & _NEW_HINT) - _swrast_update_hint( ctx ); + if (swrast->NewState & (_NEW_HINT | _NEW_PROGRAM)) + _swrast_update_fog_hint( ctx ); if (swrast->NewState & _SWRAST_NEW_TEXTURE_ENV_MODE) _swrast_update_texture_env( ctx ); + if (swrast->NewState & _NEW_FOG) { + _swrast_update_fog_state( ctx ); + } + swrast->NewState = 0; swrast->StateChanges = 0; swrast->InvalidateState = _swrast_invalidate_state; diff --git a/src/mesa/swrast/s_context.h b/src/mesa/swrast/s_context.h index a9144af700..081d2557ad 100644 --- a/src/mesa/swrast/s_context.h +++ b/src/mesa/swrast/s_context.h @@ -1,8 +1,8 @@ /* * Mesa 3-D graphics library - * Version: 5.1 + * Version: 6.1 * - * Copyright (C) 1999-2003 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2004 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"), @@ -271,8 +271,10 @@ typedef struct GLuint _RasterMask; GLfloat _MinMagThresh[MAX_TEXTURE_IMAGE_UNITS]; GLfloat _BackfaceSign; - GLboolean _PreferPixelFog; + GLboolean _PreferPixelFog; /* Compute fog blend factor per fragment? */ GLboolean _AnyTextureCombine; + GLchan _FogColor[3]; + GLboolean _FogEnabled; /* Accum buffer temporaries. */ diff --git a/src/mesa/swrast/s_fog.c b/src/mesa/swrast/s_fog.c index da06e3f354..c46032b53c 100644 --- a/src/mesa/swrast/s_fog.c +++ b/src/mesa/swrast/s_fog.c @@ -67,204 +67,144 @@ _swrast_z_to_fogfactor(GLcontext *ctx, GLfloat z) } - /** - * 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? + * Apply fog to a span of RGBA pixels. + * The fog value are either in the span->array->fog array or interpolated from + * the fog/fogStep values. + * They fog values are either fog coordinates (Z) or fog blend factors. + * _PreferPixelFog should be in sync with that state! */ -static void -compute_fog_factors_from_z( const GLcontext *ctx, - GLuint n, - const GLdepth z[], - GLfloat fogFact[] ) +void +_swrast_fog_rgba_span( const GLcontext *ctx, struct sw_span *span ) { - 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]; - GLfloat szInv; - GLuint i; + const SWcontext *swrast = SWRAST_CONTEXT(ctx); + const GLchan rFog = swrast->_FogColor[RCOMP]; + const GLchan gFog = swrast->_FogColor[GCOMP]; + const GLchan bFog = swrast->_FogColor[BCOMP]; + const GLuint haveW = (span->interpMask & SPAN_W); + GLchan (*rgba)[4] = (GLchan (*)[4]) span->array->rgba; - if (ctx->Viewport._WindowMap.m[MAT_SZ] == 0.0) - szInv = 1.0F; - else - szInv = 1.0F / ctx->Viewport._WindowMap.m[MAT_SZ]; + ASSERT(swrast->_FogEnabled); + ASSERT((span->interpMask | span->arrayMask) & SPAN_FOG); + ASSERT(span->arrayMask & SPAN_RGBA); - /* - * Note: to compute eyeZ from the ndcZ we have to solve the following: - * - * p[10] * eyeZ + p[14] * eyeW - * ndcZ = --------------------------- - * p[11] * eyeZ + p[15] * eyeW - * - * Thus: - * - * p[14] * eyeW - p[15] * eyeW * ndcZ - * eyeZ = ---------------------------------- - * p[11] * ndcZ - p[10] - * - * If we note: - * a) if using an orthographic projection, p[11] = 0 and p[15] = 1. - * b) if using a perspective projection, p[11] = -1 and p[15] = 0. - * c) we assume eyeW = 1 (not always true- glVertex4) - * - * Then we can simplify the calculation of eyeZ quite a bit. We do - * separate calculations for the orthographic and perspective cases below. - * Note that we drop a negative sign or two since they don't matter. + /* NOTE: if haveW is true, that means the fog start/step values are + * perspective-corrected and we have to divide each fog coord by W. */ - switch (ctx->Fog.Mode) { + /* we need to compute fog blend factors */ + if (swrast->_PreferPixelFog) { + /* The span's fog values are fog coordinates, now compute blend factors + * and blend the fragment colors with the fog color. + */ + switch (ctx->Fog.Mode) { case GL_LINEAR: { - GLfloat fogEnd = ctx->Fog.End; - 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;i<n;i++) { - GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv; - GLfloat eyez = (ndcz - p14) / p10; - GLfloat f; - if (eyez < 0.0) - eyez = -eyez; - f = (fogEnd - eyez) * fogScale; - fogFact[i] = CLAMP(f, 0.0F, 1.0F); - } - } - else { - /* perspective */ - for (i=0;i<n;i++) { - GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv; - GLfloat eyez = p14 / (ndcz + p10); - GLfloat f; - if (eyez < 0.0) - eyez = -eyez; - f = (fogEnd - eyez) * fogScale; - fogFact[i] = CLAMP(f, 0.0F, 1.0F); - } + const GLfloat fogEnd = ctx->Fog.End; + const GLfloat fogScale = (ctx->Fog.Start == ctx->Fog.End) + ? 1.0F : 1.0F / (ctx->Fog.End - ctx->Fog.Start); + const GLfloat fogStep = span->fogStep; + GLfloat fogCoord = span->fog; + const GLfloat wStep = haveW ? span->dwdx : 0.0F; + GLfloat w = haveW ? span->w : 1.0F; + GLuint i; + for (i = 0; i < span->end; i++) { + GLfloat f, oneMinusF; + f = (fogEnd - FABSF(fogCoord/w)) * fogScale; + f = CLAMP(f, 0.0F, 1.0F); + oneMinusF = 1.0F - f; + rgba[i][RCOMP] = (GLchan) (f * rgba[i][RCOMP] + oneMinusF * rFog); + rgba[i][GCOMP] = (GLchan) (f * rgba[i][GCOMP] + oneMinusF * gFog); + rgba[i][BCOMP] = (GLchan) (f * rgba[i][BCOMP] + oneMinusF * bFog); + fogCoord += fogStep; + w += wStep; } } - break; + break; case GL_EXP: - if (ortho) { - for (i=0;i<n;i++) { - GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv; - GLfloat eyez = (ndcz - p14) / p10; - if (eyez < 0.0) - eyez = -eyez; - fogFact[i] = (GLfloat) exp( -ctx->Fog.Density * eyez ); - } - } - else { - /* perspective */ - for (i=0;i<n;i++) { - GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv; - GLfloat eyez = p14 / (ndcz + p10); - if (eyez < 0.0) - eyez = -eyez; - fogFact[i] = (GLfloat) exp( -ctx->Fog.Density * eyez ); + { + const GLfloat density = -ctx->Fog.Density; + const GLfloat fogStep = span->fogStep; + GLfloat fogCoord = span->fog; + const GLfloat wStep = haveW ? span->dwdx : 0.0F; + GLfloat w = haveW ? span->w : 1.0F; + GLuint i; + for (i = 0; i < span->end; i++) { + GLfloat f, oneMinusF; + f = (GLfloat) exp(density * FABSF(fogCoord/w)); + oneMinusF = 1.0F - f; + rgba[i][RCOMP] = (GLchan) (f * rgba[i][RCOMP] + oneMinusF * rFog); + rgba[i][GCOMP] = (GLchan) (f * rgba[i][GCOMP] + oneMinusF * gFog); + rgba[i][BCOMP] = (GLchan) (f * rgba[i][BCOMP] + oneMinusF * bFog); + fogCoord += fogStep; + w += wStep; } } - break; + break; case GL_EXP2: { - GLfloat negDensitySquared = -ctx->Fog.Density * ctx->Fog.Density; - if (ortho) { - for (i=0;i<n;i++) { - GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv; - GLfloat eyez = (ndcz - p14) / p10; - GLfloat tmp = negDensitySquared * eyez * eyez; + const GLfloat negDensitySquared = -ctx->Fog.Density * ctx->Fog.Density; + const GLfloat fogStep = span->fogStep; + GLfloat fogCoord = span->fog; + const GLfloat wStep = haveW ? span->dwdx : 0.0F; + GLfloat w = haveW ? span->w : 1.0F; + GLuint i; + for (i = 0; i < span->end; i++) { + const GLfloat coord = fogCoord / w; + GLfloat tmp = negDensitySquared * coord * coord; + GLfloat f, oneMinusF; #if defined(__alpha__) || defined(__alpha) - /* XXX this underflow check may be needed for other systems*/ - if (tmp < FLT_MIN_10_EXP) - tmp = FLT_MIN_10_EXP; + /* XXX this underflow check may be needed for other systems*/ + if (tmp < FLT_MIN_10_EXP) + tmp = FLT_MIN_10_EXP; #endif - fogFact[i] = (GLfloat) exp( tmp ); - } - } - else { - /* perspective */ - for (i=0;i<n;i++) { - GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv; - GLfloat eyez = p14 / (ndcz + p10); - GLfloat tmp = negDensitySquared * eyez * eyez; -#if defined(__alpha__) || defined(__alpha) - /* XXX this underflow check may be needed for other systems*/ - if (tmp < FLT_MIN_10_EXP) - tmp = FLT_MIN_10_EXP; -#endif - fogFact[i] = (GLfloat) exp( tmp ); - } + f = (GLfloat) exp(tmp); + f = CLAMP(f, 0.0F, 1.0F); + oneMinusF = 1.0F - f; + rgba[i][RCOMP] = (GLchan) (f * rgba[i][RCOMP] + oneMinusF * rFog); + rgba[i][GCOMP] = (GLchan) (f * rgba[i][GCOMP] + oneMinusF * gFog); + rgba[i][BCOMP] = (GLchan) (f * rgba[i][BCOMP] + oneMinusF * bFog); + fogCoord += fogStep; + w += wStep; } } - break; + break; default: - _mesa_problem(ctx, "Bad fog mode in compute_fog_factors_from_z"); + _mesa_problem(ctx, "Bad fog mode in _swrast_fog_rgba_span"); return; + } } -} - - - -/** - * Apply fog to a span of RGBA pixels. - * The fog factors are either in the span->array->fog or stored as base/step. - * These are fog _factors_, not fog coords. Fog coords were converted to - * fog factors per vertex. - */ -void -_swrast_fog_rgba_span( const GLcontext *ctx, struct sw_span *span ) -{ - const SWcontext *swrast = SWRAST_CONTEXT(ctx); - const GLuint n = span->end; - GLchan (*rgba)[4] = (GLchan (*)[4]) span->array->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) - _swrast_span_interpolate_z(ctx, span); - compute_fog_factors_from_z(ctx, n, span->array->z, span->array->fog); - span->arrayMask |= SPAN_FOG; - } - - if (span->arrayMask & SPAN_FOG) { - /* use fog array in span */ + else if (span->arrayMask & SPAN_FOG) { + /* The span's fog array values are blend factors. + * They were previously computed per-vertex. + */ GLuint i; - for (i = 0; i < n; i++) { - const GLfloat fog = span->array->fog[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); + for (i = 0; i < span->end; i++) { + const GLfloat f = span->array->fog[i]; + const GLfloat oneMinusF = 1.0F - f; + rgba[i][RCOMP] = (GLchan) (f * rgba[i][RCOMP] + oneMinusF * rFog); + rgba[i][GCOMP] = (GLchan) (f * rgba[i][GCOMP] + oneMinusF * gFog); + rgba[i][BCOMP] = (GLchan) (f * rgba[i][BCOMP] + oneMinusF * bFog); } } else { - /* interpolate fog factors */ - GLfloat fog = span->fog, dFog = span->fogStep; + /* The span's fog start/step values are blend factors. + * They were previously computed per-vertex. + */ + const GLfloat fogStep = span->fogStep; + GLfloat fog = span->fog; + const GLfloat wStep = haveW ? span->dwdx : 0.0F; + GLfloat w = haveW ? span->w : 1.0F; 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; + ASSERT(span->interpMask & SPAN_FOG); + for (i = 0; i < span->end; i++) { + const GLfloat fact = fog / w; + const GLfloat oneMinusF = 1.0F - fact; + rgba[i][RCOMP] = (GLchan) (fact * rgba[i][RCOMP] + oneMinusF * rFog); + rgba[i][GCOMP] = (GLchan) (fact * rgba[i][GCOMP] + oneMinusF * gFog); + rgba[i][BCOMP] = (GLchan) (fact * rgba[i][BCOMP] + oneMinusF * bFog); + fog += fogStep; + w += wStep; } } } @@ -277,37 +217,110 @@ void _swrast_fog_ci_span( const GLcontext *ctx, struct sw_span *span ) { const SWcontext *swrast = SWRAST_CONTEXT(ctx); - const GLuint n = span->end; + const GLuint haveW = (span->interpMask & SPAN_W); + const GLuint fogIndex = (GLuint) ctx->Fog.Index; GLuint *index = span->array->index; - ASSERT(ctx->Fog.Enabled); + ASSERT(swrast->_FogEnabled); ASSERT(span->arrayMask & SPAN_INDEX); ASSERT((span->interpMask | span->arrayMask) & SPAN_FOG); + /* we need to compute fog blend factors */ if (swrast->_PreferPixelFog) { - /* compute fog factor from each fragment's Z value */ - if ((span->interpMask & SPAN_Z) && (span->arrayMask & SPAN_Z) == 0) - _swrast_span_interpolate_z(ctx, span); - compute_fog_factors_from_z(ctx, n, span->array->z, span->array->fog); - span->arrayMask |= SPAN_FOG; + /* The span's fog values are fog coordinates, now compute blend factors + * and blend the fragment colors with the fog color. + */ + switch (ctx->Fog.Mode) { + case GL_LINEAR: + { + const GLfloat fogEnd = ctx->Fog.End; + const GLfloat fogScale = (ctx->Fog.Start == ctx->Fog.End) + ? 1.0F : 1.0F / (ctx->Fog.End - ctx->Fog.Start); + const GLfloat fogStep = span->fogStep; + GLfloat fogCoord = span->fog; + const GLfloat wStep = haveW ? span->dwdx : 0.0F; + GLfloat w = haveW ? span->w : 1.0F; + GLuint i; + for (i = 0; i < span->end; i++) { + GLfloat f = (fogEnd - FABSF(fogCoord/w)) * fogScale; + f = CLAMP(f, 0.0F, 1.0F); + index[i] = (GLuint) ((GLfloat) index[i] + (1.0F - f) * fogIndex); + fogCoord += fogStep; + w += wStep; + } + } + break; + case GL_EXP: + { + const GLfloat density = -ctx->Fog.Density; + const GLfloat fogStep = span->fogStep; + GLfloat fogCoord = span->fog; + const GLfloat wStep = haveW ? span->dwdx : 0.0F; + GLfloat w = haveW ? span->w : 1.0F; + GLuint i; + for (i = 0; i < span->end; i++) { + GLfloat f = (GLfloat) exp(density * FABSF(fogCoord/w)); + index[i] = (GLuint) ((GLfloat) index[i] + (1.0F - f) * fogIndex); + fogCoord += fogStep; + w += wStep; + } + } + break; + case GL_EXP2: + { + const GLfloat negDensitySquared = -ctx->Fog.Density * ctx->Fog.Density; + const GLfloat fogStep = span->fogStep; + GLfloat fogCoord = span->fog; + const GLfloat wStep = haveW ? span->dwdx : 0.0F; + GLfloat w = haveW ? span->w : 1.0F; + GLuint i; + for (i = 0; i < span->end; i++) { + const GLfloat coord = fogCoord / w; + GLfloat tmp = negDensitySquared * coord * coord; + GLfloat f; +#if defined(__alpha__) || defined(__alpha) + /* XXX this underflow check may be needed for other systems*/ + if (tmp < FLT_MIN_10_EXP) + tmp = FLT_MIN_10_EXP; +#endif + f = (GLfloat) exp(tmp); + f = CLAMP(f, 0.0F, 1.0F); + index[i] = (GLuint) ((GLfloat) index[i] + (1.0F - f) * fogIndex); + fogCoord += fogStep; + w += wStep; + } + } + break; + default: + _mesa_problem(ctx, "Bad fog mode in _swrast_fog_ci_span"); + return; + } } - - if (span->arrayMask & SPAN_FOG) { - const GLuint idx = (GLuint) ctx->Fog.Index; + else if (span->arrayMask & SPAN_FOG) { + /* The span's fog array values are blend factors. + * They were previously computed per-vertex. + */ GLuint i; - for (i = 0; i < n; i++) { - const GLfloat f = CLAMP(span->array->fog[i], 0.0F, 1.0F); - index[i] = (GLuint) ((GLfloat) index[i] + (1.0F - f) * idx); + for (i = 0; i < span->end; i++) { + const GLfloat f = span->array->fog[i]; + index[i] = (GLuint) ((GLfloat) index[i] + (1.0F - f) * fogIndex); } } else { - GLfloat fog = span->fog, dFog = span->fogStep; - const GLuint idx = (GLuint) ctx->Fog.Index; + /* The span's fog start/step values are blend factors. + * They were previously computed per-vertex. + */ + const GLfloat fogStep = span->fogStep; + GLfloat fog = span->fog; + const GLfloat wStep = haveW ? span->dwdx : 0.0F; + GLfloat w = haveW ? span->w : 1.0F; 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; + ASSERT(span->interpMask & SPAN_FOG); + for (i = 0; i < span->end; i++) { + const GLfloat f = fog / w; + index[i] = (GLuint) ((GLfloat) index[i] + (1.0F - f) * fogIndex); + fog += fogStep; + w += wStep; } } } diff --git a/src/mesa/swrast/s_span.c b/src/mesa/swrast/s_span.c index ee46f32307..cdd97f613a 100644 --- a/src/mesa/swrast/s_span.c +++ b/src/mesa/swrast/s_span.c @@ -1079,7 +1079,7 @@ _swrast_write_rgba_span( GLcontext *ctx, struct sw_span *span) } /* Fog */ - if (ctx->Fog.Enabled) { + if (swrast->_FogEnabled) { _swrast_fog_rgba_span(ctx, span); monoColor = GL_FALSE; } @@ -1354,7 +1354,7 @@ _swrast_write_texture_span( GLcontext *ctx, struct sw_span *span) } /* Fog */ - if (ctx->Fog.Enabled) { + if (swrast->_FogEnabled) { _swrast_fog_rgba_span(ctx, span); } diff --git a/src/mesa/swrast/s_triangle.c b/src/mesa/swrast/s_triangle.c index 257f06c24d..01cd754e4a 100644 --- a/src/mesa/swrast/s_triangle.c +++ b/src/mesa/swrast/s_triangle.c @@ -798,6 +798,7 @@ fast_persp_span(GLcontext *ctx, struct sw_span *span, */ #define NAME persp_textured_triangle #define INTERP_Z 1 +#define INTERP_W 1 #define INTERP_FOG 1 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE #define INTERP_RGB 1 diff --git a/src/mesa/swrast/s_tritemp.h b/src/mesa/swrast/s_tritemp.h index 28a80dee66..2e25e531cc 100644 --- a/src/mesa/swrast/s_tritemp.h +++ b/src/mesa/swrast/s_tritemp.h @@ -411,8 +411,14 @@ static void NAME(GLcontext *ctx, const SWvertex *v0, #ifdef INTERP_FOG span.interpMask |= SPAN_FOG; { +# ifdef INTERP_W + const GLfloat wMax = vMax->win[3], wMin = vMin->win[3], wMid = vMid->win[3]; + const GLfloat eMaj_dfog = vMax->fog * wMax - vMin->fog * wMin; + const GLfloat eBot_dfog = vMid->fog * wMid - vMin->fog * wMin; +# else const GLfloat eMaj_dfog = vMax->fog - vMin->fog; const GLfloat eBot_dfog = vMid->fog - vMin->fog; +# endif span.dfogdx = oneOverArea * (eMaj_dfog * eBot.dy - eMaj.dy * eBot_dfog); span.dfogdy = oneOverArea * (eMaj.dx * eBot_dfog - eMaj_dfog * eBot.dx); span.fogStep = span.dfogdx; @@ -802,7 +808,11 @@ static void NAME(GLcontext *ctx, const SWvertex *v0, dwOuter = span.dwdy + dxOuter * span.dwdx; #endif #ifdef INTERP_FOG +# ifdef INTERP_W + fogLeft = vLower->fog * vLower->win[3] + (span.dfogdx * adjx + span.dfogdy * adjy) * (1.0F/FIXED_SCALE); +# else fogLeft = vLower->fog + (span.dfogdx * adjx + span.dfogdy * adjy) * (1.0F/FIXED_SCALE); +# endif dfogOuter = span.dfogdy + dxOuter * span.dfogdx; #endif #ifdef INTERP_RGB diff --git a/src/mesa/tnl/t_context.c b/src/mesa/tnl/t_context.c index ec5f88cd96..626aa5290e 100644 --- a/src/mesa/tnl/t_context.c +++ b/src/mesa/tnl/t_context.c @@ -102,6 +102,7 @@ _tnl_CreateContext( GLcontext *ctx ) tnl->NeedNdcCoords = GL_TRUE; tnl->LoopbackDListCassettes = GL_FALSE; tnl->CalcDListNormalLengths = GL_TRUE; + tnl->AllowVertexFog = GL_TRUE; /* Hook our functions into exec and compile dispatch tables. */ @@ -144,6 +145,10 @@ _tnl_InvalidateState( GLcontext *ctx, GLuint new_state ) { TNLcontext *tnl = TNL_CONTEXT(ctx); + if (new_state & (_NEW_HINT)) { + tnl->_DoVertexFog = tnl->AllowVertexFog && (ctx->Hint.Fog != GL_NICEST); + } + if (new_state & _NEW_ARRAY) { tnl->pipeline.run_input_changes |= ctx->Array.NewState; /* overkill */ } @@ -259,3 +264,11 @@ _tnl_isolate_materials( GLcontext *ctx, GLboolean mode ) TNLcontext *tnl = TNL_CONTEXT(ctx); tnl->IsolateMaterials = mode; } + +void +_tnl_allow_vertex_fog( GLcontext *ctx, GLboolean value ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + tnl->AllowVertexFog = value; +} + diff --git a/src/mesa/tnl/t_context.h b/src/mesa/tnl/t_context.h index a9d36d2488..b7aff6c626 100644 --- a/src/mesa/tnl/t_context.h +++ b/src/mesa/tnl/t_context.h @@ -364,11 +364,6 @@ struct tnl_save { }; - - - - - struct tnl_vertex_arrays { /* Conventional vertex attribute arrays */ @@ -433,14 +428,13 @@ struct vertex_buffer /* Private data from _tnl_render_stage that has no business being * in this struct. */ - }; - /** Describes an individual operation on the pipeline. */ -struct tnl_pipeline_stage { +struct tnl_pipeline_stage +{ const char *name; GLuint check_state; /* All state referenced in check() -- * When is the pipeline_stage struct @@ -513,7 +507,8 @@ typedef void (*insert_func)( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in ); -struct tnl_clipspace_attr { +struct tnl_clipspace_attr +{ int attrib; int vertoffset; int vertattrsize; @@ -546,7 +541,8 @@ typedef void (*setup_func)( GLcontext *ctx, -struct tnl_clipspace { +struct tnl_clipspace +{ GLboolean need_extras; GLuint new_inputs; @@ -564,7 +560,8 @@ struct tnl_clipspace { }; -struct tnl_device_driver { +struct tnl_device_driver +{ /*** *** TNL Pipeline ***/ @@ -588,7 +585,8 @@ struct tnl_device_driver { /*** *** Rendering -- These functions called only from t_vb_render.c ***/ - struct { + struct + { void (*Start)(GLcontext *ctx); void (*Finish)(GLcontext *ctx); /* Called before and after all rendering operations, including DrawPixels, @@ -667,8 +665,11 @@ struct tnl_device_driver { }; -typedef struct { - +/** + * Context state for T&L context. + */ +typedef struct +{ /* Driver interface. */ struct tnl_device_driver Driver; @@ -693,23 +694,21 @@ typedef struct { struct tnl_vertex_arrays current; struct tnl_vertex_arrays array_inputs; - /* Clipspace/ndc/window vertex managment: */ struct tnl_clipspace clipspace; - /* Probably need a better configuration mechanism: */ GLboolean NeedNdcCoords; GLboolean LoopbackDListCassettes; GLboolean CalcDListNormalLengths; GLboolean IsolateMaterials; + GLboolean AllowVertexFog; - /* - */ - GLuint render_inputs; + GLboolean _DoVertexFog; /* eval fog function at each vertex? */ + GLuint render_inputs; GLvertexformat exec_vtxfmt; GLvertexformat save_vtxfmt; diff --git a/src/mesa/tnl/t_vb_fog.c b/src/mesa/tnl/t_vb_fog.c index 34f1e811cc..3be62e887b 100644 --- a/src/mesa/tnl/t_vb_fog.c +++ b/src/mesa/tnl/t_vb_fog.c @@ -71,7 +71,11 @@ do { \ #endif -static void init_static_data( void ) +/** + * Initialize the exp_table[] lookup table for approximating exp(). + */ +static void +init_static_data( void ) { GLfloat f = 0.0F; GLint i = 0; @@ -89,8 +93,8 @@ static void init_static_data( void ) * near and far clip plane distances). * Fog blend factors are in the range [0,1]. */ -static void compute_fog_blend_factors( GLcontext *ctx, GLvector4f *out, - const GLvector4f *in ) +static void +compute_fog_blend_factors(GLcontext *ctx, GLvector4f *out, const GLvector4f *in) { GLfloat end = ctx->Fog.End; GLfloat *v = in->start; @@ -109,19 +113,22 @@ static void compute_fog_blend_factors( GLcontext *ctx, GLvector4f *out, else d = 1.0F / (ctx->Fog.End - ctx->Fog.Start); for ( i = 0 ; i < n ; i++, STRIDE_F(v, stride)) { - GLfloat f = (end - FABSF(*v)) * d; + const GLfloat z = FABSF(*v); + GLfloat f = (end - z) * d; data[i][0] = CLAMP(f, 0.0F, 1.0F); } break; case GL_EXP: d = ctx->Fog.Density; - for ( i = 0 ; i < n ; i++, STRIDE_F(v,stride)) - NEG_EXP( data[i][0], d * FABSF(*v) ); + for ( i = 0 ; i < n ; i++, STRIDE_F(v,stride)) { + const GLfloat z = FABSF(*v); + NEG_EXP( data[i][0], d * z ); + } break; case GL_EXP2: d = ctx->Fog.Density*ctx->Fog.Density; for ( i = 0 ; i < n ; i++, STRIDE_F(v, stride)) { - GLfloat z = *v; + const GLfloat z = *v; NEG_EXP( data[i][0], d * z * z ); } break; @@ -132,10 +139,11 @@ static void compute_fog_blend_factors( GLcontext *ctx, GLvector4f *out, } -static GLboolean run_fog_stage( GLcontext *ctx, - struct tnl_pipeline_stage *stage ) +static GLboolean +run_fog_stage(GLcontext *ctx, struct tnl_pipeline_stage *stage) { - struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &tnl->vb; struct fog_stage_data *store = FOG_STAGE_DATA(stage); GLvector4f *input; @@ -143,12 +151,13 @@ static GLboolean run_fog_stage( GLcontext *ctx, return GL_TRUE; if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT) { - /* fog computed from Z depth */ + /* Fog is computed from vertex or fragment Z values */ /* source = VB->ObjPtr or VB->EyePtr coords */ /* dest = VB->FogCoordPtr = fog stage private storage */ VB->FogCoordPtr = &store->fogcoord; if (!ctx->_NeedEyeCoords) { + /* compute fog coords from object coords */ const GLfloat *m = ctx->ModelviewMatrixStack.Top->m; GLfloat plane[4]; @@ -171,6 +180,7 @@ static GLboolean run_fog_stage( GLcontext *ctx, input->count = VB->ObjPtr->count; } else { + /* fog coordinates = eye Z coordinates (use ABS later) */ input = &store->input; if (VB->EyePtr->size < 2) @@ -184,21 +194,26 @@ static GLboolean run_fog_stage( GLcontext *ctx, } else { /* use glFogCoord() coordinates */ - /* source = VB->FogCoordPtr */ - input = VB->FogCoordPtr; - /* dest = fog stage private storage */ - VB->FogCoordPtr = &store->fogcoord; + input = VB->FogCoordPtr; /* source data */ + VB->FogCoordPtr = &store->fogcoord; /* dest data */ } - /* compute blend factors from fog coordinates */ - compute_fog_blend_factors( ctx, VB->FogCoordPtr, input ); + if (tnl->_DoVertexFog) { + /* compute blend factors from fog coordinates */ + compute_fog_blend_factors( ctx, VB->FogCoordPtr, input ); + } + else { + /* results = incoming fog coords (compute fog per-fragment later) */ + VB->FogCoordPtr = input; + } VB->AttribPtr[_TNL_ATTRIB_FOG] = VB->FogCoordPtr; return GL_TRUE; } -static void check_fog_stage( GLcontext *ctx, struct tnl_pipeline_stage *stage ) +static void +check_fog_stage(GLcontext *ctx, struct tnl_pipeline_stage *stage) { stage->active = ctx->Fog.Enabled && !ctx->VertexProgram.Enabled; @@ -211,8 +226,8 @@ static void check_fog_stage( GLcontext *ctx, struct tnl_pipeline_stage *stage ) /* Called the first time stage->run() is invoked. */ -static GLboolean alloc_fog_data( GLcontext *ctx, - struct tnl_pipeline_stage *stage ) +static GLboolean +alloc_fog_data(GLcontext *ctx, struct tnl_pipeline_stage *stage) { TNLcontext *tnl = TNL_CONTEXT(ctx); struct fog_stage_data *store; @@ -234,7 +249,8 @@ static GLboolean alloc_fog_data( GLcontext *ctx, } -static void free_fog_data( struct tnl_pipeline_stage *stage ) +static void +free_fog_data(struct tnl_pipeline_stage *stage) { struct fog_stage_data *store = FOG_STAGE_DATA(stage); if (store) { diff --git a/src/mesa/tnl/tnl.h b/src/mesa/tnl/tnl.h index 9a2241d8fc..3be222a6e0 100644 --- a/src/mesa/tnl/tnl.h +++ b/src/mesa/tnl/tnl.h @@ -75,4 +75,10 @@ extern void _tnl_isolate_materials( GLcontext *ctx, GLboolean flag ); +/* Control whether T&L does per-vertex fog + */ +extern void +_tnl_allow_vertex_fog( GLcontext *ctx, GLboolean value ); + + #endif |