Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygent_vb_lighttmp.h
Go to the documentation of this file.
00001 /* 00002 * Mesa 3-D graphics library 00003 * Version: 5.1 00004 * 00005 * Copyright (C) 1999-2003 Brian Paul All Rights Reserved. 00006 * 00007 * Permission is hereby granted, free of charge, to any person obtaining a 00008 * copy of this software and associated documentation files (the "Software"), 00009 * to deal in the Software without restriction, including without limitation 00010 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 00011 * and/or sell copies of the Software, and to permit persons to whom the 00012 * Software is furnished to do so, subject to the following conditions: 00013 * 00014 * The above copyright notice and this permission notice shall be included 00015 * in all copies or substantial portions of the Software. 00016 * 00017 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 00018 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00019 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 00020 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 00021 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 00022 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00023 * 00024 * 00025 * Authors: 00026 * Brian Paul 00027 * Keith Whitwell <keith@tungstengraphics.com> 00028 */ 00029 00030 00031 #if IDX & LIGHT_TWOSIDE 00032 # define NR_SIDES 2 00033 #else 00034 # define NR_SIDES 1 00035 #endif 00036 00037 00038 /* define TRACE to trace lighting code */ 00039 /* #define TRACE 1 */ 00040 00041 /* 00042 * ctx is the current context 00043 * VB is the vertex buffer 00044 * stage is the lighting stage-private data 00045 * input is the vector of eye or object-space vertex coordinates 00046 */ 00047 static void TAG(light_rgba_spec)( GLcontext *ctx, 00048 struct vertex_buffer *VB, 00049 struct tnl_pipeline_stage *stage, 00050 GLvector4f *input ) 00051 { 00052 struct light_stage_data *store = LIGHT_STAGE_DATA(stage); 00053 GLfloat (*base)[3] = ctx->Light._BaseColor; 00054 GLfloat sumA[2]; 00055 GLuint j; 00056 00057 const GLuint vstride = input->stride; 00058 const GLfloat *vertex = (GLfloat *)input->data; 00059 const GLuint nstride = VB->AttribPtr[_TNL_ATTRIB_NORMAL]->stride; 00060 const GLfloat *normal = (GLfloat *)VB->AttribPtr[_TNL_ATTRIB_NORMAL]->data; 00061 00062 GLfloat (*Fcolor)[4] = (GLfloat (*)[4]) store->LitColor[0].data; 00063 GLfloat (*Fspec)[4] = (GLfloat (*)[4]) store->LitSecondary[0].data; 00064 #if IDX & LIGHT_TWOSIDE 00065 GLfloat (*Bcolor)[4] = (GLfloat (*)[4]) store->LitColor[1].data; 00066 GLfloat (*Bspec)[4] = (GLfloat (*)[4]) store->LitSecondary[1].data; 00067 #endif 00068 00069 const GLuint nr = VB->Count; 00070 00071 #ifdef TRACE 00072 fprintf(stderr, "%s\n", __FUNCTION__ ); 00073 #endif 00074 00075 VB->ColorPtr[0] = &store->LitColor[0]; 00076 VB->SecondaryColorPtr[0] = &store->LitSecondary[0]; 00077 sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]; 00078 00079 #if IDX & LIGHT_TWOSIDE 00080 VB->ColorPtr[1] = &store->LitColor[1]; 00081 VB->SecondaryColorPtr[1] = &store->LitSecondary[1]; 00082 sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]; 00083 #endif 00084 00085 00086 store->LitColor[0].stride = 16; 00087 store->LitColor[1].stride = 16; 00088 00089 for (j = 0; j < nr; j++,STRIDE_F(vertex,vstride),STRIDE_F(normal,nstride)) { 00090 GLfloat sum[2][3], spec[2][3]; 00091 struct gl_light *light; 00092 00093 #if IDX & LIGHT_MATERIAL 00094 update_materials( ctx, store ); 00095 sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]; 00096 #if IDX & LIGHT_TWOSIDE 00097 sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]; 00098 #endif 00099 #endif 00100 00101 COPY_3V(sum[0], base[0]); 00102 ZERO_3V(spec[0]); 00103 00104 #if IDX & LIGHT_TWOSIDE 00105 COPY_3V(sum[1], base[1]); 00106 ZERO_3V(spec[1]); 00107 #endif 00108 00109 /* Add contribution from each enabled light source */ 00110 foreach (light, &ctx->Light.EnabledList) { 00111 GLfloat n_dot_h; 00112 GLfloat correction; 00113 GLint side; 00114 GLfloat contrib[3]; 00115 GLfloat attenuation; 00116 GLfloat VP[3]; /* unit vector from vertex to light */ 00117 GLfloat n_dot_VP; /* n dot VP */ 00118 GLfloat *h; 00119 00120 /* compute VP and attenuation */ 00121 if (!(light->_Flags & LIGHT_POSITIONAL)) { 00122 /* directional light */ 00123 COPY_3V(VP, light->_VP_inf_norm); 00124 attenuation = light->_VP_inf_spot_attenuation; 00125 } 00126 else { 00127 GLfloat d; /* distance from vertex to light */ 00128 00129 SUB_3V(VP, light->_Position, vertex); 00130 00131 d = (GLfloat) LEN_3FV( VP ); 00132 00133 if (d > 1e-6) { 00134 GLfloat invd = 1.0F / d; 00135 SELF_SCALE_SCALAR_3V(VP, invd); 00136 } 00137 00138 attenuation = 1.0F / (light->ConstantAttenuation + d * 00139 (light->LinearAttenuation + d * 00140 light->QuadraticAttenuation)); 00141 00142 /* spotlight attenuation */ 00143 if (light->_Flags & LIGHT_SPOT) { 00144 GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection); 00145 00146 if (PV_dot_dir<light->_CosCutoff) { 00147 continue; /* this light makes no contribution */ 00148 } 00149 else { 00150 GLdouble x = PV_dot_dir * (EXP_TABLE_SIZE-1); 00151 GLint k = (GLint) x; 00152 GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0] 00153 + (x-k)*light->_SpotExpTable[k][1]); 00154 attenuation *= spot; 00155 } 00156 } 00157 } 00158 00159 if (attenuation < 1e-3) 00160 continue; /* this light makes no contribution */ 00161 00162 /* Compute dot product or normal and vector from V to light pos */ 00163 n_dot_VP = DOT3( normal, VP ); 00164 00165 /* Which side gets the diffuse & specular terms? */ 00166 if (n_dot_VP < 0.0F) { 00167 ACC_SCALE_SCALAR_3V(sum[0], attenuation, light->_MatAmbient[0]); 00168 #if IDX & LIGHT_TWOSIDE 00169 side = 1; 00170 correction = -1; 00171 n_dot_VP = -n_dot_VP; 00172 #else 00173 continue; 00174 #endif 00175 } 00176 else { 00177 #if IDX & LIGHT_TWOSIDE 00178 ACC_SCALE_SCALAR_3V( sum[1], attenuation, light->_MatAmbient[1]); 00179 #endif 00180 side = 0; 00181 correction = 1; 00182 } 00183 00184 /* diffuse term */ 00185 COPY_3V(contrib, light->_MatAmbient[side]); 00186 ACC_SCALE_SCALAR_3V(contrib, n_dot_VP, light->_MatDiffuse[side]); 00187 ACC_SCALE_SCALAR_3V(sum[side], attenuation, contrib ); 00188 00189 /* specular term - cannibalize VP... */ 00190 if (ctx->Light.Model.LocalViewer) { 00191 GLfloat v[3]; 00192 COPY_3V(v, vertex); 00193 NORMALIZE_3FV(v); 00194 SUB_3V(VP, VP, v); /* h = VP + VPe */ 00195 h = VP; 00196 NORMALIZE_3FV(h); 00197 } 00198 else if (light->_Flags & LIGHT_POSITIONAL) { 00199 h = VP; 00200 ACC_3V(h, ctx->_EyeZDir); 00201 NORMALIZE_3FV(h); 00202 } 00203 else { 00204 h = light->_h_inf_norm; 00205 } 00206 00207 n_dot_h = correction * DOT3(normal, h); 00208 00209 if (n_dot_h > 0.0F) { 00210 GLfloat spec_coef; 00211 struct gl_shine_tab *tab = ctx->_ShineTable[side]; 00212 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef ); 00213 00214 if (spec_coef > 1.0e-10) { 00215 spec_coef *= attenuation; 00216 ACC_SCALE_SCALAR_3V( spec[side], spec_coef, 00217 light->_MatSpecular[side]); 00218 } 00219 } 00220 } /*loop over lights*/ 00221 00222 COPY_3V( Fcolor[j], sum[0] ); 00223 COPY_3V( Fspec[j], spec[0] ); 00224 Fcolor[j][3] = sumA[0]; 00225 00226 #if IDX & LIGHT_TWOSIDE 00227 COPY_3V( Bcolor[j], sum[1] ); 00228 COPY_3V( Bspec[j], spec[1] ); 00229 Bcolor[j][3] = sumA[1]; 00230 #endif 00231 } 00232 } 00233 00234 00235 static void TAG(light_rgba)( GLcontext *ctx, 00236 struct vertex_buffer *VB, 00237 struct tnl_pipeline_stage *stage, 00238 GLvector4f *input ) 00239 { 00240 struct light_stage_data *store = LIGHT_STAGE_DATA(stage); 00241 GLuint j; 00242 00243 GLfloat (*base)[3] = ctx->Light._BaseColor; 00244 GLfloat sumA[2]; 00245 00246 const GLuint vstride = input->stride; 00247 const GLfloat *vertex = (GLfloat *) input->data; 00248 const GLuint nstride = VB->AttribPtr[_TNL_ATTRIB_NORMAL]->stride; 00249 const GLfloat *normal = (GLfloat *)VB->AttribPtr[_TNL_ATTRIB_NORMAL]->data; 00250 00251 GLfloat (*Fcolor)[4] = (GLfloat (*)[4]) store->LitColor[0].data; 00252 #if IDX & LIGHT_TWOSIDE 00253 GLfloat (*Bcolor)[4] = (GLfloat (*)[4]) store->LitColor[1].data; 00254 #endif 00255 00256 const GLuint nr = VB->Count; 00257 00258 #ifdef TRACE 00259 fprintf(stderr, "%s\n", __FUNCTION__ ); 00260 #endif 00261 00262 VB->ColorPtr[0] = &store->LitColor[0]; 00263 sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]; 00264 00265 #if IDX & LIGHT_TWOSIDE 00266 VB->ColorPtr[1] = &store->LitColor[1]; 00267 sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]; 00268 #endif 00269 00270 store->LitColor[0].stride = 16; 00271 store->LitColor[1].stride = 16; 00272 00273 for (j = 0; j < nr; j++,STRIDE_F(vertex,vstride),STRIDE_F(normal,nstride)) { 00274 GLfloat sum[2][3]; 00275 struct gl_light *light; 00276 00277 #if IDX & LIGHT_MATERIAL 00278 update_materials( ctx, store ); 00279 sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]; 00280 #if IDX & LIGHT_TWOSIDE 00281 sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]; 00282 #endif 00283 #endif 00284 00285 COPY_3V(sum[0], base[0]); 00286 00287 #if IDX & LIGHT_TWOSIDE 00288 COPY_3V(sum[1], base[1]); 00289 #endif 00290 00291 /* Add contribution from each enabled light source */ 00292 foreach (light, &ctx->Light.EnabledList) { 00293 00294 GLfloat n_dot_h; 00295 GLfloat correction; 00296 GLint side; 00297 GLfloat contrib[3]; 00298 GLfloat attenuation = 1.0; 00299 GLfloat VP[3]; /* unit vector from vertex to light */ 00300 GLfloat n_dot_VP; /* n dot VP */ 00301 GLfloat *h; 00302 00303 /* compute VP and attenuation */ 00304 if (!(light->_Flags & LIGHT_POSITIONAL)) { 00305 /* directional light */ 00306 COPY_3V(VP, light->_VP_inf_norm); 00307 attenuation = light->_VP_inf_spot_attenuation; 00308 } 00309 else { 00310 GLfloat d; /* distance from vertex to light */ 00311 00312 00313 SUB_3V(VP, light->_Position, vertex); 00314 00315 d = (GLfloat) LEN_3FV( VP ); 00316 00317 if ( d > 1e-6) { 00318 GLfloat invd = 1.0F / d; 00319 SELF_SCALE_SCALAR_3V(VP, invd); 00320 } 00321 00322 attenuation = 1.0F / (light->ConstantAttenuation + d * 00323 (light->LinearAttenuation + d * 00324 light->QuadraticAttenuation)); 00325 00326 /* spotlight attenuation */ 00327 if (light->_Flags & LIGHT_SPOT) { 00328 GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection); 00329 00330 if (PV_dot_dir<light->_CosCutoff) { 00331 continue; /* this light makes no contribution */ 00332 } 00333 else { 00334 GLdouble x = PV_dot_dir * (EXP_TABLE_SIZE-1); 00335 GLint k = (GLint) x; 00336 GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0] 00337 + (x-k)*light->_SpotExpTable[k][1]); 00338 attenuation *= spot; 00339 } 00340 } 00341 } 00342 00343 if (attenuation < 1e-3) 00344 continue; /* this light makes no contribution */ 00345 00346 /* Compute dot product or normal and vector from V to light pos */ 00347 n_dot_VP = DOT3( normal, VP ); 00348 00349 /* which side are we lighting? */ 00350 if (n_dot_VP < 0.0F) { 00351 ACC_SCALE_SCALAR_3V(sum[0], attenuation, light->_MatAmbient[0]); 00352 #if IDX & LIGHT_TWOSIDE 00353 side = 1; 00354 correction = -1; 00355 n_dot_VP = -n_dot_VP; 00356 #else 00357 continue; 00358 #endif 00359 } 00360 else { 00361 #if IDX & LIGHT_TWOSIDE 00362 ACC_SCALE_SCALAR_3V( sum[1], attenuation, light->_MatAmbient[1]); 00363 #endif 00364 side = 0; 00365 correction = 1; 00366 } 00367 00368 COPY_3V(contrib, light->_MatAmbient[side]); 00369 00370 /* diffuse term */ 00371 ACC_SCALE_SCALAR_3V(contrib, n_dot_VP, light->_MatDiffuse[side]); 00372 00373 /* specular term - cannibalize VP... */ 00374 { 00375 if (ctx->Light.Model.LocalViewer) { 00376 GLfloat v[3]; 00377 COPY_3V(v, vertex); 00378 NORMALIZE_3FV(v); 00379 SUB_3V(VP, VP, v); /* h = VP + VPe */ 00380 h = VP; 00381 NORMALIZE_3FV(h); 00382 } 00383 else if (light->_Flags & LIGHT_POSITIONAL) { 00384 h = VP; 00385 ACC_3V(h, ctx->_EyeZDir); 00386 NORMALIZE_3FV(h); 00387 } 00388 else { 00389 h = light->_h_inf_norm; 00390 } 00391 00392 n_dot_h = correction * DOT3(normal, h); 00393 00394 if (n_dot_h > 0.0F) 00395 { 00396 GLfloat spec_coef; 00397 struct gl_shine_tab *tab = ctx->_ShineTable[side]; 00398 00399 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef ); 00400 00401 ACC_SCALE_SCALAR_3V( contrib, spec_coef, 00402 light->_MatSpecular[side]); 00403 } 00404 } 00405 00406 ACC_SCALE_SCALAR_3V( sum[side], attenuation, contrib ); 00407 } 00408 00409 COPY_3V( Fcolor[j], sum[0] ); 00410 Fcolor[j][3] = sumA[0]; 00411 00412 #if IDX & LIGHT_TWOSIDE 00413 COPY_3V( Bcolor[j], sum[1] ); 00414 Bcolor[j][3] = sumA[1]; 00415 #endif 00416 } 00417 } 00418 00419 00420 00421 00422 /* As below, but with just a single light. 00423 */ 00424 static void TAG(light_fast_rgba_single)( GLcontext *ctx, 00425 struct vertex_buffer *VB, 00426 struct tnl_pipeline_stage *stage, 00427 GLvector4f *input ) 00428 00429 { 00430 struct light_stage_data *store = LIGHT_STAGE_DATA(stage); 00431 const GLuint nstride = VB->AttribPtr[_TNL_ATTRIB_NORMAL]->stride; 00432 const GLfloat *normal = (GLfloat *)VB->AttribPtr[_TNL_ATTRIB_NORMAL]->data; 00433 GLfloat (*Fcolor)[4] = (GLfloat (*)[4]) store->LitColor[0].data; 00434 #if IDX & LIGHT_TWOSIDE 00435 GLfloat (*Bcolor)[4] = (GLfloat (*)[4]) store->LitColor[1].data; 00436 #endif 00437 const struct gl_light *light = ctx->Light.EnabledList.next; 00438 GLuint j = 0; 00439 GLfloat base[2][4]; 00440 #if IDX & LIGHT_MATERIAL 00441 const GLuint nr = VB->Count; 00442 #else 00443 const GLuint nr = VB->AttribPtr[_TNL_ATTRIB_NORMAL]->count; 00444 #endif 00445 00446 #ifdef TRACE 00447 fprintf(stderr, "%s\n", __FUNCTION__ ); 00448 #endif 00449 00450 (void) input; /* doesn't refer to Eye or Obj */ 00451 00452 VB->ColorPtr[0] = &store->LitColor[0]; 00453 #if IDX & LIGHT_TWOSIDE 00454 VB->ColorPtr[1] = &store->LitColor[1]; 00455 #endif 00456 00457 if (nr > 1) { 00458 store->LitColor[0].stride = 16; 00459 store->LitColor[1].stride = 16; 00460 } 00461 else { 00462 store->LitColor[0].stride = 0; 00463 store->LitColor[1].stride = 0; 00464 } 00465 00466 for (j = 0; j < nr; j++, STRIDE_F(normal,nstride)) { 00467 00468 GLfloat n_dot_VP; 00469 00470 #if IDX & LIGHT_MATERIAL 00471 update_materials( ctx, store ); 00472 #endif 00473 00474 /* No attenuation, so incoporate _MatAmbient into base color. 00475 */ 00476 #if !(IDX & LIGHT_MATERIAL) 00477 if ( j == 0 ) 00478 #endif 00479 { 00480 COPY_3V(base[0], light->_MatAmbient[0]); 00481 ACC_3V(base[0], ctx->Light._BaseColor[0] ); 00482 base[0][3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]; 00483 00484 #if IDX & LIGHT_TWOSIDE 00485 COPY_3V(base[1], light->_MatAmbient[1]); 00486 ACC_3V(base[1], ctx->Light._BaseColor[1]); 00487 base[1][3] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]; 00488 #endif 00489 } 00490 00491 n_dot_VP = DOT3(normal, light->_VP_inf_norm); 00492 00493 if (n_dot_VP < 0.0F) { 00494 #if IDX & LIGHT_TWOSIDE 00495 GLfloat n_dot_h = -DOT3(normal, light->_h_inf_norm); 00496 GLfloat sum[3]; 00497 COPY_3V(sum, base[1]); 00498 ACC_SCALE_SCALAR_3V(sum, -n_dot_VP, light->_MatDiffuse[1]); 00499 if (n_dot_h > 0.0F) { 00500 GLfloat spec; 00501 GET_SHINE_TAB_ENTRY( ctx->_ShineTable[1], n_dot_h, spec ); 00502 ACC_SCALE_SCALAR_3V(sum, spec, light->_MatSpecular[1]); 00503 } 00504 COPY_3V(Bcolor[j], sum ); 00505 Bcolor[j][3] = base[1][3]; 00506 #endif 00507 COPY_4FV(Fcolor[j], base[0]); 00508 } 00509 else { 00510 GLfloat n_dot_h = DOT3(normal, light->_h_inf_norm); 00511 GLfloat sum[3]; 00512 COPY_3V(sum, base[0]); 00513 ACC_SCALE_SCALAR_3V(sum, n_dot_VP, light->_MatDiffuse[0]); 00514 if (n_dot_h > 0.0F) { 00515 GLfloat spec; 00516 GET_SHINE_TAB_ENTRY( ctx->_ShineTable[0], n_dot_h, spec ); 00517 ACC_SCALE_SCALAR_3V(sum, spec, light->_MatSpecular[0]); 00518 00519 } 00520 COPY_3V(Fcolor[j], sum ); 00521 Fcolor[j][3] = base[0][3]; 00522 #if IDX & LIGHT_TWOSIDE 00523 COPY_4FV(Bcolor[j], base[1]); 00524 #endif 00525 } 00526 } 00527 } 00528 00529 00530 /* Light infinite lights 00531 */ 00532 static void TAG(light_fast_rgba)( GLcontext *ctx, 00533 struct vertex_buffer *VB, 00534 struct tnl_pipeline_stage *stage, 00535 GLvector4f *input ) 00536 { 00537 struct light_stage_data *store = LIGHT_STAGE_DATA(stage); 00538 GLfloat sumA[2]; 00539 const GLuint nstride = VB->AttribPtr[_TNL_ATTRIB_NORMAL]->stride; 00540 const GLfloat *normal = (GLfloat *)VB->AttribPtr[_TNL_ATTRIB_NORMAL]->data; 00541 GLfloat (*Fcolor)[4] = (GLfloat (*)[4]) store->LitColor[0].data; 00542 #if IDX & LIGHT_TWOSIDE 00543 GLfloat (*Bcolor)[4] = (GLfloat (*)[4]) store->LitColor[1].data; 00544 #endif 00545 GLuint j = 0; 00546 #if IDX & LIGHT_MATERIAL 00547 const GLuint nr = VB->Count; 00548 #else 00549 const GLuint nr = VB->AttribPtr[_TNL_ATTRIB_NORMAL]->count; 00550 #endif 00551 const struct gl_light *light; 00552 00553 #ifdef TRACE 00554 fprintf(stderr, "%s %d\n", __FUNCTION__, nr ); 00555 #endif 00556 00557 (void) input; 00558 00559 sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]; 00560 sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]; 00561 00562 VB->ColorPtr[0] = &store->LitColor[0]; 00563 #if IDX & LIGHT_TWOSIDE 00564 VB->ColorPtr[1] = &store->LitColor[1]; 00565 #endif 00566 00567 if (nr > 1) { 00568 store->LitColor[0].stride = 16; 00569 store->LitColor[1].stride = 16; 00570 } 00571 else { 00572 store->LitColor[0].stride = 0; 00573 store->LitColor[1].stride = 0; 00574 } 00575 00576 for (j = 0; j < nr; j++, STRIDE_F(normal,nstride)) { 00577 00578 GLfloat sum[2][3]; 00579 00580 #if IDX & LIGHT_MATERIAL 00581 update_materials( ctx, store ); 00582 00583 sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]; 00584 #if IDX & LIGHT_TWOSIDE 00585 sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]; 00586 #endif 00587 #endif 00588 00589 00590 COPY_3V(sum[0], ctx->Light._BaseColor[0]); 00591 #if IDX & LIGHT_TWOSIDE 00592 COPY_3V(sum[1], ctx->Light._BaseColor[1]); 00593 #endif 00594 00595 foreach (light, &ctx->Light.EnabledList) { 00596 GLfloat n_dot_h, n_dot_VP, spec; 00597 00598 ACC_3V(sum[0], light->_MatAmbient[0]); 00599 #if IDX & LIGHT_TWOSIDE 00600 ACC_3V(sum[1], light->_MatAmbient[1]); 00601 #endif 00602 00603 n_dot_VP = DOT3(normal, light->_VP_inf_norm); 00604 00605 if (n_dot_VP > 0.0F) { 00606 ACC_SCALE_SCALAR_3V(sum[0], n_dot_VP, light->_MatDiffuse[0]); 00607 n_dot_h = DOT3(normal, light->_h_inf_norm); 00608 if (n_dot_h > 0.0F) { 00609 struct gl_shine_tab *tab = ctx->_ShineTable[0]; 00610 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec ); 00611 ACC_SCALE_SCALAR_3V( sum[0], spec, light->_MatSpecular[0]); 00612 } 00613 } 00614 #if IDX & LIGHT_TWOSIDE 00615 else { 00616 ACC_SCALE_SCALAR_3V(sum[1], -n_dot_VP, light->_MatDiffuse[1]); 00617 n_dot_h = -DOT3(normal, light->_h_inf_norm); 00618 if (n_dot_h > 0.0F) { 00619 struct gl_shine_tab *tab = ctx->_ShineTable[1]; 00620 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec ); 00621 ACC_SCALE_SCALAR_3V( sum[1], spec, light->_MatSpecular[1]); 00622 } 00623 } 00624 #endif 00625 } 00626 00627 COPY_3V( Fcolor[j], sum[0] ); 00628 Fcolor[j][3] = sumA[0]; 00629 00630 #if IDX & LIGHT_TWOSIDE 00631 COPY_3V( Bcolor[j], sum[1] ); 00632 Bcolor[j][3] = sumA[1]; 00633 #endif 00634 } 00635 } 00636 00637 00638 00639 00640 00641 /* 00642 * Use current lighting/material settings to compute the color indexes 00643 * for an array of vertices. 00644 * Input: n - number of vertices to light 00645 * side - 0=use front material, 1=use back material 00646 * vertex - array of [n] vertex position in eye coordinates 00647 * normal - array of [n] surface normal vector 00648 * Output: indexResult - resulting array of [n] color indexes 00649 */ 00650 static void TAG(light_ci)( GLcontext *ctx, 00651 struct vertex_buffer *VB, 00652 struct tnl_pipeline_stage *stage, 00653 GLvector4f *input ) 00654 { 00655 struct light_stage_data *store = LIGHT_STAGE_DATA(stage); 00656 GLuint j; 00657 const GLuint vstride = input->stride; 00658 const GLfloat *vertex = (GLfloat *) input->data; 00659 const GLuint nstride = VB->AttribPtr[_TNL_ATTRIB_NORMAL]->stride; 00660 const GLfloat *normal = (GLfloat *)VB->AttribPtr[_TNL_ATTRIB_NORMAL]->data; 00661 GLfloat *indexResult[2]; 00662 const GLuint nr = VB->Count; 00663 00664 #ifdef TRACE 00665 fprintf(stderr, "%s\n", __FUNCTION__ ); 00666 #endif 00667 00668 VB->IndexPtr[0] = &store->LitIndex[0]; 00669 #if IDX & LIGHT_TWOSIDE 00670 VB->IndexPtr[1] = &store->LitIndex[1]; 00671 #endif 00672 00673 indexResult[0] = (GLfloat *)VB->IndexPtr[0]->data; 00674 #if IDX & LIGHT_TWOSIDE 00675 indexResult[1] = (GLfloat *)VB->IndexPtr[1]->data; 00676 #endif 00677 00678 /* loop over vertices */ 00679 for (j=0; j<nr; j++,STRIDE_F(vertex,vstride),STRIDE_F(normal, nstride)) { 00680 GLfloat diffuse[2], specular[2]; 00681 GLuint side = 0; 00682 struct gl_light *light; 00683 00684 #if IDX & LIGHT_MATERIAL 00685 update_materials( ctx, store ); 00686 #endif 00687 00688 diffuse[0] = specular[0] = 0.0F; 00689 00690 #if IDX & LIGHT_TWOSIDE 00691 diffuse[1] = specular[1] = 0.0F; 00692 #endif 00693 00694 /* Accumulate diffuse and specular from each light source */ 00695 foreach (light, &ctx->Light.EnabledList) { 00696 00697 GLfloat attenuation = 1.0F; 00698 GLfloat VP[3]; /* unit vector from vertex to light */ 00699 GLfloat n_dot_VP; /* dot product of l and n */ 00700 GLfloat *h, n_dot_h, correction = 1.0; 00701 00702 /* compute l and attenuation */ 00703 if (!(light->_Flags & LIGHT_POSITIONAL)) { 00704 /* directional light */ 00705 COPY_3V(VP, light->_VP_inf_norm); 00706 } 00707 else { 00708 GLfloat d; /* distance from vertex to light */ 00709 00710 SUB_3V(VP, light->_Position, vertex); 00711 00712 d = (GLfloat) LEN_3FV( VP ); 00713 if ( d > 1e-6) { 00714 GLfloat invd = 1.0F / d; 00715 SELF_SCALE_SCALAR_3V(VP, invd); 00716 } 00717 00718 attenuation = 1.0F / (light->ConstantAttenuation + d * 00719 (light->LinearAttenuation + d * 00720 light->QuadraticAttenuation)); 00721 00722 /* spotlight attenuation */ 00723 if (light->_Flags & LIGHT_SPOT) { 00724 GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection); 00725 if (PV_dot_dir < light->_CosCutoff) { 00726 continue; /* this light makes no contribution */ 00727 } 00728 else { 00729 GLdouble x = PV_dot_dir * (EXP_TABLE_SIZE-1); 00730 GLint k = (GLint) x; 00731 GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0] 00732 + (x-k)*light->_SpotExpTable[k][1]); 00733 attenuation *= spot; 00734 } 00735 } 00736 } 00737 00738 if (attenuation < 1e-3) 00739 continue; /* this light makes no contribution */ 00740 00741 n_dot_VP = DOT3( normal, VP ); 00742 00743 /* which side are we lighting? */ 00744 if (n_dot_VP < 0.0F) { 00745 #if IDX & LIGHT_TWOSIDE 00746 side = 1; 00747 correction = -1; 00748 n_dot_VP = -n_dot_VP; 00749 #else 00750 continue; 00751 #endif 00752 } 00753 00754 /* accumulate diffuse term */ 00755 diffuse[side] += n_dot_VP * light->_dli * attenuation; 00756 00757 /* specular term */ 00758 if (ctx->Light.Model.LocalViewer) { 00759 GLfloat v[3]; 00760 COPY_3V(v, vertex); 00761 NORMALIZE_3FV(v); 00762 SUB_3V(VP, VP, v); /* h = VP + VPe */ 00763 h = VP; 00764 NORMALIZE_3FV(h); 00765 } 00766 else if (light->_Flags & LIGHT_POSITIONAL) { 00767 h = VP; 00768 /* Strangely, disabling this addition fixes a conformance 00769 * problem. If this code is enabled, l_sed.c fails. 00770 */ 00771 /*ACC_3V(h, ctx->_EyeZDir);*/ 00772 NORMALIZE_3FV(h); 00773 } 00774 else { 00775 h = light->_h_inf_norm; 00776 } 00777 00778 n_dot_h = correction * DOT3(normal, h); 00779 if (n_dot_h > 0.0F) { 00780 GLfloat spec_coef; 00781 struct gl_shine_tab *tab = ctx->_ShineTable[side]; 00782 GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef); 00783 specular[side] += spec_coef * light->_sli * attenuation; 00784 } 00785 } /*loop over lights*/ 00786 00787 /* Now compute final color index */ 00788 for (side = 0 ; side < NR_SIDES ; side++) { 00789 const GLfloat *ind = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_INDEXES + side]; 00790 GLfloat index; 00791 00792 if (specular[side] > 1.0F) { 00793 index = ind[MAT_INDEX_SPECULAR]; 00794 } 00795 else { 00796 GLfloat d_a = ind[MAT_INDEX_DIFFUSE] - ind[MAT_INDEX_AMBIENT]; 00797 GLfloat s_a = ind[MAT_INDEX_SPECULAR] - ind[MAT_INDEX_AMBIENT]; 00798 index = (ind[MAT_INDEX_AMBIENT] 00799 + diffuse[side] * (1.0F-specular[side]) * d_a 00800 + specular[side] * s_a); 00801 if (index > ind[MAT_INDEX_SPECULAR]) { 00802 index = ind[MAT_INDEX_SPECULAR]; 00803 } 00804 } 00805 indexResult[side][j] = index; 00806 } 00807 } /*for vertex*/ 00808 } 00809 00810 00811 00812 static void TAG(init_light_tab)( void ) 00813 { 00814 _tnl_light_tab[IDX] = TAG(light_rgba); 00815 _tnl_light_fast_tab[IDX] = TAG(light_fast_rgba); 00816 _tnl_light_fast_single_tab[IDX] = TAG(light_fast_rgba_single); 00817 _tnl_light_spec_tab[IDX] = TAG(light_rgba_spec); 00818 _tnl_light_ci_tab[IDX] = TAG(light_ci); 00819 } 00820 00821 00822 #undef TAG 00823 #undef IDX 00824 #undef NR_SIDES Generated on Sun May 27 2012 04:20:46 for ReactOS by
1.7.6.1
|