Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1901 serge 1
/*
2
 * Mesa 3-D graphics library
3
 * Version:  7.1
4
 *
5
 * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining a
8
 * copy of this software and associated documentation files (the "Software"),
9
 * to deal in the Software without restriction, including without limitation
10
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
 * and/or sell copies of the Software, and to permit persons to whom the
12
 * Software is furnished to do so, subject to the following conditions:
13
 *
14
 * The above copyright notice and this permission notice shall be included
15
 * in all copies or substantial portions of the Software.
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20
 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
 */
24
 
25
 
26
#include "main/glheader.h"
27
#include "main/colormac.h"
28
#include "main/feedback.h"
29
#include "main/light.h"
30
#include "main/macros.h"
31
#include "main/simple_list.h"
32
#include "main/mtypes.h"
33
 
34
#include "math/m_matrix.h"
35
#include "tnl/tnl.h"
36
 
37
 
38
 
39
/**
40
 * Clip a point against the view volume.
41
 *
42
 * \param v vertex vector describing the point to clip.
43
 *
44
 * \return zero if outside view volume, or one if inside.
45
 */
46
static GLuint
47
viewclip_point_xy( const GLfloat v[] )
48
{
49
   if (   v[0] > v[3] || v[0] < -v[3]
50
       || v[1] > v[3] || v[1] < -v[3] ) {
51
      return 0;
52
   }
53
   else {
54
      return 1;
55
   }
56
}
57
 
58
 
59
/**
60
 * Clip a point against the far/near Z clipping planes.
61
 *
62
 * \param v vertex vector describing the point to clip.
63
 *
64
 * \return zero if outside view volume, or one if inside.
65
 */
66
static GLuint
67
viewclip_point_z( const GLfloat v[] )
68
{
69
   if (v[2] > v[3] || v[2] < -v[3] ) {
70
      return 0;
71
   }
72
   else {
73
      return 1;
74
   }
75
}
76
 
77
 
78
/**
79
 * Clip a point against the user clipping planes.
80
 *
81
 * \param ctx GL context.
82
 * \param v vertex vector describing the point to clip.
83
 *
84
 * \return zero if the point was clipped, or one otherwise.
85
 */
86
static GLuint
87
userclip_point( struct gl_context *ctx, const GLfloat v[] )
88
{
89
   GLuint p;
90
 
91
   for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
92
      if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
93
	 GLfloat dot = v[0] * ctx->Transform._ClipUserPlane[p][0]
94
		     + v[1] * ctx->Transform._ClipUserPlane[p][1]
95
		     + v[2] * ctx->Transform._ClipUserPlane[p][2]
96
		     + v[3] * ctx->Transform._ClipUserPlane[p][3];
97
         if (dot < 0.0F) {
98
            return 0;
99
         }
100
      }
101
   }
102
 
103
   return 1;
104
}
105
 
106
 
107
/**
108
 * Compute lighting for the raster position.  Both RGB and CI modes computed.
109
 * \param ctx the context
110
 * \param vertex vertex location
111
 * \param normal normal vector
112
 * \param Rcolor returned color
113
 * \param Rspec returned specular color (if separate specular enabled)
114
 * \param Rindex returned color index
115
 */
116
static void
117
shade_rastpos(struct gl_context *ctx,
118
              const GLfloat vertex[4],
119
              const GLfloat normal[3],
120
              GLfloat Rcolor[4],
121
              GLfloat Rspec[4])
122
{
123
   /*const*/ GLfloat (*base)[3] = ctx->Light._BaseColor;
124
   const struct gl_light *light;
125
   GLfloat diffuseColor[4], specularColor[4];  /* for RGB mode only */
126
   GLfloat diffuseCI = 0.0, specularCI = 0.0;  /* for CI mode only */
127
 
128
   _mesa_validate_all_lighting_tables( ctx );
129
 
130
   COPY_3V(diffuseColor, base[0]);
131
   diffuseColor[3] = CLAMP(
132
      ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3], 0.0F, 1.0F );
