BakeMesh.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745
  1. // Copyright (c) 2014-2017, THUNDERBEAST GAMES LLC All rights reserved
  2. //
  3. // Permission is hereby granted, free of charge, to any person obtaining a copy
  4. // of this software and associated documentation files (the "Software"), to deal
  5. // in the Software without restriction, including without limitation the rights
  6. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. // copies of the Software, and to permit persons to whom the Software is
  8. // furnished to do so, subject to the following conditions:
  9. //
  10. // The above copyright notice and this permission notice shall be included in
  11. // all copies or substantial portions of the Software.
  12. //
  13. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19. // THE SOFTWARE.
  20. //
  21. #include "EmbreeScene.h"
  22. #include <Atomic/Core/WorkQueue.h>
  23. #include <Atomic/IO/Log.h>
  24. #include <Atomic/Graphics/Zone.h>
  25. #include <AtomicGlow/Common/GlowSettings.h>
  26. #include "Raster.h"
  27. #include "LightRay.h"
  28. #include "SceneBaker.h"
  29. #include "RadianceMap.h"
  30. #include "BakeLight.h"
  31. #include "BakeMesh.h"
  32. namespace AtomicGlow
  33. {
  34. BakeMesh::BakeMesh(Context* context, SceneBaker *sceneBaker) : BakeNode(context, sceneBaker),
  35. numVertices_(0),
  36. numTriangles_(0),
  37. radianceHeight_(0),
  38. radianceWidth_(0),
  39. bounceWidth_(0),
  40. bounceHeight_(0),
  41. bounceGranularity_(0),
  42. embreeGeomID_(RTC_INVALID_GEOMETRY_ID),
  43. numWorkItems_(0),
  44. ambientColor_(Color::BLACK)
  45. {
  46. }
  47. BakeMesh::~BakeMesh()
  48. {
  49. }
  50. void BakeMesh::Pack(unsigned lightmapIdx, Vector4 tilingOffset)
  51. {
  52. if (radianceMap_.NotNull())
  53. {
  54. radianceMap_->packed_ = true;
  55. }
  56. // modify the in memory scene, which will either become data for the editor
  57. // or in standalone mode, saved out the scene
  58. if (staticModel_)
  59. {
  60. staticModel_->SetLightMask(0);
  61. staticModel_->SetLightmapIndex(lightmapIdx);
  62. staticModel_->SetLightmapTilingOffset(tilingOffset);
  63. }
  64. }
  65. bool BakeMesh::FillLexelsCallback(void* param, int x, int y, const Vector3& barycentric,const Vector3& dx, const Vector3& dy, float coverage)
  66. {
  67. return ((ShaderData*) param)->bakeMesh_->LightPixel((ShaderData*) param, x, y, barycentric, dx, dy, coverage);
  68. }
  69. bool BakeMesh::LightPixel(ShaderData* shaderData, int x, int y, const Vector3& barycentric,const Vector3& dx, const Vector3& dy, float coverage)
  70. {
  71. if (x >= radianceWidth_ || y >= radianceHeight_)
  72. return true;
  73. meshMutex_.Acquire();
  74. bool accept = radiancePassAccept_[y * radianceWidth_ + x];
  75. const Vector3& rad = radiance_[y * radianceWidth_ + x];
  76. // check whether we've already lit this pixel
  77. if (accept)
  78. {
  79. meshMutex_.Release();
  80. return true;
  81. }
  82. radiancePassAccept_[y * radianceWidth_ + x] = true;
  83. meshMutex_.Release();
  84. MMTriangle* tri = &triangles_[shaderData->triangleIdx_];
  85. MMVertex* verts[3];
  86. verts[0] = &vertices_[tri->indices_[0]];
  87. verts[1] = &vertices_[tri->indices_[1]];
  88. verts[2] = &vertices_[tri->indices_[2]];
  89. LightRay ray;
  90. LightRay::SamplePoint& sample = ray.samplePoint_;
  91. sample.bakeMesh = this;
  92. sample.triangle = shaderData->triangleIdx_;
  93. sample.barycentric = barycentric;
  94. sample.radianceX = x;
  95. sample.radianceY = y;
  96. sample.position = verts[0]->position_ * barycentric.x_ +
  97. verts[1]->position_ * barycentric.y_ +
  98. verts[2]->position_ * barycentric.z_;
  99. sample.normal = verts[0]->normal_ * barycentric.x_ +
  100. verts[1]->normal_ * barycentric.y_ +
  101. verts[2]->normal_ * barycentric.z_;
  102. sample.uv0 = verts[0]->uv0_ * barycentric.x_ +
  103. verts[1]->uv0_ * barycentric.y_ +
  104. verts[2]->uv0_ * barycentric.z_;
  105. sample.uv1 = verts[0]->uv1_ * barycentric.x_ +
  106. verts[1]->uv1_ * barycentric.y_ +
  107. verts[2]->uv1_ * barycentric.z_;
  108. sceneBaker_->TraceRay(&ray, bakeLights_);
  109. return true;
  110. }
  111. void BakeMesh::LightTrianglesWork(const WorkItem* item, unsigned threadIndex)
  112. {
  113. ShaderData shaderData;
  114. BakeMesh* bakeMesh = shaderData.bakeMesh_ = (BakeMesh*) item->aux_;
  115. shaderData.lightMode_ = bakeMesh->GetSceneBaker()->GetCurrentLightMode();
  116. Vector2 triUV1[3];
  117. Vector2 extents(bakeMesh->radianceWidth_, bakeMesh->radianceHeight_);
  118. MMTriangle* start = reinterpret_cast<MMTriangle*>(item->start_);
  119. MMTriangle* end = reinterpret_cast<MMTriangle*>(item->end_);
  120. while (start <= end)
  121. {
  122. MMTriangle* tri = start;
  123. shaderData.triangleIdx_ = tri - &bakeMesh->triangles_[0];
  124. start++;
  125. for (unsigned j = 0; j < 3; j++)
  126. {
  127. unsigned idx = tri->indices_[j];
  128. triUV1[j] = bakeMesh->vertices_[idx].uv1_;
  129. triUV1[j].x_ *= float(bakeMesh->radianceWidth_);
  130. triUV1[j].y_ *= float(bakeMesh->radianceHeight_);
  131. triUV1[j].x_ = Clamp<float>(triUV1[j].x_, 0.0f, bakeMesh->radianceWidth_);
  132. triUV1[j].y_ = Clamp<float>(triUV1[j].y_, 0.0f, bakeMesh->radianceHeight_);
  133. }
  134. Raster::DrawTriangle(true, extents, false, triUV1, FillLexelsCallback, &shaderData );
  135. }
  136. }
  137. void BakeMesh::ContributeRadiance(const LightRay* lightRay, const Vector3& radiance, GlowLightMode lightMode)
  138. {
  139. MutexLock lock(meshMutex_);
  140. const LightRay::SamplePoint& source = lightRay->samplePoint_;
  141. unsigned radX = source.radianceX;
  142. unsigned radY = source.radianceY;
  143. const Vector3& v = radiance_[radY * radianceWidth_ + radX];
  144. radianceTriIndices_[radY * radianceWidth_ + radX] = source.triangle;
  145. if (v.x_ < 0.0f)
  146. {
  147. radiance_[radY * radianceWidth_ + radX] = radiance;
  148. }
  149. else
  150. {
  151. radiance_[radY * radianceWidth_ + radX] += radiance;
  152. }
  153. if (lightMode == GLOW_LIGHTMODE_AMBIENT || !GlobalGlowSettings.giEnabled_)
  154. return;
  155. // setup GI
  156. // TODO: filter on < radiance + bounce settings
  157. // OPTIMIZE: We can exit here if last bounce pass
  158. // this should be replaced with a GetBounceColor which uses UV0 diffuse
  159. // though takes into account additional settings, materials, etc
  160. Color uv0Color;
  161. // TODO: need to factor in alpha baked on BakeMaterial, not UV color from diffuse texture
  162. if (!GetUV0Color(source.triangle, source.barycentric, uv0Color))// || uv0Color.a_ < 0.5f)
  163. {
  164. return;
  165. }
  166. if (uv0Color.ToVector3().Length() < 0.15f)
  167. {
  168. return;
  169. }
  170. int iX = (source.radianceX) & ~(bounceGranularity_-1);
  171. int iY = (source.radianceY) & ~(bounceGranularity_-1);
  172. iX /= bounceGranularity_;
  173. iY /= bounceGranularity_;
  174. assert(iY * bounceWidth_ + iX < bounceWidth_ * bounceHeight_);
  175. if (bounceSamples_.Null())
  176. {
  177. bounceSamples_ = new BounceSample[bounceWidth_ * bounceHeight_];
  178. for (unsigned j = 0; j < bounceWidth_ * bounceHeight_; j++)
  179. {
  180. bounceSamples_[j].Reset();
  181. }
  182. }
  183. BounceSample& b = bounceSamples_[iY * bounceWidth_ + iX];
  184. for (unsigned i = 0 ; i < GLOW_MAX_BOUNCE_SAMPLE_TRIANGLES; i++)
  185. {
  186. // check if already in use by another triangle
  187. if (b.triIndex_[i] != -1 && b.triIndex_[i] != source.triangle)
  188. continue;
  189. if (b.triIndex_[i] == -1)
  190. {
  191. b.triIndex_[i] = source.triangle;
  192. b.position_ = source.position;
  193. b.radiance_ = radiance;
  194. b.srcColor_ = uv0Color.ToVector3();
  195. b.hits_ = 1;
  196. //ATOMIC_LOGINFOF("+ Tri: %i, Pos: %s, Rad: %s, BTri: %i", b.triIndex_, b.position_.ToString().CString(), b.radiance_.ToString().CString(), i);
  197. return;
  198. }
  199. //ATOMIC_LOGINFOF("- Tri: %i, Pos: %s, Rad: %s, BTri: %i", b.triIndex_, b.position_.ToString().CString(), b.radiance_.ToString().CString(), i);
  200. b.position_ += source.position;
  201. b.radiance_ += radiance;
  202. b.srcColor_ += uv0Color.ToVector3();
  203. b.hits_++;
  204. break;
  205. }
  206. }
  207. void BakeMesh::GenerateRadianceMap()
  208. {
  209. if (radianceMap_.NotNull())
  210. return;
  211. radianceMap_ = new RadianceMap(context_, this);
  212. }
  213. void BakeMesh::ResetBounce()
  214. {
  215. if (bounceSamples_.Null())
  216. return;
  217. for (unsigned i = 0; i < bounceWidth_ * bounceHeight_; i++)
  218. {
  219. bounceSamples_[i].Reset();
  220. }
  221. }
  222. void BakeMesh::Light(GlowLightMode mode)
  223. {
  224. if (mode == GLOW_LIGHTMODE_INDIRECT && !GlobalGlowSettings.giEnabled_)
  225. return;
  226. if (!GetLightmap() || !radianceWidth_ || !radianceHeight_ || !numTriangles_)
  227. return;
  228. bakeLights_.Clear();
  229. sceneBaker_->QueryLights(boundingBox_, bakeLights_);
  230. // for all triangles
  231. for (unsigned i = 0; i < radianceWidth_ * radianceHeight_; i++)
  232. {
  233. radiancePassAccept_[i] = false;
  234. }
  235. WorkQueue* queue = GetSubsystem<WorkQueue>();
  236. unsigned numTrianglePerItem = numTriangles_ / 4 ? numTriangles_ / 4 : numTriangles_;
  237. unsigned curIdx = 0;
  238. numWorkItems_ = 0;
  239. while (true)
  240. {
  241. SharedPtr<WorkItem> item = queue->GetFreeItem();
  242. item->priority_ = M_MAX_UNSIGNED;
  243. item->workFunction_ = LightTrianglesWork;
  244. item->aux_ = this;
  245. item->start_ = &triangles_[curIdx];
  246. unsigned endIdx = curIdx + numTrianglePerItem;
  247. if (endIdx < numTriangles_)
  248. {
  249. item->end_ = &triangles_[endIdx];
  250. }
  251. else
  252. {
  253. item->end_ = &triangles_[numTriangles_ - 1];
  254. }
  255. item->sendEvent_ = true;
  256. queue->AddWorkItem(item);
  257. numWorkItems_++;
  258. if (item->end_ == &triangles_[numTriangles_ - 1])
  259. break;
  260. curIdx += numTrianglePerItem + 1;
  261. }
  262. }
  263. static unsigned CalcLightMapSize(unsigned sz)
  264. {
  265. // highest multiple of 8, note rasterizer requires a multiple of 8!
  266. sz = (sz + 8) & ~7;
  267. if (sz > 512 && !IsPowerOfTwo(sz))
  268. {
  269. sz = NextPowerOfTwo(sz)/2;
  270. }
  271. sz = Clamp<unsigned>(sz, 32, GlobalGlowSettings.lightmapSize_);
  272. return sz;
  273. }
  274. void BakeMesh::Preprocess()
  275. {
  276. RTCScene scene = sceneBaker_->GetEmbreeScene()->GetRTCScene();
  277. if (staticModel_ && staticModel_->GetZone())
  278. {
  279. ambientColor_ = staticModel_->GetZone()->GetAmbientColor();
  280. }
  281. if (staticModel_ && staticModel_->GetCastShadows())
  282. {
  283. // Create the embree mesh
  284. embreeGeomID_ = rtcNewTriangleMesh(scene, RTC_GEOMETRY_STATIC, numTriangles_, numVertices_);
  285. rtcSetUserData(scene, embreeGeomID_, this);
  286. rtcSetOcclusionFilterFunction(scene, embreeGeomID_, OcclusionFilter);
  287. rtcSetIntersectionFilterFunction(scene, embreeGeomID_, IntersectFilter);
  288. // Populate vertices
  289. float* vertices = (float*) rtcMapBuffer(scene, embreeGeomID_, RTC_VERTEX_BUFFER);
  290. MMVertex* vIn = &vertices_[0];
  291. for (unsigned i = 0; i < numVertices_; i++, vIn++)
  292. {
  293. *vertices++ = vIn->position_.x_;
  294. *vertices++ = vIn->position_.y_;
  295. *vertices++ = vIn->position_.z_;
  296. // Note that RTC_VERTEX_BUFFER is 16 byte aligned, thus extra component
  297. // which isn't used, though we'll initialize it
  298. *vertices++ = 0.0f;
  299. }
  300. rtcUnmapBuffer(scene, embreeGeomID_, RTC_VERTEX_BUFFER);
  301. uint32_t* triangles = (uint32_t*) rtcMapBuffer(scene, embreeGeomID_, RTC_INDEX_BUFFER);
  302. for (size_t i = 0; i < numTriangles_; i++)
  303. {
  304. MMTriangle* tri = &triangles_[i];
  305. *triangles++ = tri->indices_[0];
  306. *triangles++ = tri->indices_[1];
  307. *triangles++ = tri->indices_[2];
  308. }
  309. rtcUnmapBuffer(scene, embreeGeomID_, RTC_INDEX_BUFFER);
  310. }
  311. float lmScale = staticModel_->GetLightmapScale();
  312. // if we aren't lightmapped, we just contribute to occlusion
  313. if (!GetLightmap() || lmScale <= 0.0f)
  314. return;
  315. unsigned lmSize = staticModel_->GetLightmapSize();
  316. if (!lmSize)
  317. {
  318. float totalarea = 0.0f;
  319. for (unsigned i = 0; i < numTriangles_; i++)
  320. {
  321. MMTriangle* tri = &triangles_[i];
  322. MMVertex* v0 = &vertices_[tri->indices_[0]];
  323. MMVertex* v1 = &vertices_[tri->indices_[1]];
  324. MMVertex* v2 = &vertices_[tri->indices_[2]];
  325. totalarea += AreaOfTriangle(v0->position_,
  326. v1->position_,
  327. v2->position_);
  328. }
  329. totalarea = Clamp<float>(totalarea, 1, 64.0f);
  330. lmSize = CalcLightMapSize(totalarea * 64.0f * lmScale * GlobalGlowSettings.lexelDensity_ * GlobalGlowSettings.sceneLexelDensityScale_);
  331. }
  332. if (lmSize < 32)
  333. lmSize = 32;
  334. if (lmSize > 2048)
  335. lmSize = 2048;
  336. radianceWidth_ = lmSize;
  337. radianceHeight_ = lmSize;
  338. // init radiance
  339. radiance_ = new Vector3[radianceWidth_ * radianceHeight_];
  340. radianceTriIndices_ = new int[radianceWidth_ * radianceHeight_];
  341. radiancePassAccept_ = new bool[radianceWidth_ * radianceHeight_];
  342. Vector3 v(-1, -1, -1);
  343. for (unsigned i = 0; i < radianceWidth_ * radianceHeight_; i++)
  344. {
  345. radiance_[i] = v;
  346. radianceTriIndices_[i] = -1;
  347. radiancePassAccept_[i] = false;
  348. }
  349. // If GI is enabled, setup bounce metrics
  350. if (GlobalGlowSettings.giEnabled_)
  351. {
  352. bounceGranularity_ = GlobalGlowSettings.giGranularity_;
  353. bounceWidth_ = (radianceWidth_ + bounceGranularity_) & ~(bounceGranularity_-1);
  354. bounceHeight_ = (radianceHeight_ + bounceGranularity_) & ~(bounceGranularity_-1);
  355. bounceWidth_ /= bounceGranularity_;
  356. bounceHeight_ /= bounceGranularity_;
  357. }
  358. }
  359. bool BakeMesh::SetStaticModel(StaticModel* staticModel)
  360. {
  361. if (!staticModel || !staticModel->GetNode())
  362. return false;
  363. staticModel_ = staticModel;
  364. node_ = staticModel_->GetNode();
  365. bakeModel_ = GetSubsystem<BakeModelCache>()->GetBakeModel(staticModel_->GetModel());
  366. if (bakeModel_.Null())
  367. {
  368. return false;
  369. }
  370. ModelPacker* modelPacker = bakeModel_->GetModelPacker();
  371. if (modelPacker->lodLevels_.Size() < 1)
  372. {
  373. return false;
  374. }
  375. MPLODLevel* lodLevel = modelPacker->lodLevels_[0];
  376. // LOD must have LM coords
  377. if (!lodLevel->HasElement(TYPE_VECTOR2, SEM_TEXCOORD, 1))
  378. {
  379. return false;
  380. }
  381. // materials
  382. if (staticModel_->GetNumGeometries() != lodLevel->mpGeometry_.Size())
  383. {
  384. ATOMIC_LOGERROR("BakeMesh::Preprocess() - Geometry mismatch");
  385. return false;
  386. }
  387. for (unsigned i = 0; i < staticModel_->GetNumGeometries(); i++)
  388. {
  389. BakeMaterial* bakeMaterial = GetSubsystem<BakeMaterialCache>()->GetBakeMaterial(staticModel_->GetMaterial(i));
  390. bakeMaterials_.Push(bakeMaterial);
  391. }
  392. // allocate
  393. numVertices_ = 0;
  394. unsigned totalIndices = 0;
  395. lodLevel->GetTotalCounts(numVertices_, totalIndices);
  396. if (!numVertices_ || ! totalIndices)
  397. {
  398. return false;
  399. }
  400. numTriangles_ = totalIndices/3;
  401. vertices_ = new MMVertex[numVertices_];
  402. triangles_ = new MMTriangle[numTriangles_];
  403. MMVertex* vOut = &vertices_[0];
  404. MMTriangle* tri = &triangles_[0];
  405. unsigned vertexStart = 0;
  406. unsigned indexStart = 0;
  407. const Matrix3x4& wtransform = node_->GetWorldTransform();
  408. for (unsigned i = 0; i < lodLevel->mpGeometry_.Size(); i++)
  409. {
  410. MPGeometry* mpGeo = lodLevel->mpGeometry_[i];
  411. // Setup Vertices
  412. MPVertex* vIn = &mpGeo->vertices_[0];
  413. for (unsigned j = 0; j < mpGeo->vertices_.Size(); j++)
  414. {
  415. vOut->position_ = wtransform * vIn->position_;
  416. vOut->normal_ = wtransform.Rotation() * vIn->normal_;
  417. vOut->uv0_ = vIn->uv0_;
  418. vOut->uv1_ = vIn->uv1_;
  419. boundingBox_.Merge(vOut->position_);
  420. vOut++;
  421. vIn++;
  422. }
  423. // Setup Triangles
  424. for (unsigned j = 0; j < mpGeo->numIndices_; j+=3, tri++)
  425. {
  426. tri->materialIndex_ = i;
  427. tri->indices_[0] = mpGeo->indices_[j] + vertexStart;
  428. tri->indices_[1] = mpGeo->indices_[j + 1] + vertexStart;
  429. tri->indices_[2] = mpGeo->indices_[j + 2] + vertexStart;
  430. tri->normal_ = vertices_[tri->indices_[0]].normal_;
  431. tri->normal_ += vertices_[tri->indices_[1]].normal_;
  432. tri->normal_ += vertices_[tri->indices_[2]].normal_;
  433. tri->normal_ /= 3.0f;
  434. tri->normal_.Normalize();
  435. }
  436. indexStart += mpGeo->numIndices_;
  437. vertexStart += mpGeo->vertices_.Size();
  438. }
  439. return true;
  440. }
  441. bool BakeMesh::GetUV0Color(int triIndex, const Vector3& barycentric, Color& colorOut) const
  442. {
  443. colorOut = Color::BLACK;
  444. if (triIndex < 0 || triIndex >= numTriangles_)
  445. return false;
  446. const MMTriangle* tri = &triangles_[triIndex];
  447. const BakeMaterial* material = bakeMaterials_[tri->materialIndex_];
  448. const Image* diffuse = material->GetDiffuseTexture();
  449. if (!diffuse)
  450. {
  451. return false;
  452. }
  453. const Vector2& st0 = vertices_[tri->indices_[0]].uv0_;
  454. const Vector2& st1 = vertices_[tri->indices_[1]].uv0_;
  455. const Vector2& st2 = vertices_[tri->indices_[2]].uv0_;
  456. const float u = barycentric.x_, v = barycentric.y_, w = barycentric.z_;
  457. const Vector2 st = w*st0 + u*st1 + v*st2;
  458. int x = diffuse->GetWidth() * st.x_;
  459. int y = diffuse->GetHeight() * st.y_;
  460. if (x < 0)
  461. x = diffuse->GetWidth() + x;
  462. if (y < 0)
  463. y = diffuse->GetWidth() + y;
  464. colorOut = diffuse->GetPixel(x, y);
  465. return true;
  466. }
  467. BounceBakeLight* BakeMesh::GenerateBounceBakeLight()
  468. {
  469. if (bounceSamples_.Null())
  470. return 0;
  471. BounceSample b;
  472. PODVector<BounceSample> bounceSamples;
  473. for (int y = 0; y < bounceHeight_; y++)
  474. {
  475. for (int x = 0; x < bounceWidth_; x++)
  476. {
  477. const BounceSample& bSrc = bounceSamples_[y * bounceWidth_ + x];
  478. if (bSrc.triIndex_[0] == -1)
  479. continue;
  480. b = bSrc;
  481. // average of positions
  482. b.position_ = bSrc.position_ / bSrc.hits_;
  483. // average of colors
  484. b.srcColor_ = bSrc.srcColor_ / bSrc.hits_;
  485. if (b.srcColor_.Length() < 0.15f)
  486. continue;
  487. b.radiance_ = bSrc.radiance_;
  488. // TODO: proper falloff
  489. b.radiance_ *= 0.4f;
  490. if ((b.radiance_/b.hits_).Length() < 0.05)
  491. continue;
  492. bounceSamples.Push(b);
  493. const bool generateDebugNodes = false;
  494. if (generateDebugNodes)
  495. {
  496. node_->CreateChild(ToString("Bounce Pass:%i x:%i y:%i", sceneBaker_->GetCurrentGIBounce(), x, y))->SetWorldPosition(b.position_);
  497. }
  498. }
  499. }
  500. if (!bounceSamples.Size())
  501. {
  502. ResetBounce();
  503. return 0;
  504. }
  505. BounceBakeLight* bakeLight = new BounceBakeLight(context_, sceneBaker_);
  506. bakeLight->SetBakeMesh(this);
  507. bakeLight->SetBounceSamples(bounceSamples);
  508. ResetBounce();
  509. return bakeLight;
  510. }
  511. void BakeMesh::IntersectFilter(void* ptr, RTCRay& ray)
  512. {
  513. CommonFilter(static_cast<BakeMesh*>(ptr), ray);
  514. }
  515. void BakeMesh::OcclusionFilter(void* ptr, RTCRay& ray)
  516. {
  517. CommonFilter(static_cast<BakeMesh*>(ptr), ray);
  518. }
  519. bool BakeMesh::CommonFilter(const BakeMesh* bakeMesh, RTCRay& ray)
  520. {
  521. if (ray.primID >= (unsigned) bakeMesh->numTriangles_)
  522. return false;
  523. const MMTriangle* tri = &bakeMesh->triangles_[ray.primID];
  524. const BakeMaterial* material = bakeMesh->bakeMaterials_[tri->materialIndex_];
  525. if (!material)
  526. return false;
  527. if (!material->GetOcclusionMasked())
  528. return false;
  529. Color color;
  530. if (bakeMesh->GetUV0Color(ray.primID, Vector3(ray.u, ray.v, 1.0f-ray.u-ray.v), color))
  531. {
  532. if (color.a_ < 0.5f)
  533. {
  534. ray.geomID = RTC_INVALID_GEOMETRY_ID;
  535. return true;
  536. }
  537. }
  538. return false;
  539. }
  540. }