X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fswrast%2Fs_fog.c;h=8b0bdf8fa289f6ed8cf9a0a1632535f068cc2794;hb=75da9c9933a97e6f2baf0884b98350df800ee785;hp=caaefcb688fbd14ef71b211e7d867b6265bbe40e;hpb=b37a084357dd08573b86d6d8c5ba43d65bdc1bd7;p=mesa.git diff --git a/src/mesa/swrast/s_fog.c b/src/mesa/swrast/s_fog.c index caaefcb688f..8b0bdf8fa28 100644 --- a/src/mesa/swrast/s_fog.c +++ b/src/mesa/swrast/s_fog.c @@ -1,10 +1,7 @@ -/* $Id: s_fog.c,v 1.21 2002/02/02 21:40:33 brianp Exp $ */ - /* * Mesa 3-D graphics library - * Version: 4.1 * - * Copyright (C) 1999-2002 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2006 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"), @@ -19,29 +16,26 @@ * 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 - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. */ -#include "glheader.h" -#include "colormac.h" -#include "context.h" -#include "macros.h" -#include "mmath.h" +#include "c99_math.h" +#include "main/glheader.h" +#include "main/macros.h" #include "s_context.h" #include "s_fog.h" - - /** * Used to convert current raster distance to a fog factor in [0,1]. */ GLfloat -_mesa_z_to_fogfactor(GLcontext *ctx, GLfloat z) +_swrast_z_to_fogfactor(struct gl_context *ctx, GLfloat z) { GLfloat d, f; @@ -55,321 +49,196 @@ _mesa_z_to_fogfactor(GLcontext *ctx, GLfloat z) return CLAMP(f, 0.0F, 1.0F); case GL_EXP: d = ctx->Fog.Density; - f = (GLfloat) exp(-d * z); + f = expf(-d * z); + f = CLAMP(f, 0.0F, 1.0F); return f; case GL_EXP2: d = ctx->Fog.Density; - f = (GLfloat) exp(-(d * d * z * z)); + f = expf(-(d * d * z * z)); + f = CLAMP(f, 0.0F, 1.0F); return f; default: - _mesa_problem(ctx, "Bad fog mode in make_fog_coord"); + _mesa_problem(ctx, "Bad fog mode in _swrast_z_to_fogfactor"); return 0.0; } } +#define LINEAR_FOG(f, coord) f = (fogEnd - coord) * fogScale -/** - * Apply fog to a span of RGBA pixels. - * Input: ctx - - * span - where span->fog and span->fogStep have to be set. - * red, green, blue, alpha - pixel colors - * Output: red, green, blue, alpha - fogged pixel colors - */ -void -_mesa_fog_rgba_pixels( const GLcontext *ctx, struct sw_span *span, - GLchan rgba[][4] ) -{ - GLuint i; - GLfloat fog = span->fog, Dfog = span->fogStep; - GLchan rFog, gFog, bFog; - - ASSERT(ctx->Fog.Enabled); - ASSERT(span->interpMask & 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]); +#define EXP_FOG(f, coord) f = expf(density * coord) - for (i = 0; i < span->end; i++) { - const GLfloat one_min_fog = 1.0F - fog; - rgba[i][RCOMP] = (GLchan) (fog * rgba[i][RCOMP] + one_min_fog * rFog); - rgba[i][GCOMP] = (GLchan) (fog * rgba[i][GCOMP] + one_min_fog * gFog); - rgba[i][BCOMP] = (GLchan) (fog * rgba[i][BCOMP] + one_min_fog * bFog); - fog += Dfog; - } -} +#define EXP2_FOG(f, coord) \ +do { \ + GLfloat tmp = negDensitySquared * coord * coord; \ + if (tmp < FLT_MIN_10_EXP) \ + tmp = FLT_MIN_10_EXP; \ + f = expf(tmp); \ + } while(0) -/** - * Apply fog given in an array to RGBA pixels. - * Input: ctx - - * span - - * fog - array of fog factors in [0,1] - * red, green, blue, alpha - pixel colors - * Output: red, green, blue, alpha - fogged pixel colors - */ -void -_mesa_fog_rgba_pixels_with_array( const GLcontext *ctx, struct sw_span *span, - const GLfloat fog[], GLchan rgba[][4] ) -{ - GLuint i; - GLchan rFog, gFog, bFog; - - ASSERT(fog != NULL); - ASSERT(ctx->Fog.Enabled); - 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]); - - for (i = span->start; i < span->end; i++) { - const GLfloat f = fog[i]; - const GLfloat g = 1.0F - f; - rgba[i][RCOMP] = (GLchan) (f * rgba[i][RCOMP] + g * rFog); - rgba[i][GCOMP] = (GLchan) (f * rgba[i][GCOMP] + g * gFog); - rgba[i][BCOMP] = (GLchan) (f * rgba[i][BCOMP] + g * bFog); - } -} +#define BLEND_FOG(f, coord) f = coord /** - * Apply fog to a span of color index pixels. - * Input: ctx - - * span - where span->fog and span->fogStep have to be set. - * index - pixel color indexes - * Output: index - fogged pixel color indexes + * Template code for computing fog blend factor and applying it to colors. + * \param TYPE either GLubyte, GLushort or GLfloat. + * \param COMPUTE_F code to compute the fog blend factor, f. */ -void -_mesa_fog_ci_pixels( const GLcontext *ctx, struct sw_span *span, - GLuint index[] ) -{ - GLuint idx = (GLuint) ctx->Fog.Index; - GLuint i; - GLfloat fog = span->fog, Dfog = span->fogStep; - - ASSERT(ctx->Fog.Enabled); - ASSERT(span->interpMask & SPAN_FOG); - ASSERT(span->arrayMask & SPAN_INDEX); - - for (i = 0; i < span->end; i++) { - const GLfloat f = CLAMP(fog, 0.0F, 1.0F); - index[i] = (GLuint) ((GLfloat) index[i] + (1.0F - f) * idx); - fog += Dfog; - } +#define FOG_LOOP(TYPE, FOG_FUNC) \ +if (span->arrayAttribs & VARYING_BIT_FOGC) { \ + GLuint i; \ + for (i = 0; i < span->end; i++) { \ + const GLfloat fogCoord = span->array->attribs[VARYING_SLOT_FOGC][i][0]; \ + const GLfloat c = fabsf(fogCoord); \ + GLfloat f, oneMinusF; \ + FOG_FUNC(f, c); \ + f = CLAMP(f, 0.0F, 1.0F); \ + oneMinusF = 1.0F - f; \ + rgba[i][RCOMP] = (TYPE) (f * rgba[i][RCOMP] + oneMinusF * rFog); \ + rgba[i][GCOMP] = (TYPE) (f * rgba[i][GCOMP] + oneMinusF * gFog); \ + rgba[i][BCOMP] = (TYPE) (f * rgba[i][BCOMP] + oneMinusF * bFog); \ + } \ +} \ +else { \ + const GLfloat fogStep = span->attrStepX[VARYING_SLOT_FOGC][0]; \ + GLfloat fogCoord = span->attrStart[VARYING_SLOT_FOGC][0]; \ + const GLfloat wStep = span->attrStepX[VARYING_SLOT_POS][3]; \ + GLfloat w = span->attrStart[VARYING_SLOT_POS][3]; \ + GLuint i; \ + for (i = 0; i < span->end; i++) { \ + const GLfloat c = fabsf(fogCoord) / w; \ + GLfloat f, oneMinusF; \ + FOG_FUNC(f, c); \ + f = CLAMP(f, 0.0F, 1.0F); \ + oneMinusF = 1.0F - f; \ + rgba[i][RCOMP] = (TYPE) (f * rgba[i][RCOMP] + oneMinusF * rFog); \ + rgba[i][GCOMP] = (TYPE) (f * rgba[i][GCOMP] + oneMinusF * gFog); \ + rgba[i][BCOMP] = (TYPE) (f * rgba[i][BCOMP] + oneMinusF * bFog); \ + fogCoord += fogStep; \ + w += wStep; \ + } \ } - /** - * Apply fog given in an array to a span of color index pixels. - * Input: ctx - - * span - - * fog - array of fog factors in [0,1] - * index - pixel color indexes - * Output: index - fogged pixel color indexes + * 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! */ void -_mesa_fog_ci_pixels_with_array( const GLcontext *ctx, struct sw_span *span, - const GLfloat fog[], GLuint index[] ) +_swrast_fog_rgba_span( const struct gl_context *ctx, SWspan *span ) { - GLuint idx = (GLuint) ctx->Fog.Index; - GLuint i; + const SWcontext *swrast = CONST_SWRAST_CONTEXT(ctx); + GLfloat rFog, gFog, bFog; - ASSERT(fog != NULL); - ASSERT(ctx->Fog.Enabled); - ASSERT(span->arrayMask & SPAN_INDEX); + assert(swrast->_FogEnabled); + assert(span->arrayMask & SPAN_RGBA); - for (i = span->start; i < span->end; i++) { - const GLfloat f = CLAMP(fog[i], 0.0F, 1.0F); - index[i] = (GLuint) ((GLfloat) index[i] + (1.0F - f) * idx); + /* compute (scaled) fog color */ + if (span->array->ChanType == GL_UNSIGNED_BYTE) { + rFog = ctx->Fog.Color[RCOMP] * 255.0F; + gFog = ctx->Fog.Color[GCOMP] * 255.0F; + bFog = ctx->Fog.Color[BCOMP] * 255.0F; + } + else if (span->array->ChanType == GL_UNSIGNED_SHORT) { + rFog = ctx->Fog.Color[RCOMP] * 65535.0F; + gFog = ctx->Fog.Color[GCOMP] * 65535.0F; + bFog = ctx->Fog.Color[BCOMP] * 65535.0F; + } + else { + rFog = ctx->Fog.Color[RCOMP]; + gFog = ctx->Fog.Color[GCOMP]; + bFog = ctx->Fog.Color[BCOMP]; } -} - - - -/** - * 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? - */ -static void -compute_fog_factors_from_z( const GLcontext *ctx, - GLuint n, - const GLdepth z[], - GLfloat fogFact[] ) -{ - 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; - - 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: - * - * 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. - */ - switch (ctx->Fog.Mode) { + 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;iFog.End; + const GLfloat fogScale = (ctx->Fog.Start == ctx->Fog.End) + ? 1.0F : 1.0F / (ctx->Fog.End - ctx->Fog.Start); + if (span->array->ChanType == GL_UNSIGNED_BYTE) { + GLubyte (*rgba)[4] = span->array->rgba8; + FOG_LOOP(GLubyte, LINEAR_FOG); + } + else if (span->array->ChanType == GL_UNSIGNED_SHORT) { + GLushort (*rgba)[4] = span->array->rgba16; + FOG_LOOP(GLushort, LINEAR_FOG); } else { - /* perspective */ - for (i=0;iarray->attribs[VARYING_SLOT_COL0]; + assert(span->array->ChanType == GL_FLOAT); + FOG_LOOP(GLfloat, LINEAR_FOG); } } - break; + break; + case GL_EXP: - if (ortho) { - for (i=0;iFog.Density * eyez ); + { + const GLfloat density = -ctx->Fog.Density; + if (span->array->ChanType == GL_UNSIGNED_BYTE) { + GLubyte (*rgba)[4] = span->array->rgba8; + FOG_LOOP(GLubyte, EXP_FOG); } - } - else { - /* perspective */ - for (i=0;iFog.Density * eyez ); + else if (span->array->ChanType == GL_UNSIGNED_SHORT) { + GLushort (*rgba)[4] = span->array->rgba16; + FOG_LOOP(GLushort, EXP_FOG); + } + else { + GLfloat (*rgba)[4] = span->array->attribs[VARYING_SLOT_COL0]; + assert(span->array->ChanType == GL_FLOAT); + FOG_LOOP(GLfloat, EXP_FOG); } } - break; + break; + case GL_EXP2: { - GLfloat negDensitySquared = -ctx->Fog.Density * ctx->Fog.Density; - if (ortho) { - for (i=0;iFog.Density * ctx->Fog.Density; + if (span->array->ChanType == GL_UNSIGNED_BYTE) { + GLubyte (*rgba)[4] = span->array->rgba8; + FOG_LOOP(GLubyte, EXP2_FOG); + } + else if (span->array->ChanType == GL_UNSIGNED_SHORT) { + GLushort (*rgba)[4] = span->array->rgba16; + FOG_LOOP(GLushort, EXP2_FOG); } else { - /* perspective */ - for (i=0;iarray->attribs[VARYING_SLOT_COL0]; + assert(span->array->ChanType == GL_FLOAT); + FOG_LOOP(GLfloat, EXP2_FOG); } } - 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; + } + } + else { + /* The span's fog start/step/array values are blend factors in [0,1]. + * They were previously computed per-vertex. + */ + if (span->array->ChanType == GL_UNSIGNED_BYTE) { + GLubyte (*rgba)[4] = span->array->rgba8; + FOG_LOOP(GLubyte, BLEND_FOG); + } + else if (span->array->ChanType == GL_UNSIGNED_SHORT) { + GLushort (*rgba)[4] = span->array->rgba16; + FOG_LOOP(GLushort, BLEND_FOG); + } + else { + GLfloat (*rgba)[4] = span->array->attribs[VARYING_SLOT_COL0]; + assert(span->array->ChanType == GL_FLOAT); + FOG_LOOP(GLfloat, BLEND_FOG); + } } -} - - -/** - * Apply fog to a span of RGBA pixels. - * Input: ctx - - * span - where span->zArray has to be filled. - * red, green, blue, alpha - pixel colors - * Output: red, green, blue, alpha - fogged pixel colors - */ -void -_mesa_depth_fog_rgba_pixels(const GLcontext *ctx, struct sw_span *span, - GLchan rgba[][4]) -{ - GLfloat fogFact[MAX_WIDTH]; - - ASSERT(ctx->Fog.Enabled); - ASSERT(span->arrayMask & SPAN_Z); - ASSERT(span->end <= MAX_WIDTH); - - compute_fog_factors_from_z(ctx, span->end, span->zArray, fogFact ); - _mesa_fog_rgba_pixels_with_array( ctx, span, fogFact, rgba ); -} - - -/** - * Apply fog to a span of color index pixels. - * Input: ctx - - * span - where span->zArray has to be filled. - * index - pixel color indexes - * Output: index - fogged pixel color indexes - */ -void -_mesa_depth_fog_ci_pixels( const GLcontext *ctx, struct sw_span *span, - GLuint index[] ) -{ - GLfloat fogFact[MAX_WIDTH]; - - ASSERT(ctx->Fog.Enabled); - ASSERT(span->arrayMask & SPAN_Z); - ASSERT(span->end <= MAX_WIDTH); - - compute_fog_factors_from_z(ctx, span->end, span->zArray, fogFact ); - _mesa_fog_ci_pixels_with_array( ctx, span, fogFact, index ); }