133
   ASSIGN_4V(specularColor, 0.0, 0.0, 0.0, 1.0);
134
 
135
   foreach (light, &ctx->Light.EnabledList) {
136
      GLfloat attenuation = 1.0;
137
      GLfloat VP[3]; /* vector from vertex to light pos */
138
      GLfloat n_dot_VP;
139
      GLfloat diffuseContrib[3], specularContrib[3];
140
 
141
      if (!(light->_Flags & LIGHT_POSITIONAL)) {
142
         /* light at infinity */
143
	 COPY_3V(VP, light->_VP_inf_norm);
144
	 attenuation = light->_VP_inf_spot_attenuation;
145
      }
146
      else {
147
         /* local/positional light */
148
	 GLfloat d;
149
 
150
         /* VP = vector from vertex pos to light[i].pos */
151
	 SUB_3V(VP, light->_Position, vertex);
152
         /* d = length(VP) */
153
	 d = (GLfloat) LEN_3FV( VP );
154
	 if (d > 1.0e-6) {
155
            /* normalize VP */
156
	    GLfloat invd = 1.0F / d;
157
	    SELF_SCALE_SCALAR_3V(VP, invd);
158
	 }
159
 
160
         /* atti */
161
	 attenuation = 1.0F / (light->ConstantAttenuation + d *
162
			       (light->LinearAttenuation + d *
163
				light->QuadraticAttenuation));
164
 
165
	 if (light->_Flags & LIGHT_SPOT) {
166
	    GLfloat PV_dot_dir = - DOT3(VP, light->_NormSpotDirection);
167
 
168
	    if (PV_dot_dir_CosCutoff) {
169
	       continue;
170
	    }
171
	    else {
172
	       double x = PV_dot_dir * (EXP_TABLE_SIZE-1);
173
	       int k = (int) x;
174
	       GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0]
175
			       + (x-k)*light->_SpotExpTable[k][1]);
176
	       attenuation *= spot;
177
	    }
178
	 }
179
      }
180
 
181
      if (attenuation < 1e-3)
182
	 continue;
183
 
184
      n_dot_VP = DOT3( normal, VP );
185
 
186
      if (n_dot_VP < 0.0F) {
187
	 ACC_SCALE_SCALAR_3V(diffuseColor, attenuation, light->_MatAmbient[0]);
188
	 continue;
189
      }
190
 
191
      /* Ambient + diffuse */
192
      COPY_3V(diffuseContrib, light->_MatAmbient[0]);
193
      ACC_SCALE_SCALAR_3V(diffuseContrib, n_dot_VP, light->_MatDiffuse[0]);
194
      diffuseCI += n_dot_VP * light->_dli * attenuation;
195
 
196
      /* Specular */
197
      {
198
         const GLfloat *h;
199
         GLfloat n_dot_h;
200
 
201
         ASSIGN_3V(specularContrib, 0.0, 0.0, 0.0);
202
 
203
	 if (ctx->Light.Model.LocalViewer) {
204
	    GLfloat v[3];
205
	    COPY_3V(v, vertex);
206
	    NORMALIZE_3FV(v);
207
	    SUB_3V(VP, VP, v);
208
            NORMALIZE_3FV(VP);
209
	    h = VP;
210
	 }
211
	 else if (light->_Flags & LIGHT_POSITIONAL) {
212
	    ACC_3V(VP, ctx->_EyeZDir);
213
            NORMALIZE_3FV(VP);
214
	    h = VP;
215
	 }
216
         else {
217
	    h = light->_h_inf_norm;
218
	 }
219
 
220
	 n_dot_h = DOT3(normal, h);
221
 
222
	 if (n_dot_h > 0.0F) {
223
	    GLfloat spec_coef;
224
	    GET_SHINE_TAB_ENTRY( ctx->_ShineTable[0], n_dot_h, spec_coef );
225
 
226
	    if (spec_coef > 1.0e-10) {
227
               if (ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR) {
228
                  ACC_SCALE_SCALAR_3V( specularContrib, spec_coef,
229
                                       light->_MatSpecular[0]);
230
               }
231
               else {
232
                  ACC_SCALE_SCALAR_3V( diffuseContrib, spec_coef,
233
                                       light->_MatSpecular[0]);
234
               }
235
               /*assert(light->_sli > 0.0);*/
236
               specularCI += spec_coef * light->_sli * attenuation;
237
	    }
238
	 }
239
      }
