00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "std3d.h"
00025
00026 #include "nel/3d/render_trav.h"
00027 #include "nel/3d/hrc_trav.h"
00028 #include "nel/3d/clip_trav.h"
00029 #include "nel/3d/light_trav.h"
00030 #include "nel/3d/driver.h"
00031 #include "nel/3d/light.h"
00032 #include "nel/3d/skeleton_model.h"
00033 #include "nel/3d/scene.h"
00034 #include "nel/3d/coarse_mesh_manager.h"
00035 #include "nel/3d/lod_character_manager.h"
00036 #include "nel/3d/water_model.h"
00037 #include "nel/3d/water_shape.h"
00038 #include "nel/misc/hierarchical_timer.h"
00039
00040 #include "nel/3d/transform.h"
00041 #include "nel/misc/fast_floor.h"
00042 #include "nel/3d/vertex_stream_manager.h"
00043 #include "nel/3d/landscape_model.h"
00044 #include "nel/3d/shape_bank.h"
00045
00046 using namespace std;
00047 using namespace NLMISC;
00048
00049 namespace NL3D
00050 {
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 CRenderTrav::CRenderTrav()
00069 {
00070 RenderList.resize(1024);
00071 _CurrentNumVisibleModels= 0;
00072 _MaxTransparencyPriority = 0;
00073 OrderOpaqueList.init(1024);
00074 setupTransparencySorting();
00075 Driver = NULL;
00076 _CurrentPassOpaque = true;
00077
00078 _CacheLightContribution= NULL;
00079
00080
00081 LightingSystemEnabled= false;
00082 AmbientGlobal= CRGBA(50, 50, 50);
00083 SunAmbient= CRGBA::Black;
00084 SunDiffuse= SunSpecular= CRGBA::White;
00085 _SunDirection.set(0, 0.5, -0.5);
00086 _SunDirection.normalize();
00087
00088 _StrongestLightTouched = true;
00089
00090 _MeshSkinManager= NULL;
00091 _ShadowMeshSkinManager= NULL;
00092
00093 _LayersRenderingOrder= true;
00094 _FirstWaterModel = NULL;
00095 }
00096
00097
00098
00099
00100
00101
00102 void CRenderTrav::traverse(UScene::TRenderPart renderPart, bool newRender)
00103 {
00104 #ifdef NL_DEBUG_RENDER_TRAV
00105 nlwarning("Render trave begin");
00106 #endif
00107 H_AUTO( NL3D_TravRender );
00108 if (getDriver()->isLost()) return;
00109 CTravCameraScene::update();
00110
00111 setupDriverCamera();
00112 getDriver()->setupViewport(_Viewport);
00113
00114
00115 resetLightSetup();
00116 if (newRender)
00117 {
00118
00119
00120 if(_MeshSkinManager)
00121 {
00122 if(Driver!=_MeshSkinManager->getDriver())
00123 {
00124 _MeshSkinManager->release();
00125 _MeshSkinManager->init(Driver,
00126 NL3D_MESH_SKIN_MANAGER_VERTEXFORMAT,
00127 NL3D_MESH_SKIN_MANAGER_MAXVERTICES,
00128 NL3D_MESH_SKIN_MANAGER_NUMVB,
00129 "MRMSkinVB", true);
00130 }
00131 }
00132
00133
00134 if(_ShadowMeshSkinManager)
00135 {
00136 if(getAuxDriver()!=_ShadowMeshSkinManager->getDriver())
00137 {
00138 _ShadowMeshSkinManager->release();
00139 _ShadowMeshSkinManager->init(getAuxDriver(),
00140 NL3D_SHADOW_MESH_SKIN_MANAGER_VERTEXFORMAT,
00141 NL3D_SHADOW_MESH_SKIN_MANAGER_MAXVERTICES,
00142 NL3D_SHADOW_MESH_SKIN_MANAGER_NUMVB,
00143 "ShadowSkinVB", true);
00144 }
00145 }
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156 OrderOpaqueList.reset(_CurrentNumVisibleModels);
00157 for(uint k = 0; k <= (uint) _MaxTransparencyPriority; ++k)
00158 {
00159 _OrderTransparentListByPriority[k].reset(_CurrentNumVisibleModels);
00160
00161 }
00162
00163
00164 CTransform **itRdrModel= NULL;
00165 uint32 nNbModels = _CurrentNumVisibleModels;
00166 if(nNbModels)
00167 itRdrModel= &RenderList[0];
00168 float rPseudoZ, rPseudoZ2;
00169
00170
00171 float OOFar= 1.0f / this->Far;
00172 uint32 opaqueOtSize= OrderOpaqueList.getSize();
00173 uint32 opaqueOtMax= OrderOpaqueList.getSize()-1;
00174 uint32 transparentOtSize= _OrderTransparentListByPriority[0].getSize();
00175 uint32 transparentOtMax= _OrderTransparentListByPriority[0].getSize()-1;
00176 uint32 otId;
00177
00178 NLMISC::OptFastFloorBegin();
00179
00180 for( ; nNbModels>0; itRdrModel++, nNbModels-- )
00181 {
00182 CTransform *pTransform = *itRdrModel;
00183
00184
00185 if(!pTransform)
00186 continue;
00187
00188
00189 rPseudoZ = (pTransform->getWorldMatrix().getPos() - CamPos).norm();
00190
00191
00192 rPseudoZ = sqrtf( rPseudoZ * OOFar );
00193
00194 if( pTransform->isOpaque() )
00195 {
00196
00197 rPseudoZ2 = rPseudoZ * opaqueOtSize;
00198 otId= NLMISC::OptFastFloor(rPseudoZ2);
00199 otId= min(otId, opaqueOtMax);
00200 OrderOpaqueList.insert( otId, pTransform );
00201 }
00202 if( pTransform->isTransparent() )
00203 {
00204
00205 rPseudoZ2 = rPseudoZ * transparentOtSize;
00206 otId= NLMISC::OptFastFloor(rPseudoZ2);
00207 otId= min(otId, transparentOtMax);
00208
00209 _OrderTransparentListByPriority[std::min(pTransform->getTransparencyPriority(), _MaxTransparencyPriority)].insert( pTransform->getOrderingLayer(), pTransform, transparentOtMax-otId );
00210 }
00211
00212 }
00213
00214 NLMISC::OptFastFloorEnd();
00215 }
00216
00217 if (renderPart & UScene::RenderOpaque)
00218 {
00219
00220
00221
00222
00223
00224
00225
00226
00227 clearRenderLandscapeList();
00228
00229
00230 CLodCharacterManager *clodMngr= Scene->getLodCharacterManager();
00231 if(clodMngr)
00232 clodMngr->beginRender(getDriver(), CamPos);
00233
00234
00235 _CurrentPassOpaque = true;
00236 OrderOpaqueList.begin();
00237 while( OrderOpaqueList.get() != NULL )
00238 {
00239 CTransform *tr= OrderOpaqueList.get();
00240 #ifdef NL_DEBUG_RENDER_TRAV
00241 CTransformShape *trShape = dynamic_cast<CTransformShape *>(tr);
00242 if (trShape)
00243 {
00244 const std::string *shapeName = Scene->getShapeBank()->getShapeNameFromShapePtr(trShape->Shape);
00245 if (shapeName)
00246 {
00247 nlwarning("Displaying %s", shapeName->c_str());
00248 }
00249 }
00250 #endif
00251 tr->traverseRender();
00252 OrderOpaqueList.next();
00253 }
00254
00255
00256
00257
00258
00259
00260 MeshBlockManager.flush(Driver, Scene, this);
00261
00262
00263
00264 if(clodMngr)
00265 clodMngr->endRender();
00266
00267
00268
00269
00270
00271
00272 if( Scene->getCoarseMeshManager() )
00273 Scene->getCoarseMeshManager()->flushRender(Driver);
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289 _ShadowMapManager.renderGenerate(Scene);
00290
00291
00292 renderLandscapes();
00293
00294
00295 if(Scene->getLandscapePolyDrawingCallback() != NULL)
00296 {
00297 Scene->getLandscapePolyDrawingCallback()->beginPolyDrawing();
00298 }
00299 _ShadowMapManager.renderProject(Scene);
00300 if(Scene->getLandscapePolyDrawingCallback())
00301 {
00302 Scene->getLandscapePolyDrawingCallback()->endPolyDrawing();
00303 }
00304
00305
00306 if(Scene->isNextRenderProfile())
00307 {
00308 OrderOpaqueList.begin();
00309 while( OrderOpaqueList.get() != NULL )
00310 {
00311 OrderOpaqueList.get()->profileRender();
00312 OrderOpaqueList.next();
00313 }
00314 }
00315 }
00316
00317
00318 if (renderPart & UScene::RenderTransparent)
00319 {
00320 if (_FirstWaterModel)
00321 {
00322
00323 CWaterModel *curr = _FirstWaterModel;
00324 uint numWantedVertices = 0;
00325 while (curr)
00326 {
00327 numWantedVertices += curr->getNumWantedVertices();
00328 curr = curr->_Next;
00329 }
00330 if (numWantedVertices != 0)
00331 {
00332 CWaterModel::setupVertexBuffer(Scene->getWaterVB(), numWantedVertices, getDriver());
00333
00334 {
00335 CVertexBufferReadWrite vbrw;
00336 Scene->getWaterVB().lock(vbrw);
00337 CWaterModel *curr = _FirstWaterModel;
00338 void *datas = vbrw.getVertexCoordPointer(0);
00339
00340 uint tri = 0;
00341 while (curr)
00342 {
00343 tri = curr->fillVB(datas, tri, *getDriver());
00344 nlassert(tri <= numWantedVertices);
00345 curr = curr->_Next;
00346 }
00347 nlassert(tri * 3 == numWantedVertices);
00348 }
00349 }
00350
00351 clearWaterModelList();
00352 }
00353 }
00354
00355 if ((renderPart & UScene::RenderTransparent) &&
00356 (renderPart & UScene::RenderFlare)
00357 )
00358 {
00359
00360
00361
00362 _CurrentPassOpaque = false;
00363 for(std::vector<CLayeredOrderingTable<CTransform> >::iterator it = _OrderTransparentListByPriority.begin(); it != _OrderTransparentListByPriority.end(); ++it)
00364 {
00365 it->begin(_LayersRenderingOrder);
00366 while( it->get() != NULL )
00367 {
00368 #ifdef NL_DEBUG_RENDER_TRAV
00369 CTransformShape *trShape = dynamic_cast<CTransformShape *>(it->get());
00370 if (trShape)
00371 {
00372 const std::string *shapeName = Scene->getShapeBank()->getShapeNameFromShapePtr(trShape->Shape);
00373 if (shapeName)
00374 {
00375 nlwarning("Displaying %s", shapeName->c_str());
00376 }
00377 }
00378 #endif
00379 it->get()->traverseRender();
00380 it->next();
00381 }
00382 }
00383
00384
00385 if(Scene->isNextRenderProfile())
00386 {
00387 for(std::vector<CLayeredOrderingTable<CTransform> >::iterator it = _OrderTransparentListByPriority.begin(); it != _OrderTransparentListByPriority.end(); ++it)
00388 {
00389 it->begin();
00390 while( it->get() != NULL )
00391 {
00392 it->get()->profileRender();
00393 it->next();
00394 }
00395 }
00396 }
00397 }
00398 else if (renderPart & UScene::RenderTransparent)
00399 {
00400
00401
00402 _CurrentPassOpaque = false;
00403 for(std::vector<CLayeredOrderingTable<CTransform> >::iterator it = _OrderTransparentListByPriority.begin(); it != _OrderTransparentListByPriority.end(); ++it)
00404 {
00405 it->begin(_LayersRenderingOrder);
00406 while( it->get() != NULL )
00407 {
00408 if (!it->get()->isFlare())
00409 {
00410 #ifdef NL_DEBUG_RENDER_TRAV
00411 CTransformShape *trShape = dynamic_cast<CTransformShape *>(it->get());
00412 if (trShape)
00413 {
00414 const std::string *shapeName = Scene->getShapeBank()->getShapeNameFromShapePtr(trShape->Shape);
00415 if (shapeName)
00416 {
00417 nlwarning("Displaying %s", shapeName->c_str());
00418 }
00419 }
00420 #endif
00421 it->get()->traverseRender();
00422 }
00423 it->next();
00424 }
00425 }
00426
00427
00428 if(Scene->isNextRenderProfile())
00429 {
00430 for(std::vector<CLayeredOrderingTable<CTransform> >::iterator it = _OrderTransparentListByPriority.begin(); it != _OrderTransparentListByPriority.end(); ++it)
00431 {
00432 it->begin();
00433 while( it->get() != NULL )
00434 {
00435 if (!it->get()->isFlare())
00436 {
00437 it->get()->profileRender();
00438 }
00439 it->next();
00440 }
00441 }
00442 }
00443 }
00444 else if (renderPart & UScene::RenderFlare)
00445 {
00446
00447
00448 _CurrentPassOpaque = false;
00449 for(std::vector<CLayeredOrderingTable<CTransform> >::iterator it = _OrderTransparentListByPriority.begin(); it != _OrderTransparentListByPriority.end(); ++it)
00450 {
00451 it->begin(_LayersRenderingOrder);
00452 while( it->get() != NULL )
00453 {
00454 if (it->get()->isFlare())
00455 {
00456 #ifdef NL_DEBUG_RENDER_TRAV
00457 CTransformShape *trShape = dynamic_cast<CTransformShape *>(it->get());
00458 if (trShape)
00459 {
00460 const std::string *shapeName = Scene->getShapeBank()->getShapeNameFromShapePtr(trShape->Shape);
00461 if (shapeName)
00462 {
00463 nlwarning("Displaying %s", shapeName->c_str());
00464 }
00465 }
00466 #endif
00467 it->get()->traverseRender();
00468 }
00469 it->next();
00470 }
00471 }
00472
00473
00474 if(Scene->isNextRenderProfile())
00475 {
00476 for(std::vector<CLayeredOrderingTable<CTransform> >::iterator it = _OrderTransparentListByPriority.begin(); it != _OrderTransparentListByPriority.end(); ++it)
00477 {
00478 it->begin();
00479 while( it->get() != NULL )
00480 {
00481 if (it->get()->isFlare())
00482 {
00483 it->get()->profileRender();
00484 }
00485 it->next();
00486 }
00487 }
00488 }
00489 }
00490
00491
00492
00493
00494
00495 resetLightSetup();
00496
00497 }
00498
00499
00500 void CRenderTrav::setupDriverCamera()
00501 {
00502 getDriver()->setFrustum(Left, Right, Bottom, Top, Near, Far, Perspective);
00503
00504 getDriver()->setupViewMatrixEx(ViewMatrix, CamPos);
00505 }
00506
00507
00508 void CRenderTrav::clearRenderList()
00509 {
00510 _CurrentNumVisibleModels= 0;
00511 }
00512
00513
00514
00515 void CRenderTrav::setSunDirection(const CVector &dir)
00516 {
00517 _SunDirection= dir;
00518 _SunDirection.normalize();
00519 }
00520
00521
00522
00523 void CRenderTrav::setMeshSkinManager(CVertexStreamManager *msm)
00524 {
00525 _MeshSkinManager= msm;
00526 }
00527
00528
00529 void CRenderTrav::setShadowMeshSkinManager(CVertexStreamManager *msm)
00530 {
00531 _ShadowMeshSkinManager= msm;
00532 }
00533
00534
00535 void CRenderTrav::reserveRenderList(uint numModels)
00536 {
00537
00538 if(numModels>RenderList.size())
00539 RenderList.resize(numModels);
00540 }
00541
00542
00543 void CRenderTrav::removeRenderModel(CTransform *m)
00544 {
00545
00546 uint lsb= m->_IndexLSBInRenderList;
00547
00548
00549
00550 for(uint i=lsb;i<_CurrentNumVisibleModels;i+=256)
00551 {
00552
00553 if(RenderList[i]==m)
00554 {
00555 RenderList[i]= NULL;
00556 break;
00557 }
00558 }
00559 }
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570 void CRenderTrav::resetLightSetup()
00571 {
00572
00573 if(!LightingSystemEnabled)
00574 {
00575
00576 _NumLightEnabled= 1;
00577
00578 CVector defDir(-0.5f, 0.0, -0.85f);
00579 defDir.normalize();
00580 CRGBA aday= CRGBA(130, 105, 119);
00581 CRGBA dday= CRGBA(238, 225, 204);
00582 _DriverLight[0].setupDirectional(aday, dday, dday, defDir);
00583
00584 return;
00585 }
00586 else
00587 {
00588 uint i;
00589
00590
00591 for(i=0; i<Driver->getMaxLight(); ++i)
00592 {
00593 Driver->enableLight(uint8(i), false);
00594 }
00595
00596
00597
00598
00599 _LastSunFactor= 0;
00600 _LastFinalAmbient.set(0,0,0,255);
00601 _DriverLight[0].setupDirectional(CRGBA::Black, CRGBA::Black, CRGBA::Black, _SunDirection);
00602 Driver->setLight(0, _DriverLight[0]);
00603
00604 for(i=0; i<NL3D_MAX_LIGHT_CONTRIBUTION; i++)
00605 {
00606 _LastPointLight[i]= NULL;
00607 }
00608
00609
00610
00611 Driver->setAmbientColor(AmbientGlobal);
00612
00613
00614
00615 _CacheLightContribution= NULL;
00616 _NumLightEnabled= 0;
00617
00618 _StrongestLightTouched = true;
00619 }
00620 }
00621
00622
00623
00624 void CRenderTrav::changeLightSetup(CLightContribution *lightContribution, bool useLocalAttenuation)
00625 {
00626
00627 if(!LightingSystemEnabled)
00628 return;
00629
00630 uint i;
00631
00632
00633 if(_CacheLightContribution == lightContribution && _LastLocalAttenuation == useLocalAttenuation)
00634 return;
00635
00636 else
00637 {
00638 _StrongestLightTouched = true;
00639
00640 if(lightContribution)
00641 {
00642
00643
00644
00645 CRGBA finalAmbient= lightContribution->computeCurrentAmbient(SunAmbient);
00646
00647 if(lightContribution->UseMergedPointLight)
00648 finalAmbient.addRGBOnly(finalAmbient, lightContribution->MergedPointLight);
00649
00650 finalAmbient.A= 255;
00651
00652
00653
00654
00655
00656 uint ufactor= lightContribution->SunContribution;
00657
00658
00659 if(ufactor != _LastSunFactor || finalAmbient != _LastFinalAmbient)
00660 {
00661
00662 _LastSunFactor= ufactor;
00663
00664 _LastFinalAmbient= finalAmbient;
00665
00666
00667 ufactor+= ufactor>>7;
00668
00669 CRGBA sunDiffuse, sunSpecular;
00670 sunDiffuse.modulateFromuiRGBOnly(SunDiffuse, ufactor);
00671 sunSpecular.modulateFromuiRGBOnly(SunSpecular, ufactor);
00672
00673 _DriverLight[0].setupDirectional(finalAmbient, sunDiffuse, sunSpecular, _SunDirection);
00674 Driver->setLight(0, _DriverLight[0]);
00675 }
00676
00677
00678
00679
00680 uint plId=0;
00681
00682 while(lightContribution->PointLight[plId]!=NULL)
00683 {
00684 CPointLight *pl= lightContribution->PointLight[plId];
00685 uint inf;
00686 if(useLocalAttenuation)
00687 inf= lightContribution->Factor[plId];
00688 else
00689 inf= lightContribution->AttFactor[plId];
00690
00691
00692
00693
00694 if( pl!=_LastPointLight[plId] ||
00695 inf!=_LastPointLightFactor[plId] ||
00696 useLocalAttenuation!=_LastPointLightLocalAttenuation[plId] )
00697 {
00698
00699 _LastPointLight[plId]= pl;
00700 _LastPointLightFactor[plId]= uint8(inf);
00701 _LastPointLightLocalAttenuation[plId]= useLocalAttenuation;
00702
00703
00704 if(useLocalAttenuation)
00705 pl->setupDriverLight(_DriverLight[plId+1], uint8(inf));
00706 else
00707
00708 pl->setupDriverLightUserAttenuation(_DriverLight[plId+1], uint8(inf));
00709
00710
00711 Driver->setLight(uint8(plId+1), _DriverLight[plId+1]);
00712 }
00713
00714
00715 plId++;
00716 if(plId>=NL3D_MAX_LIGHT_CONTRIBUTION)
00717 break;
00718 }
00719
00720
00721
00722
00723
00724 uint newNumLightEnabled;
00725
00726 newNumLightEnabled= plId + 1;
00727
00728
00729 for(i=_NumLightEnabled; i<newNumLightEnabled; i++)
00730 {
00731 Driver->enableLight(uint8(i), true);
00732 }
00733
00734
00735 for(i=newNumLightEnabled; i<_NumLightEnabled; i++)
00736 {
00737 Driver->enableLight(uint8(i), false);
00738 }
00739
00740
00741 _CacheLightContribution = lightContribution;
00742 _NumLightEnabled= newNumLightEnabled;
00743 _LastLocalAttenuation= useLocalAttenuation;
00744 }
00745 else
00746 {
00747
00748
00749
00750 for(i=0; i<_NumLightEnabled; i++)
00751 {
00752 Driver->enableLight(uint8(i), false);
00753 }
00754
00755
00756 _CacheLightContribution = NULL;
00757 _NumLightEnabled= 0;
00758 }
00759
00760
00761 }
00762 }
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772 void CRenderTrav::beginVPLightSetup(uint ctStart, bool supportSpecular, const CMatrix &invObjectWM)
00773 {
00774 uint i;
00775 nlassert(MaxVPLight==4);
00776 _VPNumLights= min(_NumLightEnabled, (uint)MaxVPLight);
00777 _VPCurrentCtStart= ctStart;
00778 _VPSupportSpecular= supportSpecular;
00779
00780
00781
00782
00783 _VPFinalAmbient= AmbientGlobal;
00784 for(i=0; i<_VPNumLights; i++)
00785 {
00786 _VPFinalAmbient+= _DriverLight[i].getAmbiant();
00787 }
00788
00789 for(i=0; i<_VPNumLights; i++)
00790 {
00791 _VPLightDiffuse[i]= _DriverLight[i].getDiffuse();
00792 }
00793
00794 for(; i<MaxVPLight; i++)
00795 {
00796 _VPLightDiffuse[i]= CRGBA::Black;
00797 Driver->setConstant(_VPCurrentCtStart+1+i, 0.f, 0.f, 0.f, 0.f);
00798 }
00799
00800 if(supportSpecular)
00801 {
00802 for(i=0; i<_VPNumLights; i++)
00803 {
00804 _VPLightSpecular[i]= _DriverLight[i].getSpecular();
00805 }
00806
00807 for(; i<MaxVPLight; i++)
00808 {
00809 _VPLightSpecular[i]= CRGBA::Black;
00810 Driver->setConstant(_VPCurrentCtStart+5+i, 0.f, 0.f, 0.f, 0.f);
00811 }
00812 }
00813
00814
00815
00816 CVector eye= invObjectWM * CamPos;
00817
00818
00819
00820
00821 CVector lightDir;
00822
00823 lightDir= invObjectWM.mulVector(_DriverLight[0].getDirection());
00824 lightDir.normalize();
00825 lightDir= -lightDir;
00826 if(supportSpecular)
00827 {
00828
00829 Driver->setConstant(_VPCurrentCtStart+9, lightDir);
00830 }
00831 else
00832 {
00833
00834 Driver->setConstant(_VPCurrentCtStart+5, lightDir);
00835 }
00836
00837
00838
00839
00840 uint startPLPos;
00841 if(supportSpecular)
00842 {
00843
00844 Driver->setConstant(_VPCurrentCtStart+11, eye);
00845
00846 startPLPos= 12;
00847 }
00848 else
00849 {
00850
00851 startPLPos= 6;
00852 }
00853
00854 for(i=1; i<_VPNumLights; i++)
00855 {
00856
00857 CVector lightPos;
00858 lightPos= invObjectWM * _DriverLight[i].getPosition();
00859 Driver->setConstant(_VPCurrentCtStart+startPLPos+(i-1), lightPos);
00860 }
00861
00862
00863
00864 _VPMaterialCacheDirty= true;
00865 }
00866
00867
00868 void CRenderTrav::changeVPLightSetupMaterial(const CMaterial &mat, bool excludeStrongest)
00869 {
00870
00871 if(!_VPMaterialCacheDirty)
00872 {
00873
00874 if( _VPMaterialCacheEmissive == mat.getEmissive().getPacked() &&
00875 _VPMaterialCacheAmbient == mat.getAmbient().getPacked() &&
00876 _VPMaterialCacheDiffuse == mat.getDiffuse().getPacked() )
00877 {
00878
00879 if( !_VPSupportSpecular ||
00880 ( _VPMaterialCacheSpecular == mat.getSpecular().getPacked() &&
00881 _VPMaterialCacheShininess == mat.getShininess() ) )
00882 {
00883
00884 return;
00885 }
00886 }
00887 }
00888
00889
00890 _VPMaterialCacheDirty= false;
00891 _VPMaterialCacheEmissive= mat.getEmissive().getPacked();
00892 _VPMaterialCacheAmbient= mat.getDiffuse().getPacked();
00893 _VPMaterialCacheDiffuse= mat.getDiffuse().getPacked();
00894 _VPMaterialCacheSpecular= mat.getSpecular().getPacked();
00895 _VPMaterialCacheShininess= mat.getShininess();
00896
00897
00898 CRGBAF color;
00899 uint i;
00900 CRGBAF matDiff= mat.getDiffuse();
00901 CRGBAF matSpec= mat.getSpecular();
00902 float specExp= mat.getShininess();
00903
00904 uint strongestLightIndex = excludeStrongest ? getStrongestLightIndex() : _VPNumLights;
00905
00906
00907 color= _VPFinalAmbient * mat.getAmbient();
00908 color+= mat.getEmissive();
00909 Driver->setConstant(_VPCurrentCtStart+0, 1, &color.R);
00910
00911
00912
00913
00914
00915 for(i = 0; i < strongestLightIndex; ++i)
00916 {
00917 color= _VPLightDiffuse[i] * matDiff;
00918 Driver->setConstant(_VPCurrentCtStart+1+i, 1, &color.R);
00919 }
00920
00921
00922 if (i != _VPNumLights)
00923 {
00924 color= _VPLightDiffuse[i] * matDiff;
00925 _StrongestLightDiffuse.set((uint8) (255.f * color.R), (uint8) (255.f * color.G), (uint8) (255.f * color.B), (uint8) (255.f * color.A));
00926
00927 Driver->setConstant(_VPCurrentCtStart + 1 + i, 0.f, 0.f, 0.f, 0.f);
00928 ++i;
00929
00930 for(; i < _VPNumLights; i++)
00931 {
00932 color= _VPLightDiffuse[i] * matDiff;
00933 Driver->setConstant(_VPCurrentCtStart + 1 + i, 1, &color.R);
00934 }
00935 }
00936
00937
00938 if(_VPSupportSpecular)
00939 {
00940 for(i = 0; i < strongestLightIndex; ++i)
00941 {
00942 color= _VPLightSpecular[i] * matSpec;
00943 color.A= specExp;
00944 Driver->setConstant(_VPCurrentCtStart+5+i, 1, &color.R);
00945 }
00946
00947 if (i != _VPNumLights)
00948 {
00949 color= _VPLightSpecular[i] * matSpec;
00950 _StrongestLightSpecular.set((uint8) (255.f * color.R), (uint8) (255.f * color.G), (uint8) (255.f * color.B), (uint8) (255.f * color.A));
00951
00952
00953 Driver->setConstant(_VPCurrentCtStart + 5 + i, 0.f, 0.f, 0.f, 0.f);
00954 ++i;
00955
00956 for(; i < _VPNumLights; i++)
00957 {
00958 color= _VPLightSpecular[i] * matSpec;
00959 color.A= specExp;
00960 Driver->setConstant(_VPCurrentCtStart + 5 + i, 1, &color.R);
00961 }
00962 }
00963 }
00964
00965
00966 static float alphaCte[4]= {0,0,1,0};
00967 alphaCte[3]= matDiff.A;
00968
00969 if(_VPSupportSpecular)
00970 Driver->setConstant(_VPCurrentCtStart+10, 1, alphaCte);
00971 else
00972 Driver->setConstant(_VPCurrentCtStart+9, 1, alphaCte);
00973 }
00974
00975
00976 sint CRenderTrav::getStrongestLightIndex() const
00977 {
00978 if (!_StrongestLightTouched) return -1;
00979 uint vpNumLights = min(_NumLightEnabled, (uint)MaxVPLight);
00980
00981
00982 if (vpNumLights == 0) return -1;
00983 if (vpNumLights == 1) return 0;
00984
00985 float lumDir = _VPLightDiffuse[0].R + _VPLightDiffuse[0].G + _VPLightDiffuse[0].B + _VPLightDiffuse[0].A
00986 + _VPLightSpecular[0].R + _VPLightSpecular[0].G + _VPLightSpecular[0].B + _VPLightSpecular[0].A;
00987 float lumOmni = _VPLightDiffuse[1].R + _VPLightDiffuse[1].G + _VPLightDiffuse[1].B + _VPLightDiffuse[1].A
00988 + _VPLightSpecular[1].R + _VPLightSpecular[1].G + _VPLightSpecular[1].B + _VPLightSpecular[1].A;
00989 return lumDir > lumOmni ? 0 : 1;
00990 }
00991
00992
00993 void CRenderTrav::getStrongestLightColors(NLMISC::CRGBA &diffuse, NLMISC::CRGBA &specular)
00994 {
00995 sint strongestLightIndex = getStrongestLightIndex();
00996 if (strongestLightIndex == -1)
00997 {
00998 diffuse = specular = NLMISC::CRGBA::Black;
00999 }
01000 else
01001 {
01002 diffuse = _StrongestLightDiffuse;
01003 specular = _StrongestLightSpecular;
01004 }
01005 }
01006
01007
01008
01009 static const char* LightingVPFragmentNormalize=
01010 " # normalize normal \n\
01011 DP3 R6.w, R6, R6; \n\
01012 RSQ R6.w, R6.w; \n\
01013 MUL R6, R6, R6.w; \n\
01014 ";
01015
01016
01017
01018
01019 static const char* LightingVPFragmentNoSpecular_Begin=
01020 " \n\
01021 # Global Ambient. \n\
01022 MOV R2, c[CTS+0]; \n\
01023 \n\
01024 # Diffuse Sun \n\
01025 DP3 R0.x, R6, c[CTS+5]; # R0.x= normal*-lightDir \n\
01026 LIT R0.y, R0.xxxx; # R0.y= R0.x clamped \n\
01027 MAD R2, R0.y, c[CTS+1], R2; # R2= summed vertex color. \n\
01028 ";
01029
01030
01031 static const char* LightingVPFragmentNoSpecular_PL[]=
01032 {
01033 " # Diffuse PointLight 0. \n\
01034 ADD R0, c[CTS+6], -R5; # R0= lightPos-vertex \n\
01035 DP3 R0.w, R0, R0; # normalize R0. \n\
01036 RSQ R0.w, R0.w; \n\
01037 MUL R0, R0, R0.w; \n\
01038 DP3 R0.x, R6, R0; # R0.x= normal*lightDir \n\
01039 LIT R0.y, R0.xxxx; # R0.y= R0.x clamped \n\
01040 MAD R2, R0.y, c[CTS+2], R2; # R2= summed vertex color. \n\
01041 ",
01042 " # Diffuse PointLight 1. \n\
01043 ADD R0, c[CTS+7], -R5; # R0= lightPos-vertex \n\
01044 DP3 R0.w, R0, R0; # normalize R0. \n\
01045 RSQ R0.w, R0.w; \n\
01046 MUL R0, R0, R0.w; \n\
01047 DP3 R0.x, R6, R0; # R0.x= normal*lightDir \n\
01048 LIT R0.y, R0; # R0.y= R0.x clamped \n\
01049 MAD R2, R0.y, c[CTS+3], R2; # R2= summed vertex color. \n\
01050 ",
01051 " # Diffuse PointLight 2. \n\
01052 ADD R0, c[CTS+8], -R5; # R0= lightPos-vertex \n\
01053 DP3 R0.w, R0, R0; # normalize R0. \n\
01054 RSQ R0.w, R0.w; \n\
01055 MUL R0, R0, R0.w; \n\
01056 DP3 R0.x, R6, R0; # R0.x= normal*lightDir \n\
01057 LIT R0.y, R0; # R0.y= R0.x clamped \n\
01058 MAD R2, R0.y, c[CTS+4], R2; # R2= summed vertex color. \n\
01059 "
01060 };
01061
01062
01063 static const char* LightingVPFragmentNoSpecular_End=
01064 " # output to o[COL0] only, replacing alpha with material alpha. \n\
01065 MAD o[COL0], R2, c[CTS+9].zzzx, c[CTS+9].xxxw; \n\
01066 ";
01067
01068
01069
01070
01071 static const char* LightingVPFragmentSpecular_Begin=
01072 " \n\
01073 # Global Ambient. \n\
01074 MOV R2, c[CTS+0]; \n\
01075 \n\
01076 # Always keep Specular exponent in R0.w \n\
01077 MOV R0.w, c[CTS+5].w; \n\
01078 \n\
01079 # Compute vertex-to-eye vector normed. \n\
01080 ADD R4, c[CTS+11], -R5; \n\
01081 DP3 R4.w, R4, R4; \n\
01082 RSQ R4.w, R4.w; \n\
01083 MUL R4, R4, R4.w; \n\
01084 \n\
01085 # Diffuse-Specular Sun \n\
01086 # Compute R1= halfAngleVector= (lightDir+R4).normed(). \n\
01087 ADD R1.xyz, c[CTS+9], R4; # R1= halfAngleVector \n\
01088 DP3 R1.w, R1, R1; # normalize R1. \n\
01089 RSQ R1.w, R1.w; \n\
01090 MUL R1.xyz, R1, R1.w; \n\
01091 # Compute Factors and colors. \n\
01092 DP3 R0.x, R6, c[CTS+9]; # R0.x= normal*-lightDir \n\
01093 DP3 R0.yz, R6, R1; # R0.yz= normal*halfAngleVector \n\
01094 LIT R0.yz, R0; # R0.y= R0.x clamped, R0.z= pow(spec, R0.w) clamp \n\
01095 MAD R2, R0.y, c[CTS+1], R2; # R2= summed vertex color. \n\
01096 MUL R3, R0.z, c[CTS+5]; # R3= specular color. \n\
01097 ";
01098
01099
01100 static const char* LightingVPFragmentSpecular_PL[]=
01101 {
01102 " # Diffuse-Specular PointLight 0. \n\
01103 # Compute R0= (lightPos-vertex).normed(). \n\
01104 ADD R0.xyz, c[CTS+12], -R5; # R0= lightPos-vertex \n\
01105 DP3 R1.w, R0, R0; # normalize R0. \n\
01106 RSQ R1.w, R1.w; \n\
01107 MUL R0.xyz, R0, R1.w; \n\
01108 # Compute R1= halfAngleVector= (R0+R4).normed(). \n\
01109 ADD R1.xyz, R0, R4; # R1= halfAngleVector \n\
01110 DP3 R1.w, R1, R1; # normalize R1. \n\
01111 RSQ R1.w, R1.w; \n\
01112 MUL R1.xyz, R1, R1.w; \n\
01113 # Compute Factors and colors. \n\
01114 DP3 R0.x, R6, R0; # R0.x= normal*lightDir \n\
01115 DP3 R0.yz, R6, R1; # R0.yz= normal*halfAngleVector \n\
01116 LIT R0.yz, R0; # R0.y= R0.x clamped, R0.z= pow(spec, R0.w) clamp \n\
01117 MAD R2, R0.y, c[CTS+2], R2; # R2= summed vertex color. \n\
01118 MAD R3, R0.z, c[CTS+6], R3; # R3= summed specular color. \n\
01119 ",
01120 " # Diffuse-Specular PointLight 1. \n\
01121 # Compute R0= (lightPos-vertex).normed(). \n\
01122 ADD R0.xyz, c[CTS+13], -R5; # R0= lightPos-vertex \n\
01123 DP3 R1.w, R0, R0; # normalize R0. \n\
01124 RSQ R1.w, R1.w; \n\
01125 MUL R0.xyz, R0, R1.w; \n\
01126 # Compute R1= halfAngleVector= (R0+R4).normed(). \n\
01127 ADD R1.xyz, R0, R4; # R1= halfAngleVector \n\
01128 DP3 R1.w, R1, R1; # normalize R1. \n\
01129 RSQ R1.w, R1.w; \n\
01130 MUL R1.xyz, R1, R1.w; \n\
01131 # Compute Factors and colors. \n\
01132 DP3 R0.x, R6, R0; # R0.x= normal*lightDir \n\
01133 DP3 R0.yz, R6, R1; # R0.yz= normal*halfAngleVector \n\
01134 LIT R0.yz, R0; # R0.y= R0.x clamped, R0.z= pow(spec, R0.w) clamp \n\
01135 MAD R2, R0.y, c[CTS+3], R2; # R2= summed vertex color. \n\
01136 MAD R3, R0.z, c[CTS+7], R3; # R3= summed specular color. \n\
01137 ",
01138 " # Diffuse-Specular PointLight 2. \n\
01139 # Compute R0= (lightPos-vertex).normed(). \n\
01140 ADD R0.xyz, c[CTS+14], -R5; # R0= lightPos-vertex \n\
01141 DP3 R1.w, R0, R0; # normalize R0. \n\
01142 RSQ R1.w, R1.w; \n\
01143 MUL R0.xyz, R0, R1.w; \n\
01144 # Compute R1= halfAngleVector= (R0+R4).normed(). \n\
01145 ADD R1.xyz, R0, R4; # R1= halfAngleVector \n\
01146 DP3 R1.w, R1, R1; # normalize R1. \n\
01147 RSQ R1.w, R1.w; \n\
01148 MUL R1.xyz, R1, R1.w; \n\
01149 # Compute Factors and colors. \n\
01150 DP3 R0.x, R6, R0; # R0.x= normal*lightDir \n\
01151 DP3 R0.yz, R6, R1; # R0.yz= normal*halfAngleVector \n\
01152 LIT R0.yz, R0; # R0.y= R0.x clamped, R0.z= pow(spec, R0.w) clamp \n\
01153 MAD R2, R0.y, c[CTS+4], R2; # R2= summed vertex color. \n\
01154 "
01155 };
01156
01157
01158
01159 static const char* LightingVPFragmentSpecular_End=
01160 " # output directly to secondary color. \n\
01161 MAD o[COL1], R0.z, c[CTS+8], R3; # final summed specular color. \n\
01162 \n\
01163 # output diffuse to o[COL0], replacing alpha with material alpha. \n\
01164 MAD o[COL0], R2, c[CTS+10].zzzx, c[CTS+10].xxxw; \n\
01165 ";
01166
01167
01168 static void strReplaceAll(string &strInOut, const string &tokenSrc, const string &tokenDst)
01169 {
01170 string::size_type pos;
01171 string::difference_type srcLen= tokenSrc.size();
01172 while( (pos=strInOut.find(tokenSrc)) != string::npos)
01173 {
01174 strInOut.replace(pos, srcLen, tokenDst);
01175 }
01176 }
01177
01178
01179 std::string CRenderTrav::getLightVPFragment(uint numActivePointLights, uint ctStart, bool supportSpecular, bool normalize)
01180 {
01181 string ret;
01182
01183
01184 nlassert(MaxVPLight==4);
01185 nlassert(numActivePointLights<=MaxVPLight-1);
01186
01187
01188 if(normalize)
01189 ret+= LightingVPFragmentNormalize;
01190
01191
01192 if(supportSpecular)
01193 {
01194
01195 ret+= LightingVPFragmentSpecular_Begin;
01196
01197
01198 for(uint i=0;i<numActivePointLights;i++)
01199 {
01200 ret+= LightingVPFragmentSpecular_PL[i];
01201 }
01202
01203
01204 ret+= LightingVPFragmentSpecular_End;
01205 }
01206 else
01207 {
01208
01209 ret+= LightingVPFragmentNoSpecular_Begin;
01210
01211
01212 for(uint i=0;i<numActivePointLights;i++)
01213 {
01214 ret+= LightingVPFragmentNoSpecular_PL[i];
01215 }
01216
01217
01218 ret+= LightingVPFragmentNoSpecular_End;
01219 }
01220
01221
01222
01223 for(sint i=14; i>=0; i--)
01224 {
01225 char tokenSrc[256];
01226 sprintf(tokenSrc, "CTS+%d", i);
01227 char tokenDst[256];
01228 sprintf(tokenDst, "%d", ctStart+i);
01229
01230 strReplaceAll(ret, tokenSrc, tokenDst);
01231 }
01232
01233
01234 nlassert( ret.find("CTS+")==string::npos );
01235
01236 return ret;
01237 }
01238
01239
01240
01241
01242
01243
01244
01245
01246 void CRenderTrav::clearRenderLandscapeList()
01247 {
01248 _LandscapeRenderList.clear();
01249 }
01250
01251
01252 void CRenderTrav::addRenderLandscape(CLandscapeModel *model)
01253 {
01254 _LandscapeRenderList.push_back(model);
01255 }
01256
01257
01258 void CRenderTrav::renderLandscapes()
01259 {
01260
01261 for(uint i=0;i<_LandscapeRenderList.size();i++)
01262 {
01263 _LandscapeRenderList[i]->clipAndRenderLandscape();
01264 }
01265 }
01266
01267
01268 void CRenderTrav::setupTransparencySorting(uint8 maxPriority ,uint NbDistanceEntries )
01269 {
01270 NLMISC::contReset(_OrderTransparentListByPriority);
01271 _OrderTransparentListByPriority.resize((uint) maxPriority + 1);
01272 for(uint k = 0; k < _OrderTransparentListByPriority.size(); ++k)
01273 {
01274 _OrderTransparentListByPriority[k].init(NbDistanceEntries);
01275 if (k != 0) _OrderTransparentListByPriority[k].shareAllocator(_OrderTransparentListByPriority[0]);
01276 }
01277 _MaxTransparencyPriority = maxPriority;
01278 }
01279
01280
01281 void CRenderTrav::clearWaterModelList()
01282 {
01283 while (_FirstWaterModel)
01284 {
01285 _FirstWaterModel->unlink();
01286 }
01287 }
01288
01289
01290 void CRenderTrav::debugWaterModelMemory(const char *tag, bool dumpList)
01291 {
01292
01293
01294
01295 if(dumpList)
01296 _DebugWaterModelList.clear();
01297
01298 CWaterModel *curr= _FirstWaterModel;
01299 while(curr)
01300 {
01301
01302 CWaterModelDump dmp;
01303 dmp.Address= (void*)curr;
01304 curr->debugDumpMem(dmp.ClippedPolyBegin, dmp.ClippedPolyEnd);
01305
01306 if(dmp.ClippedPolyBegin==dmp.ClippedPolyEnd)
01307 {
01308
01309 nlwarning("******* WaterModelList crash after %s", tag);
01310 nlwarning("Current: Ptr:%x. List:%x/%x", (ptrdiff_t)dmp.Address, (ptrdiff_t)dmp.ClippedPolyBegin, (ptrdiff_t)dmp.ClippedPolyEnd);
01311
01312 for(uint i=0;i<_DebugWaterModelList.size();i++)
01313 {
01314 CWaterModelDump &bkup= _DebugWaterModelList[i];
01315 nlwarning("List%02d: Ptr:%x. Array:%x/%x", i, (ptrdiff_t)bkup.Address, (ptrdiff_t)bkup.ClippedPolyBegin, (ptrdiff_t)bkup.ClippedPolyEnd);
01316 }
01317
01318
01319 nlassert(dmp.ClippedPolyBegin!=dmp.ClippedPolyEnd);
01320 }
01321
01322
01323 if(dumpList)
01324 _DebugWaterModelList.push_back(dmp);
01325
01326
01327 curr= curr->_Next;
01328 }
01329 }
01330
01331 }
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375