00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "std3d.h"
00027
00028 #include "3d/render_trav.h"
00029 #include "3d/hrc_trav.h"
00030 #include "3d/clip_trav.h"
00031 #include "3d/light_trav.h"
00032 #include "3d/driver.h"
00033 #include "3d/light.h"
00034 #include "3d/skeleton_model.h"
00035 #include "3d/scene.h"
00036 #include "3d/coarse_mesh_manager.h"
00037 #include "3d/lod_character_manager.h"
00038 #include "nel/misc/hierarchical_timer.h"
00039
00040 #include "3d/transform.h"
00041 #include "3d/fast_floor.h"
00042 #include "3d/mesh_skin_manager.h"
00043
00044 using namespace std;
00045 using namespace NLMISC;
00046
00047
00048 namespace NL3D
00049 {
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060 CRenderTrav::CRenderTrav()
00061 {
00062 RenderList.reserve(1024);
00063 OrderOpaqueList.init(1024);
00064 OrderTransparentList.init(1024);
00065 Driver = NULL;
00066 _CurrentPassOpaque = true;
00067
00068 _CacheLightContribution= NULL;
00069
00070
00071 LightingSystemEnabled= false;
00072 AmbientGlobal= CRGBA(50, 50, 50);
00073 SunAmbient= CRGBA::Black;
00074 SunDiffuse= SunSpecular= CRGBA::White;
00075 _SunDirection.set(0, 0.5, -0.5);
00076 _SunDirection.normalize();
00077
00078 _StrongestLightTouched = true;
00079
00080 _MeshSkinManager= NULL;
00081
00082 _LayersRenderingOrder= true;
00083 }
00084
00085 IObs *CRenderTrav::createDefaultObs() const
00086 {
00087 return new CDefaultRenderObs;
00088 }
00089
00090 void CRenderTrav::traverse()
00091 {
00092 H_AUTO( NL3D_TravRender );
00093
00094 ITravCameraScene::update();
00095
00096
00097 getDriver()->setFrustum(Left, Right, Bottom, Top, Near, Far, Perspective);
00098
00099 getDriver()->setupViewMatrixEx(ViewMatrix, CamPos);
00100 getDriver()->setupViewport(_Viewport);
00101
00102
00103 resetLightSetup();
00104
00105
00106
00107 if(_MeshSkinManager)
00108 {
00109 if(Driver!=_MeshSkinManager->getDriver())
00110 {
00111 _MeshSkinManager->release();
00112 _MeshSkinManager->init(Driver, NL3D_MESH_SKIN_MANAGER_VERTEXFORMAT, NL3D_MESH_SKIN_MANAGER_MAXVERTICES);
00113 }
00114 }
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125 OrderOpaqueList.reset(RenderList.size());
00126 OrderTransparentList.reset(RenderList.size());
00127
00128
00129 IBaseRenderObs **itRdrObs= NULL;
00130 uint32 nNbObs = RenderList.size();
00131 if(nNbObs)
00132 itRdrObs= &RenderList[0];
00133 float rPseudoZ, rPseudoZ2;
00134
00135
00136 float OOFar= 1.0f / this->Far;
00137 uint32 opaqueOtSize= OrderOpaqueList.getSize();
00138 uint32 opaqueOtMax= OrderOpaqueList.getSize()-1;
00139 uint32 transparentOtSize= OrderTransparentList.getSize();
00140 uint32 transparentOtMax= OrderTransparentList.getSize()-1;
00141 uint32 otId;
00142
00143 OptFastFloorBegin();
00144
00145 for( ; nNbObs>0; itRdrObs++, nNbObs-- )
00146 {
00147 IBaseRenderObs *pObs= *itRdrObs;
00148
00149 CTransform *pTransform = safe_cast<CTransform*>(pObs->Model);
00150 CTransformHrcObs *trHrcObs= safe_cast<CTransformHrcObs*>(pObs->HrcObs);
00151
00152
00153 rPseudoZ = (trHrcObs->WorldMatrix.getPos() - CamPos).norm();
00154
00155
00156 rPseudoZ = sqrtf( rPseudoZ * OOFar );
00157
00158 if( pTransform->isOpaque() )
00159 {
00160
00161 rPseudoZ2 = rPseudoZ * opaqueOtSize;
00162 otId= OptFastFloor(rPseudoZ2);
00163 otId= min(otId, opaqueOtMax);
00164 OrderOpaqueList.insert( otId, pObs );
00165 }
00166 if( pTransform->isTransparent() )
00167 {
00168
00169 rPseudoZ2 = rPseudoZ * transparentOtSize;
00170 otId= OptFastFloor(rPseudoZ2);
00171 otId= min(otId, transparentOtMax);
00172
00173 OrderTransparentList.insert( pTransform->getOrderingLayer(), pObs, transparentOtMax-otId );
00174 }
00175
00176 }
00177
00178 OptFastFloorEnd();
00179
00180
00181
00182
00183
00184
00185 if(Root)
00186 Root->traverse(NULL);
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198 CLodCharacterManager *clodMngr= Scene->getLodCharacterManager();
00199 if(clodMngr)
00200 clodMngr->beginRender(getDriver(), CamPos);
00201
00202
00203 _CurrentPassOpaque = true;
00204 OrderOpaqueList.begin();
00205 IBaseRenderObs *pBRO;
00206 while( OrderOpaqueList.get() != NULL )
00207 {
00208 pBRO = OrderOpaqueList.get();
00209 pBRO->traverse(NULL);
00210 OrderOpaqueList.next();
00211 }
00212
00213
00214
00215
00216
00217
00218 MeshBlockManager.flush(Driver, Scene, this);
00219
00220
00221
00222 if(clodMngr)
00223 clodMngr->endRender();
00224
00225
00226
00227
00228
00229
00230
00231 Scene->getDynamicCoarseMeshManager()->render(Driver);
00232
00233 Scene->getStaticCoarseMeshManager()->render(Driver);
00234
00235
00236
00237
00238
00239
00240 _CurrentPassOpaque = false;
00241 OrderTransparentList.begin(_LayersRenderingOrder);
00242 while( OrderTransparentList.get() != NULL )
00243 {
00244 pBRO = OrderTransparentList.get();
00245 pBRO->traverse(NULL);
00246 OrderTransparentList.next();
00247 }
00248
00249
00250
00251
00252
00253
00254 resetLightSetup();
00255
00256 }
00257
00258 void CRenderTrav::clearRenderList()
00259 {
00260 RenderList.clear();
00261 }
00262
00263 void CRenderTrav::addRenderObs(IBaseRenderObs *o)
00264 {
00265 RenderList.push_back(o);
00266 }
00267
00268
00269
00270 void CRenderTrav::setSunDirection(const CVector &dir)
00271 {
00272 _SunDirection= dir;
00273 _SunDirection.normalize();
00274 }
00275
00276
00277
00278 void CRenderTrav::setMeshSkinManager(CMeshSkinManager *msm)
00279 {
00280 _MeshSkinManager= msm;
00281 }
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292 void CRenderTrav::resetLightSetup()
00293 {
00294
00295 if(!LightingSystemEnabled)
00296 {
00297
00298 _NumLightEnabled= 1;
00299
00300 CVector defDir(-0.5f, 0.0, -0.85f);
00301 defDir.normalize();
00302 CRGBA aday= CRGBA(130, 105, 119);
00303 CRGBA dday= CRGBA(238, 225, 204);
00304 _DriverLight[0].setupDirectional(aday, dday, dday, defDir);
00305
00306 return;
00307 }
00308 else
00309 {
00310 uint i;
00311
00312
00313 for(i=0; i<Driver->getMaxLight(); i++)
00314 {
00315 Driver->enableLight(i, false);
00316 }
00317
00318
00319
00320
00321 _LastSunFactor= 0;
00322 _LastSunAmbient.set(0,0,0,255);
00323 _DriverLight[0].setupDirectional(CRGBA::Black, CRGBA::Black, CRGBA::Black, _SunDirection);
00324 Driver->setLight(0, _DriverLight[0]);
00325
00326 for(i=0; i<NL3D_MAX_LIGHT_CONTRIBUTION; i++)
00327 {
00328 _LastPointLight[i]= NULL;
00329 }
00330
00331
00332
00333
00334 _LastSunFactor= 0;
00335 _LastSunAmbient.set(0,0,0,255);
00336 CLight light;
00337 light.setupDirectional(CRGBA::Black, CRGBA::Black, CRGBA::Black, _SunDirection);
00338 _DriverLight[0].setupDirectional(CRGBA::Black, CRGBA::Black, CRGBA::Black, _SunDirection);
00339 Driver->setLight(0, light);
00340
00341 for(i=0; i<NL3D_MAX_LIGHT_CONTRIBUTION; i++)
00342 {
00343 _LastPointLight[i]= NULL;
00344 }
00345
00346
00347 Driver->setAmbientColor(AmbientGlobal);
00348
00349
00350
00351 _CacheLightContribution= NULL;
00352 _NumLightEnabled= 0;
00353
00354 _StrongestLightTouched = true;
00355 }
00356 }
00357
00358
00359
00360 void CRenderTrav::changeLightSetup(CLightContribution *lightContribution, bool useLocalAttenuation)
00361 {
00362
00363 if(!LightingSystemEnabled)
00364 return;
00365
00366 uint i;
00367
00368
00369 if(_CacheLightContribution == lightContribution && _LastLocalAttenuation == useLocalAttenuation)
00370 return;
00371
00372 else
00373 {
00374 _StrongestLightTouched = true;
00375
00376 if(lightContribution)
00377 {
00378
00379
00380 CRGBA finalAmbient;
00381
00382 if(lightContribution->FrozenStaticLightSetup)
00383 {
00384
00385 if(lightContribution->FrozenAmbientLight)
00386
00387 finalAmbient= lightContribution->FrozenAmbientLight->getAmbient();
00388 else
00389
00390 finalAmbient= SunAmbient;
00391 }
00392 else
00393 {
00394
00395 uint uAmbFactor= lightContribution->LocalAmbient.A;
00396
00397 uAmbFactor+= uAmbFactor>>7;
00398
00399 finalAmbient.modulateFromuiRGBOnly(SunAmbient, 256 - uAmbFactor);
00400 finalAmbient.addRGBOnly(finalAmbient, lightContribution->LocalAmbient);
00401 }
00402
00403 finalAmbient.A= 255;
00404
00405
00406
00407
00408
00409 uint ufactor= lightContribution->SunContribution;
00410
00411
00412 if(ufactor != _LastSunFactor || finalAmbient != _LastSunAmbient)
00413 {
00414
00415 _LastSunFactor= ufactor;
00416
00417 _LastSunAmbient= finalAmbient;
00418
00419
00420 ufactor+= ufactor>>7;
00421
00422 CRGBA sunDiffuse, sunSpecular;
00423 sunDiffuse.modulateFromuiRGBOnly(SunDiffuse, ufactor);
00424 sunSpecular.modulateFromuiRGBOnly(SunSpecular, ufactor);
00425
00426 _DriverLight[0].setupDirectional(finalAmbient, sunDiffuse, sunSpecular, _SunDirection);
00427 Driver->setLight(0, _DriverLight[0]);
00428 }
00429
00430
00431
00432
00433 uint plId=0;
00434
00435 while(lightContribution->PointLight[plId]!=NULL)
00436 {
00437 CPointLight *pl= lightContribution->PointLight[plId];
00438 uint inf;
00439 if(useLocalAttenuation)
00440 inf= lightContribution->Factor[plId];
00441 else
00442 inf= lightContribution->AttFactor[plId];
00443
00444
00445
00446
00447 if( pl!=_LastPointLight[plId] ||
00448 inf!=_LastPointLightFactor[plId] ||
00449 useLocalAttenuation!=_LastPointLightLocalAttenuation[plId] )
00450 {
00451
00452 _LastPointLight[plId]= pl;
00453 _LastPointLightFactor[plId]= inf;
00454 _LastPointLightLocalAttenuation[plId]= useLocalAttenuation;
00455
00456
00457 if(useLocalAttenuation)
00458 pl->setupDriverLight(_DriverLight[plId+1], inf);
00459 else
00460
00461 pl->setupDriverLightUserAttenuation(_DriverLight[plId+1], inf);
00462
00463
00464 Driver->setLight(plId+1, _DriverLight[plId+1]);
00465 }
00466
00467
00468 plId++;
00469 if(plId>=NL3D_MAX_LIGHT_CONTRIBUTION)
00470 break;
00471 }
00472
00473
00474
00475
00476
00477 uint newNumLightEnabled;
00478
00479 newNumLightEnabled= plId + 1;
00480
00481
00482 for(i=_NumLightEnabled; i<newNumLightEnabled; i++)
00483 {
00484 Driver->enableLight(i, true);
00485 }
00486
00487
00488 for(i=newNumLightEnabled; i<_NumLightEnabled; i++)
00489 {
00490 Driver->enableLight(i, false);
00491 }
00492
00493
00494 _CacheLightContribution = lightContribution;
00495 _NumLightEnabled= newNumLightEnabled;
00496 _LastLocalAttenuation= useLocalAttenuation;
00497 }
00498 else
00499 {
00500
00501
00502
00503 for(i=0; i<_NumLightEnabled; i++)
00504 {
00505 Driver->enableLight(i, false);
00506 }
00507
00508
00509 _CacheLightContribution = NULL;
00510 _NumLightEnabled= 0;
00511 }
00512
00513
00514 }
00515 }
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525 void CRenderTrav::beginVPLightSetup(uint ctStart, bool supportSpecular, const CMatrix &invObjectWM)
00526 {
00527 uint i;
00528 nlassert(MaxVPLight==4);
00529 _VPNumLights= min(_NumLightEnabled, (uint)MaxVPLight);
00530 _VPCurrentCtStart= ctStart;
00531 _VPSupportSpecular= supportSpecular;
00532
00533
00534
00535
00536 _VPFinalAmbient= AmbientGlobal;
00537 for(i=0; i<_VPNumLights; i++)
00538 {
00539 _VPFinalAmbient+= _DriverLight[i].getAmbiant();
00540 }
00541
00542 for(i=0; i<_VPNumLights; i++)
00543 {
00544 _VPLightDiffuse[i]= _DriverLight[i].getDiffuse();
00545 }
00546
00547 for(; i<MaxVPLight; i++)
00548 {
00549 _VPLightDiffuse[i]= CRGBA::Black;
00550 Driver->setConstant(_VPCurrentCtStart+1+i, 0.f, 0.f, 0.f, 0.f);
00551 }
00552
00553 if(supportSpecular)
00554 {
00555 for(i=0; i<_VPNumLights; i++)
00556 {
00557 _VPLightSpecular[i]= _DriverLight[i].getSpecular();
00558 }
00559
00560 for(; i<MaxVPLight; i++)
00561 {
00562 _VPLightSpecular[i]= CRGBA::Black;
00563 Driver->setConstant(_VPCurrentCtStart+5+i, 0.f, 0.f, 0.f, 0.f);
00564 }
00565 }
00566
00567
00568
00569 CVector eye= invObjectWM * CamPos;
00570
00571
00572
00573
00574 CVector lightDir;
00575
00576 lightDir= invObjectWM.mulVector(_DriverLight[0].getDirection());
00577 lightDir.normalize();
00578 lightDir= -lightDir;
00579 if(supportSpecular)
00580 {
00581
00582 Driver->setConstant(_VPCurrentCtStart+9, lightDir);
00583 }
00584 else
00585 {
00586
00587 Driver->setConstant(_VPCurrentCtStart+5, lightDir);
00588 }
00589
00590
00591
00592
00593 uint startPLPos;
00594 if(supportSpecular)
00595 {
00596
00597 Driver->setConstant(_VPCurrentCtStart+11, eye);
00598
00599 startPLPos= 12;
00600 }
00601 else
00602 {
00603
00604 startPLPos= 6;
00605 }
00606
00607 for(i=1; i<_VPNumLights; i++)
00608 {
00609
00610 CVector lightPos;
00611 lightPos= invObjectWM * _DriverLight[i].getPosition();
00612 Driver->setConstant(_VPCurrentCtStart+startPLPos+(i-1), lightPos);
00613 }
00614
00615
00616
00617 _VPMaterialCacheDirty= true;
00618 }
00619
00620
00621 void CRenderTrav::changeVPLightSetupMaterial(const CMaterial &mat, bool excludeStrongest)
00622 {
00623
00624 if(!_VPMaterialCacheDirty)
00625 {
00626
00627 if( _VPMaterialCacheEmissive == mat.getEmissive().getPacked() &&
00628 _VPMaterialCacheAmbient == mat.getAmbient().getPacked() &&
00629 _VPMaterialCacheDiffuse == mat.getDiffuse().getPacked() )
00630 {
00631
00632 if( !_VPSupportSpecular ||
00633 ( _VPMaterialCacheSpecular == mat.getSpecular().getPacked() &&
00634 _VPMaterialCacheShininess == mat.getShininess() ) )
00635 {
00636
00637 return;
00638 }
00639 }
00640 }
00641
00642
00643 _VPMaterialCacheDirty= false;
00644 _VPMaterialCacheEmissive= mat.getEmissive().getPacked();
00645 _VPMaterialCacheAmbient= mat.getDiffuse().getPacked();
00646 _VPMaterialCacheDiffuse= mat.getDiffuse().getPacked();
00647 _VPMaterialCacheSpecular= mat.getSpecular().getPacked();
00648 _VPMaterialCacheShininess= mat.getShininess();
00649
00650
00651 CRGBAF color;
00652 uint i;
00653 CRGBAF matDiff= mat.getDiffuse();
00654 CRGBAF matSpec= mat.getSpecular();
00655 float specExp= mat.getShininess();
00656
00657 uint strongestLightIndex = excludeStrongest ? getStrongestLightIndex() : _VPNumLights;
00658
00659
00660 color= _VPFinalAmbient * mat.getAmbient();
00661 color+= mat.getEmissive();
00662 Driver->setConstant(_VPCurrentCtStart+0, 1, &color.R);
00663
00664
00665
00666
00667
00668 for(i = 0; i < strongestLightIndex; ++i)
00669 {
00670 color= _VPLightDiffuse[i] * matDiff;
00671 Driver->setConstant(_VPCurrentCtStart+1+i, 1, &color.R);
00672 }
00673
00674
00675 if (i != _VPNumLights)
00676 {
00677 color= _VPLightDiffuse[i] * matDiff;
00678 _StrongestLightDiffuse.set((uint8) (255.f * color.R), (uint8) (255.f * color.G), (uint8) (255.f * color.B), (uint8) (255.f * color.A));
00679
00680 Driver->setConstant(_VPCurrentCtStart + 1 + i, 0.f, 0.f, 0.f, 0.f);
00681 ++i;
00682
00683 for(; i < _VPNumLights; i++)
00684 {
00685 color= _VPLightDiffuse[i] * matDiff;
00686 Driver->setConstant(_VPCurrentCtStart + 1 + i, 1, &color.R);
00687 }
00688 }
00689
00690
00691 if(_VPSupportSpecular)
00692 {
00693 for(i = 0; i < strongestLightIndex; ++i)
00694 {
00695 color= _VPLightSpecular[i] * matSpec;
00696 color.A= specExp;
00697 Driver->setConstant(_VPCurrentCtStart+5+i, 1, &color.R);
00698 }
00699
00700 if (i != _VPNumLights)
00701 {
00702 color= _VPLightSpecular[i] * matSpec;
00703 _StrongestLightSpecular.set((uint8) (255.f * color.R), (uint8) (255.f * color.G), (uint8) (255.f * color.B), (uint8) (255.f * color.A));
00704
00705
00706 Driver->setConstant(_VPCurrentCtStart + 5 + i, 0.f, 0.f, 0.f, 0.f);
00707 ++i;
00708
00709 for(; i < _VPNumLights; i++)
00710 {
00711 color= _VPLightSpecular[i] * matSpec;
00712 color.A= specExp;
00713 Driver->setConstant(_VPCurrentCtStart + 5 + i, 1, &color.R);
00714 }
00715 }
00716 }
00717
00718
00719 static float alphaCte[4]= {0,0,1,0};
00720 alphaCte[3]= matDiff.A;
00721
00722 if(_VPSupportSpecular)
00723 Driver->setConstant(_VPCurrentCtStart+10, 1, alphaCte);
00724 else
00725 Driver->setConstant(_VPCurrentCtStart+9, 1, alphaCte);
00726 }
00727
00728
00729 sint CRenderTrav::getStrongestLightIndex() const
00730 {
00731 if (!_StrongestLightTouched) return -1;
00732 uint vpNumLights = min(_NumLightEnabled, (uint)MaxVPLight);
00733
00734
00735 if (vpNumLights == 0) return -1;
00736 if (vpNumLights == 1) return 0;
00737
00738 float lumDir = _VPLightDiffuse[0].R + _VPLightDiffuse[0].G + _VPLightDiffuse[0].B + _VPLightDiffuse[0].A
00739 + _VPLightSpecular[0].R + _VPLightSpecular[0].G + _VPLightSpecular[0].B + _VPLightSpecular[0].A;
00740 float lumOmni = _VPLightDiffuse[1].R + _VPLightDiffuse[1].G + _VPLightDiffuse[1].B + _VPLightDiffuse[1].A
00741 + _VPLightSpecular[1].R + _VPLightSpecular[1].G + _VPLightSpecular[1].B + _VPLightSpecular[1].A;
00742 return lumDir > lumOmni ? 0 : 1;
00743 }
00744
00745
00746 void CRenderTrav::getStrongestLightColors(NLMISC::CRGBA &diffuse, NLMISC::CRGBA &specular)
00747 {
00748 sint strongestLightIndex = getStrongestLightIndex();
00749 if (strongestLightIndex == -1)
00750 {
00751 diffuse = specular = NLMISC::CRGBA::Black;
00752 }
00753 else
00754 {
00755 diffuse = _StrongestLightDiffuse;
00756 specular = _StrongestLightSpecular;
00757 }
00758 }
00759
00760
00761
00762 static const char* LightingVPFragmentNormalize=
00763 " # normalize normal \n\
00764 DP3 R6.w, R6, R6; \n\
00765 RSQ R6.w, R6.w; \n\
00766 MUL R6, R6, R6.w; \n\
00767 ";
00768
00769
00770
00771
00772 static const char* LightingVPFragmentNoSpecular_Begin=
00773 " \n\
00774 # Global Ambient. \n\
00775 MOV R2, c[CTS+0]; \n\
00776 \n\
00777 # Diffuse Sun \n\
00778 DP3 R0.x, R6, c[CTS+5]; # R0.x= normal*-lightDir \n\
00779 LIT R0.y, R0.xxxx; # R0.y= R0.x clamped \n\
00780 MAD R2, R0.y, c[CTS+1], R2; # R2= summed vertex color. \n\
00781 ";
00782
00783
00784 static const char* LightingVPFragmentNoSpecular_PL[]=
00785 {
00786 " # Diffuse PointLight 0. \n\
00787 ADD R0, c[CTS+6], -R5; # R0= lightPos-vertex \n\
00788 DP3 R0.w, R0, R0; # normalize R0. \n\
00789 RSQ R0.w, R0.w; \n\
00790 MUL R0, R0, R0.w; \n\
00791 DP3 R0.x, R6, R0; # R0.x= normal*lightDir \n\
00792 LIT R0.y, R0.xxxx; # R0.y= R0.x clamped \n\
00793 MAD R2, R0.y, c[CTS+2], R2; # R2= summed vertex color. \n\
00794 ",
00795 " # Diffuse PointLight 1. \n\
00796 ADD R0, c[CTS+7], -R5; # R0= lightPos-vertex \n\
00797 DP3 R0.w, R0, R0; # normalize R0. \n\
00798 RSQ R0.w, R0.w; \n\
00799 MUL R0, R0, R0.w; \n\
00800 DP3 R0.x, R6, R0; # R0.x= normal*lightDir \n\
00801 LIT R0.y, R0; # R0.y= R0.x clamped \n\
00802 MAD R2, R0.y, c[CTS+3], R2; # R2= summed vertex color. \n\
00803 ",
00804 " # Diffuse PointLight 2. \n\
00805 ADD R0, c[CTS+8], -R5; # R0= lightPos-vertex \n\
00806 DP3 R0.w, R0, R0; # normalize R0. \n\
00807 RSQ R0.w, R0.w; \n\
00808 MUL R0, R0, R0.w; \n\
00809 DP3 R0.x, R6, R0; # R0.x= normal*lightDir \n\
00810 LIT R0.y, R0; # R0.y= R0.x clamped \n\
00811 MAD R2, R0.y, c[CTS+4], R2; # R2= summed vertex color. \n\
00812 "
00813 };
00814
00815
00816 static const char* LightingVPFragmentNoSpecular_End=
00817 " # output to o[COL0] only, replacing alpha with material alpha. \n\
00818 MAD o[COL0], R2, c[CTS+9].zzzx, c[CTS+9].xxxw; \n\
00819 ";
00820
00821
00822
00823
00824 static const char* LightingVPFragmentSpecular_Begin=
00825 " \n\
00826 # Global Ambient. \n\
00827 MOV R2, c[CTS+0]; \n\
00828 \n\
00829 # Always keep Specular exponent in R0.w \n\
00830 MOV R0.w, c[CTS+5].w; \n\
00831 \n\
00832 # Compute vertex-to-eye vector normed. \n\
00833 ADD R4, c[CTS+11], -R5; \n\
00834 DP3 R4.w, R4, R4; \n\
00835 RSQ R4.w, R4.w; \n\
00836 MUL R4, R4, R4.w; \n\
00837 \n\
00838 # Diffuse-Specular Sun \n\
00839 # Compute R1= halfAngleVector= (lightDir+R4).normed(). \n\
00840 ADD R1.xyz, c[CTS+9], R4; # R1= halfAngleVector \n\
00841 DP3 R1.w, R1, R1; # normalize R1. \n\
00842 RSQ R1.w, R1.w; \n\
00843 MUL R1.xyz, R1, R1.w; \n\
00844 # Compute Factors and colors. \n\
00845 DP3 R0.x, R6, c[CTS+9]; # R0.x= normal*-lightDir \n\
00846 DP3 R0.yz, R6, R1; # R0.yz= normal*halfAngleVector \n\
00847 LIT R0.yz, R0; # R0.y= R0.x clamped, R0.z= pow(spec, R0.w) clamp \n\
00848 MAD R2, R0.y, c[CTS+1], R2; # R2= summed vertex color. \n\
00849 MUL R3, R0.z, c[CTS+5]; # R3= specular color. \n\
00850 ";
00851
00852
00853 static const char* LightingVPFragmentSpecular_PL[]=
00854 {
00855 " # Diffuse-Specular PointLight 0. \n\
00856 # Compute R0= (lightPos-vertex).normed(). \n\
00857 ADD R0.xyz, c[CTS+12], -R5; # R0= lightPos-vertex \n\
00858 DP3 R1.w, R0, R0; # normalize R0. \n\
00859 RSQ R1.w, R1.w; \n\
00860 MUL R0.xyz, R0, R1.w; \n\
00861 # Compute R1= halfAngleVector= (R0+R4).normed(). \n\
00862 ADD R1.xyz, R0, R4; # R1= halfAngleVector \n\
00863 DP3 R1.w, R1, R1; # normalize R1. \n\
00864 RSQ R1.w, R1.w; \n\
00865 MUL R1.xyz, R1, R1.w; \n\
00866 # Compute Factors and colors. \n\
00867 DP3 R0.x, R6, R0; # R0.x= normal*lightDir \n\
00868 DP3 R0.yz, R6, R1; # R0.yz= normal*halfAngleVector \n\
00869 LIT R0.yz, R0; # R0.y= R0.x clamped, R0.z= pow(spec, R0.w) clamp \n\
00870 MAD R2, R0.y, c[CTS+2], R2; # R2= summed vertex color. \n\
00871 MAD R3, R0.z, c[CTS+6], R3; # R3= summed specular color. \n\
00872 ",
00873 " # Diffuse-Specular PointLight 1. \n\
00874 # Compute R0= (lightPos-vertex).normed(). \n\
00875 ADD R0.xyz, c[CTS+13], -R5; # R0= lightPos-vertex \n\
00876 DP3 R1.w, R0, R0; # normalize R0. \n\
00877 RSQ R1.w, R1.w; \n\
00878 MUL R0.xyz, R0, R1.w; \n\
00879 # Compute R1= halfAngleVector= (R0+R4).normed(). \n\
00880 ADD R1.xyz, R0, R4; # R1= halfAngleVector \n\
00881 DP3 R1.w, R1, R1; # normalize R1. \n\
00882 RSQ R1.w, R1.w; \n\
00883 MUL R1.xyz, R1, R1.w; \n\
00884 # Compute Factors and colors. \n\
00885 DP3 R0.x, R6, R0; # R0.x= normal*lightDir \n\
00886 DP3 R0.yz, R6, R1; # R0.yz= normal*halfAngleVector \n\
00887 LIT R0.yz, R0; # R0.y= R0.x clamped, R0.z= pow(spec, R0.w) clamp \n\
00888 MAD R2, R0.y, c[CTS+3], R2; # R2= summed vertex color. \n\
00889 MAD R3, R0.z, c[CTS+7], R3; # R3= summed specular color. \n\
00890 ",
00891 " # Diffuse-Specular PointLight 2. \n\
00892 # Compute R0= (lightPos-vertex).normed(). \n\
00893 ADD R0.xyz, c[CTS+14], -R5; # R0= lightPos-vertex \n\
00894 DP3 R1.w, R0, R0; # normalize R0. \n\
00895 RSQ R1.w, R1.w; \n\
00896 MUL R0.xyz, R0, R1.w; \n\
00897 # Compute R1= halfAngleVector= (R0+R4).normed(). \n\
00898 ADD R1.xyz, R0, R4; # R1= halfAngleVector \n\
00899 DP3 R1.w, R1, R1; # normalize R1. \n\
00900 RSQ R1.w, R1.w; \n\
00901 MUL R1.xyz, R1, R1.w; \n\
00902 # Compute Factors and colors. \n\
00903 DP3 R0.x, R6, R0; # R0.x= normal*lightDir \n\
00904 DP3 R0.yz, R6, R1; # R0.yz= normal*halfAngleVector \n\
00905 LIT R0.yz, R0; # R0.y= R0.x clamped, R0.z= pow(spec, R0.w) clamp \n\
00906 MAD R2, R0.y, c[CTS+4], R2; # R2= summed vertex color. \n\
00907 "
00908 };
00909
00910
00911
00912 static const char* LightingVPFragmentSpecular_End=
00913 " # output directly to secondary color. \n\
00914 MAD o[COL1], R0.z, c[CTS+8], R3; # final summed specular color. \n\
00915 \n\
00916 # output diffuse to o[COL0], replacing alpha with material alpha. \n\
00917 MAD o[COL0], R2, c[CTS+10].zzzx, c[CTS+10].xxxw; \n\
00918 ";
00919
00920
00921 static void strReplaceAll(string &strInOut, const string &tokenSrc, const string &tokenDst)
00922 {
00923 uint32 pos;
00924 sint srcLen= tokenSrc.size();
00925 while( (pos=strInOut.find(tokenSrc)) != string::npos)
00926 {
00927 strInOut.replace(pos, srcLen, tokenDst);
00928 }
00929 }
00930
00931
00932 std::string CRenderTrav::getLightVPFragment(uint numActivePointLights, uint ctStart, bool supportSpecular, bool normalize)
00933 {
00934 string ret;
00935
00936
00937 nlassert(MaxVPLight==4);
00938 nlassert(numActivePointLights<=MaxVPLight-1);
00939
00940
00941 if(normalize)
00942 ret+= LightingVPFragmentNormalize;
00943
00944
00945 if(supportSpecular)
00946 {
00947
00948 ret+= LightingVPFragmentSpecular_Begin;
00949
00950
00951 for(uint i=0;i<numActivePointLights;i++)
00952 {
00953 ret+= LightingVPFragmentSpecular_PL[i];
00954 }
00955
00956
00957 ret+= LightingVPFragmentSpecular_End;
00958 }
00959 else
00960 {
00961
00962 ret+= LightingVPFragmentNoSpecular_Begin;
00963
00964
00965 for(uint i=0;i<numActivePointLights;i++)
00966 {
00967 ret+= LightingVPFragmentNoSpecular_PL[i];
00968 }
00969
00970
00971 ret+= LightingVPFragmentNoSpecular_End;
00972 }
00973
00974
00975
00976 for(sint i=14; i>=0; i--)
00977 {
00978 char tokenSrc[256];
00979 sprintf(tokenSrc, "CTS+%d", i);
00980 char tokenDst[256];
00981 sprintf(tokenDst, "%d", ctStart+i);
00982
00983 strReplaceAll(ret, tokenSrc, tokenDst);
00984 }
00985
00986
00987 nlassert( ret.find("CTS+")==string::npos );
00988
00989 return ret;
00990 }
00991
00992
00993 }