Renderer.cpp 61 KB

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