lightQuery.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "platform/platform.h"
  23. #include "lighting/lightQuery.h"
  24. #include "lighting/lightManager.h"
  25. #include "platform/profiler.h"
  26. LightQuery::LightQuery( U32 maxLights )
  27. : mMaxLights( maxLights )
  28. {
  29. }
  30. LightQuery::~LightQuery()
  31. {
  32. }
  33. void LightQuery::init( const Point3F &cameraPos,
  34. const Point3F &cameraDir,
  35. F32 viewDist )
  36. {
  37. mVolume.center = cameraPos;
  38. mVolume.radius = viewDist;
  39. mLights.clear();
  40. }
  41. void LightQuery::init( const SphereF &bounds )
  42. {
  43. mVolume = bounds;
  44. mLights.clear();
  45. }
  46. void LightQuery::init( const Box3F &bounds )
  47. {
  48. bounds.getCenter( &mVolume.center );
  49. mVolume.radius = ( bounds.maxExtents - mVolume.center ).len();
  50. mLights.clear();
  51. }
  52. void LightQuery::getLights( LightInfo** outLights, U32 maxLights )
  53. {
  54. PROFILE_SCOPE( LightQuery_getLights );
  55. // Gather lights if we haven't already.
  56. if ( mLights.empty() )
  57. _scoreLights();
  58. U32 lightCount = getMin( (U32)mLights.size(), getMin( mMaxLights, maxLights ) );
  59. // Copy them over.
  60. for ( U32 i = 0; i < lightCount; i++ )
  61. {
  62. LightInfo *light = mLights[i];
  63. // If the score reaches zero then we got to
  64. // the end of the valid lights for this object.
  65. if ( light->getScore() <= 0.0f )
  66. break;
  67. outLights[i] = light;
  68. }
  69. }
  70. void LightQuery::_scoreLights()
  71. {
  72. PROFILE_SCOPE( LightQuery_scoreLights );
  73. if ( !LIGHTMGR )
  74. return;
  75. // Get all the lights.
  76. LIGHTMGR->getAllUnsortedLights( &mLights );
  77. LightInfo *sun = LIGHTMGR->getSpecialLight( LightManager::slSunLightType );
  78. const Point3F lumDot( 0.2125f, 0.7154f, 0.0721f );
  79. Vector<LightInfo*>::iterator iter = mLights.begin();
  80. for ( ; iter != mLights.end(); iter++ )
  81. {
  82. // Get the light.
  83. LightInfo *light = (*iter);
  84. F32 luminace = 0.0f;
  85. F32 dist = 0.0f;
  86. F32 weight = 0.0f;
  87. const bool isSpot = light->getType() == LightInfo::Spot;
  88. const bool isPoint = light->getType() == LightInfo::Point;
  89. if ( isPoint || isSpot )
  90. {
  91. // Get the luminocity.
  92. luminace = mDot( light->getColor(), lumDot ) * light->getBrightness();
  93. // Get the distance to the light... score it 1 to 0 near to far.
  94. F32 lenSq = ( mVolume.center - light->getPosition() ).lenSquared();
  95. F32 radiusSq = mSquared( light->getRange().x + mVolume.radius );
  96. F32 distSq = radiusSq - lenSq;
  97. if ( distSq > 0.0f )
  98. dist = mClampF( distSq / ( 1000.0f * 1000.0f ), 0.0f, 1.0f );
  99. // TODO: This culling is broken... it culls spotlights
  100. // that are actually visible.
  101. if ( false && isSpot && dist > 0.0f )
  102. {
  103. // TODO: I cannot test to see if we're within
  104. // the cone without a more detailed test... so
  105. // just reject if we're behind the spot direction.
  106. Point3F toCenter = mVolume.center - light->getPosition();
  107. F32 angDot = mDot( toCenter, light->getDirection() );
  108. if ( angDot < 0.0f )
  109. dist = 0.0f;
  110. }
  111. weight = light->getPriority();
  112. }
  113. else
  114. {
  115. // The sun always goes first
  116. // regardless of the settings.
  117. if ( light == sun )
  118. {
  119. weight = F32_MAX;
  120. dist = 1.0f;
  121. luminace = 1.0f;
  122. }
  123. else
  124. {
  125. // TODO: When we have multiple directional
  126. // lights we should score them here.
  127. }
  128. }
  129. // TODO: Manager ambient lights here too!
  130. light->setScore( luminace * weight * dist );
  131. }
  132. // Sort them!
  133. mLights.sort( _lightScoreCmp );
  134. }
  135. S32 LightQuery::_lightScoreCmp( LightInfo* const *a, LightInfo* const *b )
  136. {
  137. F32 diff = (*a)->getScore() - (*b)->getScore();
  138. return diff < 0 ? 1 : diff > 0 ? -1 : 0;
  139. }