Subversion Repositories shark

Rev

Rev 56 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
56 pj 1
/* $Id: t_vb_fog.c,v 1.1 2003-02-28 11:48:07 pj Exp $ */
2
 
3
/*
4
 * Mesa 3-D graphics library
5
 * Version:  4.1
6
 *
7
 * Copyright (C) 1999-2002  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
 * Authors:
27
 *    Keith Whitwell <keith@tungstengraphics.com>
28
 */
29
 
30
 
31
#include "glheader.h"
32
#include "colormac.h"
33
#include "context.h"
34
#include "macros.h"
35
#include "imports.h"
36
#include "mmath.h"
37
#include "mtypes.h"
38
 
39
#include "math/m_xform.h"
40
 
41
#include "t_context.h"
42
#include "t_pipeline.h"
43
 
44
 
45
struct fog_stage_data {
46
   GLvector4f fogcoord;         /* has actual storage allocated */
47
   GLvector4f input;            /* points into VB->EyePtr Z values */
48
};
49
 
50
#define FOG_STAGE_DATA(stage) ((struct fog_stage_data *)stage->privatePtr)
51
 
52
#define FOG_EXP_TABLE_SIZE 256
53
#define FOG_MAX (10.0)
54
#define EXP_FOG_MAX .0006595
55
#define FOG_INCR (FOG_MAX/FOG_EXP_TABLE_SIZE)
56
static GLfloat exp_table[FOG_EXP_TABLE_SIZE];
57
static GLfloat inited = 0;
58
 
59
#if 1
60
#define NEG_EXP( result, narg )                                         \
61
do {                                                                    \
62
   GLfloat f = (GLfloat) (narg * (1.0/FOG_INCR));                       \
63
   GLint k = (GLint) f;                                                 \
64
   if (k > FOG_EXP_TABLE_SIZE-2)                                        \
65
      result = (GLfloat) EXP_FOG_MAX;                                   \
66
   else                                                                 \
67
      result = exp_table[k] + (f-k)*(exp_table[k+1]-exp_table[k]);      \
68
} while (0)
69
#else
70
#define NEG_EXP( result, narg )                                 \
71
do {                                                            \
72
   result = exp(-narg);                                         \
73
} while (0)
74
#endif
75
 
76
 
77
static void init_static_data( void )
78
{
79
   GLfloat f = 0.0F;
80
   GLint i = 0;
81
   for ( ; i < FOG_EXP_TABLE_SIZE ; i++, f += FOG_INCR) {
82
      exp_table[i] = (GLfloat) exp(-f);
83
   }
84
   inited = 1;
85
}
86
 
87
 
88
static void make_win_fog_coords( GLcontext *ctx, GLvector4f *out,
89
                                 const GLvector4f *in )
90
{
91
   GLfloat end  = ctx->Fog.End;
92
   GLfloat *v = in->start;
93
   GLuint stride = in->stride;
94
   GLuint n = in->count;
95
   GLfloat (*data)[4] = out->data;
96
   GLfloat d;
97
   GLuint i;
98
 
99
   out->count = in->count;
100
 
101
   switch (ctx->Fog.Mode) {
102
   case GL_LINEAR:
103
      if (ctx->Fog.Start == ctx->Fog.End)
104
         d = 1.0F;
105
      else
106
         d = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
107
      for ( i = 0 ; i < n ; i++, STRIDE_F(v, stride)) {
108
         GLfloat f = (end - ABSF(*v)) * d;
109
         data[i][0] = CLAMP(f, 0.0F, 1.0F);
110
      }
111
      break;
112
   case GL_EXP:
113
      d = ctx->Fog.Density;
114
      for ( i = 0 ; i < n ; i++, STRIDE_F(v,stride))
115
         NEG_EXP( data[i][0], d * ABSF(*v) );
116
      break;
117
   case GL_EXP2:
118
      d = ctx->Fog.Density*ctx->Fog.Density;
119
      for ( i = 0 ; i < n ; i++, STRIDE_F(v, stride)) {
120
         GLfloat z = *v;
121
         NEG_EXP( data[i][0], d * z * z );
122
      }
123
      break;
124
   default:
125
      _mesa_problem(ctx, "Bad fog mode in make_fog_coord");
126
      return;
127
   }
128
}
129
 
130
 
131
static GLboolean run_fog_stage( GLcontext *ctx,
132
                                struct gl_pipeline_stage *stage )