240
 
241
      ACC_SCALE_SCALAR_3V( diffuseColor, attenuation, diffuseContrib );
242
      ACC_SCALE_SCALAR_3V( specularColor, attenuation, specularContrib );
243
   }
244
 
245
   Rcolor[0] = CLAMP(diffuseColor[0], 0.0F, 1.0F);
246
   Rcolor[1] = CLAMP(diffuseColor[1], 0.0F, 1.0F);
247
   Rcolor[2] = CLAMP(diffuseColor[2], 0.0F, 1.0F);
248
   Rcolor[3] = CLAMP(diffuseColor[3], 0.0F, 1.0F);
249
   Rspec[0] = CLAMP(specularColor[0], 0.0F, 1.0F);
250
   Rspec[1] = CLAMP(specularColor[1], 0.0F, 1.0F);
251
   Rspec[2] = CLAMP(specularColor[2], 0.0F, 1.0F);
252
   Rspec[3] = CLAMP(specularColor[3], 0.0F, 1.0F);
253
}
254
 
255
 
256
/**
257
 * Do texgen needed for glRasterPos.
258
 * \param ctx  rendering context
259
 * \param vObj  object-space vertex coordinate
260
 * \param vEye  eye-space vertex coordinate
261
 * \param normal  vertex normal
262
 * \param unit  texture unit number
263
 * \param texcoord  incoming texcoord and resulting texcoord
264
 */
265
static void
266
compute_texgen(struct gl_context *ctx, const GLfloat vObj[4], const GLfloat vEye[4],
267
               const GLfloat normal[3], GLuint unit, GLfloat texcoord[4])
