Renderer.cpp 64 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036
  1. //
  2. // Copyright (c) 2008-2017 the Urho3D project.
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. #include "../Precompiled.h"
  23. #include "../Core/CoreEvents.h"
  24. #include "../Core/Profiler.h"
  25. #include "../Graphics/Camera.h"
  26. #include "../Graphics/DebugRenderer.h"
  27. #include "../Graphics/Geometry.h"
  28. #include "../Graphics/Graphics.h"
  29. #include "../Graphics/GraphicsEvents.h"
  30. #include "../Graphics/GraphicsImpl.h"
  31. #include "../Graphics/IndexBuffer.h"
  32. #include "../Graphics/Material.h"
  33. #include "../Graphics/OcclusionBuffer.h"
  34. #include "../Graphics/Octree.h"
  35. #include "../Graphics/Renderer.h"
  36. #include "../Graphics/RenderPath.h"
  37. #include "../Graphics/ShaderVariation.h"
  38. #include "../Graphics/Technique.h"
  39. #include "../Graphics/Texture2D.h"
  40. #include "../Graphics/TextureCube.h"
  41. #include "../Graphics/VertexBuffer.h"
  42. #include "../Graphics/View.h"
  43. #include "../Graphics/Zone.h"
  44. #include "../IO/Log.h"
  45. #include "../Resource/ResourceCache.h"
  46. #include "../Resource/XMLFile.h"
  47. #include "../Scene/Scene.h"
  48. #include "../DebugNew.h"
  49. #ifdef _MSC_VER
  50. #pragma warning(disable:6293)
  51. #endif
  52. namespace Urho3D
  53. {
  54. static const float dirLightVertexData[] =
  55. {
  56. -1, 1, 0,
  57. 1, 1, 0,
  58. 1, -1, 0,
  59. -1, -1, 0,
  60. };
  61. static const unsigned short dirLightIndexData[] =
  62. {
  63. 0, 1, 2,
  64. 2, 3, 0,
  65. };
  66. static const float pointLightVertexData[] =
  67. {
  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. -0.423169f, 1.000000f, -0.423169f,
  74. -0.423169f, 1.000000f, 0.423169f,
  75. 0.423169f, 1.000000f, 0.423169f,
  76. -1.000000f, 0.423169f, -0.423169f,
  77. -1.000000f, -0.423169f, -0.423169f,
  78. -1.000000f, -0.423169f, 0.423169f,
  79. -1.000000f, 0.423169f, 0.423169f,
  80. 0.423169f, 0.423169f, -1.000000f,
  81. 0.423169f, -0.423169f, -1.000000f,
  82. -0.423169f, -0.423169f, -1.000000f,
  83. -0.423169f, 0.423169f, -1.000000f,
  84. 1.000000f, 0.423169f, 0.423169f,
  85. 1.000000f, -0.423169f, 0.423169f,
  86. 1.000000f, -0.423169f, -0.423169f,
  87. 1.000000f, 0.423169f, -0.423169f,
  88. 0.423169f, -0.423169f, 1.000000f,
  89. 0.423169f, 0.423169f, 1.000000f,
  90. -0.423169f, 0.423169f, 1.000000f,
  91. -0.423169f, -0.423169f, 1.000000f
  92. };
  93. static const unsigned short pointLightIndexData[] =
  94. {
  95. 0, 1, 2,
  96. 0, 2, 3,
  97. 4, 5, 6,
  98. 4, 6, 7,
  99. 8, 9, 10,
  100. 8, 10, 11,
  101. 12, 13, 14,
  102. 12, 14, 15,
  103. 16, 17, 18,
  104. 16, 18, 19,
  105. 20, 21, 22,
  106. 20, 22, 23,
  107. 0, 10, 9,
  108. 0, 9, 1,
  109. 13, 2, 1,
  110. 13, 1, 14,
  111. 23, 0, 3,
  112. 23, 3, 20,
  113. 17, 3, 2,
  114. 17, 2, 18,
  115. 21, 7, 6,
  116. 21, 6, 22,
  117. 7, 16, 19,
  118. 7, 19, 4,
  119. 5, 8, 11,
  120. 5, 11, 6,
  121. 4, 12, 15,
  122. 4, 15, 5,
  123. 22, 11, 10,
  124. 22, 10, 23,
  125. 8, 15, 14,
  126. 8, 14, 9,
  127. 12, 19, 18,
  128. 12, 18, 13,
  129. 16, 21, 20,
  130. 16, 20, 17,
  131. 0, 23, 10,
  132. 1, 9, 14,
  133. 2, 13, 18,
  134. 3, 17, 20,
  135. 6, 11, 22,
  136. 5, 15, 8,
  137. 4, 19, 12,
  138. 7, 21, 16
  139. };
  140. static const float spotLightVertexData[] =
  141. {
  142. 0.00001f, 0.00001f, 0.00001f,
  143. 0.00001f, -0.00001f, 0.00001f,
  144. -0.00001f, -0.00001f, 0.00001f,
  145. -0.00001f, 0.00001f, 0.00001f,
  146. 1.00000f, 1.00000f, 0.99999f,
  147. 1.00000f, -1.00000f, 0.99999f,
  148. -1.00000f, -1.00000f, 0.99999f,
  149. -1.00000f, 1.00000f, 0.99999f,
  150. };
  151. static const unsigned short spotLightIndexData[] =
  152. {
  153. 3, 0, 1,
  154. 3, 1, 2,
  155. 0, 4, 5,
  156. 0, 5, 1,
  157. 3, 7, 4,
  158. 3, 4, 0,
  159. 7, 3, 2,
  160. 7, 2, 6,
  161. 6, 2, 1,
  162. 6, 1, 5,
  163. 7, 5, 4,
  164. 7, 6, 5
  165. };
  166. static const char* geometryVSVariations[] =
  167. {
  168. "",
  169. "SKINNED ",
  170. "INSTANCED ",
  171. "BILLBOARD ",
  172. "DIRBILLBOARD ",
  173. "TRAILFACECAM ",
  174. "TRAILBONE "
  175. };
  176. static const char* lightVSVariations[] =
  177. {
  178. "PERPIXEL DIRLIGHT ",
  179. "PERPIXEL SPOTLIGHT ",
  180. "PERPIXEL POINTLIGHT ",
  181. "PERPIXEL DIRLIGHT SHADOW ",
  182. "PERPIXEL SPOTLIGHT SHADOW ",
  183. "PERPIXEL POINTLIGHT SHADOW ",
  184. "PERPIXEL DIRLIGHT SHADOW NORMALOFFSET ",
  185. "PERPIXEL SPOTLIGHT SHADOW NORMALOFFSET ",
  186. "PERPIXEL POINTLIGHT SHADOW NORMALOFFSET "
  187. };
  188. static const char* vertexLightVSVariations[] =
  189. {
  190. "",
  191. "NUMVERTEXLIGHTS=1 ",
  192. "NUMVERTEXLIGHTS=2 ",
  193. "NUMVERTEXLIGHTS=3 ",
  194. "NUMVERTEXLIGHTS=4 ",
  195. };
  196. static const char* deferredLightVSVariations[] =
  197. {
  198. "",
  199. "DIRLIGHT ",
  200. "ORTHO ",
  201. "DIRLIGHT ORTHO "
  202. };
  203. static const char* lightPSVariations[] =
  204. {
  205. "PERPIXEL DIRLIGHT ",
  206. "PERPIXEL SPOTLIGHT ",
  207. "PERPIXEL POINTLIGHT ",
  208. "PERPIXEL POINTLIGHT CUBEMASK ",
  209. "PERPIXEL DIRLIGHT SPECULAR ",
  210. "PERPIXEL SPOTLIGHT SPECULAR ",
  211. "PERPIXEL POINTLIGHT SPECULAR ",
  212. "PERPIXEL POINTLIGHT CUBEMASK SPECULAR ",
  213. "PERPIXEL DIRLIGHT SHADOW ",
  214. "PERPIXEL SPOTLIGHT SHADOW ",
  215. "PERPIXEL POINTLIGHT SHADOW ",
  216. "PERPIXEL POINTLIGHT CUBEMASK SHADOW ",
  217. "PERPIXEL DIRLIGHT SPECULAR SHADOW ",
  218. "PERPIXEL SPOTLIGHT SPECULAR SHADOW ",
  219. "PERPIXEL POINTLIGHT SPECULAR SHADOW ",
  220. "PERPIXEL POINTLIGHT CUBEMASK SPECULAR SHADOW ",
  221. "PERPIXEL DIRLIGHT SHADOW NORMALOFFSET ",
  222. "PERPIXEL SPOTLIGHT SHADOW NORMALOFFSET ",
  223. "PERPIXEL POINTLIGHT SHADOW NORMALOFFSET ",
  224. "PERPIXEL POINTLIGHT CUBEMASK SHADOW NORMALOFFSET ",
  225. "PERPIXEL DIRLIGHT SPECULAR SHADOW NORMALOFFSET ",
  226. "PERPIXEL SPOTLIGHT SPECULAR SHADOW NORMALOFFSET ",
  227. "PERPIXEL POINTLIGHT SPECULAR SHADOW NORMALOFFSET ",
  228. "PERPIXEL POINTLIGHT CUBEMASK SPECULAR SHADOW NORMALOFFSET "
  229. };
  230. static const char* heightFogVariations[] =
  231. {
  232. "",
  233. "HEIGHTFOG "
  234. };
  235. static const unsigned MAX_BUFFER_AGE = 1000;
  236. static const int MAX_EXTRA_INSTANCING_BUFFER_ELEMENTS = 4;
  237. inline PODVector<VertexElement> CreateInstancingBufferElements(unsigned numExtraElements)
  238. {
  239. static const unsigned NUM_INSTANCEMATRIX_ELEMENTS = 3;
  240. static const unsigned FIRST_UNUSED_TEXCOORD = 4;
  241. PODVector<VertexElement> elements;
  242. for (unsigned i = 0; i < NUM_INSTANCEMATRIX_ELEMENTS + numExtraElements; ++i)
  243. elements.Push(VertexElement(TYPE_VECTOR4, SEM_TEXCOORD, FIRST_UNUSED_TEXCOORD + i, true));
  244. return elements;
  245. }
  246. Renderer::Renderer(Context* context) :
  247. Object(context),
  248. defaultZone_(new Zone(context)),
  249. shadowMapFilterInstance_(nullptr),
  250. shadowMapFilter_(nullptr),
  251. textureAnisotropy_(4),
  252. textureFilterMode_(FILTER_TRILINEAR),
  253. textureQuality_(QUALITY_HIGH),
  254. materialQuality_(QUALITY_HIGH),
  255. shadowMapSize_(1024),
  256. shadowQuality_(SHADOWQUALITY_PCF_16BIT),
  257. shadowSoftness_(1.0f),
  258. vsmShadowParams_(0.0000001f, 0.9f),
  259. vsmMultiSample_(1),
  260. maxShadowMaps_(1),
  261. minInstances_(2),
  262. maxSortedInstances_(1000),
  263. maxOccluderTriangles_(5000),
  264. occlusionBufferSize_(256),
  265. occluderSizeThreshold_(0.025f),
  266. mobileShadowBiasMul_(1.0f),
  267. mobileShadowBiasAdd_(0.0f),
  268. mobileNormalOffsetMul_(1.0f),
  269. numOcclusionBuffers_(0),
  270. numShadowCameras_(0),
  271. shadersChangedFrameNumber_(M_MAX_UNSIGNED),
  272. hdrRendering_(false),
  273. specularLighting_(true),
  274. drawShadows_(true),
  275. reuseShadowMaps_(true),
  276. dynamicInstancing_(true),
  277. numExtraInstancingBufferElements_(0),
  278. threadedOcclusion_(false),
  279. shadersDirty_(true),
  280. initialized_(false),
  281. resetViews_(false)
  282. {
  283. SubscribeToEvent(E_SCREENMODE, URHO3D_HANDLER(Renderer, HandleScreenMode));
  284. // Try to initialize right now, but skip if screen mode is not yet set
  285. Initialize();
  286. }
  287. Renderer::~Renderer()
  288. {
  289. }
  290. void Renderer::SetNumViewports(unsigned num)
  291. {
  292. viewports_.Resize(num);
  293. }
  294. void Renderer::SetViewport(unsigned index, Viewport* viewport)
  295. {
  296. if (index >= viewports_.Size())
  297. viewports_.Resize(index + 1);
  298. viewports_[index] = viewport;
  299. }
  300. void Renderer::SetDefaultRenderPath(RenderPath* renderPath)
  301. {
  302. if (renderPath)
  303. defaultRenderPath_ = renderPath;
  304. }
  305. void Renderer::SetDefaultRenderPath(XMLFile* xmlFile)
  306. {
  307. SharedPtr<RenderPath> newRenderPath(new RenderPath());
  308. if (newRenderPath->Load(xmlFile))
  309. defaultRenderPath_ = newRenderPath;
  310. }
  311. void Renderer::SetDefaultTechnique(Technique* technique)
  312. {
  313. defaultTechnique_ = technique;
  314. }
  315. void Renderer::SetHDRRendering(bool enable)
  316. {
  317. hdrRendering_ = enable;
  318. }
  319. void Renderer::SetSpecularLighting(bool enable)
  320. {
  321. specularLighting_ = enable;
  322. }
  323. void Renderer::SetTextureAnisotropy(int level)
  324. {
  325. textureAnisotropy_ = Max(level, 1);
  326. }
  327. void Renderer::SetTextureFilterMode(TextureFilterMode mode)
  328. {
  329. textureFilterMode_ = mode;
  330. }
  331. void Renderer::SetTextureQuality(int quality)
  332. {
  333. quality = Clamp(quality, QUALITY_LOW, QUALITY_HIGH);
  334. if (quality != textureQuality_)
  335. {
  336. textureQuality_ = quality;
  337. ReloadTextures();
  338. }
  339. }
  340. void Renderer::SetMaterialQuality(int quality)
  341. {
  342. quality = Clamp(quality, QUALITY_LOW, QUALITY_MAX);
  343. if (quality != materialQuality_)
  344. {
  345. materialQuality_ = quality;
  346. shadersDirty_ = true;
  347. // Reallocate views to not store eg. pass information that might be unnecessary on the new material quality level
  348. resetViews_ = true;
  349. }
  350. }
  351. void Renderer::SetDrawShadows(bool enable)
  352. {
  353. if (!graphics_ || !graphics_->GetShadowMapFormat())
  354. return;
  355. drawShadows_ = enable;
  356. if (!drawShadows_)
  357. ResetShadowMaps();
  358. }
  359. void Renderer::SetShadowMapSize(int size)
  360. {
  361. if (!graphics_)
  362. return;
  363. size = NextPowerOfTwo((unsigned)Max(size, SHADOW_MIN_PIXELS));
  364. if (size != shadowMapSize_)
  365. {
  366. shadowMapSize_ = size;
  367. ResetShadowMaps();
  368. }
  369. }
  370. void Renderer::SetShadowQuality(ShadowQuality quality)
  371. {
  372. if (!graphics_)
  373. return;
  374. // If no hardware PCF, do not allow to select one-sample quality
  375. if (!graphics_->GetHardwareShadowSupport())
  376. {
  377. if (quality == SHADOWQUALITY_SIMPLE_16BIT)
  378. quality = SHADOWQUALITY_PCF_16BIT;
  379. if (quality == SHADOWQUALITY_SIMPLE_24BIT)
  380. quality = SHADOWQUALITY_PCF_24BIT;
  381. }
  382. // if high resolution is not allowed
  383. if (!graphics_->GetHiresShadowMapFormat())
  384. {
  385. if (quality == SHADOWQUALITY_SIMPLE_24BIT)
  386. quality = SHADOWQUALITY_SIMPLE_16BIT;
  387. if (quality == SHADOWQUALITY_PCF_24BIT)
  388. quality = SHADOWQUALITY_PCF_16BIT;
  389. }
  390. if (quality != shadowQuality_)
  391. {
  392. shadowQuality_ = quality;
  393. shadersDirty_ = true;
  394. if (quality == SHADOWQUALITY_BLUR_VSM)
  395. SetShadowMapFilter(this, static_cast<ShadowMapFilter>(&Renderer::BlurShadowMap));
  396. else
  397. SetShadowMapFilter(nullptr, nullptr);
  398. ResetShadowMaps();
  399. }
  400. }
  401. void Renderer::SetShadowSoftness(float shadowSoftness)
  402. {
  403. shadowSoftness_ = Max(shadowSoftness, 0.0f);
  404. }
  405. void Renderer::SetVSMShadowParameters(float minVariance, float lightBleedingReduction)
  406. {
  407. vsmShadowParams_.x_ = Max(minVariance, 0.0f);
  408. vsmShadowParams_.y_ = Clamp(lightBleedingReduction, 0.0f, 1.0f);
  409. }
  410. void Renderer::SetVSMMultiSample(int multiSample)
  411. {
  412. multiSample = Clamp(multiSample, 1, 16);
  413. if (multiSample != vsmMultiSample_)
  414. {
  415. vsmMultiSample_ = multiSample;
  416. ResetShadowMaps();
  417. }
  418. }
  419. void Renderer::SetShadowMapFilter(Object* instance, ShadowMapFilter functionPtr)
  420. {
  421. shadowMapFilterInstance_ = instance;
  422. shadowMapFilter_ = functionPtr;
  423. }
  424. void Renderer::SetReuseShadowMaps(bool enable)
  425. {
  426. reuseShadowMaps_ = enable;
  427. }
  428. void Renderer::SetMaxShadowMaps(int shadowMaps)
  429. {
  430. if (shadowMaps < 1)
  431. return;
  432. maxShadowMaps_ = shadowMaps;
  433. for (HashMap<int, Vector<SharedPtr<Texture2D> > >::Iterator i = shadowMaps_.Begin(); i != shadowMaps_.End(); ++i)
  434. {
  435. if ((int)i->second_.Size() > maxShadowMaps_)
  436. i->second_.Resize((unsigned)maxShadowMaps_);
  437. }
  438. }
  439. void Renderer::SetDynamicInstancing(bool enable)
  440. {
  441. if (!instancingBuffer_)
  442. enable = false;
  443. dynamicInstancing_ = enable;
  444. }
  445. void Renderer::SetNumExtraInstancingBufferElements(int elements)
  446. {
  447. if (numExtraInstancingBufferElements_ != elements)
  448. {
  449. numExtraInstancingBufferElements_ = Clamp(elements, 0, MAX_EXTRA_INSTANCING_BUFFER_ELEMENTS);
  450. CreateInstancingBuffer();
  451. }
  452. }
  453. void Renderer::SetMinInstances(int instances)
  454. {
  455. minInstances_ = Max(instances, 1);
  456. }
  457. void Renderer::SetMaxSortedInstances(int instances)
  458. {
  459. maxSortedInstances_ = Max(instances, 0);
  460. }
  461. void Renderer::SetMaxOccluderTriangles(int triangles)
  462. {
  463. maxOccluderTriangles_ = Max(triangles, 0);
  464. }
  465. void Renderer::SetOcclusionBufferSize(int size)
  466. {
  467. occlusionBufferSize_ = Max(size, 1);
  468. occlusionBuffers_.Clear();
  469. }
  470. void Renderer::SetMobileShadowBiasMul(float mul)
  471. {
  472. mobileShadowBiasMul_ = mul;
  473. }
  474. void Renderer::SetMobileShadowBiasAdd(float add)
  475. {
  476. mobileShadowBiasAdd_ = add;
  477. }
  478. void Renderer::SetMobileNormalOffsetMul(float mul)
  479. {
  480. mobileNormalOffsetMul_ = mul;
  481. }
  482. void Renderer::SetOccluderSizeThreshold(float screenSize)
  483. {
  484. occluderSizeThreshold_ = Max(screenSize, 0.0f);
  485. }
  486. void Renderer::SetThreadedOcclusion(bool enable)
  487. {
  488. if (enable != threadedOcclusion_)
  489. {
  490. threadedOcclusion_ = enable;
  491. occlusionBuffers_.Clear();
  492. }
  493. }
  494. void Renderer::ReloadShaders()
  495. {
  496. shadersDirty_ = true;
  497. }
  498. void Renderer::ApplyShadowMapFilter(View* view, Texture2D* shadowMap, float blurScale)
  499. {
  500. if (shadowMapFilterInstance_ && shadowMapFilter_)
  501. (shadowMapFilterInstance_->*shadowMapFilter_)(view, shadowMap, blurScale);
  502. }
  503. Viewport* Renderer::GetViewport(unsigned index) const
  504. {
  505. return index < viewports_.Size() ? viewports_[index] : nullptr;
  506. }
  507. Viewport* Renderer::GetViewportForScene(Scene* scene, unsigned index) const
  508. {
  509. for (unsigned i = 0; i < viewports_.Size(); ++i)
  510. {
  511. Viewport* viewport = viewports_[i];
  512. if (viewport && viewport->GetScene() == scene)
  513. {
  514. if (index == 0)
  515. return viewport;
  516. else
  517. --index;
  518. }
  519. }
  520. return nullptr;
  521. }
  522. RenderPath* Renderer::GetDefaultRenderPath() const
  523. {
  524. return defaultRenderPath_;
  525. }
  526. Technique* Renderer::GetDefaultTechnique() const
  527. {
  528. // Assign default when first asked if not assigned yet
  529. if (!defaultTechnique_)
  530. const_cast<SharedPtr<Technique>& >(defaultTechnique_) = GetSubsystem<ResourceCache>()->GetResource<Technique>("Techniques/NoTexture.xml");
  531. return defaultTechnique_;
  532. }
  533. unsigned Renderer::GetNumGeometries(bool allViews) const
  534. {
  535. unsigned numGeometries = 0;
  536. unsigned lastView = allViews ? views_.Size() : 1;
  537. for (unsigned i = 0; i < lastView; ++i)
  538. {
  539. // Use the source view's statistics if applicable
  540. View* view = GetActualView(views_[i]);
  541. if (!view)
  542. continue;
  543. numGeometries += view->GetGeometries().Size();
  544. }
  545. return numGeometries;
  546. }
  547. unsigned Renderer::GetNumLights(bool allViews) const
  548. {
  549. unsigned numLights = 0;
  550. unsigned lastView = allViews ? views_.Size() : 1;
  551. for (unsigned i = 0; i < lastView; ++i)
  552. {
  553. View* view = GetActualView(views_[i]);
  554. if (!view)
  555. continue;
  556. numLights += view->GetLights().Size();
  557. }
  558. return numLights;
  559. }
  560. unsigned Renderer::GetNumShadowMaps(bool allViews) const
  561. {
  562. unsigned numShadowMaps = 0;
  563. unsigned lastView = allViews ? views_.Size() : 1;
  564. for (unsigned i = 0; i < lastView; ++i)
  565. {
  566. View* view = GetActualView(views_[i]);
  567. if (!view)
  568. continue;
  569. const Vector<LightBatchQueue>& lightQueues = view->GetLightQueues();
  570. for (Vector<LightBatchQueue>::ConstIterator i = lightQueues.Begin(); i != lightQueues.End(); ++i)
  571. {
  572. if (i->shadowMap_)
  573. ++numShadowMaps;
  574. }
  575. }
  576. return numShadowMaps;
  577. }
  578. unsigned Renderer::GetNumOccluders(bool allViews) const
  579. {
  580. unsigned numOccluders = 0;
  581. unsigned lastView = allViews ? views_.Size() : 1;
  582. for (unsigned i = 0; i < lastView; ++i)
  583. {
  584. View* view = GetActualView(views_[i]);
  585. if (!view)
  586. continue;
  587. numOccluders += view->GetNumActiveOccluders();
  588. }
  589. return numOccluders;
  590. }
  591. void Renderer::Update(float timeStep)
  592. {
  593. URHO3D_PROFILE(UpdateViews);
  594. views_.Clear();
  595. preparedViews_.Clear();
  596. // If device lost, do not perform update. This is because any dynamic vertex/index buffer updates happen already here,
  597. // and if the device is lost, the updates queue up, causing memory use to rise constantly
  598. if (!graphics_ || !graphics_->IsInitialized() || graphics_->IsDeviceLost())
  599. return;
  600. // Set up the frameinfo structure for this frame
  601. frame_.frameNumber_ = GetSubsystem<Time>()->GetFrameNumber();
  602. frame_.timeStep_ = timeStep;
  603. frame_.camera_ = nullptr;
  604. numShadowCameras_ = 0;
  605. numOcclusionBuffers_ = 0;
  606. updatedOctrees_.Clear();
  607. // Reload shaders now if needed
  608. if (shadersDirty_)
  609. LoadShaders();
  610. // Queue update of the main viewports. Use reverse order, as rendering order is also reverse
  611. // to render auxiliary views before dependent main views
  612. for (unsigned i = viewports_.Size() - 1; i < viewports_.Size(); --i)
  613. QueueViewport(nullptr, viewports_[i]);
  614. // Update main viewports. This may queue further views
  615. unsigned numMainViewports = queuedViewports_.Size();
  616. for (unsigned i = 0; i < numMainViewports; ++i)
  617. UpdateQueuedViewport(i);
  618. // Gather queued & autoupdated render surfaces
  619. SendEvent(E_RENDERSURFACEUPDATE);
  620. // Update viewports that were added as result of the event above
  621. for (unsigned i = numMainViewports; i < queuedViewports_.Size(); ++i)
  622. UpdateQueuedViewport(i);
  623. queuedViewports_.Clear();
  624. resetViews_ = false;
  625. }
  626. void Renderer::Render()
  627. {
  628. // Engine does not render when window is closed or device is lost
  629. assert(graphics_ && graphics_->IsInitialized() && !graphics_->IsDeviceLost());
  630. URHO3D_PROFILE(RenderViews);
  631. // If the indirection textures have lost content (OpenGL mode only), restore them now
  632. if (faceSelectCubeMap_ && faceSelectCubeMap_->IsDataLost())
  633. SetIndirectionTextureData();
  634. graphics_->SetDefaultTextureFilterMode(textureFilterMode_);
  635. graphics_->SetDefaultTextureAnisotropy((unsigned)textureAnisotropy_);
  636. // If no views that render to the backbuffer, clear the screen so that e.g. the UI is not rendered on top of previous frame
  637. bool hasBackbufferViews = false;
  638. for (unsigned i = 0; i < views_.Size(); ++i)
  639. {
  640. if (!views_[i]->GetRenderTarget())
  641. {
  642. hasBackbufferViews = true;
  643. break;
  644. }
  645. }
  646. if (!hasBackbufferViews)
  647. {
  648. graphics_->SetBlendMode(BLEND_REPLACE);
  649. graphics_->SetColorWrite(true);
  650. graphics_->SetDepthWrite(true);
  651. graphics_->SetScissorTest(false);
  652. graphics_->SetStencilTest(false);
  653. graphics_->ResetRenderTargets();
  654. graphics_->Clear(CLEAR_COLOR | CLEAR_DEPTH | CLEAR_STENCIL, defaultZone_->GetFogColor());
  655. }
  656. // Render views from last to first. Each main (backbuffer) view is rendered after the auxiliary views it depends on
  657. for (unsigned i = views_.Size() - 1; i < views_.Size(); --i)
  658. {
  659. if (!views_[i])
  660. continue;
  661. // Screen buffers can be reused between views, as each is rendered completely
  662. PrepareViewRender();
  663. views_[i]->Render();
  664. }
  665. // Copy the number of batches & primitives from Graphics so that we can account for 3D geometry only
  666. numPrimitives_ = graphics_->GetNumPrimitives();
  667. numBatches_ = graphics_->GetNumBatches();
  668. // Remove unused occlusion buffers and renderbuffers
  669. RemoveUnusedBuffers();
  670. // All views done, custom rendering can now be done before UI
  671. SendEvent(E_ENDALLVIEWSRENDER);
  672. }
  673. void Renderer::DrawDebugGeometry(bool depthTest)
  674. {
  675. URHO3D_PROFILE(RendererDrawDebug);
  676. /// \todo Because debug geometry is per-scene, if two cameras show views of the same area, occlusion is not shown correctly
  677. HashSet<Drawable*> processedGeometries;
  678. HashSet<Light*> processedLights;
  679. for (unsigned i = 0; i < views_.Size(); ++i)
  680. {
  681. View* view = views_[i];
  682. if (!view || !view->GetDrawDebug())
  683. continue;
  684. Octree* octree = view->GetOctree();
  685. if (!octree)
  686. continue;
  687. DebugRenderer* debug = octree->GetComponent<DebugRenderer>();
  688. if (!debug || !debug->IsEnabledEffective())
  689. continue;
  690. // Process geometries / lights only once
  691. const PODVector<Drawable*>& geometries = view->GetGeometries();
  692. const PODVector<Light*>& lights = view->GetLights();
  693. for (unsigned i = 0; i < geometries.Size(); ++i)
  694. {
  695. if (!processedGeometries.Contains(geometries[i]))
  696. {
  697. geometries[i]->DrawDebugGeometry(debug, depthTest);
  698. processedGeometries.Insert(geometries[i]);
  699. }
  700. }
  701. for (unsigned i = 0; i < lights.Size(); ++i)
  702. {
  703. if (!processedLights.Contains(lights[i]))
  704. {
  705. lights[i]->DrawDebugGeometry(debug, depthTest);
  706. processedLights.Insert(lights[i]);
  707. }
  708. }
  709. }
  710. }
  711. void Renderer::QueueRenderSurface(RenderSurface* renderTarget)
  712. {
  713. if (renderTarget)
  714. {
  715. unsigned numViewports = renderTarget->GetNumViewports();
  716. for (unsigned i = 0; i < numViewports; ++i)
  717. QueueViewport(renderTarget, renderTarget->GetViewport(i));
  718. }
  719. }
  720. void Renderer::QueueViewport(RenderSurface* renderTarget, Viewport* viewport)
  721. {
  722. if (viewport)
  723. {
  724. Pair<WeakPtr<RenderSurface>, WeakPtr<Viewport> > newView =
  725. MakePair(WeakPtr<RenderSurface>(renderTarget), WeakPtr<Viewport>(viewport));
  726. // Prevent double add of the same rendertarget/viewport combination
  727. if (!queuedViewports_.Contains(newView))
  728. queuedViewports_.Push(newView);
  729. }
  730. }
  731. Geometry* Renderer::GetLightGeometry(Light* light)
  732. {
  733. switch (light->GetLightType())
  734. {
  735. case LIGHT_DIRECTIONAL:
  736. return dirLightGeometry_;
  737. case LIGHT_SPOT:
  738. return spotLightGeometry_;
  739. case LIGHT_POINT:
  740. return pointLightGeometry_;
  741. }
  742. return nullptr;
  743. }
  744. Geometry* Renderer::GetQuadGeometry()
  745. {
  746. return dirLightGeometry_;
  747. }
  748. Texture2D* Renderer::GetShadowMap(Light* light, Camera* camera, unsigned viewWidth, unsigned viewHeight)
  749. {
  750. LightType type = light->GetLightType();
  751. const FocusParameters& parameters = light->GetShadowFocus();
  752. float size = (float)shadowMapSize_ * light->GetShadowResolution();
  753. // Automatically reduce shadow map size when far away
  754. if (parameters.autoSize_ && type != LIGHT_DIRECTIONAL)
  755. {
  756. const Matrix3x4& view = camera->GetView();
  757. const Matrix4& projection = camera->GetProjection();
  758. BoundingBox lightBox;
  759. float lightPixels;
  760. if (type == LIGHT_POINT)
  761. {
  762. // Calculate point light pixel size from the projection of its diagonal
  763. Vector3 center = view * light->GetNode()->GetWorldPosition();
  764. float extent = 0.58f * light->GetRange();
  765. lightBox.Define(center + Vector3(extent, extent, extent), center - Vector3(extent, extent, extent));
  766. }
  767. else
  768. {
  769. // Calculate spot light pixel size from the projection of its frustum far vertices
  770. Frustum lightFrustum = light->GetViewSpaceFrustum(view);
  771. lightBox.Define(&lightFrustum.vertices_[4], 4);
  772. }
  773. Vector2 projectionSize = lightBox.Projected(projection).Size();
  774. lightPixels = Max(0.5f * (float)viewWidth * projectionSize.x_, 0.5f * (float)viewHeight * projectionSize.y_);
  775. // Clamp pixel amount to a sufficient minimum to avoid self-shadowing artifacts due to loss of precision
  776. if (lightPixels < SHADOW_MIN_PIXELS)
  777. lightPixels = SHADOW_MIN_PIXELS;
  778. size = Min(size, lightPixels);
  779. }
  780. /// \todo Allow to specify maximum shadow maps per resolution, as smaller shadow maps take less memory
  781. int width = NextPowerOfTwo((unsigned)size);
  782. int height = width;
  783. // Adjust the size for directional or point light shadow map atlases
  784. if (type == LIGHT_DIRECTIONAL)
  785. {
  786. unsigned numSplits = (unsigned)light->GetNumShadowSplits();
  787. if (numSplits > 1)
  788. width *= 2;
  789. if (numSplits > 2)
  790. height *= 2;
  791. }
  792. else if (type == LIGHT_POINT)
  793. {
  794. width *= 2;
  795. height *= 3;
  796. }
  797. int searchKey = (width << 16) | height;
  798. if (shadowMaps_.Contains(searchKey))
  799. {
  800. // If shadow maps are reused, always return the first
  801. if (reuseShadowMaps_)
  802. return shadowMaps_[searchKey][0];
  803. else
  804. {
  805. // If not reused, check allocation count and return existing shadow map if possible
  806. unsigned allocated = shadowMapAllocations_[searchKey].Size();
  807. if (allocated < shadowMaps_[searchKey].Size())
  808. {
  809. shadowMapAllocations_[searchKey].Push(light);
  810. return shadowMaps_[searchKey][allocated];
  811. }
  812. else if ((int)allocated >= maxShadowMaps_)
  813. return nullptr;
  814. }
  815. }
  816. // Find format and usage of the shadow map
  817. unsigned shadowMapFormat = 0;
  818. TextureUsage shadowMapUsage = TEXTURE_DEPTHSTENCIL;
  819. int multiSample = 1;
  820. switch (shadowQuality_)
  821. {
  822. case SHADOWQUALITY_SIMPLE_16BIT:
  823. case SHADOWQUALITY_PCF_16BIT:
  824. shadowMapFormat = graphics_->GetShadowMapFormat();
  825. break;
  826. case SHADOWQUALITY_SIMPLE_24BIT:
  827. case SHADOWQUALITY_PCF_24BIT:
  828. shadowMapFormat = graphics_->GetHiresShadowMapFormat();
  829. break;
  830. case SHADOWQUALITY_VSM:
  831. case SHADOWQUALITY_BLUR_VSM:
  832. shadowMapFormat = graphics_->GetRGFloat32Format();
  833. shadowMapUsage = TEXTURE_RENDERTARGET;
  834. multiSample = vsmMultiSample_;
  835. break;
  836. }
  837. if (!shadowMapFormat)
  838. return nullptr;
  839. SharedPtr<Texture2D> newShadowMap(new Texture2D(context_));
  840. int retries = 3;
  841. unsigned dummyColorFormat = graphics_->GetDummyColorFormat();
  842. // Disable mipmaps from the shadow map
  843. newShadowMap->SetNumLevels(1);
  844. while (retries)
  845. {
  846. if (!newShadowMap->SetSize(width, height, shadowMapFormat, shadowMapUsage, multiSample))
  847. {
  848. width >>= 1;
  849. height >>= 1;
  850. --retries;
  851. }
  852. else
  853. {
  854. #ifndef GL_ES_VERSION_2_0
  855. // OpenGL (desktop) and D3D11: shadow compare mode needs to be specifically enabled for the shadow map
  856. newShadowMap->SetFilterMode(FILTER_BILINEAR);
  857. newShadowMap->SetShadowCompare(shadowMapUsage == TEXTURE_DEPTHSTENCIL);
  858. #endif
  859. #ifndef URHO3D_OPENGL
  860. // Direct3D9: when shadow compare must be done manually, use nearest filtering so that the filtering of point lights
  861. // and other shadowed lights matches
  862. newShadowMap->SetFilterMode(graphics_->GetHardwareShadowSupport() ? FILTER_BILINEAR : FILTER_NEAREST);
  863. #endif
  864. // Create dummy color texture for the shadow map if necessary: Direct3D9, or OpenGL when working around an OS X +
  865. // Intel driver bug
  866. if (shadowMapUsage == TEXTURE_DEPTHSTENCIL && dummyColorFormat)
  867. {
  868. // If no dummy color rendertarget for this size exists yet, create one now
  869. if (!colorShadowMaps_.Contains(searchKey))
  870. {
  871. colorShadowMaps_[searchKey] = new Texture2D(context_);
  872. colorShadowMaps_[searchKey]->SetNumLevels(1);
  873. colorShadowMaps_[searchKey]->SetSize(width, height, dummyColorFormat, TEXTURE_RENDERTARGET);
  874. }
  875. // Link the color rendertarget to the shadow map
  876. newShadowMap->GetRenderSurface()->SetLinkedRenderTarget(colorShadowMaps_[searchKey]->GetRenderSurface());
  877. }
  878. break;
  879. }
  880. }
  881. // If failed to set size, store a null pointer so that we will not retry
  882. if (!retries)
  883. newShadowMap.Reset();
  884. shadowMaps_[searchKey].Push(newShadowMap);
  885. if (!reuseShadowMaps_)
  886. shadowMapAllocations_[searchKey].Push(light);
  887. return newShadowMap;
  888. }
  889. Texture* Renderer::GetScreenBuffer(int width, int height, unsigned format, int multiSample, bool autoResolve, bool cubemap, bool filtered, bool srgb,
  890. unsigned persistentKey)
  891. {
  892. bool depthStencil = (format == Graphics::GetDepthStencilFormat()) || (format == Graphics::GetReadableDepthFormat());
  893. if (depthStencil)
  894. {
  895. filtered = false;
  896. srgb = false;
  897. }
  898. if (cubemap)
  899. height = width;
  900. multiSample = Clamp(multiSample, 1, 16);
  901. if (multiSample == 1)
  902. autoResolve = false;
  903. long long searchKey = ((long long)format << 32) | (multiSample << 24) | (width << 12) | height;
  904. if (filtered)
  905. searchKey |= 0x8000000000000000LL;
  906. if (srgb)
  907. searchKey |= 0x4000000000000000LL;
  908. if (cubemap)
  909. searchKey |= 0x2000000000000000LL;
  910. if (autoResolve)
  911. searchKey |= 0x1000000000000000LL;
  912. // Add persistent key if defined
  913. if (persistentKey)
  914. searchKey += ((long long)persistentKey << 32);
  915. // If new size or format, initialize the allocation stats
  916. if (screenBuffers_.Find(searchKey) == screenBuffers_.End())
  917. screenBufferAllocations_[searchKey] = 0;
  918. // Reuse depth-stencil buffers whenever the size matches, instead of allocating new
  919. // Unless persistency specified
  920. unsigned allocations = screenBufferAllocations_[searchKey];
  921. if (!depthStencil || persistentKey)
  922. ++screenBufferAllocations_[searchKey];
  923. if (allocations >= screenBuffers_[searchKey].Size())
  924. {
  925. SharedPtr<Texture> newBuffer;
  926. if (!cubemap)
  927. {
  928. SharedPtr<Texture2D> newTex2D(new Texture2D(context_));
  929. /// \todo Mipmaps disabled for now. Allow to request mipmapped buffer?
  930. newTex2D->SetNumLevels(1);
  931. newTex2D->SetSize(width, height, format, depthStencil ? TEXTURE_DEPTHSTENCIL : TEXTURE_RENDERTARGET, multiSample, autoResolve);
  932. #ifdef URHO3D_OPENGL
  933. // OpenGL hack: clear persistent floating point screen buffers to ensure the initial contents aren't illegal (NaN)?
  934. // Otherwise eg. the AutoExposure post process will not work correctly
  935. if (persistentKey && Texture::GetDataType(format) == GL_FLOAT)
  936. {
  937. // Note: this loses current rendertarget assignment
  938. graphics_->ResetRenderTargets();
  939. graphics_->SetRenderTarget(0, newTex2D);
  940. graphics_->SetDepthStencil((RenderSurface*)0);
  941. graphics_->SetViewport(IntRect(0, 0, width, height));
  942. graphics_->Clear(CLEAR_COLOR);
  943. }
  944. #endif
  945. newBuffer = newTex2D;
  946. }
  947. else
  948. {
  949. SharedPtr<TextureCube> newTexCube(new TextureCube(context_));
  950. newTexCube->SetNumLevels(1);
  951. newTexCube->SetSize(width, format, TEXTURE_RENDERTARGET, multiSample);
  952. newBuffer = newTexCube;
  953. }
  954. newBuffer->SetSRGB(srgb);
  955. newBuffer->SetFilterMode(filtered ? FILTER_BILINEAR : FILTER_NEAREST);
  956. newBuffer->ResetUseTimer();
  957. screenBuffers_[searchKey].Push(newBuffer);
  958. URHO3D_LOGDEBUG("Allocated new screen buffer size " + String(width) + "x" + String(height) + " format " + String(format));
  959. return newBuffer;
  960. }
  961. else
  962. {
  963. Texture* buffer = screenBuffers_[searchKey][allocations];
  964. buffer->ResetUseTimer();
  965. return buffer;
  966. }
  967. }
  968. RenderSurface* Renderer::GetDepthStencil(int width, int height, int multiSample, bool autoResolve)
  969. {
  970. // Return the default depth-stencil surface if applicable
  971. // (when using OpenGL Graphics will allocate right size surfaces on demand to emulate Direct3D9)
  972. if (width == graphics_->GetWidth() && height == graphics_->GetHeight() && multiSample == 1 &&
  973. graphics_->GetMultiSample() == multiSample)
  974. return nullptr;
  975. else
  976. {
  977. return static_cast<Texture2D*>(GetScreenBuffer(width, height, Graphics::GetDepthStencilFormat(), multiSample, autoResolve,
  978. false, false, false))->GetRenderSurface();
  979. }
  980. }
  981. OcclusionBuffer* Renderer::GetOcclusionBuffer(Camera* camera)
  982. {
  983. assert(numOcclusionBuffers_ <= occlusionBuffers_.Size());
  984. if (numOcclusionBuffers_ == occlusionBuffers_.Size())
  985. {
  986. SharedPtr<OcclusionBuffer> newBuffer(new OcclusionBuffer(context_));
  987. occlusionBuffers_.Push(newBuffer);
  988. }
  989. int width = occlusionBufferSize_;
  990. int height = (int)((float)occlusionBufferSize_ / camera->GetAspectRatio() + 0.5f);
  991. OcclusionBuffer* buffer = occlusionBuffers_[numOcclusionBuffers_++];
  992. buffer->SetSize(width, height, threadedOcclusion_);
  993. buffer->SetView(camera);
  994. buffer->ResetUseTimer();
  995. return buffer;
  996. }
  997. Camera* Renderer::GetShadowCamera()
  998. {
  999. MutexLock lock(rendererMutex_);
  1000. assert(numShadowCameras_ <= shadowCameraNodes_.Size());
  1001. if (numShadowCameras_ == shadowCameraNodes_.Size())
  1002. {
  1003. SharedPtr<Node> newNode(new Node(context_));
  1004. newNode->CreateComponent<Camera>();
  1005. shadowCameraNodes_.Push(newNode);
  1006. }
  1007. Camera* camera = shadowCameraNodes_[numShadowCameras_++]->GetComponent<Camera>();
  1008. camera->SetOrthographic(false);
  1009. camera->SetZoom(1.0f);
  1010. return camera;
  1011. }
  1012. void Renderer::StorePreparedView(View* view, Camera* camera)
  1013. {
  1014. if (view && camera)
  1015. preparedViews_[camera] = view;
  1016. }
  1017. View* Renderer::GetPreparedView(Camera* camera)
  1018. {
  1019. HashMap<Camera*, WeakPtr<View> >::Iterator i = preparedViews_.Find(camera);
  1020. return i != preparedViews_.End() ? i->second_ : nullptr;
  1021. }
  1022. View* Renderer::GetActualView(View* view)
  1023. {
  1024. if (view && view->GetSourceView())
  1025. return view->GetSourceView();
  1026. else
  1027. return view;
  1028. }
  1029. void Renderer::SetBatchShaders(Batch& batch, Technique* tech, bool allowShadows, const BatchQueue& queue)
  1030. {
  1031. Pass* pass = batch.pass_;
  1032. // Check if need to release/reload all shaders
  1033. if (pass->GetShadersLoadedFrameNumber() != shadersChangedFrameNumber_)
  1034. pass->ReleaseShaders();
  1035. Vector<SharedPtr<ShaderVariation> >& vertexShaders = queue.hasExtraDefines_ ? pass->GetVertexShaders(queue.vsExtraDefinesHash_) : pass->GetVertexShaders();
  1036. Vector<SharedPtr<ShaderVariation> >& pixelShaders = queue.hasExtraDefines_ ? pass->GetPixelShaders(queue.psExtraDefinesHash_) : pass->GetPixelShaders();
  1037. // Load shaders now if necessary
  1038. if (!vertexShaders.Size() || !pixelShaders.Size())
  1039. LoadPassShaders(pass, vertexShaders, pixelShaders, queue);
  1040. // Make sure shaders are loaded now
  1041. if (vertexShaders.Size() && pixelShaders.Size())
  1042. {
  1043. bool heightFog = batch.zone_ && batch.zone_->GetHeightFog();
  1044. // If instancing is not supported, but was requested, choose static geometry vertex shader instead
  1045. if (batch.geometryType_ == GEOM_INSTANCED && !GetDynamicInstancing())
  1046. batch.geometryType_ = GEOM_STATIC;
  1047. if (batch.geometryType_ == GEOM_STATIC_NOINSTANCING)
  1048. batch.geometryType_ = GEOM_STATIC;
  1049. // Check whether is a pixel lit forward pass. If not, there is only one pixel shader
  1050. if (pass->GetLightingMode() == LIGHTING_PERPIXEL)
  1051. {
  1052. LightBatchQueue* lightQueue = batch.lightQueue_;
  1053. if (!lightQueue)
  1054. {
  1055. // Do not log error, as it would result in a lot of spam
  1056. batch.vertexShader_ = nullptr;
  1057. batch.pixelShader_ = nullptr;
  1058. return;
  1059. }
  1060. Light* light = lightQueue->light_;
  1061. unsigned vsi = 0;
  1062. unsigned psi = 0;
  1063. vsi = batch.geometryType_ * MAX_LIGHT_VS_VARIATIONS;
  1064. bool materialHasSpecular = batch.material_ ? batch.material_->GetSpecular() : true;
  1065. if (specularLighting_ && light->GetSpecularIntensity() > 0.0f && materialHasSpecular)
  1066. psi += LPS_SPEC;
  1067. if (allowShadows && lightQueue->shadowMap_)
  1068. {
  1069. if (light->GetShadowBias().normalOffset_ > 0.0f)
  1070. vsi += LVS_SHADOWNORMALOFFSET;
  1071. else
  1072. vsi += LVS_SHADOW;
  1073. psi += LPS_SHADOW;
  1074. }
  1075. switch (light->GetLightType())
  1076. {
  1077. case LIGHT_DIRECTIONAL:
  1078. vsi += LVS_DIR;
  1079. break;
  1080. case LIGHT_SPOT:
  1081. psi += LPS_SPOT;
  1082. vsi += LVS_SPOT;
  1083. break;
  1084. case LIGHT_POINT:
  1085. if (light->GetShapeTexture())
  1086. psi += LPS_POINTMASK;
  1087. else
  1088. psi += LPS_POINT;
  1089. vsi += LVS_POINT;
  1090. break;
  1091. }
  1092. if (heightFog)
  1093. psi += MAX_LIGHT_PS_VARIATIONS;
  1094. batch.vertexShader_ = vertexShaders[vsi];
  1095. batch.pixelShader_ = pixelShaders[psi];
  1096. }
  1097. else
  1098. {
  1099. // Check if pass has vertex lighting support
  1100. if (pass->GetLightingMode() == LIGHTING_PERVERTEX)
  1101. {
  1102. unsigned numVertexLights = 0;
  1103. if (batch.lightQueue_)
  1104. numVertexLights = batch.lightQueue_->vertexLights_.Size();
  1105. unsigned vsi = batch.geometryType_ * MAX_VERTEXLIGHT_VS_VARIATIONS + numVertexLights;
  1106. batch.vertexShader_ = vertexShaders[vsi];
  1107. }
  1108. else
  1109. {
  1110. unsigned vsi = batch.geometryType_;
  1111. batch.vertexShader_ = vertexShaders[vsi];
  1112. }
  1113. batch.pixelShader_ = pixelShaders[heightFog ? 1 : 0];
  1114. }
  1115. }
  1116. // Log error if shaders could not be assigned, but only once per technique
  1117. if (!batch.vertexShader_ || !batch.pixelShader_)
  1118. {
  1119. if (!shaderErrorDisplayed_.Contains(tech))
  1120. {
  1121. shaderErrorDisplayed_.Insert(tech);
  1122. URHO3D_LOGERROR("Technique " + tech->GetName() + " has missing shaders");
  1123. }
  1124. }
  1125. }
  1126. void Renderer::SetLightVolumeBatchShaders(Batch& batch, Camera* camera, const String& vsName, const String& psName, const String& vsDefines,
  1127. const String& psDefines)
  1128. {
  1129. assert(deferredLightPSVariations_.Size());
  1130. unsigned vsi = DLVS_NONE;
  1131. unsigned psi = DLPS_NONE;
  1132. Light* light = batch.lightQueue_->light_;
  1133. switch (light->GetLightType())
  1134. {
  1135. case LIGHT_DIRECTIONAL:
  1136. vsi += DLVS_DIR;
  1137. break;
  1138. case LIGHT_SPOT:
  1139. psi += DLPS_SPOT;
  1140. break;
  1141. case LIGHT_POINT:
  1142. if (light->GetShapeTexture())
  1143. psi += DLPS_POINTMASK;
  1144. else
  1145. psi += DLPS_POINT;
  1146. break;
  1147. }
  1148. if (batch.lightQueue_->shadowMap_)
  1149. {
  1150. if (light->GetShadowBias().normalOffset_ > 0.0)
  1151. psi += DLPS_SHADOWNORMALOFFSET;
  1152. else
  1153. psi += DLPS_SHADOW;
  1154. }
  1155. if (specularLighting_ && light->GetSpecularIntensity() > 0.0f)
  1156. psi += DLPS_SPEC;
  1157. if (camera->IsOrthographic())
  1158. {
  1159. vsi += DLVS_ORTHO;
  1160. psi += DLPS_ORTHO;
  1161. }
  1162. if (vsDefines.Length())
  1163. batch.vertexShader_ = graphics_->GetShader(VS, vsName, deferredLightVSVariations[vsi] + vsDefines);
  1164. else
  1165. batch.vertexShader_ = graphics_->GetShader(VS, vsName, deferredLightVSVariations[vsi]);
  1166. if (psDefines.Length())
  1167. batch.pixelShader_ = graphics_->GetShader(PS, psName, deferredLightPSVariations_[psi] + psDefines);
  1168. else
  1169. batch.pixelShader_ = graphics_->GetShader(PS, psName, deferredLightPSVariations_[psi]);
  1170. }
  1171. void Renderer::SetCullMode(CullMode mode, Camera* camera)
  1172. {
  1173. // If a camera is specified, check whether it reverses culling due to vertical flipping or reflection
  1174. if (camera && camera->GetReverseCulling())
  1175. {
  1176. if (mode == CULL_CW)
  1177. mode = CULL_CCW;
  1178. else if (mode == CULL_CCW)
  1179. mode = CULL_CW;
  1180. }
  1181. graphics_->SetCullMode(mode);
  1182. }
  1183. bool Renderer::ResizeInstancingBuffer(unsigned numInstances)
  1184. {
  1185. if (!instancingBuffer_ || !dynamicInstancing_)
  1186. return false;
  1187. unsigned oldSize = instancingBuffer_->GetVertexCount();
  1188. if (numInstances <= oldSize)
  1189. return true;
  1190. unsigned newSize = INSTANCING_BUFFER_DEFAULT_SIZE;
  1191. while (newSize < numInstances)
  1192. newSize <<= 1;
  1193. const PODVector<VertexElement> instancingBufferElements = CreateInstancingBufferElements(numExtraInstancingBufferElements_);
  1194. if (!instancingBuffer_->SetSize(newSize, instancingBufferElements, true))
  1195. {
  1196. URHO3D_LOGERROR("Failed to resize instancing buffer to " + String(newSize));
  1197. // If failed, try to restore the old size
  1198. instancingBuffer_->SetSize(oldSize, instancingBufferElements, true);
  1199. return false;
  1200. }
  1201. URHO3D_LOGDEBUG("Resized instancing buffer to " + String(newSize));
  1202. return true;
  1203. }
  1204. void Renderer::OptimizeLightByScissor(Light* light, Camera* camera)
  1205. {
  1206. if (light && light->GetLightType() != LIGHT_DIRECTIONAL)
  1207. graphics_->SetScissorTest(true, GetLightScissor(light, camera));
  1208. else
  1209. graphics_->SetScissorTest(false);
  1210. }
  1211. void Renderer::OptimizeLightByStencil(Light* light, Camera* camera)
  1212. {
  1213. if (light)
  1214. {
  1215. LightType type = light->GetLightType();
  1216. if (type == LIGHT_DIRECTIONAL)
  1217. {
  1218. graphics_->SetStencilTest(false);
  1219. return;
  1220. }
  1221. Geometry* geometry = GetLightGeometry(light);
  1222. const Matrix3x4& view = camera->GetView();
  1223. const Matrix4& projection = camera->GetGPUProjection();
  1224. Vector3 cameraPos = camera->GetNode()->GetWorldPosition();
  1225. float lightDist;
  1226. if (type == LIGHT_POINT)
  1227. lightDist = Sphere(light->GetNode()->GetWorldPosition(), light->GetRange() * 1.25f).Distance(cameraPos);
  1228. else
  1229. lightDist = light->GetFrustum().Distance(cameraPos);
  1230. // If the camera is actually inside the light volume, do not draw to stencil as it would waste fillrate
  1231. if (lightDist < M_EPSILON)
  1232. {
  1233. graphics_->SetStencilTest(false);
  1234. return;
  1235. }
  1236. // If the stencil value has wrapped, clear the whole stencil first
  1237. if (!lightStencilValue_)
  1238. {
  1239. graphics_->Clear(CLEAR_STENCIL);
  1240. lightStencilValue_ = 1;
  1241. }
  1242. // If possible, render the stencil volume front faces. However, close to the near clip plane render back faces instead
  1243. // to avoid clipping.
  1244. if (lightDist < camera->GetNearClip() * 2.0f)
  1245. {
  1246. SetCullMode(CULL_CW, camera);
  1247. graphics_->SetDepthTest(CMP_GREATER);
  1248. }
  1249. else
  1250. {
  1251. SetCullMode(CULL_CCW, camera);
  1252. graphics_->SetDepthTest(CMP_LESSEQUAL);
  1253. }
  1254. graphics_->SetColorWrite(false);
  1255. graphics_->SetDepthWrite(false);
  1256. graphics_->SetStencilTest(true, CMP_ALWAYS, OP_REF, OP_KEEP, OP_KEEP, lightStencilValue_);
  1257. graphics_->SetShaders(graphics_->GetShader(VS, "Stencil"), graphics_->GetShader(PS, "Stencil"));
  1258. graphics_->SetShaderParameter(VSP_VIEW, view);
  1259. graphics_->SetShaderParameter(VSP_VIEWINV, camera->GetEffectiveWorldTransform());
  1260. graphics_->SetShaderParameter(VSP_VIEWPROJ, projection * view);
  1261. graphics_->SetShaderParameter(VSP_MODEL, light->GetVolumeTransform(camera));
  1262. geometry->Draw(graphics_);
  1263. graphics_->ClearTransformSources();
  1264. graphics_->SetColorWrite(true);
  1265. graphics_->SetStencilTest(true, CMP_EQUAL, OP_KEEP, OP_KEEP, OP_KEEP, lightStencilValue_);
  1266. // Increase stencil value for next light
  1267. ++lightStencilValue_;
  1268. }
  1269. else
  1270. graphics_->SetStencilTest(false);
  1271. }
  1272. const Rect& Renderer::GetLightScissor(Light* light, Camera* camera)
  1273. {
  1274. Pair<Light*, Camera*> combination(light, camera);
  1275. HashMap<Pair<Light*, Camera*>, Rect>::Iterator i = lightScissorCache_.Find(combination);
  1276. if (i != lightScissorCache_.End())
  1277. return i->second_;
  1278. const Matrix3x4& view = camera->GetView();
  1279. const Matrix4& projection = camera->GetProjection();
  1280. assert(light->GetLightType() != LIGHT_DIRECTIONAL);
  1281. if (light->GetLightType() == LIGHT_SPOT)
  1282. {
  1283. Frustum viewFrustum(light->GetViewSpaceFrustum(view));
  1284. return lightScissorCache_[combination] = viewFrustum.Projected(projection);
  1285. }
  1286. else // LIGHT_POINT
  1287. {
  1288. BoundingBox viewBox(light->GetWorldBoundingBox().Transformed(view));
  1289. return lightScissorCache_[combination] = viewBox.Projected(projection);
  1290. }
  1291. }
  1292. void Renderer::UpdateQueuedViewport(unsigned index)
  1293. {
  1294. WeakPtr<RenderSurface>& renderTarget = queuedViewports_[index].first_;
  1295. WeakPtr<Viewport>& viewport = queuedViewports_[index].second_;
  1296. // Null pointer means backbuffer view. Differentiate between that and an expired rendersurface
  1297. if ((renderTarget.NotNull() && renderTarget.Expired()) || viewport.Expired())
  1298. return;
  1299. // (Re)allocate the view structure if necessary
  1300. if (!viewport->GetView() || resetViews_)
  1301. viewport->AllocateView();
  1302. View* view = viewport->GetView();
  1303. assert(view);
  1304. // Check if view can be defined successfully (has either valid scene, camera and octree, or no scene passes)
  1305. if (!view->Define(renderTarget, viewport))
  1306. return;
  1307. views_.Push(WeakPtr<View>(view));
  1308. const IntRect& viewRect = viewport->GetRect();
  1309. Scene* scene = viewport->GetScene();
  1310. if (!scene)
  1311. return;
  1312. Octree* octree = scene->GetComponent<Octree>();
  1313. // Update octree (perform early update for drawables which need that, and reinsert moved drawables.)
  1314. // However, if the same scene is viewed from multiple cameras, update the octree only once
  1315. if (!updatedOctrees_.Contains(octree))
  1316. {
  1317. frame_.camera_ = viewport->GetCamera();
  1318. frame_.viewSize_ = viewRect.Size();
  1319. if (frame_.viewSize_ == IntVector2::ZERO)
  1320. frame_.viewSize_ = IntVector2(graphics_->GetWidth(), graphics_->GetHeight());
  1321. octree->Update(frame_);
  1322. updatedOctrees_.Insert(octree);
  1323. // Set also the view for the debug renderer already here, so that it can use culling
  1324. /// \todo May result in incorrect debug geometry culling if the same scene is drawn from multiple viewports
  1325. DebugRenderer* debug = scene->GetComponent<DebugRenderer>();
  1326. if (debug && viewport->GetDrawDebug())
  1327. debug->SetView(viewport->GetCamera());
  1328. }
  1329. // Update view. This may queue further views. View will send update begin/end events once its state is set
  1330. ResetShadowMapAllocations(); // Each view can reuse the same shadow maps
  1331. view->Update(frame_);
  1332. }
  1333. void Renderer::PrepareViewRender()
  1334. {
  1335. ResetScreenBufferAllocations();
  1336. lightScissorCache_.Clear();
  1337. lightStencilValue_ = 1;
  1338. }
  1339. void Renderer::RemoveUnusedBuffers()
  1340. {
  1341. for (unsigned i = occlusionBuffers_.Size() - 1; i < occlusionBuffers_.Size(); --i)
  1342. {
  1343. if (occlusionBuffers_[i]->GetUseTimer() > MAX_BUFFER_AGE)
  1344. {
  1345. URHO3D_LOGDEBUG("Removed unused occlusion buffer");
  1346. occlusionBuffers_.Erase(i);
  1347. }
  1348. }
  1349. for (HashMap<long long, Vector<SharedPtr<Texture> > >::Iterator i = screenBuffers_.Begin(); i != screenBuffers_.End();)
  1350. {
  1351. HashMap<long long, Vector<SharedPtr<Texture> > >::Iterator current = i++;
  1352. Vector<SharedPtr<Texture> >& buffers = current->second_;
  1353. for (unsigned j = buffers.Size() - 1; j < buffers.Size(); --j)
  1354. {
  1355. Texture* buffer = buffers[j];
  1356. if (buffer->GetUseTimer() > MAX_BUFFER_AGE)
  1357. {
  1358. URHO3D_LOGDEBUG("Removed unused screen buffer size " + String(buffer->GetWidth()) + "x" + String(buffer->GetHeight()) +
  1359. " format " + String(buffer->GetFormat()));
  1360. buffers.Erase(j);
  1361. }
  1362. }
  1363. if (buffers.Empty())
  1364. {
  1365. screenBufferAllocations_.Erase(current->first_);
  1366. screenBuffers_.Erase(current);
  1367. }
  1368. }
  1369. }
  1370. void Renderer::ResetShadowMapAllocations()
  1371. {
  1372. for (HashMap<int, PODVector<Light*> >::Iterator i = shadowMapAllocations_.Begin(); i != shadowMapAllocations_.End(); ++i)
  1373. i->second_.Clear();
  1374. }
  1375. void Renderer::ResetScreenBufferAllocations()
  1376. {
  1377. for (HashMap<long long, unsigned>::Iterator i = screenBufferAllocations_.Begin(); i != screenBufferAllocations_.End(); ++i)
  1378. i->second_ = 0;
  1379. }
  1380. void Renderer::Initialize()
  1381. {
  1382. Graphics* graphics = GetSubsystem<Graphics>();
  1383. ResourceCache* cache = GetSubsystem<ResourceCache>();
  1384. if (!graphics || !graphics->IsInitialized() || !cache)
  1385. return;
  1386. URHO3D_PROFILE(InitRenderer);
  1387. graphics_ = graphics;
  1388. if (!graphics_->GetShadowMapFormat())
  1389. drawShadows_ = false;
  1390. // Validate the shadow quality level
  1391. SetShadowQuality(shadowQuality_);
  1392. defaultLightRamp_ = cache->GetResource<Texture2D>("Textures/Ramp.png");
  1393. defaultLightSpot_ = cache->GetResource<Texture2D>("Textures/Spot.png");
  1394. defaultMaterial_ = new Material(context_);
  1395. defaultRenderPath_ = new RenderPath();
  1396. defaultRenderPath_->Load(cache->GetResource<XMLFile>("RenderPaths/Forward.xml"));
  1397. CreateGeometries();
  1398. CreateInstancingBuffer();
  1399. viewports_.Resize(1);
  1400. ResetShadowMaps();
  1401. ResetBuffers();
  1402. shadersDirty_ = true;
  1403. initialized_ = true;
  1404. SubscribeToEvent(E_RENDERUPDATE, URHO3D_HANDLER(Renderer, HandleRenderUpdate));
  1405. URHO3D_LOGINFO("Initialized renderer");
  1406. }
  1407. void Renderer::LoadShaders()
  1408. {
  1409. URHO3D_LOGDEBUG("Reloading shaders");
  1410. // Release old material shaders, mark them for reload
  1411. ReleaseMaterialShaders();
  1412. shadersChangedFrameNumber_ = GetSubsystem<Time>()->GetFrameNumber();
  1413. // Construct new names for deferred light volume pixel shaders based on rendering options
  1414. deferredLightPSVariations_.Resize(MAX_DEFERRED_LIGHT_PS_VARIATIONS);
  1415. for (unsigned i = 0; i < MAX_DEFERRED_LIGHT_PS_VARIATIONS; ++i)
  1416. {
  1417. deferredLightPSVariations_[i] = lightPSVariations[i % DLPS_ORTHO];
  1418. if ((i % DLPS_ORTHO) >= DLPS_SHADOW)
  1419. deferredLightPSVariations_[i] += GetShadowVariations();
  1420. if (i >= DLPS_ORTHO)
  1421. deferredLightPSVariations_[i] += "ORTHO ";
  1422. }
  1423. shadersDirty_ = false;
  1424. }
  1425. void Renderer::LoadPassShaders(Pass* pass, Vector<SharedPtr<ShaderVariation> >& vertexShaders, Vector<SharedPtr<ShaderVariation> >& pixelShaders, const BatchQueue& queue)
  1426. {
  1427. URHO3D_PROFILE(LoadPassShaders);
  1428. // Forget all the old shaders
  1429. vertexShaders.Clear();
  1430. pixelShaders.Clear();
  1431. String vsDefines = pass->GetEffectiveVertexShaderDefines();
  1432. String psDefines = pass->GetEffectivePixelShaderDefines();
  1433. // Make sure to end defines with space to allow appending engine's defines
  1434. if (vsDefines.Length() && !vsDefines.EndsWith(" "))
  1435. vsDefines += ' ';
  1436. if (psDefines.Length() && !psDefines.EndsWith(" "))
  1437. psDefines += ' ';
  1438. // Append defines from batch queue (renderpath command) if needed
  1439. if (queue.vsExtraDefines_.Length())
  1440. {
  1441. vsDefines += queue.vsExtraDefines_;
  1442. vsDefines += ' ';
  1443. }
  1444. if (queue.psExtraDefines_.Length())
  1445. {
  1446. psDefines += queue.psExtraDefines_;
  1447. psDefines += ' ';
  1448. }
  1449. // Add defines for VSM in the shadow pass if necessary
  1450. if (pass->GetName() == "shadow"
  1451. && (shadowQuality_ == SHADOWQUALITY_VSM || shadowQuality_ == SHADOWQUALITY_BLUR_VSM))
  1452. {
  1453. vsDefines += "VSM_SHADOW ";
  1454. psDefines += "VSM_SHADOW ";
  1455. }
  1456. if (pass->GetLightingMode() == LIGHTING_PERPIXEL)
  1457. {
  1458. // Load forward pixel lit variations
  1459. vertexShaders.Resize(MAX_GEOMETRYTYPES * MAX_LIGHT_VS_VARIATIONS);
  1460. pixelShaders.Resize(MAX_LIGHT_PS_VARIATIONS * 2);
  1461. for (unsigned j = 0; j < MAX_GEOMETRYTYPES * MAX_LIGHT_VS_VARIATIONS; ++j)
  1462. {
  1463. unsigned g = j / MAX_LIGHT_VS_VARIATIONS;
  1464. unsigned l = j % MAX_LIGHT_VS_VARIATIONS;
  1465. vertexShaders[j] = graphics_->GetShader(VS, pass->GetVertexShader(),
  1466. vsDefines + lightVSVariations[l] + geometryVSVariations[g]);
  1467. }
  1468. for (unsigned j = 0; j < MAX_LIGHT_PS_VARIATIONS * 2; ++j)
  1469. {
  1470. unsigned l = j % MAX_LIGHT_PS_VARIATIONS;
  1471. unsigned h = j / MAX_LIGHT_PS_VARIATIONS;
  1472. if (l & LPS_SHADOW)
  1473. {
  1474. pixelShaders[j] = graphics_->GetShader(PS, pass->GetPixelShader(),
  1475. psDefines + lightPSVariations[l] + GetShadowVariations() +
  1476. heightFogVariations[h]);
  1477. }
  1478. else
  1479. pixelShaders[j] = graphics_->GetShader(PS, pass->GetPixelShader(),
  1480. psDefines + lightPSVariations[l] + heightFogVariations[h]);
  1481. }
  1482. }
  1483. else
  1484. {
  1485. // Load vertex light variations
  1486. if (pass->GetLightingMode() == LIGHTING_PERVERTEX)
  1487. {
  1488. vertexShaders.Resize(MAX_GEOMETRYTYPES * MAX_VERTEXLIGHT_VS_VARIATIONS);
  1489. for (unsigned j = 0; j < MAX_GEOMETRYTYPES * MAX_VERTEXLIGHT_VS_VARIATIONS; ++j)
  1490. {
  1491. unsigned g = j / MAX_VERTEXLIGHT_VS_VARIATIONS;
  1492. unsigned l = j % MAX_VERTEXLIGHT_VS_VARIATIONS;
  1493. vertexShaders[j] = graphics_->GetShader(VS, pass->GetVertexShader(),
  1494. vsDefines + vertexLightVSVariations[l] + geometryVSVariations[g]);
  1495. }
  1496. }
  1497. else
  1498. {
  1499. vertexShaders.Resize(MAX_GEOMETRYTYPES);
  1500. for (unsigned j = 0; j < MAX_GEOMETRYTYPES; ++j)
  1501. {
  1502. vertexShaders[j] = graphics_->GetShader(VS, pass->GetVertexShader(),
  1503. vsDefines + geometryVSVariations[j]);
  1504. }
  1505. }
  1506. pixelShaders.Resize(2);
  1507. for (unsigned j = 0; j < 2; ++j)
  1508. {
  1509. pixelShaders[j] =
  1510. graphics_->GetShader(PS, pass->GetPixelShader(), psDefines + heightFogVariations[j]);
  1511. }
  1512. }
  1513. pass->MarkShadersLoaded(shadersChangedFrameNumber_);
  1514. }
  1515. void Renderer::ReleaseMaterialShaders()
  1516. {
  1517. ResourceCache* cache = GetSubsystem<ResourceCache>();
  1518. PODVector<Material*> materials;
  1519. cache->GetResources<Material>(materials);
  1520. for (unsigned i = 0; i < materials.Size(); ++i)
  1521. materials[i]->ReleaseShaders();
  1522. }
  1523. void Renderer::ReloadTextures()
  1524. {
  1525. ResourceCache* cache = GetSubsystem<ResourceCache>();
  1526. PODVector<Resource*> textures;
  1527. cache->GetResources(textures, Texture2D::GetTypeStatic());
  1528. for (unsigned i = 0; i < textures.Size(); ++i)
  1529. cache->ReloadResource(textures[i]);
  1530. cache->GetResources(textures, TextureCube::GetTypeStatic());
  1531. for (unsigned i = 0; i < textures.Size(); ++i)
  1532. cache->ReloadResource(textures[i]);
  1533. }
  1534. void Renderer::CreateGeometries()
  1535. {
  1536. SharedPtr<VertexBuffer> dlvb(new VertexBuffer(context_));
  1537. dlvb->SetShadowed(true);
  1538. dlvb->SetSize(4, MASK_POSITION);
  1539. dlvb->SetData(dirLightVertexData);
  1540. SharedPtr<IndexBuffer> dlib(new IndexBuffer(context_));
  1541. dlib->SetShadowed(true);
  1542. dlib->SetSize(6, false);
  1543. dlib->SetData(dirLightIndexData);
  1544. dirLightGeometry_ = new Geometry(context_);
  1545. dirLightGeometry_->SetVertexBuffer(0, dlvb);
  1546. dirLightGeometry_->SetIndexBuffer(dlib);
  1547. dirLightGeometry_->SetDrawRange(TRIANGLE_LIST, 0, dlib->GetIndexCount());
  1548. SharedPtr<VertexBuffer> slvb(new VertexBuffer(context_));
  1549. slvb->SetShadowed(true);
  1550. slvb->SetSize(8, MASK_POSITION);
  1551. slvb->SetData(spotLightVertexData);
  1552. SharedPtr<IndexBuffer> slib(new IndexBuffer(context_));
  1553. slib->SetShadowed(true);
  1554. slib->SetSize(36, false);
  1555. slib->SetData(spotLightIndexData);
  1556. spotLightGeometry_ = new Geometry(context_);
  1557. spotLightGeometry_->SetVertexBuffer(0, slvb);
  1558. spotLightGeometry_->SetIndexBuffer(slib);
  1559. spotLightGeometry_->SetDrawRange(TRIANGLE_LIST, 0, slib->GetIndexCount());
  1560. SharedPtr<VertexBuffer> plvb(new VertexBuffer(context_));
  1561. plvb->SetShadowed(true);
  1562. plvb->SetSize(24, MASK_POSITION);
  1563. plvb->SetData(pointLightVertexData);
  1564. SharedPtr<IndexBuffer> plib(new IndexBuffer(context_));
  1565. plib->SetShadowed(true);
  1566. plib->SetSize(132, false);
  1567. plib->SetData(pointLightIndexData);
  1568. pointLightGeometry_ = new Geometry(context_);
  1569. pointLightGeometry_->SetVertexBuffer(0, plvb);
  1570. pointLightGeometry_->SetIndexBuffer(plib);
  1571. pointLightGeometry_->SetDrawRange(TRIANGLE_LIST, 0, plib->GetIndexCount());
  1572. #if !defined(URHO3D_OPENGL) || !defined(GL_ES_VERSION_2_0)
  1573. if (graphics_->GetShadowMapFormat())
  1574. {
  1575. faceSelectCubeMap_ = new TextureCube(context_);
  1576. faceSelectCubeMap_->SetNumLevels(1);
  1577. faceSelectCubeMap_->SetSize(1, graphics_->GetRGBAFormat());
  1578. faceSelectCubeMap_->SetFilterMode(FILTER_NEAREST);
  1579. indirectionCubeMap_ = new TextureCube(context_);
  1580. indirectionCubeMap_->SetNumLevels(1);
  1581. indirectionCubeMap_->SetSize(256, graphics_->GetRGBAFormat());
  1582. indirectionCubeMap_->SetFilterMode(FILTER_BILINEAR);
  1583. indirectionCubeMap_->SetAddressMode(COORD_U, ADDRESS_CLAMP);
  1584. indirectionCubeMap_->SetAddressMode(COORD_V, ADDRESS_CLAMP);
  1585. indirectionCubeMap_->SetAddressMode(COORD_W, ADDRESS_CLAMP);
  1586. SetIndirectionTextureData();
  1587. }
  1588. #endif
  1589. }
  1590. void Renderer::SetIndirectionTextureData()
  1591. {
  1592. unsigned char data[256 * 256 * 4];
  1593. for (unsigned i = 0; i < MAX_CUBEMAP_FACES; ++i)
  1594. {
  1595. unsigned axis = i / 2;
  1596. data[0] = (unsigned char)((axis == 0) ? 255 : 0);
  1597. data[1] = (unsigned char)((axis == 1) ? 255 : 0);
  1598. data[2] = (unsigned char)((axis == 2) ? 255 : 0);
  1599. data[3] = 0;
  1600. faceSelectCubeMap_->SetData((CubeMapFace)i, 0, 0, 0, 1, 1, data);
  1601. }
  1602. for (unsigned i = 0; i < MAX_CUBEMAP_FACES; ++i)
  1603. {
  1604. unsigned char faceX = (unsigned char)((i & 1) * 255);
  1605. unsigned char faceY = (unsigned char)((i / 2) * 255 / 3);
  1606. unsigned char* dest = data;
  1607. for (unsigned y = 0; y < 256; ++y)
  1608. {
  1609. for (unsigned x = 0; x < 256; ++x)
  1610. {
  1611. #ifdef URHO3D_OPENGL
  1612. dest[0] = (unsigned char)x;
  1613. dest[1] = (unsigned char)(255 - y);
  1614. dest[2] = faceX;
  1615. dest[3] = (unsigned char)(255 * 2 / 3 - faceY);
  1616. #else
  1617. dest[0] = (unsigned char)x;
  1618. dest[1] = (unsigned char)y;
  1619. dest[2] = faceX;
  1620. dest[3] = faceY;
  1621. #endif
  1622. dest += 4;
  1623. }
  1624. }
  1625. indirectionCubeMap_->SetData((CubeMapFace)i, 0, 0, 0, 256, 256, data);
  1626. }
  1627. faceSelectCubeMap_->ClearDataLost();
  1628. indirectionCubeMap_->ClearDataLost();
  1629. }
  1630. void Renderer::CreateInstancingBuffer()
  1631. {
  1632. // Do not create buffer if instancing not supported
  1633. if (!graphics_->GetInstancingSupport())
  1634. {
  1635. instancingBuffer_.Reset();
  1636. dynamicInstancing_ = false;
  1637. return;
  1638. }
  1639. instancingBuffer_ = new VertexBuffer(context_);
  1640. const PODVector<VertexElement> instancingBufferElements = CreateInstancingBufferElements(numExtraInstancingBufferElements_);
  1641. if (!instancingBuffer_->SetSize(INSTANCING_BUFFER_DEFAULT_SIZE, instancingBufferElements, true))
  1642. {
  1643. instancingBuffer_.Reset();
  1644. dynamicInstancing_ = false;
  1645. }
  1646. }
  1647. void Renderer::ResetShadowMaps()
  1648. {
  1649. shadowMaps_.Clear();
  1650. shadowMapAllocations_.Clear();
  1651. colorShadowMaps_.Clear();
  1652. }
  1653. void Renderer::ResetBuffers()
  1654. {
  1655. occlusionBuffers_.Clear();
  1656. screenBuffers_.Clear();
  1657. screenBufferAllocations_.Clear();
  1658. }
  1659. String Renderer::GetShadowVariations() const
  1660. {
  1661. switch (shadowQuality_)
  1662. {
  1663. case SHADOWQUALITY_SIMPLE_16BIT:
  1664. #ifdef URHO3D_OPENGL
  1665. return "SIMPLE_SHADOW ";
  1666. #else
  1667. if (graphics_->GetHardwareShadowSupport())
  1668. return "SIMPLE_SHADOW ";
  1669. else
  1670. return "SIMPLE_SHADOW SHADOWCMP ";
  1671. #endif
  1672. case SHADOWQUALITY_SIMPLE_24BIT:
  1673. return "SIMPLE_SHADOW ";
  1674. case SHADOWQUALITY_PCF_16BIT:
  1675. #ifdef URHO3D_OPENGL
  1676. return "PCF_SHADOW ";
  1677. #else
  1678. if (graphics_->GetHardwareShadowSupport())
  1679. return "PCF_SHADOW ";
  1680. else
  1681. return "PCF_SHADOW SHADOWCMP ";
  1682. #endif
  1683. case SHADOWQUALITY_PCF_24BIT:
  1684. return "PCF_SHADOW ";
  1685. case SHADOWQUALITY_VSM:
  1686. return "VSM_SHADOW ";
  1687. case SHADOWQUALITY_BLUR_VSM:
  1688. return "VSM_SHADOW ";
  1689. }
  1690. return "";
  1691. };
  1692. void Renderer::HandleScreenMode(StringHash eventType, VariantMap& eventData)
  1693. {
  1694. if (!initialized_)
  1695. Initialize();
  1696. else
  1697. resetViews_ = true;
  1698. }
  1699. void Renderer::HandleRenderUpdate(StringHash eventType, VariantMap& eventData)
  1700. {
  1701. using namespace RenderUpdate;
  1702. Update(eventData[P_TIMESTEP].GetFloat());
  1703. }
  1704. void Renderer::BlurShadowMap(View* view, Texture2D* shadowMap, float blurScale)
  1705. {
  1706. graphics_->SetBlendMode(BLEND_REPLACE);
  1707. graphics_->SetDepthTest(CMP_ALWAYS);
  1708. graphics_->SetClipPlane(false);
  1709. graphics_->SetScissorTest(false);
  1710. // Get a temporary render buffer
  1711. Texture2D* tmpBuffer = static_cast<Texture2D*>(GetScreenBuffer(shadowMap->GetWidth(), shadowMap->GetHeight(),
  1712. shadowMap->GetFormat(), 1, false, false, false, false));
  1713. graphics_->SetRenderTarget(0, tmpBuffer->GetRenderSurface());
  1714. graphics_->SetDepthStencil(GetDepthStencil(shadowMap->GetWidth(), shadowMap->GetHeight(), shadowMap->GetMultiSample(),
  1715. shadowMap->GetAutoResolve()));
  1716. graphics_->SetViewport(IntRect(0, 0, shadowMap->GetWidth(), shadowMap->GetHeight()));
  1717. // Get shaders
  1718. static const String shaderName("ShadowBlur");
  1719. ShaderVariation* vs = graphics_->GetShader(VS, shaderName);
  1720. ShaderVariation* ps = graphics_->GetShader(PS, shaderName);
  1721. graphics_->SetShaders(vs, ps);
  1722. view->SetGBufferShaderParameters(IntVector2(shadowMap->GetWidth(), shadowMap->GetHeight()), IntRect(0, 0, shadowMap->GetWidth(), shadowMap->GetHeight()));
  1723. // Horizontal blur of the shadow map
  1724. static const StringHash blurOffsetParam("BlurOffsets");
  1725. graphics_->SetShaderParameter(blurOffsetParam, Vector2(shadowSoftness_ * blurScale / shadowMap->GetWidth(), 0.0f));
  1726. graphics_->SetTexture(TU_DIFFUSE, shadowMap);
  1727. view->DrawFullscreenQuad(true);
  1728. // Vertical blur
  1729. graphics_->SetRenderTarget(0, shadowMap);
  1730. graphics_->SetViewport(IntRect(0, 0, shadowMap->GetWidth(), shadowMap->GetHeight()));
  1731. graphics_->SetShaderParameter(blurOffsetParam, Vector2(0.0f, shadowSoftness_ * blurScale / shadowMap->GetHeight()));
  1732. graphics_->SetTexture(TU_DIFFUSE, tmpBuffer);
  1733. view->DrawFullscreenQuad(true);
  1734. }
  1735. }