133
{
134
   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
135
   struct fog_stage_data *store = FOG_STAGE_DATA(stage);
136
   GLvector4f *input;
137
 
138
   if (stage->changed_inputs == 0)
139
      return GL_TRUE;
140
 
141
   if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT) {
142
      /* fog computed from Z depth */
143
      /* source = VB->ObjPtr or VB->EyePtr coords */
144
      /* dest = VB->FogCoordPtr = fog stage private storage */
145
      VB->FogCoordPtr = &store->fogcoord;
146
 
147
      if (!ctx->_NeedEyeCoords) {
148
         const GLfloat *m = ctx->ModelviewMatrixStack.Top->m;
149
         GLfloat plane[4];
150
 
151
         /* Use this to store calculated eye z values:
152
          */
153
         input = &store->fogcoord;
154
 
155
         plane[0] = m[2];
156
         plane[1] = m[6];
157
         plane[2] = m[10];
158
         plane[3] = m[14];
159
 
160
         /* Full eye coords weren't required, just calculate the
161
          * eye Z values.
162
          */
163
         _mesa_dotprod_tab[VB->ObjPtr->size]( (GLfloat *) input->data,
164
                                              4 * sizeof(GLfloat),
165
                                              VB->ObjPtr, plane );
166
 
167
         input->count = VB->ObjPtr->count;
168
      }
169
      else {
170
         input = &store->input;
171
 
172
         if (VB->EyePtr->size < 2)
173
            _mesa_vector4f_clean_elem( VB->EyePtr, VB->Count, 2 );
174
 
175
         input->data = (GLfloat (*)[4]) &(VB->EyePtr->data[0][2]);
176
         input->start = VB->EyePtr->start+2;
177
         input->stride = VB->EyePtr->stride;
178
         input->count = VB->EyePtr->count;
179
      }
180
   }
181
   else {
182
      /* use glFogCoord() coordinates */
183
      /* source = VB->FogCoordPtr */
184
      input = VB->FogCoordPtr;
185
      /* dest = fog stage private storage */
186
      VB->FogCoordPtr = &store->fogcoord;
187
   }
188
 
189
   make_win_fog_coords( ctx, VB->FogCoordPtr, input );
190
   return GL_TRUE;
191
}
192
 
193
 
194
static void check_fog_stage( GLcontext *ctx, struct gl_pipeline_stage *stage )
195
{
196
   stage->active = ctx->Fog.Enabled && !ctx->VertexProgram.Enabled;
197
 
198
   if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT)
199
      stage->inputs = VERT_BIT_EYE;
200
   else
201
      stage->inputs = VERT_BIT_FOG;
202
}
203
 
204
 
205
/* Called the first time stage->run() is invoked.
206
 */
207
static GLboolean alloc_fog_data( GLcontext *ctx,
208
                                 struct gl_pipeline_stage *stage )
209
{
210
   TNLcontext *tnl = TNL_CONTEXT(ctx);
211
   struct fog_stage_data *store;
212
   stage->privatePtr = MALLOC(sizeof(*store));
213
   store = FOG_STAGE_DATA(stage);
214
   if (!store)
215
      return GL_FALSE;
216
 
217
   _mesa_vector4f_alloc( &store->fogcoord, 0, tnl->vb.Size, 32 );
218
   _mesa_vector4f_init( &store->input, 0, 0 );
219
 
220
   if (!inited)
221
      init_static_data();
222
 
223
   /* Now run the stage.
224
    */
225
   stage->run = run_fog_stage;
226
   return stage->run( ctx, stage );
227
}
228
 
229
 
230
static void free_fog_data( struct gl_pipeline_stage *stage )
231
{
232
   struct fog_stage_data *store = FOG_STAGE_DATA(stage);
233
   if (store) {
234
      _mesa_vector4f_free( &store->fogcoord );
235
      FREE( store );
236
      stage->privatePtr = NULL;
237
   }
238
}
239
 
240
 
241
const struct gl_pipeline_stage _tnl_fog_coordinate_stage =
242
{
243
   "build fog coordinates",     /* name */
244
   _NEW_FOG,                    /* check_state */
245
   _NEW_FOG,                    /* run_state */
246
   GL_FALSE,                    /* active? */
247
   0,                           /* inputs */
248
   VERT_BIT_FOG,                /* outputs */
249
   0,                           /* changed_inputs */
250
   NULL,                        /* private_data */
251
   free_fog_data,               /* dtr */
252
   check_fog_stage,             /* check */
253
   alloc_fog_data               /* run -- initially set to init. */
254
};