From 09da0b8e6621a831e3eeb9381430f2bed18a22ad Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Tue, 17 Feb 2004 21:03:03 +0000 Subject: 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. --- src/mesa/tnl/t_context.c | 13 +++++++++++ src/mesa/tnl/t_context.h | 37 +++++++++++++++--------------- src/mesa/tnl/t_vb_fog.c | 58 ++++++++++++++++++++++++++++++------------------ src/mesa/tnl/tnl.h | 6 +++++ 4 files changed, 74 insertions(+), 40 deletions(-) (limited to 'src/mesa/tnl') 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 -- cgit v1.2.3