268
{
269
   const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
270
 
271
   /* always compute sphere map terms, just in case */
272
   GLfloat u[3], two_nu, rx, ry, rz, m, mInv;
273
   COPY_3V(u, vEye);
274
   NORMALIZE_3FV(u);
275
   two_nu = 2.0F * DOT3(normal, u);
276
   rx = u[0] - normal[0] * two_nu;
277
   ry = u[1] - normal[1] * two_nu;
278
   rz = u[2] - normal[2] * two_nu;
279
   m = rx * rx + ry * ry + (rz + 1.0F) * (rz + 1.0F);
280
   if (m > 0.0F)
281
      mInv = 0.5F * _mesa_inv_sqrtf(m);
282
   else
283
      mInv = 0.0F;
284
 
285
   if (texUnit->TexGenEnabled & S_BIT) {
286
      switch (texUnit->GenS.Mode) {
287
         case GL_OBJECT_LINEAR:
288
            texcoord[0] = DOT4(vObj, texUnit->GenS.ObjectPlane);
289
            break;
290
         case GL_EYE_LINEAR:
291
            texcoord[0] = DOT4(vEye, texUnit->GenS.EyePlane);
292
            break;
293
         case GL_SPHERE_MAP:
294
            texcoord[0] = rx * mInv + 0.5F;
295
            break;
296
         case GL_REFLECTION_MAP:
297
            texcoord[0] = rx;
298
            break;
299
         case GL_NORMAL_MAP:
300
            texcoord[0] = normal[0];
301
            break;
302
         default:
303
            _mesa_problem(ctx, "Bad S texgen in compute_texgen()");
304
            return;
305
      }
306
   }
307
 
308
   if (texUnit->TexGenEnabled & T_BIT) {
309
      switch (texUnit->GenT.Mode) {
310
         case GL_OBJECT_LINEAR:
311
            texcoord[1] = DOT4(vObj, texUnit->GenT.ObjectPlane);
312
            break;
313
         case GL_EYE_LINEAR:
314
            texcoord[1] = DOT4(vEye, texUnit->GenT.EyePlane);
315
            break;
316
         case GL_SPHERE_MAP:
317
            texcoord[1] = ry * mInv + 0.5F;
318
            break;
319
         case GL_REFLECTION_MAP:
320
            texcoord[1] = ry;
321
            break;
322
         case GL_NORMAL_MAP:
323
            texcoord[1] = normal[1];
324
            break;
325
         default:
326
            _mesa_problem(ctx, "Bad T texgen in compute_texgen()");
327
            return;
328
      }
329
   }
330
 
331
   if (texUnit->TexGenEnabled & R_BIT) {
332
      switch (texUnit->GenR.Mode) {
333
         case GL_OBJECT_LINEAR:
334
            texcoord[2] = DOT4(vObj, texUnit->GenR.ObjectPlane);
335
            break;
336
         case GL_EYE_LINEAR:
337
            texcoord[2] = DOT4(vEye, texUnit->GenR.EyePlane);
338
            break;
339
         case GL_REFLECTION_MAP:
340
            texcoord[2] = rz;
341
            break;
342
         case GL_NORMAL_MAP:
343
            texcoord[2] = normal[2];
344
            break;
345
         default:
346
            _mesa_problem(ctx, "Bad R texgen in compute_texgen()");
347
            return;
348
      }
349
   }
350
 
351
   if (texUnit->TexGenEnabled & Q_BIT) {
352
      switch (texUnit->GenQ.Mode) {
353
         case GL_OBJECT_LINEAR:
354
            texcoord[3] = DOT4(vObj, texUnit->GenQ.ObjectPlane);
355
            break;
356
         case GL_EYE_LINEAR:
357
            texcoord[3] = DOT4(vEye, texUnit->GenQ.EyePlane);
358
            break;
359
         default:
360
            _mesa_problem(ctx, "Bad Q texgen in compute_texgen()");
361
            return;
362
      }
363
   }
364
}
365
 
366
 
367
/**
368
 * glRasterPos transformation.  Typically called via ctx->Driver.RasterPos().
369
 * XXX some of this code (such as viewport xform, clip testing and setting
370
 * of ctx->Current.Raster* fields) could get lifted up into the
371
 * main/rasterpos.c code.
372
 *
373
 * \param vObj  vertex position in object space
374
 */
