Pipeline.cpp 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498
  1. //
  2. // Urho3D Engine
  3. // Copyright (c) 2008-2011 Lasse Öörni
  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. #include "Precompiled.h"
  24. #include "DebugRenderer.h"
  25. #include "Geometry.h"
  26. #include "IndexBuffer.h"
  27. #include "InstancedModel.h"
  28. #include "Light.h"
  29. #include "Log.h"
  30. #include "Material.h"
  31. #include "OcclusionBuffer.h"
  32. #include "Octree.h"
  33. #include "OctreeQuery.h"
  34. #include "Pipeline.h"
  35. #include "PixelShader.h"
  36. #include "Profiler.h"
  37. #include "Renderer.h"
  38. #include "RendererEvents.h"
  39. #include "RendererImpl.h"
  40. #include "ResourceCache.h"
  41. #include "Scene.h"
  42. #include "SceneEvents.h"
  43. #include "StringUtils.h"
  44. #include "Texture2D.h"
  45. #include "TextureCube.h"
  46. #include "VertexBuffer.h"
  47. #include "VertexShader.h"
  48. #include "View.h"
  49. #include "XMLFile.h"
  50. #include "DebugNew.h"
  51. static const float dirLightVertexData[] =
  52. {
  53. -1, 1, 0,
  54. 1, 1, 0,
  55. 1, -1, 0,
  56. -1, -1, 0,
  57. };
  58. static const unsigned short dirLightIndexData[] =
  59. {
  60. 0, 1, 2,
  61. 2, 3, 0,
  62. };
  63. static const float pointLightVertexData[] =
  64. {
  65. -0.423169f, -1.000000f, 0.423169f,
  66. -0.423169f, -1.000000f, -0.423169f,
  67. 0.423169f, -1.000000f, -0.423169f,
  68. 0.423169f, -1.000000f, 0.423169f,
  69. 0.423169f, 1.000000f, -0.423169f,
  70. -0.423169f, 1.000000f, -0.423169f,
  71. -0.423169f, 1.000000f, 0.423169f,
  72. 0.423169f, 1.000000f, 0.423169f,
  73. -1.000000f, 0.423169f, -0.423169f,
  74. -1.000000f, -0.423169f, -0.423169f,
  75. -1.000000f, -0.423169f, 0.423169f,
  76. -1.000000f, 0.423169f, 0.423169f,
  77. 0.423169f, 0.423169f, -1.000000f,
  78. 0.423169f, -0.423169f, -1.000000f,
  79. -0.423169f, -0.423169f, -1.000000f,
  80. -0.423169f, 0.423169f, -1.000000f,
  81. 1.000000f, 0.423169f, 0.423169f,
  82. 1.000000f, -0.423169f, 0.423169f,
  83. 1.000000f, -0.423169f, -0.423169f,
  84. 1.000000f, 0.423169f, -0.423169f,
  85. 0.423169f, -0.423169f, 1.000000f,
  86. 0.423169f, 0.423169f, 1.000000f,
  87. -0.423169f, 0.423169f, 1.000000f,
  88. -0.423169f, -0.423169f, 1.000000f
  89. };
  90. static const unsigned short pointLightIndexData[] =
  91. {
  92. 0, 1, 2,
  93. 0, 2, 3,
  94. 4, 5, 6,
  95. 4, 6, 7,
  96. 8, 9, 10,
  97. 8, 10, 11,
  98. 12, 13, 14,
  99. 12, 14, 15,
  100. 16, 17, 18,
  101. 16, 18, 19,
  102. 20, 21, 22,
  103. 20, 22, 23,
  104. 0, 10, 9,
  105. 0, 9, 1,
  106. 13, 2, 1,
  107. 13, 1, 14,
  108. 23, 0, 3,
  109. 23, 3, 20,
  110. 17, 3, 2,
  111. 17, 2, 18,
  112. 21, 7, 6,
  113. 21, 6, 22,
  114. 7, 16, 19,
  115. 7, 19, 4,
  116. 5, 8, 11,
  117. 5, 11, 6,
  118. 4, 12, 15,
  119. 4, 15, 5,
  120. 22, 11, 10,
  121. 22, 10, 23,
  122. 8, 15, 14,
  123. 8, 14, 9,
  124. 12, 19, 18,
  125. 12, 18, 13,
  126. 16, 21, 20,
  127. 16, 20, 17,
  128. 0, 23, 10,
  129. 1, 9, 14,
  130. 2, 13, 18,
  131. 3, 17, 20,
  132. 6, 11, 22,
  133. 5, 15, 8,
  134. 4, 19, 12,
  135. 7, 21, 16
  136. };
  137. static const float spotLightVertexData[] =
  138. {
  139. // Use slightly clamped Z-range so that shadowed point light splits line up nicely
  140. 0.00001f, 0.00001f, 0.00001f,
  141. 0.00001f, -0.00001f, 0.00001f,
  142. -0.00001f, -0.00001f, 0.00001f,
  143. -0.00001f, 0.00001f, 0.00001f,
  144. 1.00000f, 1.00000f, 0.99999f,
  145. 1.00000f, -1.00000f, 0.99999f,
  146. -1.00000f, -1.00000f, 0.99999f,
  147. -1.00000f, 1.00000f, 0.99999f,
  148. };
  149. static const unsigned short spotLightIndexData[] =
  150. {
  151. 3, 0, 1,
  152. 3, 1, 2,
  153. 0, 4, 5,
  154. 0, 5, 1,
  155. 3, 7, 4,
  156. 3, 4, 0,
  157. 7, 3, 2,
  158. 7, 2, 6,
  159. 6, 2, 1,
  160. 6, 1, 5,
  161. 7, 5, 4,
  162. 7, 6, 5
  163. };
  164. static const std::string geometryVSVariations[] =
  165. {
  166. "",
  167. "Skinned",
  168. "Instanced"
  169. };
  170. static const std::string gBufferPSVariations[] =
  171. {
  172. "",
  173. "HW"
  174. };
  175. static const std::string lightVSVariations[] =
  176. {
  177. "",
  178. "Spot",
  179. "Shadow",
  180. "SpotShadow"
  181. };
  182. static const std::string deferredLightVSVariations[] =
  183. {
  184. "",
  185. "Dir",
  186. "Ortho",
  187. "OrthoDir"
  188. };
  189. static const std::string deferredLightPSVariations[] =
  190. {
  191. "Dir",
  192. "DirSpec",
  193. "DirShadow",
  194. "DirShadowSpec",
  195. "DirNegative",
  196. "Point",
  197. "PointSpec",
  198. "PointShadow",
  199. "PointShadowSpec",
  200. "PointNegative",
  201. "Spot",
  202. "SpotSpec",
  203. "SpotShadow",
  204. "SpotShadowSpec",
  205. "SpotNegative",
  206. "OrthoDir",
  207. "OrthoDirSpec",
  208. "OrthoDirShadow",
  209. "OrthoDirShadowSpec",
  210. "OrthoDirNegative",
  211. "OrthoPoint",
  212. "OrthoPointSpec",
  213. "OrthoPointShadow",
  214. "OrthoPointShadowSpec",
  215. "OrthoPointNegative",
  216. "OrthoSpot",
  217. "OrthoSpotSpec",
  218. "OrthoSpotShadow",
  219. "OrthoSpotShadowSpec",
  220. "OrthoSpotNegative",
  221. "LinearDir",
  222. "LinearDirSpec",
  223. "LinearDirShadow",
  224. "LinearDirShadowSpec",
  225. "LinearDirNegative",
  226. "LinearPoint",
  227. "LinearPointSpec",
  228. "LinearPointShadow",
  229. "LinearPointShadowSpec",
  230. "LinearPointNegative",
  231. "LinearSpot",
  232. "LinearSpotSpec",
  233. "LinearSpotShadow",
  234. "LinearSpotShadowSpec",
  235. "LinearSpotNegative"
  236. };
  237. static const std::string shadowPSVariations[] =
  238. {
  239. "",
  240. "HW"
  241. };
  242. void EdgeFilterParameters::validate()
  243. {
  244. mThreshold = max(mThreshold, 0.0f);
  245. mFilterStep = clamp(mFilterStep, 0.0f, 1.0f);
  246. mMaxFilter = clamp(mMaxFilter, 0.0f, 1.0f);
  247. mMaxScale = max(mMaxScale, 0.0f);
  248. }
  249. Pipeline::Pipeline(Renderer* renderer, ResourceCache* cache) :
  250. mRenderer(renderer),
  251. mCache(cache),
  252. mFrameNumber(M_MAX_UNSIGNED),
  253. mNumViews(0),
  254. mNumSplitLights(0),
  255. mElapsedTime(0.0f),
  256. mSpecularLighting(true),
  257. mDrawShadows(true),
  258. mTextureAnisotropy(4),
  259. mTextureFilterMode(FILTER_TRILINEAR),
  260. mTextureQuality(QUALITY_HIGH),
  261. mMaterialQuality(QUALITY_HIGH),
  262. mLightDetailLevel(QUALITY_HIGH),
  263. mShadowMapSize(1024),
  264. mShadowMapHiresDepth(false),
  265. mMaxOccluderTriangles(5000),
  266. mOcclusionBufferSize(256),
  267. mOccluderSizeThreshold(0.1f),
  268. mEdgeFilter(EdgeFilterParameters(0.25f, 0.25f, 0.50f, 10.0f)),
  269. mDrawDebugGeometry(false),
  270. mShadersChangedFrameNumber(M_MAX_UNSIGNED),
  271. mShadersDirty(true)
  272. {
  273. if (!mRenderer)
  274. EXCEPTION("Null renderer for Pipeline");
  275. LOGINFO("Rendering pipeline created");
  276. // Check shader model support
  277. if (mRenderer->getSM3Support())
  278. {
  279. mShaderPath = "Shaders/SM3/";
  280. mVSFormat = ".vs3";
  281. mPSFormat = ".ps3";
  282. InstancedModel::setInstancingMode(HARDWARE_INSTANCING);
  283. }
  284. else
  285. {
  286. mShaderPath = "Shaders/SM2/";
  287. mVSFormat = ".vs2";
  288. mPSFormat = ".ps2";
  289. InstancedModel::setInstancingMode(SHADER_INSTANCING);
  290. }
  291. mDefaultLightRamp = mCache->getResource<Texture2D>("Textures/Ramp.png");
  292. mDefaultLightSpot = mCache->getResource<Texture2D>("Textures/Spot.png");
  293. mDefaultMaterial = mCache->getResource<Material>("Materials/Default.xml");
  294. createGeometries();
  295. if (!createShadowMaps())
  296. mDrawShadows = false;
  297. mViewports.resize(1);
  298. resetViews();
  299. subscribeToEvent(EVENT_WINDOWRESIZED, EVENT_HANDLER(Pipeline, handleWindowResized));
  300. subscribeToEvent(EVENT_POSTRENDERUPDATE, EVENT_HANDLER(Pipeline, handlePostRenderUpdate));
  301. }
  302. Pipeline::~Pipeline()
  303. {
  304. LOGINFO("Rendering pipeline shut down");
  305. }
  306. void Pipeline::setNumViewports(unsigned num)
  307. {
  308. mViewports.resize(num);
  309. }
  310. void Pipeline::setViewport(unsigned index, const Viewport& viewport)
  311. {
  312. if (index >= mViewports.size())
  313. {
  314. LOGERROR("Illegal viewport index");
  315. return;
  316. }
  317. mViewports[index] = viewport;
  318. }
  319. void Pipeline::setSpecularLighting(bool enable)
  320. {
  321. mSpecularLighting = enable;
  322. }
  323. void Pipeline::setDrawShadows(bool enable)
  324. {
  325. mDrawShadows = enable;
  326. if (!createShadowMaps())
  327. mDrawShadows = false;
  328. }
  329. void Pipeline::setTextureAnisotropy(int level)
  330. {
  331. mTextureAnisotropy = max(level, 1);
  332. }
  333. void Pipeline::setTextureFilterMode(TextureFilterMode mode)
  334. {
  335. mTextureFilterMode = mode;
  336. }
  337. void Pipeline::setTextureQuality(int quality)
  338. {
  339. quality = clamp(quality, QUALITY_LOW, QUALITY_HIGH);
  340. if (quality != mTextureQuality)
  341. {
  342. mTextureQuality = quality;
  343. Texture::setQuality(mTextureQuality);
  344. reloadTextures();
  345. }
  346. }
  347. void Pipeline::setMaterialQuality(int quality)
  348. {
  349. mMaterialQuality = clamp(quality, QUALITY_LOW, QUALITY_MAX);
  350. mShadersDirty = true;
  351. resetViews();
  352. }
  353. void Pipeline::setLightDetailLevel(int detailLevel)
  354. {
  355. mLightDetailLevel = clamp(detailLevel, QUALITY_LOW, QUALITY_MAX);
  356. }
  357. void Pipeline::setShadowMapSize(int size)
  358. {
  359. mShadowMapSize = max(size, SHADOW_MIN_PIXELS);
  360. if (!createShadowMaps())
  361. {
  362. mShadowMapSize = 1024;
  363. if (!createShadowMaps())
  364. mDrawShadows = false;
  365. }
  366. }
  367. void Pipeline::setShadowMapHiresDepth(bool enable)
  368. {
  369. if (!mRenderer->getHiresShadowSupport())
  370. enable = false;
  371. mShadowMapHiresDepth = enable;
  372. if (!createShadowMaps())
  373. mDrawShadows = false;
  374. }
  375. void Pipeline::setMaxOccluderTriangles(int triangles)
  376. {
  377. mMaxOccluderTriangles = max(triangles, 0);
  378. }
  379. void Pipeline::setOcclusionBufferSize(int size)
  380. {
  381. mOcclusionBufferSize = max(size, 1);
  382. mOcclusionBuffers.clear();
  383. }
  384. void Pipeline::setOccluderSizeThreshold(float screenSize)
  385. {
  386. mOccluderSizeThreshold = max(screenSize, 0.0f);
  387. }
  388. void Pipeline::setEdgeFilter(const EdgeFilterParameters& parameters)
  389. {
  390. mEdgeFilter = parameters;
  391. }
  392. void Pipeline::setDrawDebugGeometry(bool enable)
  393. {
  394. mDrawDebugGeometry = enable;
  395. }
  396. const Viewport& Pipeline::getViewport(unsigned index) const
  397. {
  398. static const Viewport noViewport;
  399. return index < mViewports.size() ? mViewports[index] : noViewport;
  400. }
  401. VertexShader* Pipeline::getVertexShader(const std::string& name, bool checkExists) const
  402. {
  403. // Check for extra underscore with no variations and remove
  404. std::string fullName = replace(mShaderPath + name + mVSFormat, "_.", ".");
  405. if (checkExists)
  406. {
  407. if (!mCache->exists(fullName))
  408. return 0;
  409. }
  410. return mCache->getResource<VertexShader>(fullName);
  411. }
  412. PixelShader* Pipeline::getPixelShader(const std::string& name, bool checkExists) const
  413. {
  414. // Check for extra underscore with no variations and remove
  415. std::string fullName = replace(mShaderPath + name + mPSFormat, "_.", ".");
  416. if (checkExists)
  417. {
  418. if (!mCache->exists(fullName))
  419. return 0;
  420. }
  421. return mCache->getResource<PixelShader>(fullName);
  422. }
  423. unsigned Pipeline::getNumGeometries(bool allViews) const
  424. {
  425. unsigned numGeometries = 0;
  426. unsigned lastView = allViews ? mNumViews : 1;
  427. for (unsigned i = 0; i < lastView; ++i)
  428. numGeometries += mViews[i]->getGeometries().size();
  429. return numGeometries;
  430. }
  431. unsigned Pipeline::getNumLights(bool allViews) const
  432. {
  433. unsigned numLights = 0;
  434. unsigned lastView = allViews ? mNumViews : 1;
  435. for (unsigned i = 0; i < lastView; ++i)
  436. numLights += mViews[i]->getLights().size();
  437. return numLights;
  438. }
  439. unsigned Pipeline::getNumShadowMaps(bool allViews) const
  440. {
  441. unsigned numShadowMaps = 0;
  442. unsigned lastView = allViews ? mNumViews : 1;
  443. for (unsigned i = 0; i < lastView; ++i)
  444. {
  445. const std::vector<LightBatchQueue>& lightQueues = mViews[i]->getLightQueues();
  446. for (unsigned j = 0; j < lightQueues.size(); ++j)
  447. {
  448. Light* light = lightQueues[j].mLight;
  449. if ((light) && (light->getShadowMap()))
  450. ++numShadowMaps;
  451. }
  452. }
  453. return numShadowMaps;
  454. }
  455. unsigned Pipeline::getNumOccluders(bool allViews) const
  456. {
  457. unsigned numOccluders = 0;
  458. unsigned lastView = allViews ? mNumViews : 1;
  459. for (unsigned i = 0; i < lastView; ++i)
  460. numOccluders += mViews[i]->getOccluders().size();
  461. return numOccluders;
  462. }
  463. unsigned Pipeline::getNumShadowOccluders(bool allViews) const
  464. {
  465. unsigned numShadowOccluders = 0;
  466. unsigned lastView = allViews ? mNumViews : 1;
  467. for (unsigned i = 0; i < lastView; ++i)
  468. numShadowOccluders += mViews[i]->getShadowOccluders().size();
  469. return numShadowOccluders;
  470. }
  471. const OcclusionBuffer* Pipeline::getOcclusionBuffer(float aspectRatio, bool halfResolution)
  472. {
  473. // Return an occlusion buffer for debug output purposes. Do not allocate new
  474. int width = mOcclusionBufferSize;
  475. int height = (int)(mOcclusionBufferSize / aspectRatio);
  476. if (halfResolution)
  477. {
  478. width >>= 1;
  479. height >>= 1;
  480. }
  481. int searchKey = (width << 12) | height;
  482. std::map<int, SharedPtr<OcclusionBuffer> >::iterator i = mOcclusionBuffers.find(searchKey);
  483. if (i != mOcclusionBuffers.end())
  484. return i->second;
  485. else
  486. return 0;
  487. }
  488. bool Pipeline::update(float timeStep)
  489. {
  490. PROFILE(Pipeline_Update);
  491. // If device lost, do not perform update. This is because any dynamic vertex/index buffer updates happen already here,
  492. // and if the device is lost, the updates queue up, causing memory use to rise constantly
  493. if (mRenderer->isDeviceLost())
  494. {
  495. mNumViews = 0;
  496. return false;
  497. }
  498. // Advance frame number & time, set up the frameinfo structure, and reset views & stats
  499. beginFrame(timeStep);
  500. // Reload shaders if needed
  501. if (mShadersDirty)
  502. loadShaders();
  503. // Process all viewports. Use reverse order, because during rendering the order will be reversed again to handle auxiliary
  504. // view dependencies correctly
  505. for (unsigned i = mViewports.size() - 1; i < mViewports.size(); --i)
  506. {
  507. unsigned mainView = mNumViews;
  508. Viewport& viewport = mViewports[i];
  509. if (!addView(0, viewport))
  510. continue;
  511. // Update octree (perform early update for nodes which need that, and reinsert moved nodes.)
  512. // However, if the same scene is viewed from multiple cameras, update the octree only once
  513. Octree* octree = viewport.mScene->getExtension<Octree>();
  514. if (mUpdatedOctrees.find(octree) == mUpdatedOctrees.end())
  515. {
  516. octree->updateOctree(mFrame);
  517. mUpdatedOctrees.insert(octree);
  518. }
  519. // Update the viewport's main view and any auxiliary views it creates
  520. for (unsigned i = mainView; i < mNumViews; ++i)
  521. mViews[i]->update(mFrame);
  522. }
  523. return true;
  524. }
  525. bool Pipeline::render()
  526. {
  527. PROFILE(Pipeline_Render);
  528. mRenderer->setDefaultTextureFilterMode(mTextureFilterMode);
  529. mRenderer->setTextureAnisotropy(mTextureAnisotropy);
  530. // If no views, just clear the screen
  531. if (!mNumViews)
  532. {
  533. mRenderer->setAlphaTest(false);
  534. mRenderer->setBlendMode(BLEND_REPLACE);
  535. mRenderer->setColorWrite(true);
  536. mRenderer->setDepthWrite(true);
  537. mRenderer->setFillMode(FILL_SOLID);
  538. mRenderer->setScissorTest(false);
  539. mRenderer->setStencilTest(false);
  540. mRenderer->clear(CLEAR_COLOR | CLEAR_DEPTH | CLEAR_STENCIL);
  541. return false;
  542. }
  543. // Render views from last to first (each main view is rendered after the auxiliary views it depends on)
  544. for (unsigned i = mNumViews - 1; i < mNumViews; --i)
  545. mViews[i]->render();
  546. // Disable scissor/stencil tests if left on by lights, and reset stream frequencies
  547. mRenderer->setScissorTest(false);
  548. mRenderer->setStencilTest(false);
  549. mRenderer->resetStreamFrequencies();
  550. return true;
  551. }
  552. void Pipeline::drawDebugGeometry()
  553. {
  554. PROFILE(Pipeline_DrawDebugGeometry);
  555. //! \todo Because debug geometry is per-scene, if two cameras show views of the same area, occlusion is not shown correctly
  556. static std::set<GeometryNode*> processedGeometries;
  557. static std::set<Light*> processedLights;
  558. processedGeometries.clear();
  559. processedLights.clear();
  560. for (unsigned i = 0; i < mNumViews; ++i)
  561. {
  562. // Make sure it's a main view, and process each node only once
  563. View* view = mViews[i];
  564. if (view->getRenderTarget())
  565. continue;
  566. Octree* octree = view->getOctree();
  567. if (!octree)
  568. continue;
  569. Scene* scene = octree->getScene();
  570. if (!scene)
  571. continue;
  572. DebugRenderer* debug = scene->getExtension<DebugRenderer>();
  573. if (!debug)
  574. continue;
  575. const std::vector<GeometryNode*>& geometries = view->getGeometries();
  576. const std::vector<Light*>& lights = view->getLights();
  577. for (unsigned i = 0; i < geometries.size(); ++i)
  578. {
  579. if (processedGeometries.find(geometries[i]) == processedGeometries.end())
  580. {
  581. geometries[i]->drawDebugGeometry(debug);
  582. processedGeometries.insert(geometries[i]);
  583. }
  584. }
  585. for (unsigned i = 0; i < lights.size(); ++i)
  586. {
  587. if (processedLights.find(lights[i]) == processedLights.end())
  588. {
  589. lights[i]->drawDebugGeometry(debug);
  590. processedLights.insert(lights[i]);
  591. }
  592. }
  593. }
  594. }
  595. void Pipeline::beginFrame(float timeStep)
  596. {
  597. mElapsedTime += timeStep;
  598. if (mElapsedTime >= MAX_ELAPSED_TIME)
  599. mElapsedTime -= MAX_ELAPSED_TIME;
  600. ++mFrameNumber;
  601. mFrameNumber &= M_MAX_INT;
  602. mFrame.mFrameNumber = mFrameNumber;
  603. mFrame.mTimeStep = timeStep;
  604. mFrame.mCamera = 0;
  605. mNumViews = 0;
  606. mNumSplitLights = 0;
  607. mUpdatedOctrees.clear();
  608. }
  609. void Pipeline::resetViews()
  610. {
  611. mViews.clear();
  612. mNumViews = 0;
  613. }
  614. bool Pipeline::addView(RenderSurface* renderTarget, const Viewport& viewport)
  615. {
  616. // If using a render target texture, make sure it will not be rendered to multiple times
  617. if (renderTarget)
  618. {
  619. for (unsigned i = 0; i < mNumViews; ++i)
  620. {
  621. if (mViews[i]->getRenderTarget() == renderTarget)
  622. return false;
  623. }
  624. }
  625. if (mViews.size() <= mNumViews)
  626. mViews.resize(mNumViews + 1);
  627. if (!mViews[mNumViews])
  628. mViews[mNumViews] = new View(this);
  629. if (mViews[mNumViews]->define(renderTarget, viewport))
  630. {
  631. ++mNumViews;
  632. return true;
  633. }
  634. else
  635. return false;
  636. }
  637. OcclusionBuffer* Pipeline::getOrCreateOcclusionBuffer(Camera& camera, int maxOccluderTriangles, bool halfResolution)
  638. {
  639. // Get an occlusion buffer matching the aspect ratio. If not found, allocate new
  640. int width = mOcclusionBufferSize;
  641. int height = (int)(mOcclusionBufferSize / camera.getAspectRatio());
  642. if (halfResolution)
  643. {
  644. width >>= 1;
  645. height >>= 1;
  646. }
  647. int searchKey = (width << 12) | height;
  648. SharedPtr<OcclusionBuffer> buffer;
  649. std::map<int, SharedPtr<OcclusionBuffer> >::iterator i = mOcclusionBuffers.find(searchKey);
  650. if (i != mOcclusionBuffers.end())
  651. buffer = i->second;
  652. else
  653. {
  654. buffer = new OcclusionBuffer();
  655. buffer->setSize(width, height);
  656. mOcclusionBuffers[searchKey] = buffer;
  657. }
  658. buffer->setView(camera);
  659. buffer->setMaxTriangles(maxOccluderTriangles);
  660. buffer->clear();
  661. return buffer;
  662. }
  663. Geometry* Pipeline::getLightGeometry(Light* light)
  664. {
  665. switch (light->getLightType())
  666. {
  667. case LIGHT_POINT:
  668. return mPointLightGeometry;
  669. case LIGHT_SPOT:
  670. case LIGHT_SPLITPOINT:
  671. return mSpotLightGeometry;
  672. default:
  673. return mDirLightGeometry;
  674. }
  675. }
  676. Texture2D* Pipeline::getShadowMap(float resolution)
  677. {
  678. if (resolution >= 0.75f)
  679. return mFullShadowMap;
  680. else if (resolution >= 0.375f)
  681. return mHalfShadowMap;
  682. else
  683. return mQuarterShadowMap;
  684. }
  685. void Pipeline::setBatchShaders(Batch& batch, MaterialTechnique* technique, MaterialPass* pass, bool allowShadows)
  686. {
  687. static std::set<Material*> errorDisplayed;
  688. batch.mTechnique = technique;
  689. batch.mPass = pass;
  690. // Check if shaders are unloaded or need reloading
  691. std::vector<SharedPtr<VertexShader> >& vertexShaders = pass->getVertexShaders();
  692. std::vector<SharedPtr<PixelShader> >& pixelShaders = pass->getPixelShaders();
  693. if ((!vertexShaders.size()) || (!pixelShaders.size()) || (technique->getShadersLoadedFrameNumber() !=
  694. mShadersChangedFrameNumber))
  695. {
  696. // First release all previous shaders, then load
  697. technique->releaseShaders();
  698. loadMaterialShaders(technique);
  699. }
  700. // Make sure shaders are loaded now
  701. if ((vertexShaders.size()) && (pixelShaders.size()))
  702. {
  703. // Recognize light pass from the amount of shaders
  704. if (pixelShaders.size() == 1)
  705. {
  706. unsigned vsi = 0;
  707. if (batch.mNode->getNodeFlags() & NODE_GEOMETRY)
  708. vsi = static_cast<GeometryNode*>(batch.mNode)->getGeometryType();
  709. batch.mVertexShader = vertexShaders[vsi];
  710. batch.mPixelShader = pixelShaders[0];
  711. }
  712. else
  713. {
  714. Light* light = batch.mForwardLight;
  715. if (!light)
  716. {
  717. // Do not log error, as it would result in a lot of spam
  718. batch.mVertexShader = 0;
  719. batch.mPixelShader = 0;
  720. return;
  721. }
  722. unsigned vsi = 0;
  723. unsigned psi = 0;
  724. if (batch.mNode->getNodeFlags() & NODE_GEOMETRY)
  725. vsi = static_cast<GeometryNode*>(batch.mNode)->getGeometryType() * MAX_LIGHT_VS_VARIATIONS;
  726. // Negative lights have no specular or shadows
  727. if (!light->isNegative())
  728. {
  729. if ((mSpecularLighting) && (light->getSpecularIntensity() > 0.0f))
  730. psi += LPS_SPEC;
  731. if ((allowShadows) && (light->getShadowMap()))
  732. {
  733. vsi += LVS_SHADOW;
  734. psi += LPS_SHADOW;
  735. }
  736. }
  737. else
  738. psi += LPS_NEGATIVE;
  739. switch (light->getLightType())
  740. {
  741. case LIGHT_POINT:
  742. case LIGHT_SPLITPOINT:
  743. psi += LPS_POINT;
  744. break;
  745. case LIGHT_SPOT:
  746. psi += LPS_SPOT;
  747. vsi += LVS_SPOT;
  748. break;
  749. }
  750. batch.mVertexShader = vertexShaders[vsi];
  751. batch.mPixelShader = pixelShaders[psi];
  752. }
  753. }
  754. // Log error if shaders could not be assigned, but only once per material
  755. if ((!batch.mVertexShader) || (!batch.mPixelShader))
  756. {
  757. Material* parentMat = technique->getParent();
  758. if (errorDisplayed.find(parentMat) == errorDisplayed.end())
  759. {
  760. errorDisplayed.insert(parentMat);
  761. LOGERROR("Material " + parentMat->getName() + " has missing shaders");
  762. }
  763. }
  764. }
  765. void Pipeline::setLightVolumeShaders(Batch& batch)
  766. {
  767. unsigned vsi = DLVS_NONE;
  768. unsigned psi = DLPS_NONE;
  769. Light* light = static_cast<Light*>(batch.mNode);
  770. switch(light->getLightType())
  771. {
  772. case LIGHT_DIRECTIONAL:
  773. vsi += DLVS_DIR;
  774. break;
  775. case LIGHT_POINT:
  776. case LIGHT_SPLITPOINT:
  777. psi += DLPS_POINT;
  778. break;
  779. case LIGHT_SPOT:
  780. psi += DLPS_SPOT;
  781. break;
  782. }
  783. if (!light->isNegative())
  784. {
  785. if (light->getShadowMap())
  786. psi += DLPS_SHADOW;
  787. if ((mSpecularLighting) && (light->getSpecularIntensity() > 0.0))
  788. psi += DLPS_SPEC;
  789. }
  790. else
  791. psi += DLPS_NEGATIVE;
  792. // Non-hardware depth & orthographic modes use linear depth, else reconstruct from z/w
  793. if (batch.mCamera->isOrthographic())
  794. {
  795. vsi += DLVS_ORTHO;
  796. psi += DLPS_ORTHO;
  797. }
  798. else if (!mRenderer->getHardwareDepthSupport())
  799. psi += DLPS_LINEAR;
  800. unsigned hwShadows = mRenderer->getHardwareShadowSupport() ? 1 : 0;
  801. if (!mLightVS[vsi])
  802. mLightVS[vsi] = getVertexShader(mLightShaderName + deferredLightVSVariations[vsi]);
  803. if (!mLightPS[psi])
  804. {
  805. unsigned variation = psi % 5;
  806. if ((variation == LPS_SHADOW) || (variation == LPS_SHADOWSPEC))
  807. mLightPS[psi] = getPixelShader(mLightShaderName + deferredLightPSVariations[psi] + shadowPSVariations[hwShadows]);
  808. else
  809. mLightPS[psi] = getPixelShader(mLightShaderName + deferredLightPSVariations[psi]);
  810. }
  811. batch.mVertexShader = mLightVS[vsi];
  812. batch.mPixelShader = mLightPS[psi];
  813. }
  814. void Pipeline::loadShaders()
  815. {
  816. PROFILE(Pipeline_LoadShaders);
  817. LOGINFO("Reloading shaders");
  818. // Release old material shaders, mark them for reload
  819. releaseMaterialShaders();
  820. mShadersChangedFrameNumber = mFrameNumber;
  821. // Load inbuilt shaders
  822. mStencilVS = getVertexShader("Stencil");
  823. mStencilPS = getPixelShader("Stencil");
  824. mLightVS.clear();
  825. mLightPS.clear();
  826. RenderMode renderMode = mRenderer->getRenderMode();
  827. if (renderMode != RENDER_FORWARD)
  828. {
  829. // There are rather many light volume shader variations, so load them later on-demand
  830. mLightVS.resize(MAX_DEFERRED_LIGHT_VS_VARIATIONS);
  831. mLightPS.resize(MAX_DEFERRED_LIGHT_PS_VARIATIONS);
  832. if (renderMode == RENDER_DEFERRED)
  833. mLightShaderName = "Deferred/Light_";
  834. else
  835. mLightShaderName = "Prepass/Light_";
  836. }
  837. // Remove shaders that are no longer referenced from the cache
  838. mCache->releaseResources(VertexShader::getTypeStatic());
  839. mCache->releaseResources(PixelShader::getTypeStatic());
  840. mShadersDirty = false;
  841. }
  842. void Pipeline::loadMaterialShaders(MaterialTechnique* technique)
  843. {
  844. loadMaterialPassShaders(technique, PASS_SHADOW);
  845. loadMaterialPassShaders(technique, PASS_POSTOPAQUE);
  846. if (mRenderer->getRenderMode() == RENDER_FORWARD)
  847. {
  848. loadMaterialPassShaders(technique, PASS_AMBIENT);
  849. loadMaterialPassShaders(technique, PASS_LIGHT);
  850. loadMaterialPassShaders(technique, PASS_NEGATIVE, false);
  851. }
  852. else
  853. {
  854. // G-Buffer pass types depend on whether deferred shading or light prepass is in use
  855. PassType gBufferPass, additionalPass;
  856. if (mRenderer->getRenderMode() == RENDER_DEFERRED)
  857. {
  858. gBufferPass = PASS_DEFERRED;
  859. additionalPass = PASS_EMISSIVE;
  860. }
  861. else
  862. {
  863. gBufferPass = PASS_PREPASS;
  864. additionalPass = PASS_MATERIAL;
  865. }
  866. if (technique->hasPass(gBufferPass))
  867. {
  868. loadMaterialPassShaders(technique, gBufferPass);
  869. loadMaterialPassShaders(technique, additionalPass);
  870. }
  871. else
  872. {
  873. loadMaterialPassShaders(technique, PASS_AMBIENT);
  874. // No shadows used in forward lighting, so do not load the shadowing shaders
  875. loadMaterialPassShaders(technique, PASS_LIGHT, false);
  876. loadMaterialPassShaders(technique, PASS_NEGATIVE, false);
  877. }
  878. }
  879. }
  880. void Pipeline::loadMaterialPassShaders(MaterialTechnique* technique, PassType pass, bool allowShadows)
  881. {
  882. std::map<PassType, MaterialPass>::iterator i = technique->mPasses.find(pass);
  883. if (i == technique->mPasses.end())
  884. return;
  885. std::string vertexShaderName = i->second.getVertexShaderName();
  886. std::string pixelShaderName = i->second.getPixelShaderName();
  887. // Check if the shader name is already a variation in itself
  888. if (vertexShaderName.find('_') == std::string::npos)
  889. vertexShaderName += "_";
  890. if (pixelShaderName.find('_') == std::string::npos)
  891. pixelShaderName += "_";
  892. // If INTZ depth is used, do not write depth into the third RT in GBuffer pass
  893. if ((pass == PASS_DEFERRED) || (pass == PASS_PREPASS))
  894. {
  895. unsigned hwDepth = mRenderer->getHardwareDepthSupport() ? 1 : 0;
  896. pixelShaderName += gBufferPSVariations[hwDepth];
  897. }
  898. // If ambient pass is not using REPLACE as the blend mode, do not load shadow shaders for the light pass
  899. if (pass == PASS_LIGHT)
  900. {
  901. if ((!technique->hasPass(PASS_AMBIENT)) || (technique->getPass(PASS_AMBIENT)->getBlendMode() != BLEND_REPLACE))
  902. allowShadows = false;
  903. }
  904. if (pass == PASS_NEGATIVE)
  905. allowShadows = false;
  906. unsigned hwShadows = mRenderer->getHardwareShadowSupport() ? 1 : 0;
  907. std::vector<SharedPtr<VertexShader> >& vertexShaders = i->second.getVertexShaders();
  908. std::vector<SharedPtr<PixelShader> >& pixelShaders = i->second.getPixelShaders();
  909. // Forget all the old shaders
  910. vertexShaders.clear();
  911. pixelShaders.clear();
  912. switch (i->first)
  913. {
  914. default:
  915. vertexShaders.resize(MAX_GEOMETRYTYPES);
  916. pixelShaders.resize(1);
  917. for (unsigned j = 0; j < MAX_GEOMETRYTYPES; ++j)
  918. vertexShaders[j] = getVertexShader(vertexShaderName + geometryVSVariations[j], j != 0);
  919. pixelShaders[0] = getPixelShader(pixelShaderName);
  920. break;
  921. case PASS_LIGHT:
  922. case PASS_NEGATIVE:
  923. vertexShaders.resize(MAX_GEOMETRYTYPES * MAX_LIGHT_VS_VARIATIONS);
  924. pixelShaders.resize(MAX_LIGHT_PS_VARIATIONS);
  925. for (unsigned j = 0; j < MAX_GEOMETRYTYPES * MAX_LIGHT_VS_VARIATIONS; ++j)
  926. {
  927. unsigned g = j / MAX_LIGHT_VS_VARIATIONS;
  928. unsigned l = j % MAX_LIGHT_VS_VARIATIONS;
  929. if ((!(l & LVS_SHADOW)) || (allowShadows))
  930. vertexShaders[j] = getVertexShader(vertexShaderName + lightVSVariations[l] + geometryVSVariations[g], g != 0);
  931. else
  932. vertexShaders[j].reset();
  933. }
  934. for (unsigned j = 0; j < MAX_LIGHT_PS_VARIATIONS; ++j)
  935. {
  936. unsigned variation = j % 5;
  937. if ((variation == LPS_SHADOW) || (variation == LPS_SHADOWSPEC))
  938. {
  939. if (allowShadows)
  940. pixelShaders[j] = getPixelShader(pixelShaderName + deferredLightPSVariations[j] +
  941. shadowPSVariations[hwShadows]);
  942. else
  943. pixelShaders[j].reset();
  944. }
  945. else
  946. {
  947. // For the negative pass, load only the negative version of the shader
  948. bool needed = (pass == PASS_LIGHT) ? (variation != LPS_NEGATIVE) : (variation == LPS_NEGATIVE);
  949. if (needed)
  950. pixelShaders[j] = getPixelShader(pixelShaderName + deferredLightPSVariations[j]);
  951. else
  952. pixelShaders[j].reset();
  953. }
  954. }
  955. break;
  956. }
  957. technique->markShadersLoaded(mShadersChangedFrameNumber);
  958. }
  959. void Pipeline::releaseMaterialShaders()
  960. {
  961. std::vector<Material*> materials;
  962. mCache->getResources<Material>(materials);
  963. for (unsigned i = 0; i < materials.size(); ++i)
  964. {
  965. for (unsigned j = 0; j < materials[i]->getNumTechniques(); ++j)
  966. materials[i]->releaseShaders();
  967. }
  968. }
  969. void Pipeline::reloadTextures()
  970. {
  971. std::vector<Resource*> textures;
  972. mCache->getResources(textures, Texture2D::getTypeStatic());
  973. for (unsigned i = 0; i < textures.size(); ++i)
  974. mCache->reloadResource(textures[i]);
  975. mCache->getResources(textures, TextureCube::getTypeStatic());
  976. for (unsigned i = 0; i < textures.size(); ++i)
  977. mCache->reloadResource(textures[i]);
  978. }
  979. void Pipeline::createGeometries()
  980. {
  981. PROFILE(Pipeline_CreateGeometries);
  982. SharedPtr<VertexBuffer> dlvb(new VertexBuffer(mRenderer));
  983. dlvb->setSize(4, MASK_POSITION);
  984. dlvb->setData(dirLightVertexData);
  985. SharedPtr<IndexBuffer> dlib(new IndexBuffer(mRenderer));
  986. dlib->setSize(6, false);
  987. dlib->setData(dirLightIndexData);
  988. mDirLightGeometry = new Geometry();
  989. mDirLightGeometry->setVertexBuffer(0, dlvb);
  990. mDirLightGeometry->setIndexBuffer(dlib);
  991. mDirLightGeometry->setDrawRange(TRIANGLE_LIST, 0, dlib->getIndexCount());
  992. SharedPtr<VertexBuffer> plvb(new VertexBuffer(mRenderer));
  993. plvb->setSize(24, MASK_POSITION);
  994. plvb->setData(pointLightVertexData);
  995. SharedPtr<IndexBuffer> plib(new IndexBuffer(mRenderer));
  996. plib->setSize(132, false);
  997. plib->setData(pointLightIndexData);
  998. mPointLightGeometry = new Geometry();
  999. mPointLightGeometry->setVertexBuffer(0, plvb);
  1000. mPointLightGeometry->setIndexBuffer(plib);
  1001. mPointLightGeometry->setDrawRange(TRIANGLE_LIST, 0, plib->getIndexCount());
  1002. SharedPtr<VertexBuffer> slvb(new VertexBuffer(mRenderer));
  1003. slvb->setSize(8, MASK_POSITION);
  1004. slvb->setData(spotLightVertexData);
  1005. SharedPtr<IndexBuffer> slib(new IndexBuffer(mRenderer));
  1006. slib->setSize(36, false);
  1007. slib->setData(spotLightIndexData);
  1008. mSpotLightGeometry = new Geometry();
  1009. mSpotLightGeometry->setVertexBuffer(0, slvb);
  1010. mSpotLightGeometry->setIndexBuffer(slib);
  1011. mSpotLightGeometry->setDrawRange(TRIANGLE_LIST, 0, slib->getIndexCount());
  1012. }
  1013. bool Pipeline::createShadowMaps()
  1014. {
  1015. PROFILE(Pipeline_CreateShadowMaps);
  1016. unsigned shadowMapFormat = mShadowMapHiresDepth ? mRenderer->getHiresShadowMapFormat() : mRenderer->getShadowMapFormat();
  1017. unsigned dummyColorFormat = mRenderer->getDummyColorFormat();
  1018. bool hardwarePCF = mRenderer->getHardwareShadowSupport();
  1019. if (shadowMapFormat == D3DFMT_UNKNOWN)
  1020. return false;
  1021. if (!mDrawShadows)
  1022. {
  1023. mFullShadowMap.reset();
  1024. mHalfShadowMap.reset();
  1025. mQuarterShadowMap.reset();
  1026. mFullShadowMapColor.reset();
  1027. mHalfShadowMapColor.reset();
  1028. mQuarterShadowMapColor.reset();
  1029. return true;
  1030. }
  1031. try
  1032. {
  1033. // Create shadow maps and dummy color rendertargets
  1034. if (!mFullShadowMap)
  1035. mFullShadowMap = new Texture2D(mRenderer, TEXTURE_DEPTHSTENCIL);
  1036. mFullShadowMap->setSize(mShadowMapSize, mShadowMapSize, shadowMapFormat);
  1037. mFullShadowMap->setFilterMode(hardwarePCF ? FILTER_BILINEAR : FILTER_NEAREST);
  1038. if (!mHalfShadowMap)
  1039. mHalfShadowMap = new Texture2D(mRenderer, TEXTURE_DEPTHSTENCIL);
  1040. mHalfShadowMap->setSize(mShadowMapSize >> 1, mShadowMapSize >> 1, shadowMapFormat);
  1041. mHalfShadowMap->setFilterMode(hardwarePCF ? FILTER_BILINEAR : FILTER_NEAREST);
  1042. if (!mQuarterShadowMap)
  1043. mQuarterShadowMap = new Texture2D(mRenderer, TEXTURE_DEPTHSTENCIL);
  1044. mQuarterShadowMap->setSize(mShadowMapSize >> 2, mShadowMapSize >> 2, shadowMapFormat);
  1045. mQuarterShadowMap->setFilterMode(hardwarePCF ? FILTER_BILINEAR : FILTER_NEAREST);
  1046. if (!mFullShadowMapColor)
  1047. mFullShadowMapColor = new Texture2D(mRenderer, TEXTURE_RENDERTARGET);
  1048. mFullShadowMapColor->setSize(mShadowMapSize, mShadowMapSize, dummyColorFormat);
  1049. if (!mHalfShadowMapColor)
  1050. mHalfShadowMapColor = new Texture2D(mRenderer, TEXTURE_RENDERTARGET);
  1051. mHalfShadowMapColor->setSize(mShadowMapSize >> 1, mShadowMapSize >> 1, dummyColorFormat);
  1052. if (!mQuarterShadowMapColor)
  1053. mQuarterShadowMapColor = new Texture2D(mRenderer, TEXTURE_RENDERTARGET);
  1054. mQuarterShadowMapColor->setSize(mShadowMapSize >> 2, mShadowMapSize >> 2, dummyColorFormat);
  1055. // Link the color rendertargets to depth rendertargets
  1056. mFullShadowMap->getRenderSurface()->setLinkedRenderTarget(mFullShadowMapColor->getRenderSurface());
  1057. mHalfShadowMap->getRenderSurface()->setLinkedRenderTarget(mHalfShadowMapColor->getRenderSurface());
  1058. mQuarterShadowMap->getRenderSurface()->setLinkedRenderTarget(mQuarterShadowMapColor->getRenderSurface());
  1059. }
  1060. catch (...)
  1061. {
  1062. return false;
  1063. }
  1064. return true;
  1065. }
  1066. Light* Pipeline::createSplitLight(Light* original)
  1067. {
  1068. if (mNumSplitLights >= mSplitLightStore.size())
  1069. mSplitLightStore.push_back(SharedPtr<Light>(new Light()));
  1070. Light* light = mSplitLightStore[mNumSplitLights];
  1071. light->copyFrom(original);
  1072. mNumSplitLights++;
  1073. return light;
  1074. }
  1075. void Pipeline::setupLightBatch(Batch& batch)
  1076. {
  1077. Light* light = static_cast<Light*>(batch.mNode);
  1078. const Matrix4x3* model = &light->getWorldTransform();
  1079. const Matrix4x3* view = &batch.mCamera->getInverseWorldTransform();
  1080. const Matrix4* projection = &batch.mCamera->getProjection();
  1081. light->overrideTransforms(0, *batch.mCamera, &model, &view);
  1082. float lightExtent = light->getVolumeExtent();
  1083. float lightViewDist = (light->getWorldPosition() - batch.mCamera->getWorldPosition()).getLengthFast();
  1084. mRenderer->setAlphaTest(false);
  1085. mRenderer->setBlendMode(light->isNegative() ? BLEND_MULTIPLY : BLEND_ADD);
  1086. mRenderer->setDepthWrite(false);
  1087. if (light->getLightType() == LIGHT_DIRECTIONAL)
  1088. {
  1089. // If the light does not extend to the near plane, use a stencil test. Else just draw with depth fail
  1090. if (light->getNearSplit() <= batch.mCamera->getNearClip())
  1091. {
  1092. mRenderer->setCullMode(CULL_NONE);
  1093. mRenderer->setDepthTest(CMP_GREATER);
  1094. mRenderer->setStencilTest(false);
  1095. }
  1096. else
  1097. {
  1098. Matrix4x3 nearTransform = light->getDirLightTransform(*batch.mCamera, true);
  1099. // Set state for stencil rendering
  1100. mRenderer->setColorWrite(false);
  1101. mRenderer->setCullMode(CULL_NONE);
  1102. mRenderer->setDepthTest(CMP_LESSEQUAL);
  1103. mRenderer->setStencilTest(true, CMP_ALWAYS, OP_INCR, OP_KEEP, OP_KEEP, 1);
  1104. mRenderer->setVertexShader(mStencilVS);
  1105. mRenderer->setPixelShader(mStencilPS);
  1106. mRenderer->setVertexShaderConstant(getVSRegister(VSP_MODELVIEWPROJ), (*projection) * nearTransform);
  1107. // Draw to stencil
  1108. batch.mGeometry->draw(mRenderer);
  1109. // Re-enable color write, set test for rendering the actual light
  1110. mRenderer->setColorWrite(true);
  1111. mRenderer->setDepthTest(CMP_GREATER);
  1112. mRenderer->setStencilTest(true, CMP_EQUAL, OP_ZERO, OP_KEEP, OP_ZERO, 1);
  1113. }
  1114. }
  1115. else
  1116. {
  1117. if (light->getLightType() == LIGHT_SPLITPOINT)
  1118. {
  1119. // Shadowed point light, split in 6 frustums: mask out overlapping pixels to prevent overlighting
  1120. // Check whether we should draw front or back faces
  1121. bool drawBackFaces = lightViewDist < (lightExtent + batch.mCamera->getNearClip());
  1122. mRenderer->setColorWrite(false);
  1123. mRenderer->setCullMode(drawBackFaces ? CULL_CCW : CULL_CW);
  1124. mRenderer->setDepthTest(drawBackFaces ? CMP_GREATER : CMP_LESS);
  1125. mRenderer->setStencilTest(true, CMP_EQUAL, OP_INCR, OP_KEEP, OP_KEEP, 0);
  1126. mRenderer->setVertexShader(mStencilVS);
  1127. mRenderer->setPixelShader(mStencilPS);
  1128. mRenderer->setVertexShaderConstant(getVSRegister(VSP_MODELVIEWPROJ), (*projection) * (*view) * (*model));
  1129. // Draw the other faces to stencil to mark where we should not draw
  1130. batch.mGeometry->draw(mRenderer);
  1131. mRenderer->setColorWrite(true);
  1132. mRenderer->setCullMode(drawBackFaces ? CULL_CW : CULL_CCW);
  1133. mRenderer->setStencilTest(true, CMP_EQUAL, OP_DECR, OP_DECR, OP_KEEP, 0);
  1134. }
  1135. else
  1136. {
  1137. // If light is close to near clip plane, we might be inside light volume
  1138. if (lightViewDist < (lightExtent + batch.mCamera->getNearClip()))
  1139. {
  1140. // In this case reverse cull mode & depth test and render back faces
  1141. mRenderer->setCullMode(CULL_CW);
  1142. mRenderer->setDepthTest(CMP_GREATER);
  1143. mRenderer->setStencilTest(false);
  1144. }
  1145. else
  1146. {
  1147. // If not too close to far clip plane, write the back faces to stencil for optimization,
  1148. // then render front faces. Else just render front faces.
  1149. if (lightViewDist < (batch.mCamera->getFarClip() - lightExtent))
  1150. {
  1151. // Set state for stencil rendering
  1152. mRenderer->setColorWrite(false);
  1153. mRenderer->setCullMode(CULL_CW);
  1154. mRenderer->setDepthTest(CMP_GREATEREQUAL);
  1155. mRenderer->setStencilTest(true, CMP_ALWAYS, OP_INCR, OP_KEEP, OP_KEEP, 1);
  1156. mRenderer->setVertexShader(mStencilVS);
  1157. mRenderer->setPixelShader(mStencilPS);
  1158. mRenderer->setVertexShaderConstant(getVSRegister(VSP_MODELVIEWPROJ), (*projection) * (*view) * (*model));
  1159. // Draw to stencil
  1160. batch.mGeometry->draw(mRenderer);
  1161. // Re-enable color write, set test for rendering the actual light
  1162. mRenderer->setColorWrite(true);
  1163. mRenderer->setStencilTest(true, CMP_EQUAL, OP_ZERO, OP_KEEP, OP_ZERO, 1);
  1164. mRenderer->setCullMode(CULL_CCW);
  1165. mRenderer->setDepthTest(CMP_LESS);
  1166. }
  1167. else
  1168. {
  1169. mRenderer->setStencilTest(false);
  1170. mRenderer->setCullMode(CULL_CCW);
  1171. mRenderer->setDepthTest(CMP_LESS);
  1172. }
  1173. }
  1174. }
  1175. }
  1176. }
  1177. void Pipeline::drawFullScreenQuad(Camera& camera, VertexShader* vs, PixelShader* ps, bool nearQuad)
  1178. {
  1179. Light quadDirLight;
  1180. Matrix4x3 model = quadDirLight.getDirLightTransform(camera, nearQuad);
  1181. mRenderer->setCullMode(CULL_NONE);
  1182. mRenderer->setVertexShader(vs);
  1183. mRenderer->setPixelShader(ps);
  1184. mRenderer->setVertexShaderConstant(getVSRegister(VSP_MODELVIEWPROJ), camera.getProjection() * model);
  1185. mDirLightGeometry->draw(mRenderer);
  1186. }
  1187. void Pipeline::drawSplitLightToStencil(Camera& camera, Light* light, bool clear)
  1188. {
  1189. switch (light->getLightType())
  1190. {
  1191. case LIGHT_SPLITPOINT:
  1192. {
  1193. const Matrix4x3* model = &light->getWorldTransform();
  1194. const Matrix4x3* view = &camera.getInverseWorldTransform();
  1195. const Matrix4* projection = &camera.getProjection();
  1196. light->overrideTransforms(0, camera, &model, &view);
  1197. float lightExtent = light->getVolumeExtent();
  1198. float lightViewDist = (light->getWorldPosition() - camera.getWorldPosition()).getLengthFast();
  1199. bool drawBackFaces = lightViewDist < (lightExtent + camera.getNearClip());
  1200. mRenderer->setAlphaTest(false);
  1201. mRenderer->setColorWrite(false);
  1202. mRenderer->setDepthWrite(false);
  1203. mRenderer->setCullMode(drawBackFaces ? CULL_CW : CULL_CCW);
  1204. mRenderer->setDepthTest(drawBackFaces ? CMP_GREATER : CMP_LESS);
  1205. mRenderer->setVertexShader(mStencilVS);
  1206. mRenderer->setPixelShader(mStencilPS);
  1207. mRenderer->setVertexShaderConstant(getVSRegister(VSP_MODELVIEWPROJ), (*projection) * (*view) * (*model));
  1208. if (!clear)
  1209. {
  1210. // Draw the faces to stencil which we should draw (where no light has not been rendered yet)
  1211. mRenderer->setStencilTest(true, CMP_EQUAL, OP_INCR, OP_KEEP, OP_KEEP, 0);
  1212. mSpotLightGeometry->draw(mRenderer);
  1213. // Draw the other faces to stencil to mark where we should not draw ("frees up" the pixels for other faces)
  1214. mRenderer->setCullMode(drawBackFaces ? CULL_CCW : CULL_CW);
  1215. mRenderer->setStencilTest(true, CMP_EQUAL, OP_DECR, OP_KEEP, OP_KEEP, 1);
  1216. mSpotLightGeometry->draw(mRenderer);
  1217. // Now set stencil test for rendering the lit geometries (also marks the pixels so that they will not be used again)
  1218. mRenderer->setStencilTest(true, CMP_EQUAL, OP_INCR, OP_KEEP, OP_KEEP, 1);
  1219. mRenderer->setColorWrite(true);
  1220. }
  1221. else
  1222. {
  1223. // Clear the stencil by drawing the whole point light volume
  1224. mRenderer->setStencilTest(true, CMP_ALWAYS, OP_ZERO, OP_KEEP, OP_ZERO, 0);
  1225. mPointLightGeometry->draw(mRenderer);
  1226. mRenderer->setColorWrite(true);
  1227. mRenderer->setStencilTest(false);
  1228. }
  1229. }
  1230. break;
  1231. case LIGHT_DIRECTIONAL:
  1232. // If light encompasses whole frustum, no drawing to frustum necessary
  1233. if ((light->getNearSplit() <= camera.getNearClip()) && (light->getFarSplit() >= camera.getFarClip()))
  1234. return;
  1235. else
  1236. {
  1237. const Matrix4& projection = camera.getProjection();
  1238. Matrix4x3 nearTransform = light->getDirLightTransform(camera, true);
  1239. Matrix4x3 farTransform = light->getDirLightTransform(camera, false);
  1240. mRenderer->setAlphaTest(false);
  1241. mRenderer->setColorWrite(false);
  1242. mRenderer->setDepthWrite(false);
  1243. mRenderer->setCullMode(CULL_NONE);
  1244. if (!clear)
  1245. {
  1246. // If the split begins at the near plane (first split), draw at split far plane
  1247. if (light->getNearSplit() <= camera.getNearClip())
  1248. {
  1249. mRenderer->setDepthTest(CMP_GREATEREQUAL);
  1250. mRenderer->setVertexShader(mStencilVS);
  1251. mRenderer->setPixelShader(mStencilPS);
  1252. mRenderer->setVertexShaderConstant(getVSRegister(VSP_MODELVIEWPROJ), projection * farTransform);
  1253. mRenderer->setStencilTest(true, CMP_ALWAYS, OP_REF, OP_ZERO, OP_ZERO, 1);
  1254. }
  1255. // Otherwise draw at split near plane
  1256. else
  1257. {
  1258. mRenderer->setDepthTest(CMP_LESSEQUAL);
  1259. mRenderer->setVertexShader(mStencilVS);
  1260. mRenderer->setPixelShader(mStencilPS);
  1261. mRenderer->setVertexShaderConstant(getVSRegister(VSP_MODELVIEWPROJ), projection * nearTransform);
  1262. mRenderer->setStencilTest(true, CMP_ALWAYS, OP_REF, OP_ZERO, OP_ZERO, 1);
  1263. }
  1264. mDirLightGeometry->draw(mRenderer);
  1265. mRenderer->setColorWrite(true);
  1266. mRenderer->setStencilTest(true, CMP_EQUAL, OP_KEEP, OP_KEEP, OP_KEEP, 1);
  1267. }
  1268. else
  1269. {
  1270. // Clear the stencil by drawing at the far plane (assumed to be the last and most distant split)
  1271. mRenderer->setDepthTest(CMP_GREATER);
  1272. mRenderer->setVertexShader(mStencilVS);
  1273. mRenderer->setPixelShader(mStencilPS);
  1274. mRenderer->setVertexShaderConstant(getVSRegister(VSP_MODELVIEWPROJ), projection * farTransform);
  1275. mRenderer->setStencilTest(true, CMP_ALWAYS, OP_ZERO, OP_KEEP, OP_ZERO, 0);
  1276. mDirLightGeometry->draw(mRenderer);
  1277. mRenderer->setColorWrite(true);
  1278. mRenderer->setStencilTest(false);
  1279. }
  1280. }
  1281. }
  1282. }
  1283. void Pipeline::handleWindowResized(StringHash eventType, VariantMap& eventData)
  1284. {
  1285. // When screen mode changes, reload shaders and purge old views and occlusion buffers
  1286. mShadersDirty = true;
  1287. mOcclusionBuffers.clear();
  1288. resetViews();
  1289. }
  1290. void Pipeline::handlePostRenderUpdate(StringHash eventType, VariantMap& eventData)
  1291. {
  1292. if (mDrawDebugGeometry)
  1293. drawDebugGeometry();
  1294. }