t_vb_lighttmp.h revision 22ae633d1ea636e0e07ba044a0f8fa2195c83bc6
1/* 2 * Mesa 3-D graphics library 3 * Version: 5.1 4 * 5 * Copyright (C) 1999-2003 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 * Authors: 26 * Brian Paul 27 * Keith Whitwell <keith@tungstengraphics.com> 28 */ 29 30 31#if IDX & LIGHT_TWOSIDE 32# define NR_SIDES 2 33#else 34# define NR_SIDES 1 35#endif 36 37 38/* define TRACE to trace lighting code */ 39#define TRACE 1 40 41/* 42 * ctx is the current context 43 * VB is the vertex buffer 44 * stage is the lighting stage-private data 45 * input is the vector of eye or object-space vertex coordinates 46 */ 47static void TAG(light_rgba_spec)( GLcontext *ctx, 48 struct vertex_buffer *VB, 49 struct tnl_pipeline_stage *stage, 50 GLvector4f *input ) 51{ 52 struct light_stage_data *store = LIGHT_STAGE_DATA(stage); 53 GLfloat (*base)[3] = ctx->Light._BaseColor; 54 GLfloat sumA[2]; 55 GLuint j; 56 57 const GLuint vstride = input->stride; 58 const GLfloat *vertex = (GLfloat *)input->data; 59 const GLuint nstride = VB->NormalPtr->stride; 60 const GLfloat *normal = (GLfloat *)VB->NormalPtr->data; 61 62 GLfloat (*Fcolor)[4] = (GLfloat (*)[4]) store->LitColor[0].data; 63 GLfloat (*Fspec)[4] = (GLfloat (*)[4]) store->LitSecondary[0].data; 64#if IDX & LIGHT_TWOSIDE 65 GLfloat (*Bcolor)[4] = (GLfloat (*)[4]) store->LitColor[1].data; 66 GLfloat (*Bspec)[4] = (GLfloat (*)[4]) store->LitSecondary[1].data; 67#endif 68 69 const GLuint nr = VB->Count; 70 71 (void) nstride; 72 (void) vstride; 73 74#ifdef TRACE 75 fprintf(stderr, "%s\n", __FUNCTION__ ); 76#endif 77 78 VB->ColorPtr[0] = &store->LitColor[0]; 79 VB->SecondaryColorPtr[0] = &store->LitSecondary[0]; 80 sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]; 81 82#if IDX & LIGHT_TWOSIDE 83 VB->ColorPtr[1] = &store->LitColor[1]; 84 VB->SecondaryColorPtr[1] = &store->LitSecondary[1]; 85 sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]; 86#endif 87 88 /* Side-effects done, can we finish now? 89 */ 90 if (stage->changed_inputs == 0) 91 return; 92 93 for (j = 0; j < nr; j++,STRIDE_F(vertex,vstride),STRIDE_F(normal,nstride)) { 94 GLfloat sum[2][3], spec[2][3]; 95 struct gl_light *light; 96 97#if IDX & LIGHT_MATERIAL 98 update_materials( ctx, store ); 99 sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]; 100#if IDX & LIGHT_TWOSIDE 101 sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]; 102#endif 103#endif 104 105 COPY_3V(sum[0], base[0]); 106 ZERO_3V(spec[0]); 107 108#if IDX & LIGHT_TWOSIDE 109 COPY_3V(sum[1], base[1]); 110 ZERO_3V(spec[1]); 111#endif 112 113 /* Add contribution from each enabled light source */ 114 foreach (light, &ctx->Light.EnabledList) { 115 GLfloat n_dot_h; 116 GLfloat correction; 117 GLint side; 118 GLfloat contrib[3]; 119 GLfloat attenuation; 120 GLfloat VP[3]; /* unit vector from vertex to light */ 121 GLfloat n_dot_VP; /* n dot VP */ 122 GLfloat *h; 123 124 /* compute VP and attenuation */ 125 if (!(light->_Flags & LIGHT_POSITIONAL)) { 126 /* directional light */ 127 COPY_3V(VP, light->_VP_inf_norm); 128 attenuation = light->_VP_inf_spot_attenuation; 129 } 130 else { 131 GLfloat d; /* distance from vertex to light */ 132 133 SUB_3V(VP, light->_Position, vertex); 134 135 d = (GLfloat) LEN_3FV( VP ); 136 137 if (d > 1e-6) { 138 GLfloat invd = 1.0F / d; 139 SELF_SCALE_SCALAR_3V(VP, invd); 140 } 141 142 attenuation = 1.0F / (light->ConstantAttenuation + d * 143 (light->LinearAttenuation + d * 144 light->QuadraticAttenuation)); 145 146 /* spotlight attenuation */ 147 if (light->_Flags & LIGHT_SPOT) { 148 GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection); 149 150 if (PV_dot_dir<light->_CosCutoff) { 151 continue; /* this light makes no contribution */ 152 } 153 else { 154 GLdouble x = PV_dot_dir * (EXP_TABLE_SIZE-1); 155 GLint k = (GLint) x; 156 GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0] 157 + (x-k)*light->_SpotExpTable[k][1]); 158 attenuation *= spot; 159 } 160 } 161 } 162 163 if (attenuation < 1e-3) 164 continue; /* this light makes no contribution */ 165 166 /* Compute dot product or normal and vector from V to light pos */ 167 n_dot_VP = DOT3( normal, VP ); 168 169 /* Which side gets the diffuse & specular terms? */ 170 if (n_dot_VP < 0.0F) { 171 ACC_SCALE_SCALAR_3V(sum[0], attenuation, light->_MatAmbient[0]); 172#if IDX & LIGHT_TWOSIDE 173 side = 1; 174 correction = -1; 175 n_dot_VP = -n_dot_VP; 176#else 177 continue; 178#endif 179 } 180 else { 181#if IDX & LIGHT_TWOSIDE 182 ACC_SCALE_SCALAR_3V( sum[1], attenuation, light->_MatAmbient[1]); 183#endif 184 side = 0; 185 correction = 1; 186 } 187 188 /* diffuse term */ 189 COPY_3V(contrib, light->_MatAmbient[side]); 190 ACC_SCALE_SCALAR_3V(contrib, n_dot_VP, light->_MatDiffuse[side]); 191 ACC_SCALE_SCALAR_3V(sum[side], attenuation, contrib ); 192 193 /* specular term - cannibalize VP... */ 194 if (ctx->Light.Model.LocalViewer) { 195 GLfloat v[3]; 196 COPY_3V(v, vertex); 197 NORMALIZE_3FV(v); 198 SUB_3V(VP, VP, v); /* h = VP + VPe */ 199 h = VP; 200 NORMALIZE_3FV(h); 201 } 202 else if (light->_Flags & LIGHT_POSITIONAL) { 203 h = VP; 204 ACC_3V(h, ctx->_EyeZDir); 205 NORMALIZE_3FV(h); 206 } 207 else { 208 h = light->_h_inf_norm; 209 } 210 211 n_dot_h = correction * DOT3(normal, h); 212 213 if (n_dot_h > 0.0F) { 214 GLfloat spec_coef; 215 struct gl_shine_tab *tab = ctx->_ShineTable[side]; 216 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef ); 217 218 if (spec_coef > 1.0e-10) { 219 spec_coef *= attenuation; 220 ACC_SCALE_SCALAR_3V( spec[side], spec_coef, 221 light->_MatSpecular[side]); 222 } 223 } 224 } /*loop over lights*/ 225 226 COPY_3V( Fcolor[j], sum[0] ); 227 COPY_3V( Fspec[j], spec[0] ); 228 Fcolor[j][3] = sumA[0]; 229 230#if IDX & LIGHT_TWOSIDE 231 COPY_3V( Bcolor[j], sum[1] ); 232 COPY_3V( Bspec[j], spec[1] ); 233 Bcolor[j][3] = sumA[1]; 234#endif 235 } 236} 237 238 239static void TAG(light_rgba)( GLcontext *ctx, 240 struct vertex_buffer *VB, 241 struct tnl_pipeline_stage *stage, 242 GLvector4f *input ) 243{ 244 struct light_stage_data *store = LIGHT_STAGE_DATA(stage); 245 GLuint j; 246 247 GLfloat (*base)[3] = ctx->Light._BaseColor; 248 GLfloat sumA[2]; 249 250 const GLuint vstride = input->stride; 251 const GLfloat *vertex = (GLfloat *) input->data; 252 const GLuint nstride = VB->NormalPtr->stride; 253 const GLfloat *normal = (GLfloat *)VB->NormalPtr->data; 254 255 GLfloat (*Fcolor)[4] = (GLfloat (*)[4]) store->LitColor[0].data; 256#if IDX & LIGHT_TWOSIDE 257 GLfloat (*Bcolor)[4] = (GLfloat (*)[4]) store->LitColor[1].data; 258#endif 259 260 const GLuint nr = VB->Count; 261 262#ifdef TRACE 263 fprintf(stderr, "%s\n", __FUNCTION__ ); 264#endif 265 266 (void) nstride; 267 (void) vstride; 268 269 VB->ColorPtr[0] = &store->LitColor[0]; 270 sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]; 271 272#if IDX & LIGHT_TWOSIDE 273 VB->ColorPtr[1] = &store->LitColor[1]; 274 sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]; 275#endif 276 277 if (stage->changed_inputs == 0) 278 return; 279 280 for (j = 0; j < nr; j++,STRIDE_F(vertex,vstride),STRIDE_F(normal,nstride)) { 281 GLfloat sum[2][3]; 282 struct gl_light *light; 283 284#if IDX & LIGHT_MATERIAL 285 update_materials( ctx, store ); 286 sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]; 287#if IDX & LIGHT_TWOSIDE 288 sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]; 289#endif 290#endif 291 292 COPY_3V(sum[0], base[0]); 293 294#if IDX & LIGHT_TWOSIDE 295 COPY_3V(sum[1], base[1]); 296#endif 297 298 /* Add contribution from each enabled light source */ 299 foreach (light, &ctx->Light.EnabledList) { 300 301 GLfloat n_dot_h; 302 GLfloat correction; 303 GLint side; 304 GLfloat contrib[3]; 305 GLfloat attenuation = 1.0; 306 GLfloat VP[3]; /* unit vector from vertex to light */ 307 GLfloat n_dot_VP; /* n dot VP */ 308 GLfloat *h; 309 310 /* compute VP and attenuation */ 311 if (!(light->_Flags & LIGHT_POSITIONAL)) { 312 /* directional light */ 313 COPY_3V(VP, light->_VP_inf_norm); 314 attenuation = light->_VP_inf_spot_attenuation; 315 } 316 else { 317 GLfloat d; /* distance from vertex to light */ 318 319 320 SUB_3V(VP, light->_Position, vertex); 321 322 d = (GLfloat) LEN_3FV( VP ); 323 324 if ( d > 1e-6) { 325 GLfloat invd = 1.0F / d; 326 SELF_SCALE_SCALAR_3V(VP, invd); 327 } 328 329 attenuation = 1.0F / (light->ConstantAttenuation + d * 330 (light->LinearAttenuation + d * 331 light->QuadraticAttenuation)); 332 333 /* spotlight attenuation */ 334 if (light->_Flags & LIGHT_SPOT) { 335 GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection); 336 337 if (PV_dot_dir<light->_CosCutoff) { 338 continue; /* this light makes no contribution */ 339 } 340 else { 341 GLdouble x = PV_dot_dir * (EXP_TABLE_SIZE-1); 342 GLint k = (GLint) x; 343 GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0] 344 + (x-k)*light->_SpotExpTable[k][1]); 345 attenuation *= spot; 346 } 347 } 348 } 349 350 if (attenuation < 1e-3) 351 continue; /* this light makes no contribution */ 352 353 /* Compute dot product or normal and vector from V to light pos */ 354 n_dot_VP = DOT3( normal, VP ); 355 356 /* which side are we lighting? */ 357 if (n_dot_VP < 0.0F) { 358 ACC_SCALE_SCALAR_3V(sum[0], attenuation, light->_MatAmbient[0]); 359#if IDX & LIGHT_TWOSIDE 360 side = 1; 361 correction = -1; 362 n_dot_VP = -n_dot_VP; 363#else 364 continue; 365#endif 366 } 367 else { 368#if IDX & LIGHT_TWOSIDE 369 ACC_SCALE_SCALAR_3V( sum[1], attenuation, light->_MatAmbient[1]); 370#endif 371 side = 0; 372 correction = 1; 373 } 374 375 COPY_3V(contrib, light->_MatAmbient[side]); 376 377 /* diffuse term */ 378 ACC_SCALE_SCALAR_3V(contrib, n_dot_VP, light->_MatDiffuse[side]); 379 380 /* specular term - cannibalize VP... */ 381 { 382 if (ctx->Light.Model.LocalViewer) { 383 GLfloat v[3]; 384 COPY_3V(v, vertex); 385 NORMALIZE_3FV(v); 386 SUB_3V(VP, VP, v); /* h = VP + VPe */ 387 h = VP; 388 NORMALIZE_3FV(h); 389 } 390 else if (light->_Flags & LIGHT_POSITIONAL) { 391 h = VP; 392 ACC_3V(h, ctx->_EyeZDir); 393 NORMALIZE_3FV(h); 394 } 395 else { 396 h = light->_h_inf_norm; 397 } 398 399 n_dot_h = correction * DOT3(normal, h); 400 401 if (n_dot_h > 0.0F) 402 { 403 GLfloat spec_coef; 404 struct gl_shine_tab *tab = ctx->_ShineTable[side]; 405 406 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef ); 407 408 ACC_SCALE_SCALAR_3V( contrib, spec_coef, 409 light->_MatSpecular[side]); 410 } 411 } 412 413 ACC_SCALE_SCALAR_3V( sum[side], attenuation, contrib ); 414 } 415 416 COPY_3V( Fcolor[j], sum[0] ); 417 Fcolor[j][3] = sumA[0]; 418 419#if IDX & LIGHT_TWOSIDE 420 COPY_3V( Bcolor[j], sum[1] ); 421 Bcolor[j][3] = sumA[1]; 422#endif 423 } 424} 425 426 427 428 429/* As below, but with just a single light. 430 */ 431static void TAG(light_fast_rgba_single)( GLcontext *ctx, 432 struct vertex_buffer *VB, 433 struct tnl_pipeline_stage *stage, 434 GLvector4f *input ) 435 436{ 437 struct light_stage_data *store = LIGHT_STAGE_DATA(stage); 438 const GLuint nstride = VB->NormalPtr->stride; 439 const GLfloat *normal = (GLfloat *)VB->NormalPtr->data; 440 GLfloat (*Fcolor)[4] = (GLfloat (*)[4]) store->LitColor[0].data; 441#if IDX & LIGHT_TWOSIDE 442 GLfloat (*Bcolor)[4] = (GLfloat (*)[4]) store->LitColor[1].data; 443#endif 444 const struct gl_light *light = ctx->Light.EnabledList.next; 445 GLuint j = 0; 446 GLfloat base[2][4]; 447 const GLuint nr = VB->Count; 448 449#ifdef TRACE 450 fprintf(stderr, "%s\n", __FUNCTION__ ); 451#endif 452 453 (void) input; /* doesn't refer to Eye or Obj */ 454 (void) nr; 455 (void) nstride; 456 457 VB->ColorPtr[0] = &store->LitColor[0]; 458#if IDX & LIGHT_TWOSIDE 459 VB->ColorPtr[1] = &store->LitColor[1]; 460#endif 461 462 if (stage->changed_inputs == 0) 463 return; 464 465 for (j = 0; j < nr; j++, STRIDE_F(normal,nstride)) { 466 467 GLfloat n_dot_VP; 468 469#if IDX & LIGHT_MATERIAL 470 update_materials( ctx, store ); 471#endif 472 473 /* No attenuation, so incoporate _MatAmbient into base color. 474 */ 475#if !(IDX & LIGHT_MATERIAL) 476 if ( j == 0 ) 477#endif 478 { 479 COPY_3V(base[0], light->_MatAmbient[0]); 480 ACC_3V(base[0], ctx->Light._BaseColor[0] ); 481 base[0][3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]; 482 483#if IDX & LIGHT_TWOSIDE 484 COPY_3V(base[1], light->_MatAmbient[1]); 485 ACC_3V(base[1], ctx->Light._BaseColor[1]); 486 base[1][3] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]; 487#endif 488 } 489 490 n_dot_VP = DOT3(normal, light->_VP_inf_norm); 491 492 if (n_dot_VP < 0.0F) { 493#if IDX & LIGHT_TWOSIDE 494 GLfloat n_dot_h = -DOT3(normal, light->_h_inf_norm); 495 GLfloat sum[3]; 496 COPY_3V(sum, base[1]); 497 ACC_SCALE_SCALAR_3V(sum, -n_dot_VP, light->_MatDiffuse[1]); 498 if (n_dot_h > 0.0F) { 499 GLfloat spec; 500 GET_SHINE_TAB_ENTRY( ctx->_ShineTable[1], n_dot_h, spec ); 501 ACC_SCALE_SCALAR_3V(sum, spec, light->_MatSpecular[1]); 502 } 503 COPY_3V(Bcolor[j], sum ); 504 Bcolor[j][3] = base[1][3]; 505#endif 506 COPY_4FV(Fcolor[j], base[0]); 507 } 508 else { 509 GLfloat n_dot_h = DOT3(normal, light->_h_inf_norm); 510 GLfloat sum[3]; 511 COPY_3V(sum, base[0]); 512 ACC_SCALE_SCALAR_3V(sum, n_dot_VP, light->_MatDiffuse[0]); 513 if (n_dot_h > 0.0F) { 514 GLfloat spec; 515 GET_SHINE_TAB_ENTRY( ctx->_ShineTable[0], n_dot_h, spec ); 516 ACC_SCALE_SCALAR_3V(sum, spec, light->_MatSpecular[0]); 517 518 } 519 COPY_3V(Fcolor[j], sum ); 520 Fcolor[j][3] = base[0][3]; 521#if IDX & LIGHT_TWOSIDE 522 COPY_4FV(Bcolor[j], base[1]); 523#endif 524 } 525 } 526} 527 528 529/* Light infinite lights 530 */ 531static void TAG(light_fast_rgba)( GLcontext *ctx, 532 struct vertex_buffer *VB, 533 struct tnl_pipeline_stage *stage, 534 GLvector4f *input ) 535{ 536 struct light_stage_data *store = LIGHT_STAGE_DATA(stage); 537 GLfloat sumA[2]; 538 const GLuint nstride = VB->NormalPtr->stride; 539 const GLfloat *normal = (GLfloat *)VB->NormalPtr->data; 540 GLfloat (*Fcolor)[4] = (GLfloat (*)[4]) store->LitColor[0].data; 541#if IDX & LIGHT_TWOSIDE 542 GLfloat (*Bcolor)[4] = (GLfloat (*)[4]) store->LitColor[1].data; 543#endif 544 GLuint j = 0; 545 const GLuint nr = VB->Count; 546 const struct gl_light *light; 547 548#ifdef TRACE 549 fprintf(stderr, "%s %d\n", __FUNCTION__, nr ); 550#endif 551 552 (void) input; 553 (void) nr; 554 (void) nstride; 555 556 sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]; 557 sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]; 558 559 VB->ColorPtr[0] = &store->LitColor[0]; 560#if IDX & LIGHT_TWOSIDE 561 VB->ColorPtr[1] = &store->LitColor[1]; 562#endif 563 564 if (stage->changed_inputs == 0) 565 return; 566 567 for (j = 0; j < nr; j++, STRIDE_F(normal,nstride)) { 568 569 GLfloat sum[2][3]; 570 571#if IDX & LIGHT_MATERIAL 572 update_materials( ctx, store ); 573 574 sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]; 575#if IDX & LIGHT_TWOSIDE 576 sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]; 577#endif 578#endif 579 580 581 COPY_3V(sum[0], ctx->Light._BaseColor[0]); 582#if IDX & LIGHT_TWOSIDE 583 COPY_3V(sum[1], ctx->Light._BaseColor[1]); 584#endif 585 586 foreach (light, &ctx->Light.EnabledList) { 587 GLfloat n_dot_h, n_dot_VP, spec; 588 589 ACC_3V(sum[0], light->_MatAmbient[0]); 590#if IDX & LIGHT_TWOSIDE 591 ACC_3V(sum[1], light->_MatAmbient[1]); 592#endif 593 594 n_dot_VP = DOT3(normal, light->_VP_inf_norm); 595 596 if (n_dot_VP > 0.0F) { 597 ACC_SCALE_SCALAR_3V(sum[0], n_dot_VP, light->_MatDiffuse[0]); 598 n_dot_h = DOT3(normal, light->_h_inf_norm); 599 if (n_dot_h > 0.0F) { 600 struct gl_shine_tab *tab = ctx->_ShineTable[0]; 601 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec ); 602 ACC_SCALE_SCALAR_3V( sum[0], spec, light->_MatSpecular[0]); 603 } 604 } 605#if IDX & LIGHT_TWOSIDE 606 else { 607 ACC_SCALE_SCALAR_3V(sum[1], -n_dot_VP, light->_MatDiffuse[1]); 608 n_dot_h = -DOT3(normal, light->_h_inf_norm); 609 if (n_dot_h > 0.0F) { 610 struct gl_shine_tab *tab = ctx->_ShineTable[1]; 611 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec ); 612 ACC_SCALE_SCALAR_3V( sum[1], spec, light->_MatSpecular[1]); 613 } 614 } 615#endif 616 } 617 618 COPY_3V( Fcolor[j], sum[0] ); 619 Fcolor[j][3] = sumA[0]; 620 621#if IDX & LIGHT_TWOSIDE 622 COPY_3V( Bcolor[j], sum[1] ); 623 Bcolor[j][3] = sumA[1]; 624#endif 625 } 626} 627 628 629 630 631 632/* 633 * Use current lighting/material settings to compute the color indexes 634 * for an array of vertices. 635 * Input: n - number of vertices to light 636 * side - 0=use front material, 1=use back material 637 * vertex - array of [n] vertex position in eye coordinates 638 * normal - array of [n] surface normal vector 639 * Output: indexResult - resulting array of [n] color indexes 640 */ 641static void TAG(light_ci)( GLcontext *ctx, 642 struct vertex_buffer *VB, 643 struct tnl_pipeline_stage *stage, 644 GLvector4f *input ) 645{ 646 struct light_stage_data *store = LIGHT_STAGE_DATA(stage); 647 GLuint j; 648 const GLuint vstride = input->stride; 649 const GLfloat *vertex = (GLfloat *) input->data; 650 const GLuint nstride = VB->NormalPtr->stride; 651 const GLfloat *normal = (GLfloat *)VB->NormalPtr->data; 652 GLfloat *indexResult[2]; 653 const GLuint nr = VB->Count; 654 655#ifdef TRACE 656 fprintf(stderr, "%s\n", __FUNCTION__ ); 657#endif 658 659 (void) nstride; 660 (void) vstride; 661 662 VB->IndexPtr[0] = &store->LitIndex[0]; 663#if IDX & LIGHT_TWOSIDE 664 VB->IndexPtr[1] = &store->LitIndex[1]; 665#endif 666 667 if (stage->changed_inputs == 0) 668 return; 669 670 indexResult[0] = (GLfloat *)VB->IndexPtr[0]->data; 671#if IDX & LIGHT_TWOSIDE 672 indexResult[1] = (GLfloat *)VB->IndexPtr[1]->data; 673#endif 674 675 /* loop over vertices */ 676 for (j=0; j<nr; j++,STRIDE_F(vertex,vstride),STRIDE_F(normal, nstride)) { 677 GLfloat diffuse[2], specular[2]; 678 GLuint side = 0; 679 struct gl_light *light; 680 681#if IDX & LIGHT_MATERIAL 682 update_materials( ctx, store ); 683#endif 684 685 diffuse[0] = specular[0] = 0.0F; 686 687#if IDX & LIGHT_TWOSIDE 688 diffuse[1] = specular[1] = 0.0F; 689#endif 690 691 /* Accumulate diffuse and specular from each light source */ 692 foreach (light, &ctx->Light.EnabledList) { 693 694 GLfloat attenuation = 1.0F; 695 GLfloat VP[3]; /* unit vector from vertex to light */ 696 GLfloat n_dot_VP; /* dot product of l and n */ 697 GLfloat *h, n_dot_h, correction = 1.0; 698 699 /* compute l and attenuation */ 700 if (!(light->_Flags & LIGHT_POSITIONAL)) { 701 /* directional light */ 702 COPY_3V(VP, light->_VP_inf_norm); 703 } 704 else { 705 GLfloat d; /* distance from vertex to light */ 706 707 SUB_3V(VP, light->_Position, vertex); 708 709 d = (GLfloat) LEN_3FV( VP ); 710 if ( d > 1e-6) { 711 GLfloat invd = 1.0F / d; 712 SELF_SCALE_SCALAR_3V(VP, invd); 713 } 714 715 attenuation = 1.0F / (light->ConstantAttenuation + d * 716 (light->LinearAttenuation + d * 717 light->QuadraticAttenuation)); 718 719 /* spotlight attenuation */ 720 if (light->_Flags & LIGHT_SPOT) { 721 GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection); 722 if (PV_dot_dir < light->_CosCutoff) { 723 continue; /* this light makes no contribution */ 724 } 725 else { 726 GLdouble x = PV_dot_dir * (EXP_TABLE_SIZE-1); 727 GLint k = (GLint) x; 728 GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0] 729 + (x-k)*light->_SpotExpTable[k][1]); 730 attenuation *= spot; 731 } 732 } 733 } 734 735 if (attenuation < 1e-3) 736 continue; /* this light makes no contribution */ 737 738 n_dot_VP = DOT3( normal, VP ); 739 740 /* which side are we lighting? */ 741 if (n_dot_VP < 0.0F) { 742#if IDX & LIGHT_TWOSIDE 743 side = 1; 744 correction = -1; 745 n_dot_VP = -n_dot_VP; 746#else 747 continue; 748#endif 749 } 750 751 /* accumulate diffuse term */ 752 diffuse[side] += n_dot_VP * light->_dli * attenuation; 753 754 /* specular term */ 755 if (ctx->Light.Model.LocalViewer) { 756 GLfloat v[3]; 757 COPY_3V(v, vertex); 758 NORMALIZE_3FV(v); 759 SUB_3V(VP, VP, v); /* h = VP + VPe */ 760 h = VP; 761 NORMALIZE_3FV(h); 762 } 763 else if (light->_Flags & LIGHT_POSITIONAL) { 764 h = VP; 765 /* Strangely, disabling this addition fixes a conformance 766 * problem. If this code is enabled, l_sed.c fails. 767 */ 768 /*ACC_3V(h, ctx->_EyeZDir);*/ 769 NORMALIZE_3FV(h); 770 } 771 else { 772 h = light->_h_inf_norm; 773 } 774 775 n_dot_h = correction * DOT3(normal, h); 776 if (n_dot_h > 0.0F) { 777 GLfloat spec_coef; 778 struct gl_shine_tab *tab = ctx->_ShineTable[side]; 779 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef); 780 specular[side] += spec_coef * light->_sli * attenuation; 781 } 782 } /*loop over lights*/ 783 784 /* Now compute final color index */ 785 for (side = 0 ; side < NR_SIDES ; side++) { 786 const GLfloat *ind = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_INDEXES + side]; 787 GLfloat index; 788 789 if (specular[side] > 1.0F) { 790 index = ind[MAT_INDEX_SPECULAR]; 791 } 792 else { 793 GLfloat d_a = ind[MAT_INDEX_DIFFUSE] - ind[MAT_INDEX_AMBIENT]; 794 GLfloat s_a = ind[MAT_INDEX_SPECULAR] - ind[MAT_INDEX_AMBIENT]; 795 index = (ind[MAT_INDEX_AMBIENT] 796 + diffuse[side] * (1.0F-specular[side]) * d_a 797 + specular[side] * s_a); 798 if (index > ind[MAT_INDEX_SPECULAR]) { 799 index = ind[MAT_INDEX_SPECULAR]; 800 } 801 } 802 indexResult[side][j] = index; 803 } 804 } /*for vertex*/ 805} 806 807 808 809static void TAG(init_light_tab)( void ) 810{ 811 _tnl_light_tab[IDX] = TAG(light_rgba); 812 _tnl_light_fast_tab[IDX] = TAG(light_fast_rgba); 813 _tnl_light_fast_single_tab[IDX] = TAG(light_fast_rgba_single); 814 _tnl_light_spec_tab[IDX] = TAG(light_rgba_spec); 815 _tnl_light_ci_tab[IDX] = TAG(light_ci); 816} 817 818 819#undef TAG 820#undef IDX 821#undef NR_SIDES 822