source: trunk/src/opengl/mesa/shade_tmp.h

Last change on this file was 3597, checked in by jeroen, 25 years ago

* empty log message *

File size: 26.3 KB
Line 
1/* $Id: shade_tmp.h,v 1.2 2000-05-23 20:34:55 jeroen Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version: 3.1
6 *
7 * Copyright (C) 1999 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
27/*
28 * New (3.1) transformation code written by Keith Whitwell.
29 */
30
31static void TAG(shade_rgba_spec)( struct vertex_buffer *VB )
32{
33 GLcontext *ctx = VB->ctx;
34 GLfloat (*base)[3] = ctx->Light.BaseColor;
35 GLubyte *sumA = ctx->Light.BaseAlpha;
36
37 GLuint j;
38
39 GLuint vstride = VB->Unprojected->stride;
40 const GLfloat *vertex = VB->Unprojected->start;
41 GLuint vertex_size = VB->Unprojected->size;
42
43 GLuint nstride = VB->NormalPtr->stride;
44 const GLfloat *normal = VB->NormalPtr->start;
45 CONST GLfloat (*first_normal)[3] = (CONST GLfloat (*)[3]) VB->NormalPtr->start;
46
47 /* Has stride 4 to help the drivers - and us...
48 */
49 GLubyte (*CMcolor)[4] = 0;
50
51 GLubyte (*Fcolor)[4] = (GLubyte (*)[4])VB->LitColor[0]->start;
52 GLubyte (*Bcolor)[4] = (GLubyte (*)[4])VB->LitColor[1]->start;
53 GLubyte (*Fspec)[4] = VB->Spec[0] + VB->Start;
54 GLubyte (*Bspec)[4] = VB->Spec[1] + VB->Start;
55 GLubyte *mask = VB->CullMask + VB->Start;
56 GLubyte *cullmask = mask;
57 GLuint *flags = VB->Flag + VB->Start;
58
59 struct gl_material (*new_material)[2] = VB->Material + VB->Start;
60 GLuint *new_material_mask = VB->MaterialMask + VB->Start;
61 GLuint nr = VB->Count - VB->Start;
62
63 GLuint cm_flags = 0;
64
65 (void) cullmask;
66 (void) nstride;
67 (void) first_normal;
68 (void) flags;
69
70 if (ctx->Light.ColorMaterialEnabled) {
71 cm_flags = VERT_RGBA;
72
73 if (VB->ColorPtr->flags & VEC_BAD_STRIDE)
74 gl_clean_color(VB);
75
76 CMcolor = (GLubyte (*)[4])VB->ColorPtr->start;
77 }
78
79 VB->Color[0] = VB->LitColor[0];
80 VB->Color[1] = VB->LitColor[1];
81 VB->ColorPtr = VB->LitColor[0];
82 VB->Specular = VB->Spec[0];
83
84
85 for ( j=0 ; j<nr ; j++,STRIDE_F(vertex,vstride),NEXT_VERTEX_NORMAL)
86 {
87 GLfloat sum[2][3], spec[2][3];
88 struct gl_light *light;
89
90 if ( flags[j] & cm_flags )
91 gl_update_color_material( ctx, CMcolor[j] );
92
93 if ( flags[j] & VERT_MATERIAL )
94 gl_update_material( ctx, new_material[j], new_material_mask[j] );
95
96 if ( CULL(*mask) )
97 continue;
98
99 if (LIGHT_FRONT(*mask)) {
100 COPY_3V(sum[0], base[0]);
101 ZERO_3V(spec[0]);
102 }
103
104 if (LIGHT_REAR(*mask)) {
105 COPY_3V(sum[1], base[1]);
106 ZERO_3V(spec[1]);
107 }
108
109 /* Add contribution from each enabled light source */
110 foreach (light, &ctx->Light.EnabledList) {
111 GLfloat n_dot_h;
112 GLfloat correction;
113 GLint side;
114 GLfloat contrib[3];
115 GLfloat attenuation;
116 GLfloat VP[3]; /* unit vector from vertex to light */
117 GLfloat n_dot_VP; /* n dot VP */
118 GLfloat *h;
119 GLboolean normalized;
120
121 /* compute VP and attenuation */
122 if (!(light->Flags & LIGHT_POSITIONAL)) {
123 /* directional light */
124 COPY_3V(VP, light->VP_inf_norm);
125 attenuation = light->VP_inf_spot_attenuation;
126 }
127 else {
128 GLfloat d; /* distance from vertex to light */
129
130 if (vertex_size == 2) {
131 SUB_2V(VP, light->Position, vertex);
132 VP[2] = light->Position[2];
133 } else {
134 SUB_3V(VP, light->Position, vertex);
135 }
136
137 d = (GLfloat) LEN_3FV( VP );
138
139 if (d > 1e-6) {
140 GLfloat invd = 1.0F / d;
141 SELF_SCALE_SCALAR_3V(VP, invd);
142 }
143
144 attenuation = 1.0F / (light->ConstantAttenuation + d *
145 (light->LinearAttenuation + d *
146 light->QuadraticAttenuation));
147
148 /* spotlight attenuation */
149 if (light->Flags & LIGHT_SPOT)
150 {
151 GLfloat PV_dot_dir = - DOT3(VP, light->NormDirection);
152
153 if (PV_dot_dir<light->CosCutoff) {
154 continue; /* this light makes no contribution */
155 }
156 else {
157 double x = PV_dot_dir * (EXP_TABLE_SIZE-1);
158 int k = (int) x;
159 GLfloat spot = (GLfloat) (light->SpotExpTable[k][0]
160 + (x-k)*light->SpotExpTable[k][1]);
161 attenuation *= spot;
162 }
163 }
164 }
165
166
167 if (attenuation < 1e-3)
168 continue; /* this light makes no contribution */
169
170 /* Compute dot product or normal and vector from V to light pos */
171 n_dot_VP = DOT3( normal, VP );
172
173 /* Which side gets the diffuse & specular terms? */
174 if (n_dot_VP < 0.0F) {
175 if (LIGHT_FRONT(*mask)) {
176 ACC_SCALE_SCALAR_3V(sum[0], attenuation, light->MatAmbient[0]);
177 }
178 if (!LIGHT_REAR(*mask)) {
179 continue;
180 }
181 side = 1;
182 correction = -1;
183 n_dot_VP = -n_dot_VP;
184 } else {
185 if (LIGHT_REAR(*mask)) {
186 ACC_SCALE_SCALAR_3V( sum[1], attenuation, light->MatAmbient[1]);
187 }
188 if (!LIGHT_FRONT(*mask)) {
189 continue;
190 }
191 side = 0;
192 correction = 1;
193 }
194
195 /* diffuse term */
196 COPY_3V(contrib, light->MatAmbient[side]);
197 ACC_SCALE_SCALAR_3V(contrib, n_dot_VP, light->MatDiffuse[side]);
198 ACC_SCALE_SCALAR_3V(sum[side], attenuation, contrib );
199
200 if (!light->IsMatSpecular[side])
201 continue;
202
203 /* specular term - cannibalize VP... */
204 if (ctx->Light.Model.LocalViewer) {
205 GLfloat v[3];
206 COPY_3V(v, vertex);
207 if (vertex_size == 2) v[2] = 0;
208 NORMALIZE_3FV(v);
209 SUB_3V(VP, VP, v); /* h = VP + VPe */
210 h = VP;
211 normalized = 0;
212 }
213 else if (light->Flags & LIGHT_POSITIONAL) {
214 h = VP;
215 ACC_3V(h, ctx->EyeZDir);
216 normalized = 0;
217 } else {
218 h = light->h_inf_norm;
219 normalized = 1;
220 }
221
222 n_dot_h = correction * DOT3(normal, h);
223
224 if (n_dot_h > 0.0F)
225 {
226 GLfloat spec_coef;
227 struct gl_shine_tab *tab = ctx->ShineTable[side];
228
229 if (!normalized) {
230 n_dot_h *= n_dot_h;
231 n_dot_h /= LEN_SQUARED_3FV( h );
232 tab = ctx->ShineTable[side+2];
233 }
234
235 if (n_dot_h>1.0) {
236 spec_coef = (GLfloat) pow( n_dot_h, tab->shininess );
237 } else
238 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef );
239
240 if (spec_coef > 1.0e-10) {
241 spec_coef *= attenuation;
242 ACC_SCALE_SCALAR_3V( spec[side], spec_coef,
243 light->MatSpecular[side]);
244 }
245 }
246 } /*loop over lights*/
247
248 if (LIGHT_FRONT(*mask)) {
249 FLOAT_RGB_TO_UBYTE_RGB( Fcolor[j], sum[0] );
250 FLOAT_RGB_TO_UBYTE_RGB( Fspec[j], spec[0] );
251 Fcolor[j][3] = sumA[0];
252 }
253
254 if (LIGHT_REAR(*mask)) {
255 FLOAT_RGB_TO_UBYTE_RGB( Bcolor[j], sum[1] );
256 FLOAT_RGB_TO_UBYTE_RGB( Bspec[j], spec[1] );
257 Bcolor[j][3] = sumA[1];
258 }
259 }
260
261 if ( flags[j] & cm_flags )
262 gl_update_color_material( ctx, CMcolor[j] );
263
264 if ( flags[j] & VERT_MATERIAL )
265 gl_update_material( ctx, new_material[j], new_material_mask[j] );
266}
267
268
269static void TAG(shade_rgba)( struct vertex_buffer *VB )
270{
271 GLuint j;
272 GLcontext *ctx = VB->ctx;
273
274 GLfloat (*base)[3] = ctx->Light.BaseColor;
275 GLubyte *sumA = ctx->Light.BaseAlpha;
276
277 GLuint vstride = VB->Unprojected->stride;
278 const GLfloat *vertex = (GLfloat *)VB->Unprojected->start;
279 GLuint vertex_size = VB->Unprojected->size;
280
281 GLuint nstride = VB->NormalPtr->stride;
282 const GLfloat *normal = VB->NormalPtr->start;
283 CONST GLfloat (*first_normal)[3] = (CONST GLfloat (*)[3])VB->NormalPtr->start;
284
285 GLubyte (*CMcolor)[4] = 0;
286 GLubyte (*Fcolor)[4] = (GLubyte (*)[4])VB->LitColor[0]->start;
287 GLubyte (*Bcolor)[4] = (GLubyte (*)[4])VB->LitColor[1]->start;
288 GLubyte *mask = VB->CullMask + VB->Start;
289 GLubyte *cullmask = mask;
290 GLuint *flags = VB->Flag + VB->Start;
291 GLuint cm_flags = 0;
292
293 struct gl_material (*new_material)[2] = VB->Material + VB->Start;
294 GLuint *new_material_mask = VB->MaterialMask + VB->Start;
295 GLuint nr = VB->Count - VB->Start;
296
297 (void) cullmask;
298 (void) nstride;
299 (void) first_normal;
300 (void) flags;
301
302 if (ctx->Light.ColorMaterialEnabled) {
303 cm_flags = VERT_RGBA;
304
305 if (VB->ColorPtr->flags & VEC_BAD_STRIDE)
306 gl_clean_color(VB);
307
308 CMcolor = (GLubyte (*)[4])VB->ColorPtr->start;
309 }
310
311 VB->ColorPtr = VB->LitColor[0];
312 VB->Color[0] = VB->LitColor[0];
313 VB->Color[1] = VB->LitColor[1];
314
315 for ( j=0 ; j<nr ; j++,STRIDE_F(vertex,vstride),NEXT_VERTEX_NORMAL)
316 {
317 GLfloat sum[2][3];
318 struct gl_light *light;
319
320 if ( flags[j] & cm_flags )
321 gl_update_color_material( ctx, CMcolor[j] );
322
323 if ( flags[j] & VERT_MATERIAL )
324 gl_update_material( ctx, new_material[j], new_material_mask[j] );
325
326 if ( CULL(*mask) )
327 continue;
328
329 COPY_3V(sum[0], base[0]);
330
331 if ( NR_SIDES == 2 )
332 COPY_3V(sum[1], base[1]);
333
334 /* Add contribution from each enabled light source */
335 foreach (light, &ctx->Light.EnabledList) {
336
337 GLfloat n_dot_h;
338 GLfloat correction;
339 GLint side;
340 GLfloat contrib[3];
341 GLfloat attenuation = 1.0;
342 GLfloat VP[3]; /* unit vector from vertex to light */
343 GLfloat n_dot_VP; /* n dot VP */
344 GLfloat *h;
345 GLboolean normalized;
346
347 /* compute VP and attenuation */
348 if (!(light->Flags & LIGHT_POSITIONAL)) {
349 /* directional light */
350 COPY_3V(VP, light->VP_inf_norm);
351 attenuation = light->VP_inf_spot_attenuation;
352 }
353 else {
354 GLfloat d; /* distance from vertex to light */
355
356
357 /* KW: fix me */
358 if (vertex_size == 2) {
359 SUB_2V(VP, light->Position, vertex);
360 VP[2] = light->Position[2];
361 } else {
362 SUB_3V(VP, light->Position, vertex);
363 }
364
365 d = LEN_3FV( VP );
366
367 if ( d > 1e-6) {
368 GLfloat invd = 1.0F / d;
369 SELF_SCALE_SCALAR_3V(VP, invd);
370 }
371/* if (light->Flags & LIGHT_ATTENUATED) */
372 attenuation = 1.0F / (light->ConstantAttenuation + d *
373 (light->LinearAttenuation + d *
374 light->QuadraticAttenuation));
375
376 /* spotlight attenuation */
377 if (light->Flags & LIGHT_SPOT)
378 {
379 GLfloat PV_dot_dir = - DOT3(VP, light->NormDirection);
380
381 if (PV_dot_dir<light->CosCutoff) {
382 continue; /* this light makes no contribution */
383 }
384 else {
385 double x = PV_dot_dir * (EXP_TABLE_SIZE-1);
386 int k = (int) x;
387 GLfloat spot = (light->SpotExpTable[k][0]
388 + (x-k)*light->SpotExpTable[k][1]);
389 attenuation *= spot;
390 }
391 }
392 }
393
394
395 if (attenuation < 1e-3)
396 continue; /* this light makes no contribution */
397
398
399 /* Compute dot product or normal and vector from V to light pos */
400 n_dot_VP = DOT3( normal, VP );
401
402 /* which side are we lighting? */
403 if (n_dot_VP < 0.0F) {
404 if (LIGHT_FRONT(*mask)) {
405 ACC_SCALE_SCALAR_3V(sum[0], attenuation, light->MatAmbient[0]);
406 }
407 if (!LIGHT_REAR(*mask))
408 continue;
409
410 side = 1;
411 correction = -1;
412 n_dot_VP = -n_dot_VP;
413 } else {
414 if (LIGHT_REAR(*mask)) {
415 ACC_SCALE_SCALAR_3V( sum[1], attenuation, light->MatAmbient[1]);
416 }
417 if (!LIGHT_FRONT(*mask))
418 continue;
419 side = 0;
420 correction = 1;
421 }
422
423 COPY_3V(contrib, light->MatAmbient[side]);
424
425 /* diffuse term */
426 ACC_SCALE_SCALAR_3V(contrib, n_dot_VP, light->MatDiffuse[side]);
427
428 /* specular term - cannibalize VP... */
429 if (light->IsMatSpecular[side])
430 {
431 if (ctx->Light.Model.LocalViewer) {
432 GLfloat v[3];
433 COPY_3V(v, vertex);
434 if (vertex_size == 2) v[2] = 0;
435 NORMALIZE_3FV(v);
436 SUB_3V(VP, VP, v); /* h = VP + VPe */
437 h = VP;
438 normalized = 0;
439 }
440 else if (light->Flags & LIGHT_POSITIONAL) {
441 h = VP;
442 ACC_3V(h, ctx->EyeZDir);
443 normalized = 0;
444 } else {
445 h = light->h_inf_norm;
446 normalized = 1;
447 }
448
449 n_dot_h = correction * DOT3(normal, h);
450
451 if (n_dot_h > 0.0F)
452 {
453 GLfloat spec_coef;
454 struct gl_shine_tab *tab = ctx->ShineTable[side];
455
456 if (!normalized) {
457 n_dot_h *= n_dot_h;
458 n_dot_h /= LEN_SQUARED_3FV( h );
459 tab = ctx->ShineTable[side+2];
460 }
461
462 if (n_dot_h>1.0) {
463 spec_coef = pow( n_dot_h, tab->shininess );
464 } else {
465 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef );
466 }
467
468 ACC_SCALE_SCALAR_3V( contrib, spec_coef,
469 light->MatSpecular[side]);
470 }
471 }
472
473 ACC_SCALE_SCALAR_3V( sum[side], attenuation, contrib );
474 }
475
476 if (LIGHT_FRONT(*mask)) {
477 FLOAT_RGB_TO_UBYTE_RGB( Fcolor[j], sum[0] );
478 Fcolor[j][3] = sumA[0];
479 }
480
481 if (LIGHT_REAR(*mask)) {
482 FLOAT_RGB_TO_UBYTE_RGB( Bcolor[j], sum[1] );
483 Bcolor[j][3] = sumA[1];
484 }
485 }
486
487 if ( flags[j] & cm_flags )
488 gl_update_color_material( ctx, CMcolor[j] );
489
490 if ( flags[j] & VERT_MATERIAL )
491 gl_update_material( ctx, new_material[j], new_material_mask[j] );
492}
493
494
495
496
497/* Vertex size doesn't matter - yay!
498 */
499static void TAG(shade_fast_rgba)( struct vertex_buffer *VB )
500{
501 GLcontext *ctx = VB->ctx;
502 GLfloat (*base)[3] = ctx->Light.BaseColor;
503 GLubyte *sumA = ctx->Light.BaseAlpha;
504 GLuint nstride = VB->NormalPtr->stride;
505 const GLfloat *normal = VB->NormalPtr->start;
506 CONST GLfloat (*first_normal)[3] = (CONST GLfloat (*)[3])VB->NormalPtr->start;
507 GLubyte (*CMcolor)[4] = 0;
508 GLubyte (*Fcolor)[4] = (GLubyte (*)[4])VB->LitColor[0]->start;
509 GLubyte (*Bcolor)[4] = (GLubyte (*)[4])VB->LitColor[1]->start;
510 GLubyte *mask = VB->NormCullStart;
511 GLubyte *cullmask = mask;
512 GLuint *flags = VB->Flag + VB->Start;
513 GLuint cm_flags = 0;
514 GLuint interesting;
515 GLuint j = 0;
516 struct gl_material (*new_material)[2] = VB->Material + VB->Start;
517 GLuint *new_material_mask = VB->MaterialMask + VB->Start;
518
519 (void) cullmask;
520 (void) first_normal;
521 (void) flags;
522 (void) nstride;
523
524 if (ctx->Light.ColorMaterialEnabled)
525 {
526 cm_flags = VERT_RGBA;
527
528 if (VB->ColorPtr->flags & VEC_BAD_STRIDE)
529 gl_clean_color(VB);
530
531 CMcolor = (GLubyte (*)[4])VB->ColorPtr->start;
532 if ( *flags & VERT_RGBA )
533 gl_update_color_material( ctx, *CMcolor );
534
535 }
536
537 interesting = cm_flags | VERT_MATERIAL | VERT_END_VB | VERT_NORM;
538 VB->ColorPtr = VB->LitColor[0];
539 VB->Color[0] = VB->LitColor[0];
540 VB->Color[1] = VB->LitColor[1];
541
542 if ( flags[j] & VERT_MATERIAL )
543 gl_update_material( ctx, new_material[j], new_material_mask[j] );
544
545 do {
546 do {
547 if ( !CULL(*mask) )
548 {
549 struct gl_light *light;
550 GLfloat sum[2][3];
551 GLfloat spec;
552
553 COPY_3V(sum[0], base[0]);
554 if (NR_SIDES == 2) COPY_3V(sum[1], base[1]);
555
556 if (MESA_VERBOSE&VERBOSE_LIGHTING)
557 fprintf(stderr, "light normal %d/%d, %f %f %f\n",
558 j, VB->Start, normal[0], normal[1], normal[2]);
559
560
561 foreach (light, &ctx->Light.EnabledList) {
562
563 GLfloat n_dot_h;
564 GLint side = 0;
565 GLfloat n_dot_VP = DOT3(normal, light->VP_inf_norm);
566
567 if (n_dot_VP < 0.0F) {
568 if ( !LIGHT_REAR(*mask) ) continue;
569 ACC_SCALE_SCALAR_3V(sum[1], -n_dot_VP, light->MatDiffuse[1]);
570 if (!light->IsMatSpecular[1]) continue;
571 n_dot_h = -DOT3(normal, light->h_inf_norm);
572 side = 1;
573 } else {
574 if ( !LIGHT_FRONT(*mask) ) continue;
575 ACC_SCALE_SCALAR_3V(sum[0], n_dot_VP, light->MatDiffuse[0]);
576 if (!light->IsMatSpecular[0]) continue;
577 n_dot_h = DOT3(normal, light->h_inf_norm);
578 }
579
580 if (n_dot_h > 0.0F) {
581 struct gl_shine_tab *tab = ctx->ShineTable[side];
582 if (n_dot_h > 1.0)
583 spec = pow( n_dot_h, tab->shininess );
584 else
585 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec );
586
587 ACC_SCALE_SCALAR_3V( sum[side], spec,
588 light->MatSpecular[side]);
589 }
590 }
591
592 if (LIGHT_FRONT(*mask)) {
593 FLOAT_RGB_TO_UBYTE_RGB( Fcolor[j], sum[0] );
594 Fcolor[j][3] = sumA[0];
595 }
596
597 if (LIGHT_REAR(*mask)) {
598 FLOAT_RGB_TO_UBYTE_RGB( Bcolor[j], sum[1] );
599 Bcolor[j][3] = sumA[1];
600 }
601 }
602 j++;
603 NEXT_NORMAL;
604 } while ((flags[j] & interesting) == VERT_NORM);
605
606
607 if (COMPACTED) {
608 GLuint last = j-1;
609
610 for ( ; !(flags[j] & interesting) ; j++ )
611 {
612 COPY_4UBV(Fcolor[j], Fcolor[last]);
613 if (NR_SIDES==2)
614 COPY_4UBV(Bcolor[j], Bcolor[last]);
615 }
616
617 NEXT_NORMAL;
618 }
619
620 if ( flags[j] & cm_flags )
621 gl_update_color_material( ctx, CMcolor[j] );
622
623 if ( flags[j] & VERT_MATERIAL )
624 gl_update_material( ctx, new_material[j], new_material_mask[j] );
625
626 } while (!(flags[j] & VERT_END_VB));
627}
628
629
630
631
632
633/*
634 * Use current lighting/material settings to compute the color indexes
635 * for an array of vertices.
636 * Input: n - number of vertices to shade
637 * side - 0=use front material, 1=use back material
638 * vertex - array of [n] vertex position in eye coordinates
639 * normal - array of [n] surface normal vector
640 * Output: indexResult - resulting array of [n] color indexes
641 */
642static void TAG(shade_ci)( struct vertex_buffer *VB )
643{
644 GLuint j;
645
646 GLcontext *ctx = VB->ctx;
647 GLuint vstride = VB->Unprojected->stride;
648 const GLfloat *vertex = (GLfloat *)VB->Unprojected->start;
649 GLuint vertex_size = VB->Unprojected->size;
650
651 GLuint nstride = VB->NormalPtr->stride;
652 const GLfloat *normal = VB->NormalPtr->start;
653 CONST GLfloat (*first_normal)[3] = (CONST GLfloat (*)[3])VB->NormalPtr->start;
654
655 GLubyte (*CMcolor)[4] = 0;
656 GLubyte *mask = VB->CullMask + VB->Start;
657 GLubyte *cullmask = mask;
658 GLuint *flags = VB->Flag + VB->Start;
659 GLuint cm_flags = 0;
660 GLuint *indexResult[2];
661
662 struct gl_material (*new_material)[2] = VB->Material + VB->Start;
663 GLuint *new_material_mask = VB->MaterialMask + VB->Start;
664 GLuint nr = VB->Count - VB->Start;
665
666 (void) cullmask;
667 (void) nstride;
668 (void) first_normal;
669 (void) flags;
670
671 VB->IndexPtr = VB->LitIndex[0];
672 VB->Index[0] = VB->LitIndex[0];
673 VB->Index[1] = VB->LitIndex[1];
674
675 indexResult[0] = VB->Index[0]->start;
676 indexResult[1] = VB->Index[1]->start;
677
678 /* loop over vertices */
679
680 if (ctx->Light.ColorMaterialEnabled) {
681 cm_flags = VERT_RGBA;
682
683 if (VB->ColorPtr->flags & VEC_BAD_STRIDE)
684 gl_clean_color(VB);
685
686 CMcolor = (GLubyte (*)[4])VB->ColorPtr->start;
687 }
688
689 for ( j=0 ; j<nr ; j++,STRIDE_F(vertex,vstride),NEXT_VERTEX_NORMAL)
690 {
691 GLfloat diffuse[2], specular[2];
692 GLuint side = 0;
693 struct gl_light *light;
694
695 if ( flags[j] & cm_flags )
696 gl_update_color_material( ctx, CMcolor[j] );
697
698 if ( flags[j] & VERT_MATERIAL )
699 gl_update_material( ctx, new_material[j], new_material_mask[j] );
700
701 if ( CULL(*mask) )
702 continue;
703
704 diffuse[0] = specular[0] = 0.0F;
705
706 if ( NR_SIDES == 2 ) {
707 diffuse[1] = specular[1] = 0.0F;
708 }
709
710 /* Accumulate diffuse and specular from each light source */
711 foreach (light, &ctx->Light.EnabledList) {
712
713 GLfloat attenuation = 1.0F;
714 GLfloat VP[3]; /* unit vector from vertex to light */
715 GLfloat n_dot_VP; /* dot product of l and n */
716 GLfloat *h, n_dot_h, correction = 1.0;
717 GLboolean normalized;
718
719 /* compute l and attenuation */
720 if (!(light->Flags & LIGHT_POSITIONAL)) {
721 /* directional light */
722 COPY_3V(VP, light->VP_inf_norm);
723 }
724 else {
725 GLfloat d; /* distance from vertex to light */
726
727 if (vertex_size == 2) {
728 SUB_2V(VP, light->Position, vertex);
729 VP[2] = light->Position[2];
730 } else {
731 SUB_3V(VP, light->Position, vertex);
732 }
733
734 d = (GLfloat) LEN_3FV( VP );
735 if ( d > 1e-6) {
736 GLfloat invd = 1.0F / d;
737 SELF_SCALE_SCALAR_3V(VP, invd);
738 }
739
740 attenuation = 1.0F / (light->ConstantAttenuation + d *
741 (light->LinearAttenuation + d *
742 light->QuadraticAttenuation));
743
744 /* spotlight attenuation */
745 if (light->Flags & LIGHT_SPOT)
746 {
747 GLfloat PV_dot_dir = - DOT3(VP, light->NormDirection);
748 if (PV_dot_dir<light->CosCutoff) {
749 continue; /* this light makes no contribution */
750 }
751 else {
752 double x = PV_dot_dir * (EXP_TABLE_SIZE-1);
753 int k = (int) x;
754 GLfloat spot = (GLfloat) (light->SpotExpTable[k][0]
755 + (x-k)*light->SpotExpTable[k][1]);
756 attenuation *= spot;
757 }
758 }
759 }
760
761 if (attenuation < 1e-3)
762 continue; /* this light makes no contribution */
763
764 n_dot_VP = DOT3( normal, VP );
765
766 /* which side are we lighting? */
767 if (n_dot_VP < 0.0F) {
768 if (!LIGHT_REAR(*mask))
769 continue;
770 side = 1;
771 correction = -1;
772 n_dot_VP = -n_dot_VP;
773 } else {
774 if (!LIGHT_FRONT(*mask))
775 continue;
776 }
777
778 /* accumulate diffuse term */
779 diffuse[side] += n_dot_VP * light->dli * attenuation;
780
781 /* specular term */
782 if (!(light->Flags & LIGHT_SPECULAR))
783 continue;
784
785 if (ctx->Light.Model.LocalViewer) {
786 GLfloat v[3];
787 COPY_3V(v, vertex);
788 if (vertex_size == 2) v[2] = 0;
789 NORMALIZE_3FV(v);
790 SUB_3V(VP, VP, v); /* h = VP + VPe */
791 h = VP;
792 normalized = 0;
793 }
794 else if (light->Flags & LIGHT_POSITIONAL) {
795 h = VP;
796 ACC_3V(h, ctx->EyeZDir);
797 normalized = 0;
798 } else {
799 h = light->h_inf_norm;
800 normalized = 1;
801 }
802
803 n_dot_h = correction * DOT3(normal, h);
804
805 if (n_dot_h > 0.0F)
806 {
807 GLfloat spec_coef;
808 struct gl_shine_tab *tab = ctx->ShineTable[side];
809
810 if (!normalized) {
811 n_dot_h *= n_dot_h;
812 n_dot_h /= LEN_SQUARED_3FV( h );
813 tab = ctx->ShineTable[side+2];
814 }
815
816 if (n_dot_h>1.0) {
817 spec_coef = (GLfloat) pow( n_dot_h, tab->shininess );
818 } else {
819 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef);
820 }
821 specular[side] += spec_coef * light->sli * attenuation;
822 }
823 } /*loop over lights*/
824
825 /* Now compute final color index */
826 for (side = 0 ; side < NR_SIDES ; side++)
827 {
828 GLfloat index;
829 struct gl_material *mat;
830
831 if (!LIGHT_SIDE(*mask, side))
832 continue;
833
834 mat = &ctx->Light.Material[side];
835 if (specular[side] > 1.0F) {
836 index = mat->SpecularIndex;
837 }
838 else {
839 GLfloat d_a = mat->DiffuseIndex - mat->AmbientIndex;
840 GLfloat s_a = mat->SpecularIndex - mat->AmbientIndex;
841
842 index = mat->AmbientIndex
843 + diffuse[side] * (1.0F-specular[side]) * d_a
844 + specular[side] * s_a;
845 if (index > mat->SpecularIndex) {
846 index = mat->SpecularIndex;
847 }
848 }
849 indexResult[side][j] = (GLuint) (GLint) index;
850 }
851 } /*for vertex*/
852
853 if ( flags[j] & cm_flags )
854 gl_update_color_material( ctx, CMcolor[j] );
855
856 if ( flags[j] & VERT_MATERIAL )
857 gl_update_material( ctx, new_material[j], new_material_mask[j] );
858
859}
860
861
862
863static void TAG(init_shade_tab)( void )
864{
865 gl_shade_func_tab[IDX|SHADE_RGBA_VERTICES] = TAG(shade_rgba);
866 gl_shade_func_tab[IDX|SHADE_RGBA_NORMALS] = TAG(shade_fast_rgba);
867 gl_shade_func_tab[IDX|SHADE_RGBA_SPEC] = TAG(shade_rgba_spec);
868 gl_shade_func_tab[IDX] = TAG(shade_ci);
869}
870
871
872#undef TAG
873#undef INVALID
874#undef IDX
875#undef LIGHT_FRONT
876#undef LIGHT_REAR
877#undef LIGHT_SIDE
878#undef NR_SIDES
879#undef CULL
Note: See TracBrowser for help on using the repository browser.