Pipeline.cpp 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502
  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 emptyViewport;
  399. if (index >= mViewports.size())
  400. return emptyViewport;
  401. else
  402. return mViewports[index];
  403. }
  404. VertexShader* Pipeline::getVertexShader(const std::string& name, bool checkExists) const
  405. {
  406. // Check for extra underscore with no variations and remove
  407. std::string fullName = replace(mShaderPath + name + mVSFormat, "_.", ".");
  408. if (checkExists)
  409. {
  410. if (!mCache->exists(fullName))
  411. return 0;
  412. }
  413. return mCache->getResource<VertexShader>(fullName);
  414. }
  415. PixelShader* Pipeline::getPixelShader(const std::string& name, bool checkExists) const
  416. {
  417. // Check for extra underscore with no variations and remove
  418. std::string fullName = replace(mShaderPath + name + mPSFormat, "_.", ".");
  419. if (checkExists)
  420. {
  421. if (!mCache->exists(fullName))
  422. return 0;
  423. }
  424. return mCache->getResource<PixelShader>(fullName);
  425. }
  426. unsigned Pipeline::getNumGeometries(bool allViews) const
  427. {
  428. unsigned numGeometries = 0;
  429. unsigned lastView = allViews ? mNumViews : 1;
  430. for (unsigned i = 0; i < lastView; ++i)
  431. numGeometries += mViews[i]->getGeometries().size();
  432. return numGeometries;
  433. }
  434. unsigned Pipeline::getNumLights(bool allViews) const
  435. {
  436. unsigned numLights = 0;
  437. unsigned lastView = allViews ? mNumViews : 1;
  438. for (unsigned i = 0; i < lastView; ++i)
  439. numLights += mViews[i]->getLights().size();
  440. return numLights;
  441. }
  442. unsigned Pipeline::getNumShadowMaps(bool allViews) const
  443. {
  444. unsigned numShadowMaps = 0;
  445. unsigned lastView = allViews ? mNumViews : 1;
  446. for (unsigned i = 0; i < lastView; ++i)
  447. {
  448. const std::vector<LightBatchQueue>& lightQueues = mViews[i]->getLightQueues();
  449. for (unsigned j = 0; j < lightQueues.size(); ++j)
  450. {
  451. Light* light = lightQueues[j].mLight;
  452. if ((light) && (light->getShadowMap()))
  453. ++numShadowMaps;
  454. }
  455. }
  456. return numShadowMaps;
  457. }
  458. unsigned Pipeline::getNumOccluders(bool allViews) const
  459. {
  460. unsigned numOccluders = 0;
  461. unsigned lastView = allViews ? mNumViews : 1;
  462. for (unsigned i = 0; i < lastView; ++i)
  463. numOccluders += mViews[i]->getOccluders().size();
  464. return numOccluders;
  465. }
  466. unsigned Pipeline::getNumShadowOccluders(bool allViews) const
  467. {
  468. unsigned numShadowOccluders = 0;
  469. unsigned lastView = allViews ? mNumViews : 1;
  470. for (unsigned i = 0; i < lastView; ++i)
  471. numShadowOccluders += mViews[i]->getShadowOccluders().size();
  472. return numShadowOccluders;
  473. }
  474. const OcclusionBuffer* Pipeline::getOcclusionBuffer(float aspectRatio, bool halfResolution)
  475. {
  476. // Return an occlusion buffer for debug output purposes. Do not allocate new
  477. int width = mOcclusionBufferSize;
  478. int height = (int)(mOcclusionBufferSize / aspectRatio);
  479. if (halfResolution)
  480. {
  481. width >>= 1;
  482. height >>= 1;
  483. }
  484. int searchKey = (width << 12) | height;
  485. std::map<int, SharedPtr<OcclusionBuffer> >::iterator i = mOcclusionBuffers.find(searchKey);
  486. if (i != mOcclusionBuffers.end())
  487. return i->second;
  488. else
  489. return 0;
  490. }
  491. bool Pipeline::update(float timeStep)
  492. {
  493. PROFILE(Pipeline_Update);
  494. // If device lost, do not perform update. This is because any dynamic vertex/index buffer updates happen already here,
  495. // and if the device is lost, the updates queue up, causing memory use to rise constantly
  496. if (mRenderer->isDeviceLost())
  497. {
  498. mNumViews = 0;
  499. return false;
  500. }
  501. // Advance frame number & time, set up the frameinfo structure, and reset views & stats
  502. beginFrame(timeStep);
  503. // Reload shaders if needed
  504. if (mShadersDirty)
  505. loadShaders();
  506. // Process all viewports. Use reverse order, because during rendering the order will be reversed again to handle auxiliary
  507. // view dependencies correctly
  508. for (unsigned i = mViewports.size() - 1; i < mViewports.size(); --i)
  509. {
  510. unsigned mainView = mNumViews;
  511. Viewport& viewport = mViewports[i];
  512. if (!addView(0, viewport))
  513. continue;
  514. // Update octree (perform early update for nodes which need that, and reinsert moved nodes.)
  515. // However, if the same scene is viewed from multiple cameras, update the octree only once
  516. Octree* octree = viewport.mScene->getExtension<Octree>();
  517. if (mUpdatedOctrees.find(octree) == mUpdatedOctrees.end())
  518. {
  519. octree->updateOctree(mFrame);
  520. mUpdatedOctrees.insert(octree);
  521. }
  522. // Update the viewport's main view and any auxiliary views it creates
  523. for (unsigned i = mainView; i < mNumViews; ++i)
  524. mViews[i]->update(mFrame);
  525. }
  526. return true;
  527. }
  528. bool Pipeline::render()
  529. {
  530. PROFILE(Pipeline_Render);
  531. mRenderer->setDefaultTextureFilterMode(mTextureFilterMode);
  532. mRenderer->setTextureAnisotropy(mTextureAnisotropy);
  533. // If no views, just clear the screen
  534. if (!mNumViews)
  535. {
  536. mRenderer->setAlphaTest(false);
  537. mRenderer->setBlendMode(BLEND_REPLACE);
  538. mRenderer->setColorWrite(true);
  539. mRenderer->setDepthWrite(true);
  540. mRenderer->setFillMode(FILL_SOLID);
  541. mRenderer->setScissorTest(false);
  542. mRenderer->setStencilTest(false);
  543. mRenderer->clear(CLEAR_COLOR | CLEAR_DEPTH | CLEAR_STENCIL);
  544. return false;
  545. }
  546. // Render views from last to first (each main view is rendered after the auxiliary views it depends on)
  547. for (unsigned i = mNumViews - 1; i < mNumViews; --i)
  548. mViews[i]->render();
  549. // Disable scissor/stencil tests if left on by lights, and reset stream frequencies
  550. mRenderer->setScissorTest(false);
  551. mRenderer->setStencilTest(false);
  552. mRenderer->resetStreamFrequencies();
  553. return true;
  554. }
  555. void Pipeline::drawDebugGeometry()
  556. {
  557. PROFILE(Pipeline_DrawDebugGeometry);
  558. //! \todo Because debug geometry is per-scene, if two cameras show views of the same area, occlusion is not shown correctly
  559. static std::set<GeometryNode*> processedGeometries;
  560. static std::set<Light*> processedLights;
  561. processedGeometries.clear();
  562. processedLights.clear();
  563. for (unsigned i = 0; i < mNumViews; ++i)
  564. {
  565. // Make sure it's a main view, and process each node only once
  566. View* view = mViews[i];
  567. if (view->getRenderTarget())
  568. continue;
  569. Octree* octree = view->getOctree();
  570. if (!octree)
  571. continue;
  572. Scene* scene = octree->getScene();
  573. if (!scene)
  574. continue;
  575. DebugRenderer* debug = scene->getExtension<DebugRenderer>();
  576. if (!debug)
  577. continue;
  578. const std::vector<GeometryNode*>& geometries = view->getGeometries();
  579. const std::vector<Light*>& lights = view->getLights();
  580. for (unsigned i = 0; i < geometries.size(); ++i)
  581. {
  582. if (processedGeometries.find(geometries[i]) == processedGeometries.end())
  583. {
  584. geometries[i]->drawDebugGeometry(debug);
  585. processedGeometries.insert(geometries[i]);
  586. }
  587. }
  588. for (unsigned i = 0; i < lights.size(); ++i)
  589. {
  590. if (processedLights.find(lights[i]) == processedLights.end())
  591. {
  592. lights[i]->drawDebugGeometry(debug);
  593. processedLights.insert(lights[i]);
  594. }
  595. }
  596. }
  597. }
  598. void Pipeline::beginFrame(float timeStep)
  599. {
  600. mElapsedTime += timeStep;
  601. if (mElapsedTime >= MAX_ELAPSED_TIME)
  602. mElapsedTime -= MAX_ELAPSED_TIME;
  603. ++mFrameNumber;
  604. mFrameNumber &= M_MAX_INT;
  605. mFrame.mFrameNumber = mFrameNumber;
  606. mFrame.mTimeStep = timeStep;
  607. mFrame.mCamera = 0;
  608. mNumViews = 0;
  609. mNumSplitLights = 0;
  610. mUpdatedOctrees.clear();
  611. }
  612. void Pipeline::resetViews()
  613. {
  614. mViews.clear();
  615. mNumViews = 0;
  616. }
  617. bool Pipeline::addView(RenderSurface* renderTarget, const Viewport& viewport)
  618. {
  619. // If using a render target texture, make sure it will not be rendered to multiple times
  620. if (renderTarget)
  621. {
  622. for (unsigned i = 0; i < mNumViews; ++i)
  623. {
  624. if (mViews[i]->getRenderTarget() == renderTarget)
  625. return false;
  626. }
  627. }
  628. if (mViews.size() <= mNumViews)
  629. mViews.resize(mNumViews + 1);
  630. if (!mViews[mNumViews])
  631. mViews[mNumViews] = new View(this);
  632. if (mViews[mNumViews]->define(renderTarget, viewport))
  633. {
  634. ++mNumViews;
  635. return true;
  636. }
  637. else
  638. return false;
  639. }
  640. OcclusionBuffer* Pipeline::getOrCreateOcclusionBuffer(Camera& camera, int maxOccluderTriangles, bool halfResolution)
  641. {
  642. // Get an occlusion buffer matching the aspect ratio. If not found, allocate new
  643. int width = mOcclusionBufferSize;
  644. int height = (int)(mOcclusionBufferSize / camera.getAspectRatio());
  645. if (halfResolution)
  646. {
  647. width >>= 1;
  648. height >>= 1;
  649. }
  650. int searchKey = (width << 12) | height;
  651. SharedPtr<OcclusionBuffer> buffer;
  652. std::map<int, SharedPtr<OcclusionBuffer> >::iterator i = mOcclusionBuffers.find(searchKey);
  653. if (i != mOcclusionBuffers.end())
  654. buffer = i->second;
  655. else
  656. {
  657. buffer = new OcclusionBuffer();
  658. buffer->setSize(width, height);
  659. mOcclusionBuffers[searchKey] = buffer;
  660. }
  661. buffer->setView(camera);
  662. buffer->setMaxTriangles(maxOccluderTriangles);
  663. buffer->clear();
  664. return buffer;
  665. }
  666. Geometry* Pipeline::getLightGeometry(Light* light)
  667. {
  668. switch (light->getLightType())
  669. {
  670. case LIGHT_POINT:
  671. return mPointLightGeometry;
  672. case LIGHT_SPOT:
  673. case LIGHT_SPLITPOINT:
  674. return mSpotLightGeometry;
  675. default:
  676. return mDirLightGeometry;
  677. }
  678. }
  679. Texture2D* Pipeline::getShadowMap(float resolution)
  680. {
  681. if (resolution >= 0.75f)
  682. return mFullShadowMap;
  683. else if (resolution >= 0.375f)
  684. return mHalfShadowMap;
  685. else
  686. return mQuarterShadowMap;
  687. }
  688. void Pipeline::setBatchShaders(Batch& batch, MaterialTechnique* technique, MaterialPass* pass, bool allowShadows)
  689. {
  690. static std::set<Material*> errorDisplayed;
  691. batch.mTechnique = technique;
  692. batch.mPass = pass;
  693. // Check if shaders are unloaded or need reloading
  694. std::vector<SharedPtr<VertexShader> >& vertexShaders = pass->getVertexShaders();
  695. std::vector<SharedPtr<PixelShader> >& pixelShaders = pass->getPixelShaders();
  696. if ((!vertexShaders.size()) || (!pixelShaders.size()) || (technique->getShadersLoadedFrameNumber() !=
  697. mShadersChangedFrameNumber))
  698. {
  699. // First release all previous shaders, then load
  700. technique->releaseShaders();
  701. loadMaterialShaders(technique);
  702. }
  703. // Make sure shaders are loaded now
  704. if ((vertexShaders.size()) && (pixelShaders.size()))
  705. {
  706. // Recognize light pass from the amount of shaders
  707. if (pixelShaders.size() == 1)
  708. {
  709. unsigned vsi = 0;
  710. if (batch.mNode->getNodeFlags() & NODE_GEOMETRY)
  711. vsi = static_cast<GeometryNode*>(batch.mNode)->getGeometryType();
  712. batch.mVertexShader = vertexShaders[vsi];
  713. batch.mPixelShader = pixelShaders[0];
  714. }
  715. else
  716. {
  717. Light* light = batch.mForwardLight;
  718. if (!light)
  719. {
  720. // Do not log error, as it would result in a lot of spam
  721. batch.mVertexShader = 0;
  722. batch.mPixelShader = 0;
  723. return;
  724. }
  725. unsigned vsi = 0;
  726. unsigned psi = 0;
  727. if (batch.mNode->getNodeFlags() & NODE_GEOMETRY)
  728. vsi = static_cast<GeometryNode*>(batch.mNode)->getGeometryType() * MAX_LIGHT_VS_VARIATIONS;
  729. // Negative lights have no specular or shadows
  730. if (!light->isNegative())
  731. {
  732. if ((mSpecularLighting) && (light->getSpecularIntensity() > 0.0f))
  733. psi += LPS_SPEC;
  734. if ((allowShadows) && (light->getShadowMap()))
  735. {
  736. vsi += LVS_SHADOW;
  737. psi += LPS_SHADOW;
  738. }
  739. }
  740. else
  741. psi += LPS_NEGATIVE;
  742. switch (light->getLightType())
  743. {
  744. case LIGHT_POINT:
  745. case LIGHT_SPLITPOINT:
  746. psi += LPS_POINT;
  747. break;
  748. case LIGHT_SPOT:
  749. psi += LPS_SPOT;
  750. vsi += LVS_SPOT;
  751. break;
  752. }
  753. batch.mVertexShader = vertexShaders[vsi];
  754. batch.mPixelShader = pixelShaders[psi];
  755. }
  756. }
  757. // Log error if shaders could not be assigned, but only once per material
  758. if ((!batch.mVertexShader) || (!batch.mPixelShader))
  759. {
  760. Material* parentMat = technique->getParent();
  761. if (errorDisplayed.find(parentMat) == errorDisplayed.end())
  762. {
  763. errorDisplayed.insert(parentMat);
  764. LOGERROR("Material " + parentMat->getName() + " has missing shaders");
  765. }
  766. }
  767. }
  768. void Pipeline::setLightVolumeShaders(Batch& batch)
  769. {
  770. unsigned vsi = DLVS_NONE;
  771. unsigned psi = DLPS_NONE;
  772. Light* light = static_cast<Light*>(batch.mNode);
  773. switch(light->getLightType())
  774. {
  775. case LIGHT_DIRECTIONAL:
  776. vsi += DLVS_DIR;
  777. break;
  778. case LIGHT_POINT:
  779. case LIGHT_SPLITPOINT:
  780. psi += DLPS_POINT;
  781. break;
  782. case LIGHT_SPOT:
  783. psi += DLPS_SPOT;
  784. break;
  785. }
  786. if (!light->isNegative())
  787. {
  788. if (light->getShadowMap())
  789. psi += DLPS_SHADOW;
  790. if ((mSpecularLighting) && (light->getSpecularIntensity() > 0.0))
  791. psi += DLPS_SPEC;
  792. }
  793. else
  794. psi += DLPS_NEGATIVE;
  795. // Non-hardware depth & orthographic modes use linear depth, else reconstruct from z/w
  796. if (batch.mCamera->isOrthographic())
  797. {
  798. vsi += DLVS_ORTHO;
  799. psi += DLPS_ORTHO;
  800. }
  801. else if (!mRenderer->getHardwareDepthSupport())
  802. psi += DLPS_LINEAR;
  803. unsigned hwShadows = mRenderer->getHardwareShadowSupport() ? 1 : 0;
  804. if (!mLightVS[vsi])
  805. mLightVS[vsi] = getVertexShader(mLightShaderName + deferredLightVSVariations[vsi]);
  806. if (!mLightPS[psi])
  807. {
  808. unsigned variation = psi % 5;
  809. if ((variation == LPS_SHADOW) || (variation == LPS_SHADOWSPEC))
  810. mLightPS[psi] = getPixelShader(mLightShaderName + deferredLightPSVariations[psi] + shadowPSVariations[hwShadows]);
  811. else
  812. mLightPS[psi] = getPixelShader(mLightShaderName + deferredLightPSVariations[psi]);
  813. }
  814. batch.mVertexShader = mLightVS[vsi];
  815. batch.mPixelShader = mLightPS[psi];
  816. }
  817. void Pipeline::loadShaders()
  818. {
  819. PROFILE(Pipeline_LoadShaders);
  820. LOGINFO("Reloading shaders");
  821. // Release old material shaders, mark them for reload
  822. releaseMaterialShaders();
  823. mShadersChangedFrameNumber = mFrameNumber;
  824. // Load inbuilt shaders
  825. mStencilVS = getVertexShader("Stencil");
  826. mStencilPS = getPixelShader("Stencil");
  827. mLightVS.clear();
  828. mLightPS.clear();
  829. RenderMode renderMode = mRenderer->getRenderMode();
  830. if (renderMode != RENDER_FORWARD)
  831. {
  832. // There are rather many light volume shader variations, so load them later on-demand
  833. mLightVS.resize(MAX_DEFERRED_LIGHT_VS_VARIATIONS);
  834. mLightPS.resize(MAX_DEFERRED_LIGHT_PS_VARIATIONS);
  835. if (renderMode == RENDER_DEFERRED)
  836. mLightShaderName = "Deferred/Light_";
  837. else
  838. mLightShaderName = "Prepass/Light_";
  839. }
  840. // Remove shaders that are no longer referenced from the cache
  841. mCache->releaseResources(VertexShader::getTypeStatic());
  842. mCache->releaseResources(PixelShader::getTypeStatic());
  843. mShadersDirty = false;
  844. }
  845. void Pipeline::loadMaterialShaders(MaterialTechnique* technique)
  846. {
  847. loadMaterialPassShaders(technique, PASS_SHADOW);
  848. loadMaterialPassShaders(technique, PASS_POSTOPAQUE);
  849. if (mRenderer->getRenderMode() == RENDER_FORWARD)
  850. {
  851. loadMaterialPassShaders(technique, PASS_AMBIENT);
  852. loadMaterialPassShaders(technique, PASS_LIGHT);
  853. loadMaterialPassShaders(technique, PASS_NEGATIVE, false);
  854. }
  855. else
  856. {
  857. // G-Buffer pass types depend on whether deferred shading or light prepass is in use
  858. PassType gBufferPass, additionalPass;
  859. if (mRenderer->getRenderMode() == RENDER_DEFERRED)
  860. {
  861. gBufferPass = PASS_DEFERRED;
  862. additionalPass = PASS_EMISSIVE;
  863. }
  864. else
  865. {
  866. gBufferPass = PASS_PREPASS;
  867. additionalPass = PASS_MATERIAL;
  868. }
  869. if (technique->hasPass(gBufferPass))
  870. {
  871. loadMaterialPassShaders(technique, gBufferPass);
  872. loadMaterialPassShaders(technique, additionalPass);
  873. }
  874. else
  875. {
  876. loadMaterialPassShaders(technique, PASS_AMBIENT);
  877. // No shadows used in forward lighting, so do not load the shadowing shaders
  878. loadMaterialPassShaders(technique, PASS_LIGHT, false);
  879. loadMaterialPassShaders(technique, PASS_NEGATIVE, false);
  880. }
  881. }
  882. }
  883. void Pipeline::loadMaterialPassShaders(MaterialTechnique* technique, PassType pass, bool allowShadows)
  884. {
  885. std::map<PassType, MaterialPass>::iterator i = technique->mPasses.find(pass);
  886. if (i == technique->mPasses.end())
  887. return;
  888. std::string vertexShaderName = i->second.getVertexShaderName();
  889. std::string pixelShaderName = i->second.getPixelShaderName();
  890. // Check if the shader name is already a variation in itself
  891. if (vertexShaderName.find('_') == std::string::npos)
  892. vertexShaderName += "_";
  893. if (pixelShaderName.find('_') == std::string::npos)
  894. pixelShaderName += "_";
  895. // If INTZ depth is used, do not write depth into the third RT in GBuffer pass
  896. if ((pass == PASS_DEFERRED) || (pass == PASS_PREPASS))
  897. {
  898. unsigned hwDepth = mRenderer->getHardwareDepthSupport() ? 1 : 0;
  899. pixelShaderName += gBufferPSVariations[hwDepth];
  900. }
  901. // If ambient pass is not using REPLACE as the blend mode, do not load shadow shaders for the light pass
  902. if (pass == PASS_LIGHT)
  903. {
  904. if ((!technique->hasPass(PASS_AMBIENT)) || (technique->getPass(PASS_AMBIENT)->getBlendMode() != BLEND_REPLACE))
  905. allowShadows = false;
  906. }
  907. if (pass == PASS_NEGATIVE)
  908. allowShadows = false;
  909. unsigned hwShadows = mRenderer->getHardwareShadowSupport() ? 1 : 0;
  910. std::vector<SharedPtr<VertexShader> >& vertexShaders = i->second.getVertexShaders();
  911. std::vector<SharedPtr<PixelShader> >& pixelShaders = i->second.getPixelShaders();
  912. // Forget all the old shaders
  913. vertexShaders.clear();
  914. pixelShaders.clear();
  915. switch (i->first)
  916. {
  917. default:
  918. vertexShaders.resize(MAX_GEOMETRYTYPES);
  919. pixelShaders.resize(1);
  920. for (unsigned j = 0; j < MAX_GEOMETRYTYPES; ++j)
  921. vertexShaders[j] = getVertexShader(vertexShaderName + geometryVSVariations[j], j != 0);
  922. pixelShaders[0] = getPixelShader(pixelShaderName);
  923. break;
  924. case PASS_LIGHT:
  925. case PASS_NEGATIVE:
  926. vertexShaders.resize(MAX_GEOMETRYTYPES * MAX_LIGHT_VS_VARIATIONS);
  927. pixelShaders.resize(MAX_LIGHT_PS_VARIATIONS);
  928. for (unsigned j = 0; j < MAX_GEOMETRYTYPES * MAX_LIGHT_VS_VARIATIONS; ++j)
  929. {
  930. unsigned g = j / MAX_LIGHT_VS_VARIATIONS;
  931. unsigned l = j % MAX_LIGHT_VS_VARIATIONS;
  932. if ((!(l & LVS_SHADOW)) || (allowShadows))
  933. vertexShaders[j] = getVertexShader(vertexShaderName + lightVSVariations[l] + geometryVSVariations[g], g != 0);
  934. else
  935. vertexShaders[j].reset();
  936. }
  937. for (unsigned j = 0; j < MAX_LIGHT_PS_VARIATIONS; ++j)
  938. {
  939. unsigned variation = j % 5;
  940. if ((variation == LPS_SHADOW) || (variation == LPS_SHADOWSPEC))
  941. {
  942. if (allowShadows)
  943. pixelShaders[j] = getPixelShader(pixelShaderName + deferredLightPSVariations[j] +
  944. shadowPSVariations[hwShadows]);
  945. else
  946. pixelShaders[j].reset();
  947. }
  948. else
  949. {
  950. // For the negative pass, load only the negative version of the shader
  951. bool needed = (pass == PASS_LIGHT) ? (variation != LPS_NEGATIVE) : (variation == LPS_NEGATIVE);
  952. if (needed)
  953. pixelShaders[j] = getPixelShader(pixelShaderName + deferredLightPSVariations[j]);
  954. else
  955. pixelShaders[j].reset();
  956. }
  957. }
  958. break;
  959. }
  960. technique->markShadersLoaded(mShadersChangedFrameNumber);
  961. }
  962. void Pipeline::releaseMaterialShaders()
  963. {
  964. std::vector<Material*> materials;
  965. mCache->getResources<Material>(materials);
  966. for (unsigned i = 0; i < materials.size(); ++i)
  967. {
  968. for (unsigned j = 0; j < materials[i]->getNumTechniques(); ++j)
  969. materials[i]->releaseShaders();
  970. }
  971. }
  972. void Pipeline::reloadTextures()
  973. {
  974. std::vector<Resource*> textures;
  975. mCache->getResources(textures, Texture2D::getTypeStatic());
  976. for (unsigned i = 0; i < textures.size(); ++i)
  977. mCache->reloadResource(textures[i]);
  978. mCache->getResources(textures, TextureCube::getTypeStatic());
  979. for (unsigned i = 0; i < textures.size(); ++i)
  980. mCache->reloadResource(textures[i]);
  981. }
  982. void Pipeline::createGeometries()
  983. {
  984. PROFILE(Pipeline_CreateGeometries);
  985. SharedPtr<VertexBuffer> dlvb(new VertexBuffer(mRenderer));
  986. dlvb->setSize(4, MASK_POSITION);
  987. dlvb->setData(dirLightVertexData);
  988. SharedPtr<IndexBuffer> dlib(new IndexBuffer(mRenderer));
  989. dlib->setSize(6, false);
  990. dlib->setData(dirLightIndexData);
  991. mDirLightGeometry = new Geometry();
  992. mDirLightGeometry->setVertexBuffer(0, dlvb);
  993. mDirLightGeometry->setIndexBuffer(dlib);
  994. mDirLightGeometry->setDrawRange(TRIANGLE_LIST, 0, dlib->getIndexCount());
  995. SharedPtr<VertexBuffer> plvb(new VertexBuffer(mRenderer));
  996. plvb->setSize(24, MASK_POSITION);
  997. plvb->setData(pointLightVertexData);
  998. SharedPtr<IndexBuffer> plib(new IndexBuffer(mRenderer));
  999. plib->setSize(132, false);
  1000. plib->setData(pointLightIndexData);
  1001. mPointLightGeometry = new Geometry();
  1002. mPointLightGeometry->setVertexBuffer(0, plvb);
  1003. mPointLightGeometry->setIndexBuffer(plib);
  1004. mPointLightGeometry->setDrawRange(TRIANGLE_LIST, 0, plib->getIndexCount());
  1005. SharedPtr<VertexBuffer> slvb(new VertexBuffer(mRenderer));
  1006. slvb->setSize(8, MASK_POSITION);
  1007. slvb->setData(spotLightVertexData);
  1008. SharedPtr<IndexBuffer> slib(new IndexBuffer(mRenderer));
  1009. slib->setSize(36, false);
  1010. slib->setData(spotLightIndexData);
  1011. mSpotLightGeometry = new Geometry();
  1012. mSpotLightGeometry->setVertexBuffer(0, slvb);
  1013. mSpotLightGeometry->setIndexBuffer(slib);
  1014. mSpotLightGeometry->setDrawRange(TRIANGLE_LIST, 0, slib->getIndexCount());
  1015. }
  1016. bool Pipeline::createShadowMaps()
  1017. {
  1018. PROFILE(Pipeline_CreateShadowMaps);
  1019. unsigned shadowMapFormat = mShadowMapHiresDepth ? mRenderer->getHiresShadowMapFormat() : mRenderer->getShadowMapFormat();
  1020. unsigned dummyColorFormat = mRenderer->getDummyColorFormat();
  1021. bool hardwarePCF = mRenderer->getHardwareShadowSupport();
  1022. if (shadowMapFormat == D3DFMT_UNKNOWN)
  1023. return false;
  1024. if (!mDrawShadows)
  1025. {
  1026. mFullShadowMap.reset();
  1027. mHalfShadowMap.reset();
  1028. mQuarterShadowMap.reset();
  1029. mFullShadowMapColor.reset();
  1030. mHalfShadowMapColor.reset();
  1031. mQuarterShadowMapColor.reset();
  1032. return true;
  1033. }
  1034. try
  1035. {
  1036. // Create shadow maps and dummy color rendertargets
  1037. if (!mFullShadowMap)
  1038. mFullShadowMap = new Texture2D(mRenderer, TEXTURE_DEPTHSTENCIL);
  1039. mFullShadowMap->setSize(mShadowMapSize, mShadowMapSize, shadowMapFormat);
  1040. mFullShadowMap->setFilterMode(hardwarePCF ? FILTER_BILINEAR : FILTER_NEAREST);
  1041. if (!mHalfShadowMap)
  1042. mHalfShadowMap = new Texture2D(mRenderer, TEXTURE_DEPTHSTENCIL);
  1043. mHalfShadowMap->setSize(mShadowMapSize >> 1, mShadowMapSize >> 1, shadowMapFormat);
  1044. mHalfShadowMap->setFilterMode(hardwarePCF ? FILTER_BILINEAR : FILTER_NEAREST);
  1045. if (!mQuarterShadowMap)
  1046. mQuarterShadowMap = new Texture2D(mRenderer, TEXTURE_DEPTHSTENCIL);
  1047. mQuarterShadowMap->setSize(mShadowMapSize >> 2, mShadowMapSize >> 2, shadowMapFormat);
  1048. mQuarterShadowMap->setFilterMode(hardwarePCF ? FILTER_BILINEAR : FILTER_NEAREST);
  1049. if (!mFullShadowMapColor)
  1050. mFullShadowMapColor = new Texture2D(mRenderer, TEXTURE_RENDERTARGET);
  1051. mFullShadowMapColor->setSize(mShadowMapSize, mShadowMapSize, dummyColorFormat);
  1052. if (!mHalfShadowMapColor)
  1053. mHalfShadowMapColor = new Texture2D(mRenderer, TEXTURE_RENDERTARGET);
  1054. mHalfShadowMapColor->setSize(mShadowMapSize >> 1, mShadowMapSize >> 1, dummyColorFormat);
  1055. if (!mQuarterShadowMapColor)
  1056. mQuarterShadowMapColor = new Texture2D(mRenderer, TEXTURE_RENDERTARGET);
  1057. mQuarterShadowMapColor->setSize(mShadowMapSize >> 2, mShadowMapSize >> 2, dummyColorFormat);
  1058. // Link the color rendertargets to depth rendertargets
  1059. mFullShadowMap->getRenderSurface()->setLinkedRenderTarget(mFullShadowMapColor->getRenderSurface());
  1060. mHalfShadowMap->getRenderSurface()->setLinkedRenderTarget(mHalfShadowMapColor->getRenderSurface());
  1061. mQuarterShadowMap->getRenderSurface()->setLinkedRenderTarget(mQuarterShadowMapColor->getRenderSurface());
  1062. }
  1063. catch (...)
  1064. {
  1065. return false;
  1066. }
  1067. return true;
  1068. }
  1069. Light* Pipeline::createSplitLight(Light* original)
  1070. {
  1071. if (mNumSplitLights >= mSplitLightStore.size())
  1072. mSplitLightStore.push_back(SharedPtr<Light>(new Light()));
  1073. Light* light = mSplitLightStore[mNumSplitLights];
  1074. light->copyFrom(original);
  1075. mNumSplitLights++;
  1076. return light;
  1077. }
  1078. void Pipeline::setupLightBatch(Batch& batch)
  1079. {
  1080. Light* light = static_cast<Light*>(batch.mNode);
  1081. const Matrix4x3* model = &light->getWorldTransform();
  1082. const Matrix4x3* view = &batch.mCamera->getInverseWorldTransform();
  1083. const Matrix4* projection = &batch.mCamera->getProjection();
  1084. light->overrideTransforms(0, *batch.mCamera, &model, &view);
  1085. float lightExtent = light->getVolumeExtent();
  1086. float lightViewDist = (light->getWorldPosition() - batch.mCamera->getWorldPosition()).getLengthFast();
  1087. mRenderer->setAlphaTest(false);
  1088. mRenderer->setBlendMode(light->isNegative() ? BLEND_MULTIPLY : BLEND_ADD);
  1089. mRenderer->setDepthWrite(false);
  1090. if (light->getLightType() == LIGHT_DIRECTIONAL)
  1091. {
  1092. // If the light does not extend to the near plane, use a stencil test. Else just draw with depth fail
  1093. if (light->getNearSplit() <= batch.mCamera->getNearClip())
  1094. {
  1095. mRenderer->setCullMode(CULL_NONE);
  1096. mRenderer->setDepthTest(CMP_GREATER);
  1097. mRenderer->setStencilTest(false);
  1098. }
  1099. else
  1100. {
  1101. Matrix4x3 nearTransform = light->getDirLightTransform(*batch.mCamera, true);
  1102. // Set state for stencil rendering
  1103. mRenderer->setColorWrite(false);
  1104. mRenderer->setCullMode(CULL_NONE);
  1105. mRenderer->setDepthTest(CMP_LESSEQUAL);
  1106. mRenderer->setStencilTest(true, CMP_ALWAYS, OP_INCR, OP_KEEP, OP_KEEP, 1);
  1107. mRenderer->setVertexShader(mStencilVS);
  1108. mRenderer->setPixelShader(mStencilPS);
  1109. mRenderer->setVertexShaderConstant(getVSRegister(VSP_MODELVIEWPROJ), (*projection) * nearTransform);
  1110. // Draw to stencil
  1111. batch.mGeometry->draw(mRenderer);
  1112. // Re-enable color write, set test for rendering the actual light
  1113. mRenderer->setColorWrite(true);
  1114. mRenderer->setDepthTest(CMP_GREATER);
  1115. mRenderer->setStencilTest(true, CMP_EQUAL, OP_ZERO, OP_KEEP, OP_ZERO, 1);
  1116. }
  1117. }
  1118. else
  1119. {
  1120. if (light->getLightType() == LIGHT_SPLITPOINT)
  1121. {
  1122. // Shadowed point light, split in 6 frustums: mask out overlapping pixels to prevent overlighting
  1123. // Check whether we should draw front or back faces
  1124. bool drawBackFaces = lightViewDist < (lightExtent + batch.mCamera->getNearClip());
  1125. mRenderer->setColorWrite(false);
  1126. mRenderer->setCullMode(drawBackFaces ? CULL_CCW : CULL_CW);
  1127. mRenderer->setDepthTest(drawBackFaces ? CMP_GREATER : CMP_LESS);
  1128. mRenderer->setStencilTest(true, CMP_EQUAL, OP_INCR, OP_KEEP, OP_KEEP, 0);
  1129. mRenderer->setVertexShader(mStencilVS);
  1130. mRenderer->setPixelShader(mStencilPS);
  1131. mRenderer->setVertexShaderConstant(getVSRegister(VSP_MODELVIEWPROJ), (*projection) * (*view) * (*model));
  1132. // Draw the other faces to stencil to mark where we should not draw
  1133. batch.mGeometry->draw(mRenderer);
  1134. mRenderer->setColorWrite(true);
  1135. mRenderer->setCullMode(drawBackFaces ? CULL_CW : CULL_CCW);
  1136. mRenderer->setStencilTest(true, CMP_EQUAL, OP_DECR, OP_DECR, OP_KEEP, 0);
  1137. }
  1138. else
  1139. {
  1140. // If light is close to near clip plane, we might be inside light volume
  1141. if (lightViewDist < (lightExtent + batch.mCamera->getNearClip()))
  1142. {
  1143. // In this case reverse cull mode & depth test and render back faces
  1144. mRenderer->setCullMode(CULL_CW);
  1145. mRenderer->setDepthTest(CMP_GREATER);
  1146. mRenderer->setStencilTest(false);
  1147. }
  1148. else
  1149. {
  1150. // If not too close to far clip plane, write the back faces to stencil for optimization,
  1151. // then render front faces. Else just render front faces.
  1152. if (lightViewDist < (batch.mCamera->getFarClip() - lightExtent))
  1153. {
  1154. // Set state for stencil rendering
  1155. mRenderer->setColorWrite(false);
  1156. mRenderer->setCullMode(CULL_CW);
  1157. mRenderer->setDepthTest(CMP_GREATEREQUAL);
  1158. mRenderer->setStencilTest(true, CMP_ALWAYS, OP_INCR, OP_KEEP, OP_KEEP, 1);
  1159. mRenderer->setVertexShader(mStencilVS);
  1160. mRenderer->setPixelShader(mStencilPS);
  1161. mRenderer->setVertexShaderConstant(getVSRegister(VSP_MODELVIEWPROJ), (*projection) * (*view) * (*model));
  1162. // Draw to stencil
  1163. batch.mGeometry->draw(mRenderer);
  1164. // Re-enable color write, set test for rendering the actual light
  1165. mRenderer->setColorWrite(true);
  1166. mRenderer->setStencilTest(true, CMP_EQUAL, OP_ZERO, OP_KEEP, OP_ZERO, 1);
  1167. mRenderer->setCullMode(CULL_CCW);
  1168. mRenderer->setDepthTest(CMP_LESS);
  1169. }
  1170. else
  1171. {
  1172. mRenderer->setStencilTest(false);
  1173. mRenderer->setCullMode(CULL_CCW);
  1174. mRenderer->setDepthTest(CMP_LESS);
  1175. }
  1176. }
  1177. }
  1178. }
  1179. }
  1180. void Pipeline::drawFullScreenQuad(Camera& camera, VertexShader* vs, PixelShader* ps, bool nearQuad)
  1181. {
  1182. Light quadDirLight;
  1183. Matrix4x3 model = quadDirLight.getDirLightTransform(camera, nearQuad);
  1184. mRenderer->setCullMode(CULL_NONE);
  1185. mRenderer->setVertexShader(vs);
  1186. mRenderer->setPixelShader(ps);
  1187. mRenderer->setVertexShaderConstant(getVSRegister(VSP_MODELVIEWPROJ), camera.getProjection() * model);
  1188. mDirLightGeometry->draw(mRenderer);
  1189. }
  1190. void Pipeline::drawSplitLightToStencil(Camera& camera, Light* light, bool clear)
  1191. {
  1192. switch (light->getLightType())
  1193. {
  1194. case LIGHT_SPLITPOINT:
  1195. {
  1196. const Matrix4x3* model = &light->getWorldTransform();
  1197. const Matrix4x3* view = &camera.getInverseWorldTransform();
  1198. const Matrix4* projection = &camera.getProjection();
  1199. light->overrideTransforms(0, camera, &model, &view);
  1200. float lightExtent = light->getVolumeExtent();
  1201. float lightViewDist = (light->getWorldPosition() - camera.getWorldPosition()).getLengthFast();
  1202. bool drawBackFaces = lightViewDist < (lightExtent + camera.getNearClip());
  1203. mRenderer->setAlphaTest(false);
  1204. mRenderer->setColorWrite(false);
  1205. mRenderer->setDepthWrite(false);
  1206. mRenderer->setCullMode(drawBackFaces ? CULL_CW : CULL_CCW);
  1207. mRenderer->setDepthTest(drawBackFaces ? CMP_GREATER : CMP_LESS);
  1208. mRenderer->setVertexShader(mStencilVS);
  1209. mRenderer->setPixelShader(mStencilPS);
  1210. mRenderer->setVertexShaderConstant(getVSRegister(VSP_MODELVIEWPROJ), (*projection) * (*view) * (*model));
  1211. if (!clear)
  1212. {
  1213. // Draw the faces to stencil which we should draw (where no light has not been rendered yet)
  1214. mRenderer->setStencilTest(true, CMP_EQUAL, OP_INCR, OP_KEEP, OP_KEEP, 0);
  1215. mSpotLightGeometry->draw(mRenderer);
  1216. // Draw the other faces to stencil to mark where we should not draw ("frees up" the pixels for other faces)
  1217. mRenderer->setCullMode(drawBackFaces ? CULL_CCW : CULL_CW);
  1218. mRenderer->setStencilTest(true, CMP_EQUAL, OP_DECR, OP_KEEP, OP_KEEP, 1);
  1219. mSpotLightGeometry->draw(mRenderer);
  1220. // Now set stencil test for rendering the lit geometries (also marks the pixels so that they will not be used again)
  1221. mRenderer->setStencilTest(true, CMP_EQUAL, OP_INCR, OP_KEEP, OP_KEEP, 1);
  1222. mRenderer->setColorWrite(true);
  1223. }
  1224. else
  1225. {
  1226. // Clear the stencil by drawing the whole point light volume
  1227. mRenderer->setStencilTest(true, CMP_ALWAYS, OP_ZERO, OP_KEEP, OP_ZERO, 0);
  1228. mPointLightGeometry->draw(mRenderer);
  1229. mRenderer->setColorWrite(true);
  1230. mRenderer->setStencilTest(false);
  1231. }
  1232. }
  1233. break;
  1234. case LIGHT_DIRECTIONAL:
  1235. // If light encompasses whole frustum, no drawing to frustum necessary
  1236. if ((light->getNearSplit() <= camera.getNearClip()) && (light->getFarSplit() >= camera.getFarClip()))
  1237. return;
  1238. else
  1239. {
  1240. const Matrix4& projection = camera.getProjection();
  1241. Matrix4x3 nearTransform = light->getDirLightTransform(camera, true);
  1242. Matrix4x3 farTransform = light->getDirLightTransform(camera, false);
  1243. mRenderer->setAlphaTest(false);
  1244. mRenderer->setColorWrite(false);
  1245. mRenderer->setDepthWrite(false);
  1246. mRenderer->setCullMode(CULL_NONE);
  1247. if (!clear)
  1248. {
  1249. // If the split begins at the near plane (first split), draw at split far plane
  1250. if (light->getNearSplit() <= camera.getNearClip())
  1251. {
  1252. mRenderer->setDepthTest(CMP_GREATEREQUAL);
  1253. mRenderer->setVertexShader(mStencilVS);
  1254. mRenderer->setPixelShader(mStencilPS);
  1255. mRenderer->setVertexShaderConstant(getVSRegister(VSP_MODELVIEWPROJ), projection * farTransform);
  1256. mRenderer->setStencilTest(true, CMP_ALWAYS, OP_REF, OP_ZERO, OP_ZERO, 1);
  1257. }
  1258. // Otherwise draw at split near plane
  1259. else
  1260. {
  1261. mRenderer->setDepthTest(CMP_LESSEQUAL);
  1262. mRenderer->setVertexShader(mStencilVS);
  1263. mRenderer->setPixelShader(mStencilPS);
  1264. mRenderer->setVertexShaderConstant(getVSRegister(VSP_MODELVIEWPROJ), projection * nearTransform);
  1265. mRenderer->setStencilTest(true, CMP_ALWAYS, OP_REF, OP_ZERO, OP_ZERO, 1);
  1266. }
  1267. mDirLightGeometry->draw(mRenderer);
  1268. mRenderer->setColorWrite(true);
  1269. mRenderer->setStencilTest(true, CMP_EQUAL, OP_KEEP, OP_KEEP, OP_KEEP, 1);
  1270. }
  1271. else
  1272. {
  1273. // Clear the stencil by drawing at the far plane (assumed to be the last and most distant split)
  1274. mRenderer->setDepthTest(CMP_GREATER);
  1275. mRenderer->setVertexShader(mStencilVS);
  1276. mRenderer->setPixelShader(mStencilPS);
  1277. mRenderer->setVertexShaderConstant(getVSRegister(VSP_MODELVIEWPROJ), projection * farTransform);
  1278. mRenderer->setStencilTest(true, CMP_ALWAYS, OP_ZERO, OP_KEEP, OP_ZERO, 0);
  1279. mDirLightGeometry->draw(mRenderer);
  1280. mRenderer->setColorWrite(true);
  1281. mRenderer->setStencilTest(false);
  1282. }
  1283. }
  1284. }
  1285. }
  1286. void Pipeline::handleWindowResized(StringHash eventType, VariantMap& eventData)
  1287. {
  1288. // When screen mode changes, reload shaders and purge old views and occlusion buffers
  1289. mShadersDirty = true;
  1290. mOcclusionBuffers.clear();
  1291. resetViews();
  1292. }
  1293. void Pipeline::handlePostRenderUpdate(StringHash eventType, VariantMap& eventData)
  1294. {
  1295. if (mDrawDebugGeometry)
  1296. drawDebugGeometry();
  1297. }