Light2D.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793
  1. //
  2. // Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
  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 deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // 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 FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. #include "Precompiled.h"
  23. #include "../Core/Context.h"
  24. #include "../Graphics/Graphics.h"
  25. #include "../Graphics/Viewport.h"
  26. #include "../Scene/Scene.h"
  27. #include "../Graphics/Camera.h"
  28. #include "../Graphics/Octree.h"
  29. #include "../Atomic2D/Light2D.h"
  30. #include "../Graphics/Renderer.h"
  31. #include "../Resource/XMLFile.h"
  32. #include "../Graphics/GraphicsEvents.h"
  33. #include "../Graphics/RenderPath.h"
  34. #include "../Graphics/Material.h"
  35. #include "../Graphics/Technique.h"
  36. #include "../Graphics/Zone.h"
  37. #include "../Atomic2D/RigidBody2D.h"
  38. #include "../Atomic2D/Renderer2D.h"
  39. #include "../IO/Log.h"
  40. #include "../Resource/ResourceCache.h"
  41. namespace Atomic
  42. {
  43. extern const char* ATOMIC2D_CATEGORY;
  44. Light2D::Light2D(Context* context) : Component(context),
  45. lightgroupID_(0),
  46. color_(Color::WHITE),
  47. castShadows_(false),
  48. softShadows_(false),
  49. softShadowLength_(2.5f),
  50. backtrace_(false),
  51. raysInitialized_(false)
  52. {
  53. SetNumRays(32);
  54. }
  55. Light2D::~Light2D()
  56. {
  57. }
  58. void Light2D::SetNumRays(int numRays)
  59. {
  60. raysInitialized_ = false;
  61. rays_.Resize(numRays);
  62. }
  63. void Light2D::OnSceneSet(Scene* scene)
  64. {
  65. if (scene && !context_->GetEditorContext())
  66. {
  67. PODVector<Light2DGroup*> lightgroups;
  68. scene->GetComponents<Light2DGroup>(lightgroups, true);
  69. lightgroup_ = 0;
  70. for (unsigned i = 0; i < lightgroups.Size(); i++)
  71. {
  72. Light2DGroup* lightgroup = lightgroups.At(i);
  73. if (lightgroup->GetLightGroupID() == lightgroupID_)
  74. {
  75. lightgroup_ = lightgroup;
  76. lightgroup_->AddLight2D(this);
  77. break;
  78. }
  79. }
  80. if (lightgroup_.Null())
  81. {
  82. lightgroup_ = node_->CreateComponent<Light2DGroup>();
  83. lightgroup_->SetTemporary(true);
  84. lightgroup_->AddLight2D(this);
  85. }
  86. }
  87. else
  88. {
  89. if (lightgroup_)
  90. {
  91. lightgroup_->RemoveLight2D(this);
  92. lightgroup_ = 0;
  93. }
  94. }
  95. }
  96. void Light2D::OnSetEnabled()
  97. {
  98. Component::OnSetEnabled();
  99. if (lightgroup_)
  100. lightgroup_->SetDirty();
  101. if (!enabled_)
  102. {
  103. vertices_.Clear();
  104. }
  105. }
  106. void Light2D::AddVertices(Vector<Vertex2D>& vertices)
  107. {
  108. vertices += vertices_;
  109. }
  110. void Light2D::RegisterObject(Context* context)
  111. {
  112. context->RegisterFactory<Light2D>(ATOMIC2D_CATEGORY);
  113. COPY_BASE_ATTRIBUTES(Component);
  114. ACCESSOR_ATTRIBUTE("Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
  115. ACCESSOR_ATTRIBUTE("LightGroup", GetLightGroupID, SetLightGroupID, int, 0, AM_DEFAULT);
  116. ACCESSOR_ATTRIBUTE("Color", GetColor, SetColor, Color, Color::WHITE, AM_DEFAULT);
  117. ACCESSOR_ATTRIBUTE("Cast Shadows", GetCastShadows, SetCastShadows, bool, false, AM_DEFAULT);
  118. ACCESSOR_ATTRIBUTE("Num Rays", GetNumRays, SetNumRays, int, 32, AM_DEFAULT);
  119. ACCESSOR_ATTRIBUTE("Soft Shadows", GetSoftShadows, SetSoftShadows, bool, false, AM_DEFAULT);
  120. ACCESSOR_ATTRIBUTE("Soft Shadows Length", GetSoftShadowLength, SetSoftShadowLength, float, 2.5f, AM_DEFAULT);
  121. ACCESSOR_ATTRIBUTE("Backtrace", GetBacktrace, SetBacktrace, bool, false, AM_DEFAULT);
  122. }
  123. void Light2D::CastRays()
  124. {
  125. if (!raysInitialized_ || context_->GetEditorContext())
  126. return;
  127. PhysicsWorld2D* physicsWorld = lightgroup_->GetPhysicsWorld();
  128. if (physicsWorld && castShadows_) {
  129. for (unsigned i = 0; i < rays_.Size(); i++) {
  130. Light2DRay& ray = rays_[i];
  131. Vector2 oend = ray.end_;
  132. float distance = (ray.end_ - ray.start_).Length();
  133. if (Abs(distance < .01f))
  134. distance = .01f;
  135. float bestDistance = 999999;
  136. PODVector<PhysicsRaycastResult2D> results;
  137. physicsWorld->Raycast(results, ray.start_, ray.end_);
  138. RigidBody2D* body = NULL;
  139. for (PODVector<PhysicsRaycastResult2D>::ConstIterator itr = results.Begin(); itr != results.End(); itr++)
  140. {
  141. const PhysicsRaycastResult2D& result = *itr;
  142. if (result.body_->GetCastShadows() && result.distance_ < distance && result.distance_ < bestDistance)
  143. {
  144. bestDistance = result.distance_;
  145. body = result.body_;
  146. ray.fraction_ = result.distance_ / distance;
  147. ray.end_.x_ = result.position_.x_;
  148. ray.end_.y_ = result.position_.y_;
  149. }
  150. }
  151. // backtracing can introduce artifacts, for now don't backtrace
  152. // on static hit... also, may need to clamp on a body size
  153. if (backtrace_ && body && body->GetBodyType() != BT_STATIC)
  154. {
  155. results.Clear();
  156. bestDistance = -999999;
  157. physicsWorld->Raycast(results, oend, ray.end_);
  158. for (PODVector<PhysicsRaycastResult2D>::ConstIterator itr = results.Begin(); itr != results.End(); itr++)
  159. {
  160. const PhysicsRaycastResult2D& result = *itr;
  161. if (result.distance_ > bestDistance && result.body_->GetBodyType() != BT_STATIC)
  162. {
  163. bestDistance = result.distance_;
  164. ray.fraction_ = (distance - result.distance_) / distance;
  165. ray.end_.x_ = result.position_.x_;
  166. ray.end_.y_ = result.position_.y_;
  167. }
  168. }
  169. }
  170. }
  171. }
  172. }
  173. DirectionalLight2D::DirectionalLight2D(Context* context) : Light2D(context),
  174. direction_(-45.0f)
  175. {
  176. lightType_ = LIGHT2D_DIRECTIONAL;
  177. }
  178. DirectionalLight2D::~DirectionalLight2D()
  179. {
  180. }
  181. void DirectionalLight2D::RegisterObject(Context* context)
  182. {
  183. context->RegisterFactory<DirectionalLight2D>(ATOMIC2D_CATEGORY);
  184. COPY_BASE_ATTRIBUTES(Light2D);
  185. ACCESSOR_ATTRIBUTE("Direction", GetDirection, SetDirection, float, -45.0f, AM_DEFAULT);
  186. }
  187. void DirectionalLight2D::UpdateVertices()
  188. {
  189. if (!lightgroup_ || !enabled_ || context_->GetEditorContext())
  190. {
  191. vertices_.Clear();
  192. return;
  193. }
  194. const BoundingBox& frustumBox = lightgroup_->GetFrustumBox();
  195. float cos = Cos(direction_);
  196. float sin = Sin(direction_);
  197. float width = frustumBox.Size().x_;
  198. float height = frustumBox.Size().y_;
  199. if (!width || !height)
  200. return;
  201. float sizeOfScreen = width > height ? width : height;
  202. float xAxelOffSet = sizeOfScreen * cos;
  203. float yAxelOffSet = sizeOfScreen * sin;
  204. // preventing length <0 assertion error on box2d.
  205. if ((xAxelOffSet * xAxelOffSet < 0.1f) && (yAxelOffSet * yAxelOffSet < 0.1f)) {
  206. xAxelOffSet = 1;
  207. yAxelOffSet = 1;
  208. }
  209. float widthOffSet = sizeOfScreen * -sin;
  210. float heightOffSet = sizeOfScreen * cos;
  211. float x = (frustumBox.min_.x_ + frustumBox.max_.x_) * 0.5f - widthOffSet;
  212. float y = (frustumBox.min_.y_ + frustumBox.max_.y_) * 0.5f - heightOffSet;
  213. unsigned rayNum = rays_.Size();
  214. float portionX = 2.0f * widthOffSet / (rayNum - 1);
  215. x = (floorf(x / (portionX * 2))) * portionX * 2;
  216. float portionY = 2.0f * heightOffSet / (rayNum - 1);
  217. y = (ceilf(y / (portionY * 2))) * portionY * 2;
  218. for (unsigned i = 0; i < rayNum; i++)
  219. {
  220. Light2DRay& ray = rays_[i];
  221. float steppedX = float(i) * portionX + x;
  222. float steppedY = float(i) * portionY + y;
  223. ray.start_.x_ = steppedX - xAxelOffSet;
  224. ray.start_.y_ = steppedY - yAxelOffSet;
  225. ray.end_.x_ = steppedX + xAxelOffSet;
  226. ray.end_.y_ = steppedY + yAxelOffSet;
  227. ray.fraction_ = 0.0f;
  228. }
  229. raysInitialized_ = true;
  230. CastRays();
  231. Vertex2D vertex0;
  232. Vertex2D vertex1;
  233. Vertex2D vertex2;
  234. Vertex2D vertex3;
  235. vertex0.color_ = vertex1.color_ = vertex2.color_ = vertex3.color_ = color_.ToUInt();
  236. vertex0.uv_.x_ = 1.0f;
  237. vertex2.uv_.x_ = 1.0 ;
  238. vertex1.uv_.x_ = 1.0f;
  239. vertex3.uv_.x_ = 1.0f;
  240. int vertexCount = (rayNum - 1) * 6;
  241. if (softShadows_ && castShadows_)
  242. vertexCount *= 2;
  243. if (vertices_.Size() != vertexCount)
  244. vertices_.Resize(vertexCount);
  245. Vertex2D* v = &vertices_[0];
  246. for (unsigned i = 0; i < rayNum - 1; i++) {
  247. Light2DRay& ray0 = rays_[i];
  248. Light2DRay& ray1 = rays_[i + 1];
  249. vertex0.position_.x_ = ray0.start_.x_;
  250. vertex0.position_.y_ = ray0.start_.y_;
  251. vertex1.position_.x_ = ray0.end_.x_;
  252. vertex1.position_.y_ = ray0.end_.y_;
  253. vertex2.position_.x_ = ray1.start_.x_;
  254. vertex2.position_.y_ = ray1.start_.y_;
  255. vertex3.position_.x_ = ray1.end_.x_;
  256. vertex3.position_.y_ = ray1.end_.y_;
  257. *v++ = vertex0;
  258. *v++ = vertex1;
  259. *v++ = vertex3;
  260. *v++ = vertex0;
  261. *v++ = vertex3;
  262. *v++ = vertex2;
  263. }
  264. if (softShadows_ && castShadows_)
  265. {
  266. // THIS CAN BE OPTIMIZED!
  267. for (unsigned i = 0; i < rays_.Size() - 1; i++) {
  268. Light2DRay& ray0 = rays_[i];
  269. Light2DRay& ray1 = rays_[i + 1];
  270. vertex0.position_ = Vector3( ray0.end_.x_, ray0.end_.y_, 0.0f);
  271. Vector2 v0 = (ray0.end_ - ray0.start_).Normalized();
  272. Vector2 v1 = (ray1.end_ - ray1.start_).Normalized();
  273. vertex1.position_ = Vector3( ray0.end_.x_ + v0.x_ * softShadowLength_,
  274. ray0.end_.y_ + v0.y_ * softShadowLength_, 0.0f);
  275. vertex2.position_ = Vector3( ray1.end_.x_ + v1.x_ * softShadowLength_,
  276. ray1.end_.y_ + v1.y_ * softShadowLength_, 0.0f);
  277. vertex3.position_ = Vector3( ray1.end_.x_, ray1.end_.y_, 0.0f);
  278. vertex0.color_ = 0;
  279. vertex3.color_ = 0;
  280. vertex0.uv_.x_ = 0;
  281. vertex3.uv_.x_ = 0;
  282. vertex1.color_ = 0;
  283. vertex2.color_ = 0;
  284. vertex1.uv_.x_ = 1.0;
  285. vertex2.uv_.x_ = 1.0;
  286. *v++ = vertex0;
  287. *v++ = vertex1;
  288. *v++ = vertex2;
  289. *v++ = vertex0;
  290. *v++ = vertex2;
  291. *v++ = vertex3;
  292. }
  293. }
  294. }
  295. PositionalLight2D::PositionalLight2D(Context* context) : Light2D(context)
  296. {
  297. }
  298. PositionalLight2D::~PositionalLight2D()
  299. {
  300. }
  301. void PositionalLight2D::RegisterObject(Context* context)
  302. {
  303. context->RegisterFactory<PositionalLight2D>(ATOMIC2D_CATEGORY);
  304. COPY_BASE_ATTRIBUTES(Light2D);
  305. }
  306. void PositionalLight2D::UpdateVertices()
  307. {
  308. if (!lightgroup_ || !enabled_ || context_->GetEditorContext())
  309. {
  310. vertices_.Clear();
  311. return;
  312. }
  313. CastRays();
  314. Vertex2D vertex0;
  315. Vertex2D vertex1;
  316. Vertex2D vertex2;
  317. Vertex2D vertex3;
  318. vertex0.color_ = vertex1.color_ = vertex2.color_ = vertex3.color_ = color_.ToUInt();
  319. int vertexCount = (rays_.Size() - 1 ) * 3;
  320. if (softShadows_ && castShadows_)
  321. vertexCount += (rays_.Size() - 1) * 6;
  322. if (vertices_.Size() != vertexCount)
  323. vertices_.Resize(vertexCount);
  324. Vertex2D* v = &vertices_[0];
  325. for (unsigned i = 0; i < rays_.Size() - 1; i++) {
  326. Light2DRay& ray0 = rays_[i];
  327. Light2DRay& ray1 = rays_[i + 1];
  328. vertex0.position_.x_ = ray0.start_.x_;
  329. vertex0.position_.y_ = ray0.start_.y_;
  330. vertex1.position_.x_ = ray0.end_.x_;
  331. vertex1.position_.y_ = ray0.end_.y_;
  332. vertex2.position_.x_ = ray1.end_.x_;
  333. vertex2.position_.y_ = ray1.end_.y_;
  334. vertex0.uv_.x_ = 1.0f;
  335. vertex1.uv_.x_ = 1.0f - ray0.fraction_;
  336. vertex2.uv_.x_ = 1.0f - ray1.fraction_;
  337. *v++ = vertex0;
  338. *v++ = vertex1;
  339. *v++ = vertex2;
  340. }
  341. if (softShadows_ && castShadows_)
  342. {
  343. // THIS CAN BE OPTIMIZED!
  344. for (unsigned i = 0; i < rays_.Size() - 1; i++) {
  345. Light2DRay& ray0 = rays_[i];
  346. Light2DRay& ray1 = rays_[i + 1 == rays_.Size() ? 0 : i + 1];
  347. float s0 = (1.0f - ray0.fraction_);
  348. float s1 = (1.0f - ray1.fraction_);
  349. vertex0.position_.x_ = ray0.end_.x_;
  350. vertex0.position_.y_ = ray0.end_.y_;
  351. vertex1.position_.x_ = ray0.end_.x_ + s0 * softShadowLength_ * ray0.cos_;
  352. vertex1.position_.y_ = ray0.end_.y_ + s0 * softShadowLength_ * ray0.sin_;
  353. vertex2.position_.x_ = ray1.end_.x_ + s1 * softShadowLength_ * ray1.cos_;
  354. vertex2.position_.y_ = ray1.end_.y_ + s1 * softShadowLength_ * ray1.sin_;
  355. vertex3.position_.x_ = ray1.end_.x_;
  356. vertex3.position_.y_ = ray1.end_.y_;
  357. vertex1.uv_.x_ = 0;
  358. vertex2.uv_.x_ = 0;
  359. vertex1.color_ = 0x00000000;
  360. vertex2.color_ = 0x00000000;
  361. // darkness of shadow, we should break this all out of uint
  362. vertex0.uv_.x_ = s0 * .65f;
  363. vertex3.uv_.x_ = s1 * .65f;
  364. *v++ = vertex0;
  365. *v++ = vertex1;
  366. *v++ = vertex2;
  367. *v++ = vertex0;
  368. *v++ = vertex2;
  369. *v++ = vertex3;
  370. }
  371. }
  372. }
  373. PointLight2D::PointLight2D(Context* context) : PositionalLight2D(context),
  374. radius_(4.0f)
  375. {
  376. lightType_ = LIGHT2D_POINT;
  377. }
  378. PointLight2D::~PointLight2D()
  379. {
  380. }
  381. void PointLight2D::RegisterObject(Context* context)
  382. {
  383. context->RegisterFactory<PointLight2D>(ATOMIC2D_CATEGORY);
  384. COPY_BASE_ATTRIBUTES(PositionalLight2D);
  385. ACCESSOR_ATTRIBUTE("Radius", GetRadius, SetRadius, float, 4.0f, AM_DEFAULT);
  386. }
  387. void PointLight2D::UpdateVertices()
  388. {
  389. const Node* lightNode = GetNode();
  390. if (!lightgroup_ || !enabled_ || !lightNode || context_->GetEditorContext())
  391. {
  392. vertices_.Clear();
  393. return;
  394. }
  395. Vector2 start = lightNode->GetWorldPosition2D();
  396. float angleNum = 360.0f / float((rays_.Size() - 1));
  397. for (unsigned i = 0; i < rays_.Size(); i++) {
  398. float angle = angleNum * i;
  399. Light2DRay& ray = rays_[i];
  400. ray.start_ = start;
  401. ray.sin_ = Sin(angle);
  402. ray.cos_ = Cos(angle);
  403. ray.end_.x_ = ray.start_.x_ + radius_ * ray.cos_;
  404. ray.end_.y_ = ray.start_.y_ + radius_ * ray.sin_;
  405. ray.fraction_ = 1.0f;
  406. }
  407. raysInitialized_ = true;
  408. PositionalLight2D::UpdateVertices();
  409. }
  410. void Light2DGroup::RegisterObject(Context* context)
  411. {
  412. context->RegisterFactory<Light2DGroup>(ATOMIC2D_CATEGORY);
  413. COPY_BASE_ATTRIBUTES(Drawable2D);
  414. }
  415. void Light2DGroup::OnSceneSet(Scene* scene)
  416. {
  417. if (scene && node_ && !context_->GetEditorContext())
  418. {
  419. physicsWorld_ = scene->GetOrCreateComponent<PhysicsWorld2D>();
  420. Zone* zone = scene->GetComponent<Zone>();
  421. if (zone)
  422. SetAmbientColor(zone->GetAmbientColor());
  423. renderer_ = node_->GetOrCreateComponent<Renderer2D>();
  424. renderer_->SetTemporary(true);
  425. renderer_->SetUseTris(true);
  426. if (light2DMaterial_.Null())
  427. CreateLight2DMaterial();
  428. if (IsEnabledEffective())
  429. renderer_->AddDrawable(this);
  430. node_->AddListener(this);
  431. }
  432. else
  433. {
  434. if (renderer_)
  435. renderer_->RemoveDrawable(this);
  436. }
  437. }
  438. Light2DGroup::Light2DGroup(Context* context) : Drawable2D(context),
  439. lightgroupID_(0),
  440. ambientColor_(0, 0, 0, 0),
  441. frustum_(0)
  442. {
  443. sourceBatches_.Resize(1);
  444. SubscribeToEvent(E_BEGINRENDERING, HANDLER(Light2DGroup, HandleBeginRendering));
  445. SubscribeToEvent(E_BEGINVIEWUPDATE, HANDLER(Light2DGroup, HandleBeginViewUpdate));
  446. }
  447. Light2DGroup::~Light2DGroup()
  448. {
  449. Renderer* renderer = GetSubsystem<Renderer>();
  450. if (renderer)
  451. {
  452. Viewport* viewport = renderer->GetViewport(0);
  453. if (viewport)
  454. {
  455. RenderPath* renderpath = viewport->GetRenderPath();
  456. if (renderpath)
  457. renderpath->RemoveCommands("Light2D");
  458. }
  459. }
  460. }
  461. void Light2DGroup::HandleBeginViewUpdate(StringHash eventType, VariantMap& eventData)
  462. {
  463. using namespace BeginViewUpdate;
  464. Scene* scene = GetScene();
  465. // Check that we are updating the correct scene
  466. if (scene != eventData[P_SCENE].GetPtr())
  467. return;
  468. Camera* camera = static_cast<Camera*>(eventData[P_CAMERA].GetPtr());
  469. frustum_ = &camera->GetFrustum();
  470. if (camera->IsOrthographic())// && camera->GetNode()->GetWorldDirection() == Vector3::FORWARD)
  471. {
  472. // Define bounding box with min and max points
  473. // todo: handle rotation
  474. frustumBoundingBox_.Define(frustum_->vertices_[2], frustum_->vertices_[4]);
  475. }
  476. }
  477. void Light2DGroup::HandleBeginRendering(StringHash eventType, VariantMap& eventData)
  478. {
  479. sourceBatchesDirty_ = true;
  480. }
  481. void Light2DGroup::OnWorldBoundingBoxUpdate()
  482. {
  483. boundingBox_.Define(-M_LARGE_VALUE, M_LARGE_VALUE);
  484. worldBoundingBox_.Define(-M_LARGE_VALUE, M_LARGE_VALUE);
  485. }
  486. void Light2DGroup::OnDrawOrderChanged()
  487. {
  488. sourceBatches_[0].drawOrder_ = GetDrawOrder();
  489. }
  490. void Light2DGroup::UpdateSourceBatches()
  491. {
  492. if (!sourceBatchesDirty_)
  493. return;
  494. Vector<Vertex2D>& vertices = sourceBatches_[0].vertices_;
  495. vertices.Clear();
  496. for (Vector<WeakPtr<Light2D> >::Iterator itr = lights_.Begin(); itr != lights_.End(); itr++)
  497. {
  498. Light2D* light = *itr;
  499. if (!light->IsEnabled())
  500. continue;
  501. light->UpdateVertices();
  502. light->AddVertices(vertices);
  503. }
  504. sourceBatchesDirty_ = false;
  505. }
  506. void Light2DGroup::AddLight2D(Light2D* light)
  507. {
  508. Vector<WeakPtr<Light2D>>::Iterator itr = lights_.Find(WeakPtr<Light2D>(light));
  509. if (itr != lights_.End())
  510. return;
  511. lights_.Push(WeakPtr<Light2D>(light));
  512. }
  513. void Light2DGroup::RemoveLight2D(Light2D* light)
  514. {
  515. Vector<WeakPtr<Light2D>>::Iterator itr = lights_.Find(WeakPtr<Light2D>(light));
  516. if (itr != lights_.End())
  517. lights_.Erase(itr);
  518. }
  519. void Light2DGroup::SetAmbientColor(const Color& color)
  520. {
  521. if (color == ambientColor_)
  522. return;
  523. ambientColor_ = color;
  524. Renderer* renderer = GetSubsystem<Renderer>();
  525. // only on main viewport atm and viewport must first be set
  526. if (renderer)
  527. {
  528. Viewport* viewport = renderer->GetViewport(0);
  529. if (viewport)
  530. {
  531. RenderPath* renderpath = viewport->GetRenderPath();
  532. renderpath->SetShaderParameter("ShadowAmbient", ambientColor_);
  533. }
  534. }
  535. }
  536. void Light2DGroup::CreateLight2DMaterial()
  537. {
  538. if (context_->GetEditorContext())
  539. return;
  540. Renderer* renderer = GetSubsystem<Renderer>();
  541. Viewport* viewport = renderer->GetViewport(0);
  542. RenderPath* renderpath = viewport->GetRenderPath();
  543. RenderTargetInfo ntarget;
  544. ntarget.enabled_ = true;
  545. ntarget.name_ = "light2dtarget";
  546. ntarget.tag_ = "Light2D";
  547. ntarget.format_ = Graphics::GetRGBAFormat();
  548. ntarget.sizeMode_ = SIZE_VIEWPORTDIVISOR;
  549. ntarget.size_ = Vector2(4, 4);
  550. // try true
  551. ntarget.filtered_ = false;
  552. renderpath->AddRenderTarget(ntarget);
  553. RenderPathCommand clearCommand;
  554. clearCommand.tag_ = "Light2D";
  555. clearCommand.type_ = CMD_CLEAR;
  556. clearCommand.clearColor_ = Color(0, 0, 0, 0);
  557. clearCommand.clearFlags_ = CLEAR_COLOR;
  558. clearCommand.enabled_ = true;
  559. clearCommand.SetNumOutputs(1);
  560. clearCommand.SetOutputName(0, "light2dtarget");
  561. renderpath->AddCommand(clearCommand);
  562. RenderPathCommand passCommand;
  563. passCommand.tag_ = "Light2D";
  564. passCommand.type_ = CMD_SCENEPASS;
  565. passCommand.pass_ = "light2d";
  566. passCommand.enabled_ = true;
  567. passCommand.SetNumOutputs(1);
  568. passCommand.SetOutputName(0, "light2dtarget");
  569. renderpath->AddCommand(passCommand);
  570. ResourceCache* cache = GetSubsystem<ResourceCache>();
  571. XMLFile* light2DBlur = cache->GetResource<XMLFile>("PostProcess/Light2DBlur.xml");
  572. renderpath->Append(light2DBlur);
  573. RenderPathCommand copyCommand;
  574. copyCommand.enabled_ = true;
  575. copyCommand.tag_ = "Light2D";
  576. copyCommand.type_ = CMD_QUAD;
  577. copyCommand.vertexShaderName_ = "Shadow2D";
  578. copyCommand.pixelShaderName_ = "Shadow2D";
  579. copyCommand.SetTextureName(TU_DIFFUSE, "viewport");
  580. copyCommand.SetTextureName(TU_EMISSIVE, "light2dtarget");
  581. copyCommand.SetShaderParameter("ShadowAmbient", ambientColor_);
  582. copyCommand.SetNumOutputs(1);
  583. copyCommand.SetOutputName(0, "viewport");
  584. renderpath->AddCommand(copyCommand);
  585. light2DMaterial_ = new Material(context_);
  586. light2DMaterial_->SetName("Light2DMaterial");
  587. Technique* tech = new Technique(context_);
  588. Pass* pass = tech->CreatePass("light2d");
  589. pass->SetBlendMode(BLEND_ADDALPHA);
  590. pass->SetDepthTestMode(CMP_ALWAYS);
  591. pass->SetVertexShader("Light2D");
  592. pass->SetPixelShader("Light2D");
  593. pass->SetDepthWrite(false);
  594. light2DMaterial_->SetTechnique(0, tech);
  595. light2DMaterial_->SetCullMode(CULL_NONE);
  596. sourceBatches_[0].material_ = light2DMaterial_;
  597. }
  598. }