Photons.h 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. //
  2. // Copyright (c) 2017, THUNDERBEAST GAMES LLC All rights reserved
  3. // Copyright (c) 2015 Dmitry Sovetov
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. //
  23. #pragma once
  24. #include <Atomic/Container/RefCounted.h>
  25. #include <Atomic/Container/ArrayPtr.h>
  26. #include "LightRay.h"
  27. #include "BakeLight.h"
  28. using namespace Atomic;
  29. namespace AtomicGlow
  30. {
  31. class SceneBaker;
  32. const int PHOTON_TRI_MAX = 8;
  33. const int PHOTON_TRI_INVALID = -1;
  34. class PhotonMap : public RefCounted
  35. {
  36. ATOMIC_REFCOUNTED(PhotonMap)
  37. public:
  38. struct Photon
  39. {
  40. int tris_[PHOTON_TRI_MAX];
  41. Color gathered_[PHOTON_TRI_MAX];
  42. Color color_[PHOTON_TRI_MAX];
  43. int photons_[PHOTON_TRI_MAX];
  44. int MapTriIndex(int triIndex) const
  45. {
  46. for (int i = 0; i < PHOTON_TRI_MAX; i++)
  47. {
  48. if (tris_[i] == PHOTON_TRI_INVALID)
  49. break;
  50. if (tris_[i] == triIndex)
  51. return i;
  52. }
  53. return PHOTON_TRI_INVALID;
  54. }
  55. void Reset()
  56. {
  57. for (int i = 0; i < PHOTON_TRI_MAX; i++)
  58. {
  59. tris_[i] = PHOTON_TRI_INVALID;
  60. color_[i] = gathered_[i] = Color::BLACK;
  61. photons_[i] = 0;
  62. }
  63. }
  64. };
  65. PhotonMap(BakeMesh* bakeMesh, int width, int height);
  66. virtual ~PhotonMap();
  67. // Allocates a triangle, always check return, in readOnly mode won't allocate new tri
  68. bool GetPhoton(int triIndex, const Vector2& uv, Color& color, int& photons, Color& gathered, bool readOnly = false)
  69. {
  70. color = Color::BLACK;
  71. gathered = Color::BLACK;
  72. photons = 0;
  73. int x = static_cast<int>( uv.x_ * (width_ - 1) );
  74. int y = static_cast<int>( uv.y_ * (height_ - 1) );
  75. if (x < 0 || x >= width_)
  76. return false;
  77. if (y < 0 || y >= height_)
  78. return false;
  79. Photon* photon = &photons_[y * width_ + x];
  80. int idx = photon->MapTriIndex(triIndex);
  81. if (idx == PHOTON_TRI_INVALID)
  82. {
  83. if (readOnly)
  84. {
  85. return false;
  86. }
  87. for ( int i = 0; i < PHOTON_TRI_MAX; i++ )
  88. {
  89. if (photon->tris_[i] == PHOTON_TRI_INVALID)
  90. {
  91. idx = photon->tris_[i] = triIndex;
  92. break;
  93. }
  94. }
  95. }
  96. if (idx == PHOTON_TRI_INVALID)
  97. {
  98. // out of tri storage
  99. return false;
  100. }
  101. color = photon->color_[idx];
  102. gathered = photon->gathered_[idx];
  103. photons = photon->photons_[idx];
  104. return true;
  105. }
  106. // Adds a photon
  107. bool AddPhoton(int triIndex, const Vector2& uv, const Color& color)
  108. {
  109. if (color.r_ < 0.01f && color.g_ < 0.01f && color.b_ < 0.01f)
  110. {
  111. // filter out tiny adds
  112. return false;
  113. }
  114. int x = static_cast<int>( uv.x_ * (width_ - 1) );
  115. int y = static_cast<int>( uv.y_ * (height_ - 1) );
  116. if (x < 0 || x >= width_)
  117. return false;
  118. if (y < 0 || y >= height_)
  119. return false;
  120. Photon* photon = &photons_[y * width_ + x];
  121. int idx = photon->MapTriIndex(triIndex);
  122. if (idx == PHOTON_TRI_INVALID)
  123. {
  124. for ( int i = 0; i < PHOTON_TRI_MAX; i++ )
  125. {
  126. if (photon->tris_[i] == PHOTON_TRI_INVALID)
  127. {
  128. idx = i;
  129. photon->tris_[i] = triIndex;
  130. break;
  131. }
  132. }
  133. }
  134. if (idx == PHOTON_TRI_INVALID)
  135. {
  136. // out of tri storage
  137. return false;
  138. }
  139. photon->color_[idx] += color;
  140. photon->photons_[idx]++;
  141. return true;
  142. }
  143. void SavePng(const String& filename) const;
  144. void Gather( int radius );
  145. Color Gather( int triIndex, int x, int y, int radius ) const;
  146. private:
  147. int width_;
  148. int height_;
  149. WeakPtr<BakeMesh> bakeMesh_;
  150. SharedArrayPtr<Photon> photons_;
  151. };
  152. class Photons : public RefCounted
  153. {
  154. ATOMIC_REFCOUNTED(Photon)
  155. public:
  156. // Constructs a Photons instance.
  157. // param scene Scene to be baked.
  158. // param passCount Amount of photon passes.
  159. // param maxDepth Maximum photon tracing depth (number of light bounces).
  160. // param energyThreshold The minimum energy that photon should have to continue tracing.
  161. // param maxDistance The reflected light maximum distance. All intersections above this value will be ignored.
  162. Photons( SceneBaker* sceneBaker, int passCount, int maxDepth, float energyThreshold, float maxDistance );
  163. // Emits photons from all scene lights, returning number of photons emitted
  164. virtual int Emit( const Vector<SharedPtr<BakeLight>>& bakeLights );
  165. private:
  166. // Emits photons from a given light.
  167. void EmitPhotons( const BakeLight* light );
  168. // Traces a photon path for a given depth.
  169. /*
  170. Traces a photon path for a given depth. Each time the photon bounces the
  171. reflected light is stored to a photon map.
  172. \param attenuation Light attenuation model.
  173. \param position Photon's start position.
  174. \param direction Photon's direction.
  175. \param color Photon's color.
  176. \param energy Photon's energy.
  177. \param depth Current trace depth.
  178. */
  179. void Trace(const LightAttenuation* attenuation, const Vector3& position, const Vector3& direction, const Color& color, int depth, unsigned lastGeomID = RTC_INVALID_GEOMETRY_ID, unsigned lastPrimID = RTC_INVALID_GEOMETRY_ID );
  180. //Stores a photon bounce.
  181. void Store( PhotonMap* photonmap, int triIdx, const Color& color, const Vector2& uv );
  182. private:
  183. // Parent scene.
  184. SharedPtr<SceneBaker> sceneBaker_;
  185. // Amount of photon passes, at each pass there will be emitted N photons.
  186. int passCount_;
  187. // Maximum tracing depth.
  188. int maxDepth_;
  189. // Photon energy threshold.
  190. float energyThreshold_;
  191. // Maximum intersection distance
  192. float maxDistance_;
  193. // Total amount of photons stored.
  194. int photonCount_;
  195. LightRay lightRay_;
  196. };
  197. }