375
void
376
_tnl_RasterPos(struct gl_context *ctx, const GLfloat vObj[4])
377
{
378
   if (ctx->VertexProgram._Enabled) {
379
      /* XXX implement this */
380
      _mesa_problem(ctx, "Vertex programs not implemented for glRasterPos");
381
      return;
382
   }
383
   else {
384
      GLfloat eye[4], clip[4], ndc[3], d;
385
      GLfloat *norm, eyenorm[3];
386
      GLfloat *objnorm = ctx->Current.Attrib[VERT_ATTRIB_NORMAL];
387
 
388
      /* apply modelview matrix:  eye = MV * obj */
389
      TRANSFORM_POINT( eye, ctx->ModelviewMatrixStack.Top->m, vObj );
390
      /* apply projection matrix:  clip = Proj * eye */
391
      TRANSFORM_POINT( clip, ctx->ProjectionMatrixStack.Top->m, eye );
392
 
393
      /* clip to view volume. */
394
      if (!ctx->Transform.DepthClamp) {
395
         if (viewclip_point_z(clip) == 0) {
396
            ctx->Current.RasterPosValid = GL_FALSE;
397
            return;
398
         }
399
      }
400
      if (!ctx->Transform.RasterPositionUnclipped) {
401
         if (viewclip_point_xy(clip) == 0) {
402
            ctx->Current.RasterPosValid = GL_FALSE;
403
            return;
404
         }
405
      }
406
 
407
      /* clip to user clipping planes */
408
      if (ctx->Transform.ClipPlanesEnabled && !userclip_point(ctx, clip)) {
409
         ctx->Current.RasterPosValid = GL_FALSE;
410
         return;
411
      }
412
 
413
      /* ndc = clip / W */
414
      d = (clip[3] == 0.0F) ? 1.0F : 1.0F / clip[3];
415
      ndc[0] = clip[0] * d;
416
      ndc[1] = clip[1] * d;
417
      ndc[2] = clip[2] * d;
418
      /* wincoord = viewport_mapping(ndc) */
419
      ctx->Current.RasterPos[0] = (ndc[0] * ctx->Viewport._WindowMap.m[MAT_SX]
420
                                   + ctx->Viewport._WindowMap.m[MAT_TX]);
421
      ctx->Current.RasterPos[1] = (ndc[1] * ctx->Viewport._WindowMap.m[MAT_SY]
422
                                   + ctx->Viewport._WindowMap.m[MAT_TY]);
423
      ctx->Current.RasterPos[2] = (ndc[2] * ctx->Viewport._WindowMap.m[MAT_SZ]
424
                                   + ctx->Viewport._WindowMap.m[MAT_TZ])
425
                                  / ctx->DrawBuffer->_DepthMaxF;
426
      ctx->Current.RasterPos[3] = clip[3];
427
 
428
      if (ctx->Transform.DepthClamp) {
429
	 ctx->Current.RasterPos[3] = CLAMP(ctx->Current.RasterPos[3],
430
					   ctx->Viewport.Near,
431
					   ctx->Viewport.Far);
432
      }
433
 
434
      /* compute raster distance */
435
      if (ctx->Fog.FogCoordinateSource == GL_FOG_COORDINATE_EXT)
436
         ctx->Current.RasterDistance = ctx->Current.Attrib[VERT_ATTRIB_FOG][0];
437
      else
438
         ctx->Current.RasterDistance =
439
                        SQRTF( eye[0]*eye[0] + eye[1]*eye[1] + eye[2]*eye[2] );
440
 
441
      /* compute transformed normal vector (for lighting or texgen) */
442
      if (ctx->_NeedEyeCoords) {
443
         const GLfloat *inv = ctx->ModelviewMatrixStack.Top->inv;
444
         TRANSFORM_NORMAL( eyenorm, objnorm, inv );
445
         norm = eyenorm;
446
      }
447
      else {
448
         norm = objnorm;
449
      }
450
 
451
      /* update raster color */
452
      if (ctx->Light.Enabled) {
453
         /* lighting */
454
         shade_rastpos( ctx, vObj, norm,
455
                        ctx->Current.RasterColor,
456
                        ctx->Current.RasterSecondaryColor );
457
      }
458
      else {
459
         /* use current color */
460
	 COPY_4FV(ctx->Current.RasterColor,
461
		  ctx->Current.Attrib[VERT_ATTRIB_COLOR0]);
462
	 COPY_4FV(ctx->Current.RasterSecondaryColor,
463
		  ctx->Current.Attrib[VERT_ATTRIB_COLOR1]);
464
      }
465
 
466
      /* texture coords */
467
      {
468
         GLuint u;
469
         for (u = 0; u < ctx->Const.MaxTextureCoordUnits; u++) {
470
            GLfloat tc[4];
471
            COPY_4V(tc, ctx->Current.Attrib[VERT_ATTRIB_TEX0 + u]);
472
            if (ctx->Texture.Unit[u].TexGenEnabled) {
473
               compute_texgen(ctx, vObj, eye, norm, u, tc);
474
            }
475
            TRANSFORM_POINT(ctx->Current.RasterTexCoords[u],
476
                            ctx->TextureMatrixStack[u].Top->m, tc);
477
         }
478
      }
479
 
480
      ctx->Current.RasterPosValid = GL_TRUE;
481
   }
482
 
483
   if (ctx->RenderMode == GL_SELECT) {
484
      _mesa_update_hitflag( ctx, ctx->Current.RasterPos[2] );
485
   }
486
}