DeferredView.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662
  1. //
  2. // Urho3D Engine
  3. // Copyright (c) 2008-2011 Lasse Öörni
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. //
  23. #include "Precompiled.h"
  24. #include "Geometry.h"
  25. #include "GeometryNode.h"
  26. #include "Light.h"
  27. #include "Log.h"
  28. #include "Material.h"
  29. #include "Pipeline.h"
  30. #include "PixelShader.h"
  31. #include "Profiler.h"
  32. #include "Renderer.h"
  33. #include "RendererImpl.h"
  34. #include "Texture2D.h"
  35. #include "VertexShader.h"
  36. #include "View.h"
  37. #include "DebugNew.h"
  38. static const std::string hwDepthVariations[] =
  39. {
  40. "",
  41. "HW"
  42. };
  43. static const std::string linearVariations[] =
  44. {
  45. "",
  46. "Linear"
  47. };
  48. void View::getBatchesDeferred()
  49. {
  50. Renderer* renderer = mPipeline->getRenderer();
  51. bool deferred = renderer->getRenderMode() == RENDER_DEFERRED;
  52. // G-Buffer pass types depend on whether deferred shading or light prepass is in use
  53. PassType gBufferPass, additionalPass;
  54. if (deferred)
  55. {
  56. gBufferPass = PASS_DEFERRED;
  57. additionalPass = PASS_EMISSIVE;
  58. }
  59. else
  60. {
  61. gBufferPass = PASS_PREPASS;
  62. additionalPass = PASS_MATERIAL;
  63. }
  64. // Go through geometries for GBuffer and ambient batches
  65. {
  66. PROFILE(View_GetAmbientBatches);
  67. for (unsigned i = 0; i < mGeometries.size(); ++i)
  68. {
  69. GeometryNode* node = mGeometries[i];
  70. unsigned numBatches = node->getNumBatches();
  71. for (unsigned j = 0; j < numBatches; ++j)
  72. {
  73. Geometry* geom = node->getBatchGeometry(j);
  74. if (!geom)
  75. continue;
  76. MaterialTechnique* tech = getMaterialTechnique(node, j);
  77. if (!tech)
  78. continue;
  79. // Check here if the material technique refers to a render target texture with camera(s) attached
  80. // Only check this for the main view (null rendertarget)
  81. if ((!mRenderTarget) && (tech->getAuxViewFrameNumber() != mFrame.mFrameNumber))
  82. checkTechniqueForAuxView(tech);
  83. Batch newBatch;
  84. newBatch.mNode = node;
  85. newBatch.mCamera = mCamera;
  86. newBatch.mDistance = node->getDistance();
  87. newBatch.mGeometry = geom;
  88. newBatch.mBatchIndex = j;
  89. // GBuffer pass has priority over ambient pass
  90. MaterialPass* pass = tech->getPass(gBufferPass);
  91. if (pass)
  92. {
  93. // Render opaque objects without alpha masking first
  94. newBatch.mHasPriority = !(pass->getAlphaMask() || pass->getAlphaTest());
  95. mPipeline->setBatchShaders(newBatch, tech, pass);
  96. newBatch.calculateSortKey(true, true);
  97. mGBufferQueue.push_back(newBatch);
  98. // Check for additional emissive pass with deferred rendering, and material pass with light prepass
  99. pass = tech->getPass(additionalPass);
  100. if (pass)
  101. {
  102. newBatch.mHasPriority = false;
  103. mPipeline->setBatchShaders(newBatch, tech, pass);
  104. newBatch.calculateSortKey(true, true);
  105. mForwardQueue.push_back(newBatch);
  106. }
  107. }
  108. else
  109. {
  110. pass = tech->getPass(PASS_AMBIENT);
  111. if (pass)
  112. {
  113. mPipeline->setBatchShaders(newBatch, tech, pass);
  114. if (pass->getBlendMode() == BLEND_REPLACE)
  115. {
  116. newBatch.mHasPriority = !(pass->getAlphaTest() || pass->getAlphaMask());
  117. newBatch.calculateSortKey(true, true);
  118. mAmbientQueue.push_back(newBatch);
  119. }
  120. else
  121. {
  122. newBatch.mHasPriority = true;
  123. newBatch.calculateSortKey(false, false);
  124. mTransparentQueue.push_back(newBatch);
  125. }
  126. }
  127. else
  128. {
  129. // If no other pass yet, check for post-opaque (custom) pass
  130. pass = tech->getPass(PASS_POSTOPAQUE);
  131. if (pass)
  132. {
  133. newBatch.mHasPriority = false;
  134. mPipeline->setBatchShaders(newBatch, tech, pass);
  135. newBatch.calculateSortKey(true, true);
  136. mPostOpaqueQueue.push_back(newBatch);
  137. }
  138. }
  139. }
  140. }
  141. }
  142. }
  143. // Go through lights
  144. {
  145. PROFILE_MULTIPLE(Pipeline_GetLightBatches, mLights.size());
  146. unsigned lightQueueCount = 0;
  147. for (unsigned i = 0; i < mLights.size(); ++i)
  148. {
  149. Light* light = mLights[i];
  150. unsigned splits = processLight(light);
  151. if (!splits)
  152. continue;
  153. // For split point lights, check that a transparent object is not lit multiple times
  154. bool splitPointLight = sSplitLights[0]->getLightType() == LIGHT_SPLITPOINT;
  155. static std::set<GeometryNode*> litTransparencies;
  156. litTransparencies.clear();
  157. // Negative (darkening) lighting flag
  158. bool negative = mLights[i]->isNegative();
  159. // Prepare lit object + shadow caster queues for each split
  160. if (mLightQueues.size() < lightQueueCount + splits)
  161. mLightQueues.resize(lightQueueCount + splits);
  162. unsigned prevLightQueueCount = lightQueueCount;
  163. for (unsigned j = 0; j < splits; ++j)
  164. {
  165. LightBatchQueue& lightQueue = mLightQueues[lightQueueCount];
  166. lightQueue.mLight = sSplitLights[j];
  167. lightQueue.mShadowBatches.clear();
  168. lightQueue.mBatches.clear();
  169. lightQueue.mLastSplit = false;
  170. // Loop through shadow casters
  171. Camera& shadowCamera = sSplitLights[j]->getShadowCamera();
  172. for (unsigned k = 0; k < sShadowCasters[j].size(); ++k)
  173. {
  174. GeometryNode* node = sShadowCasters[j][k];
  175. unsigned numBatches = node->getNumBatches();
  176. for (unsigned l = 0; l < numBatches; ++l)
  177. {
  178. MaterialTechnique* tech = getMaterialTechnique(node, l);
  179. if (!tech)
  180. continue;
  181. MaterialPass* pass = tech->getPass(PASS_SHADOW);
  182. // Skip if material has no shadow pass
  183. if (!pass)
  184. continue;
  185. Geometry* geom = node->getBatchGeometry(l);
  186. if (!geom)
  187. continue;
  188. // Build the shadow batch
  189. // Note: shadow cameras are never parented, so can simply use getPosition()
  190. Batch shadowBatch;
  191. shadowBatch.mNode = node;
  192. shadowBatch.mCamera = &shadowCamera;
  193. shadowBatch.mDistance = (node->getWorldPosition() - shadowCamera.getPosition()).getLengthFast();
  194. shadowBatch.mGeometry = geom;
  195. shadowBatch.mBatchIndex = l;
  196. shadowBatch.mForwardLight = sSplitLights[j];
  197. shadowBatch.mHasPriority = !(pass->getAlphaTest() || pass->getAlphaMask());
  198. mPipeline->setBatchShaders(shadowBatch, tech, pass);
  199. shadowBatch.calculateSortKey(true, true);
  200. lightQueue.mShadowBatches.push_back(shadowBatch);
  201. }
  202. }
  203. // Loop through lit geometries to get forward lit objects
  204. for (unsigned k = 0; k < sLitGeometries[j].size(); ++k)
  205. {
  206. GeometryNode* node = sLitGeometries[j][k];
  207. unsigned numBatches = node->getNumBatches();
  208. for (unsigned l = 0; l < numBatches; ++l)
  209. {
  210. MaterialTechnique* tech = getMaterialTechnique(node, l);
  211. if (!tech)
  212. continue;
  213. // Skip if material uses deferred rendering
  214. if (tech->hasPass(gBufferPass))
  215. continue;
  216. MaterialPass* pass;
  217. if (!negative)
  218. pass = tech->getPass(PASS_LIGHT);
  219. else
  220. pass = tech->getPass(PASS_NEGATIVE);
  221. // Skip if material does not receive light
  222. if (!pass)
  223. continue;
  224. Geometry* geom = node->getBatchGeometry(l);
  225. if (!geom)
  226. continue;
  227. // Build the lit batch
  228. Batch newBatch;
  229. newBatch.mNode = node;
  230. newBatch.mCamera = mCamera;
  231. newBatch.mDistance = node->getDistance();
  232. newBatch.mGeometry = geom;
  233. newBatch.mBatchIndex = l;
  234. newBatch.mForwardLight = sSplitLights[j];
  235. // No shadows in any forward lighting
  236. mPipeline->setBatchShaders(newBatch, tech, pass, false);
  237. // Check from the ambient pass whether the object is opaque
  238. MaterialPass* ambientPass = tech->getPass(PASS_AMBIENT);
  239. if ((!ambientPass) || (ambientPass->getBlendMode() == BLEND_REPLACE))
  240. {
  241. // Render negative lights first in the forward lighting queue
  242. newBatch.mHasPriority = negative;
  243. newBatch.calculateSortKey(true, true);
  244. mForwardQueue.push_back(newBatch);
  245. }
  246. else
  247. {
  248. // Prevent multi-lighting by a split point light
  249. // (transparent rendering can not handle the needed stencil masking)
  250. if (splitPointLight)
  251. {
  252. if (litTransparencies.find(node) != litTransparencies.end())
  253. continue;
  254. // Use the original light instead of the split one, to choose correct scissor
  255. newBatch.mForwardLight = mLights[i];
  256. }
  257. // If light is negative, bias the distance slightly to ensure it has priority
  258. if (negative)
  259. newBatch.mDistance -= 0.001f;
  260. newBatch.calculateSortKey(false, false);
  261. mTransparentQueue.push_back(newBatch);
  262. }
  263. }
  264. if (splitPointLight)
  265. litTransparencies.insert(node);
  266. }
  267. // Build the light volume batch
  268. // Check amount of lit geometries
  269. if (sLitGeometries[j].size())
  270. {
  271. Batch lightBatch;
  272. lightBatch.mNode = sSplitLights[j];
  273. lightBatch.mCamera = mCamera;
  274. lightBatch.mDistance = sSplitLights[j]->getDistance();
  275. lightBatch.mGeometry = mPipeline->getLightGeometry(sSplitLights[j]);
  276. mPipeline->setLightVolumeShaders(lightBatch);
  277. lightBatch.calculateSortKey(true, true);
  278. // If light is a split point light, it must be treated as shadowed in any case for correct stencil clearing
  279. if ((sSplitLights[j]->getShadowMap()) || (sSplitLights[j]->getLightType() == LIGHT_SPLITPOINT))
  280. {
  281. lightQueue.mBatches.push_back(lightBatch);
  282. lightQueueCount++;
  283. }
  284. else
  285. {
  286. if (!negative)
  287. mNoShadowLightQueue.push_back(lightBatch);
  288. else
  289. mNegativeLightQueue.push_back(lightBatch);
  290. }
  291. }
  292. }
  293. // Mark the last split
  294. if (lightQueueCount != prevLightQueueCount)
  295. mLightQueues[lightQueueCount - 1].mLastSplit = true;
  296. }
  297. // Resize the shadowed light queue vector now that final size is known
  298. mLightQueues.resize(lightQueueCount);
  299. }
  300. // Finally sort the batches
  301. {
  302. PROFILE(View_SortBatches);
  303. sortBatches(mGBufferQueue, mGBufferQueueSorted);
  304. sortBatches(mNegativeLightQueue, mNegativeLightQueueSorted);
  305. sortBatches(mNoShadowLightQueue, mNoShadowLightQueueSorted);
  306. sortBatches(mAmbientQueue, mAmbientQueueSorted);
  307. sortBatches(mForwardQueue, mForwardQueueSorted);
  308. sortBatches(mPostOpaqueQueue, mPostOpaqueQueueSorted);
  309. sortBatches(mTransparentQueue, mTransparentQueueSorted);
  310. for (unsigned i = 0; i < mLightQueues.size(); ++i)
  311. sortBatches(mLightQueues[i].mShadowBatches, mLightQueues[i].mSortedShadowBatches);
  312. }
  313. }
  314. void View::renderBatchesDeferred()
  315. {
  316. Renderer* renderer = mPipeline->getRenderer();
  317. bool deferred = renderer->getRenderMode() == RENDER_DEFERRED;
  318. Texture2D* diffBuffer = renderer->getDiffBuffer();
  319. Texture2D* normalBuffer = renderer->getNormalBuffer();
  320. Texture2D* depthBuffer = renderer->getDepthBuffer();
  321. bool hwDepth = renderer->getHardwareDepthSupport();
  322. // Check for edge filter. Only use it on the main view (null rendertarget)
  323. const EdgeFilterParameters& filterParams = mPipeline->getEdgeFilter();
  324. bool edgeFilter = (!mRenderTarget) && renderer->getMultiSample() && renderer->getScreenBuffer() &&
  325. (filterParams.mFilterStep > 0.0f) && (filterParams.mMaxFilter > 0.0f);
  326. // Use screen buffer only with edge filtering, else render direct to rendertarget or backbuffer
  327. RenderSurface* renderBuffer = edgeFilter ? renderer->getScreenBuffer()->getRenderSurface() : mRenderTarget;
  328. // Set the G-buffer UV coord adjustment here
  329. int gBufferWidth = diffBuffer->getWidth();
  330. int gBufferHeight = diffBuffer->getHeight();
  331. float widthRange = 0.5f * mWidth / gBufferWidth;
  332. float heightRange = 0.5f * mHeight / gBufferHeight;
  333. Vector4 bufferUVOffset(0.5f / gBufferWidth, 0.5f / gBufferHeight, widthRange, heightRange);
  334. renderer->setVertexShaderConstant(getVSRegister(VSP_GBUFFEROFFSETS), bufferUVOffset);
  335. {
  336. // Render G-buffer
  337. PROFILE(View_RenderGBuffer);
  338. clearLastParameterSources();
  339. // Use always the default depth stencil, so that it matches the G-buffer size, and is in the expected format
  340. // Enable depth rendertarget only if hardware depth not supported
  341. renderer->setColorWrite(true);
  342. renderer->setFillMode(FILL_SOLID);
  343. renderer->setScissorTest(false);
  344. renderer->setStencilTest(false);
  345. renderer->resetDepthStencil();
  346. renderer->setViewport(IntRect(0, 0, mWidth, mHeight));
  347. if (deferred)
  348. {
  349. renderer->setRenderTarget(0, diffBuffer);
  350. renderer->setRenderTarget(1, normalBuffer);
  351. if (!hwDepth)
  352. renderer->setRenderTarget(2, depthBuffer);
  353. }
  354. else
  355. {
  356. renderer->setRenderTarget(0, normalBuffer);
  357. if (!hwDepth)
  358. renderer->setRenderTarget(1, depthBuffer);
  359. }
  360. // Clear only depth and stencil at first, render the G-buffer batches
  361. renderer->clear(CLEAR_DEPTH | CLEAR_STENCIL);
  362. for (unsigned i = 0; i < mGBufferQueueSorted.size(); ++i)
  363. mGBufferQueueSorted[i]->draw(renderer);
  364. // Then fill the untouched parts of the G-buffer with defaults: black diffuse + specular (deferred only), far depth
  365. renderer->setAlphaTest(false);
  366. renderer->setBlendMode(BLEND_REPLACE);
  367. renderer->setDepthTest(CMP_LESSEQUAL);
  368. renderer->setDepthWrite(false);
  369. if (deferred)
  370. {
  371. renderer->resetRenderTarget(2);
  372. if (!hwDepth)
  373. renderer->setRenderTarget(1, depthBuffer);
  374. else
  375. renderer->resetRenderTarget(1);
  376. mPipeline->drawFullScreenQuad(*mCamera, mPipeline->getVertexShader("Deferred/GBufferFill"),
  377. mPipeline->getPixelShader("Deferred/GBufferFill_" + hwDepthVariations[hwDepth ? 1 : 0]), false);
  378. }
  379. else if (!hwDepth)
  380. {
  381. renderer->resetRenderTarget(1);
  382. renderer->setRenderTarget(0, depthBuffer);
  383. // The stencil shader writes color 1.0, which equals far depth
  384. mPipeline->drawFullScreenQuad(*mCamera, mPipeline->getVertexShader("Stencil"),
  385. mPipeline->getPixelShader("Stencil"), false);
  386. }
  387. }
  388. if (deferred)
  389. {
  390. // Render ambient color & fog
  391. clearLastParameterSources();
  392. renderer->setDepthTest(CMP_ALWAYS);
  393. renderer->setRenderTarget(0, renderBuffer);
  394. renderer->resetRenderTarget(1);
  395. renderer->resetRenderTarget(2);
  396. renderer->setTexture(TU_DIFFBUFFER, diffBuffer);
  397. renderer->setTexture(TU_DEPTHBUFFER, depthBuffer);
  398. // Use depth reconstruction only if necessary
  399. bool linear = mCamera->isOrthographic() || (!hwDepth);
  400. mPipeline->drawFullScreenQuad(*mCamera, mPipeline->getVertexShader("Deferred/Ambient"),
  401. mPipeline->getPixelShader("Deferred/Ambient_" + linearVariations[linear ? 1 : 0]), false);
  402. }
  403. else
  404. {
  405. // Light prepass: reset the light accumulation buffer with ambient light (half intensity to allow 2x "overburn")
  406. renderer->setRenderTarget(0, diffBuffer);
  407. renderer->resetRenderTarget(1);
  408. renderer->clear(CLEAR_COLOR, mZone->getAmbientColor() * 0.5f);
  409. }
  410. {
  411. // Render lights
  412. PROFILE(View_RenderLights);
  413. // Negative lights
  414. if (mNegativeLightQueueSorted.size())
  415. {
  416. clearLastParameterSources();
  417. if (deferred)
  418. renderer->setTexture(TU_DIFFBUFFER, diffBuffer);
  419. renderer->setTexture(TU_NORMALBUFFER, normalBuffer);
  420. renderer->setTexture(TU_DEPTHBUFFER, depthBuffer);
  421. for (unsigned i = 0; i < mNegativeLightQueueSorted.size(); ++i)
  422. {
  423. mPipeline->setupLightBatch(*mNegativeLightQueueSorted[i]);
  424. mNegativeLightQueueSorted[i]->draw(renderer);
  425. }
  426. }
  427. // Shadowed lights
  428. for (unsigned i = 0; i < mLightQueues.size(); ++i)
  429. {
  430. LightBatchQueue& queue = mLightQueues[i];
  431. Texture2D* shadowMap = queue.mLight->getShadowMap();
  432. if (shadowMap)
  433. {
  434. PROFILE(View_RenderShadowMap);
  435. clearLastParameterSources();
  436. renderer->setColorWrite(false);
  437. renderer->setStencilTest(false);
  438. renderer->setTexture(TU_SHADOWMAP, 0);
  439. renderer->setRenderTarget(0, shadowMap->getRenderSurface()->getLinkedRenderTarget());
  440. renderer->setDepthStencil(shadowMap);
  441. renderer->clear(CLEAR_DEPTH);
  442. // Set shadow depth bias
  443. BiasParameters parameters = queue.mLight->getShadowBias();
  444. renderer->setDepthBias(parameters.mConstantBias, parameters.mSlopeScaledBias);
  445. // Set a scissor rectangle to match possible shadow map size reduction by out-zooming
  446. // However, do not do this for point lights
  447. if (queue.mLight->getLightType() != LIGHT_SPLITPOINT)
  448. {
  449. Texture2D* shadowMap = queue.mLight->getShadowMap();
  450. float zoom = min(queue.mLight->getShadowCamera().getZoom(),
  451. (float)(shadowMap->getWidth() - 2) / (float)shadowMap->getWidth());
  452. Rect zoomRect(Vector2(-1.0f, -1.0f) * zoom, Vector2(1.0f, 1.0f) * zoom);
  453. renderer->setScissorTest(true, zoomRect, false);
  454. }
  455. else
  456. renderer->setScissorTest(false);
  457. const std::vector<Batch*>& sortedBatches = queue.mSortedShadowBatches;
  458. if (sortedBatches.size())
  459. {
  460. for (unsigned j = 0; j < sortedBatches.size(); ++j)
  461. sortedBatches[j]->draw(renderer);
  462. }
  463. renderer->setColorWrite(true);
  464. renderer->setDepthBias(0.0f, 0.0f);
  465. }
  466. // Light volume batches are not sorted as there should be only one of them
  467. if (queue.mBatches.size())
  468. {
  469. clearLastParameterSources();
  470. if (deferred)
  471. {
  472. renderer->setRenderTarget(0, renderBuffer);
  473. renderer->setTexture(TU_DIFFBUFFER, diffBuffer);
  474. }
  475. else
  476. renderer->setRenderTarget(0, diffBuffer);
  477. renderer->setTexture(TU_NORMALBUFFER, normalBuffer);
  478. renderer->setTexture(TU_DEPTHBUFFER, depthBuffer);
  479. renderer->resetDepthStencil();
  480. for (unsigned j = 0; j < queue.mBatches.size(); ++j)
  481. {
  482. mPipeline->setupLightBatch(queue.mBatches[j]);
  483. queue.mBatches[j].draw(renderer);
  484. }
  485. // If was the last split of a split point light, clear the stencil by rendering the point light again
  486. if ((queue.mLastSplit) && (queue.mLight->getLightType() == LIGHT_SPLITPOINT))
  487. mPipeline->drawSplitLightToStencil(*mCamera, queue.mLight, true);
  488. }
  489. }
  490. // Non-shadowed lights
  491. if (mNoShadowLightQueueSorted.size())
  492. {
  493. clearLastParameterSources();
  494. if (deferred)
  495. {
  496. renderer->setRenderTarget(0, renderBuffer);
  497. renderer->setTexture(TU_DIFFBUFFER, diffBuffer);
  498. }
  499. else
  500. renderer->setRenderTarget(0, diffBuffer);
  501. renderer->setTexture(TU_NORMALBUFFER, normalBuffer);
  502. renderer->setTexture(TU_DEPTHBUFFER, depthBuffer);
  503. renderer->resetDepthStencil();
  504. for (unsigned i = 0; i < mNoShadowLightQueueSorted.size(); ++i)
  505. {
  506. mPipeline->setupLightBatch(*mNoShadowLightQueueSorted[i]);
  507. mNoShadowLightQueueSorted[i]->draw(renderer);
  508. }
  509. }
  510. }
  511. {
  512. // Render forward passes
  513. PROFILE(View_RenderForward);
  514. clearLastParameterSources();
  515. renderer->setStencilTest(false);
  516. renderer->setRenderTarget(0, renderBuffer);
  517. renderer->setTexture(TU_DIFFBUFFER, 0);
  518. renderer->setTexture(TU_NORMALBUFFER, 0);
  519. renderer->setTexture(TU_DEPTHBUFFER, 0);
  520. if (!deferred)
  521. renderer->clear(CLEAR_COLOR, mZone->getFogColor());
  522. for (unsigned i = 0; i < mAmbientQueueSorted.size(); ++i)
  523. mAmbientQueueSorted[i]->draw(renderer);
  524. for (unsigned i = 0; i < mForwardQueueSorted.size(); ++i)
  525. {
  526. if (mForwardQueueSorted[i]->mForwardLight)
  527. optimizeLightByScissor(mForwardQueueSorted[i]->mForwardLight);
  528. else
  529. {
  530. renderer->setScissorTest(false);
  531. // Bind the light accumulation buffer for material pass of prepass mode
  532. if (!deferred)
  533. renderer->setTexture(TU_LIGHTBUFFER, diffBuffer);
  534. }
  535. mForwardQueueSorted[i]->draw(renderer);
  536. }
  537. renderer->setScissorTest(false);
  538. for (unsigned i = 0; i < mPostOpaqueQueueSorted.size(); ++i)
  539. mPostOpaqueQueueSorted[i]->draw(renderer);
  540. }
  541. {
  542. // Render transparent objects last (both ambient & additive lighting)
  543. PROFILE(View_RenderTransparent);
  544. for (unsigned i = 0; i < mTransparentQueueSorted.size(); ++i)
  545. {
  546. optimizeLightByScissor(mTransparentQueueSorted[i]->mForwardLight);
  547. mTransparentQueueSorted[i]->draw(renderer);
  548. }
  549. }
  550. // Render edge filter now if enabled
  551. if (edgeFilter)
  552. {
  553. PROFILE(View_RenderEdgeFilter);
  554. float invWidth = 0.5f / gBufferWidth;
  555. float invHeight = 0.5f / gBufferHeight;
  556. renderer->setAlphaTest(false);
  557. renderer->setBlendMode(BLEND_REPLACE);
  558. renderer->setDepthTest(CMP_ALWAYS);
  559. renderer->setDepthWrite(false);
  560. renderer->setScissorTest(false);
  561. renderer->setStencilTest(false);
  562. renderer->setRenderTarget(0, mRenderTarget);
  563. renderer->setTexture(TU_DIFFBUFFER, renderer->getScreenBuffer());
  564. renderer->setPixelShaderConstant(getPSRegister(PSP_SAMPLEOFFSETS), Vector4(invWidth, -invWidth, invHeight, -invHeight));
  565. renderer->setPixelShaderConstant(getPSRegister(PSP_EDGEFILTERPARAMS), Vector4(filterParams.mThreshold,
  566. filterParams.mFilterStep, filterParams.mMaxFilter, filterParams.mMaxScale));
  567. mPipeline->drawFullScreenQuad(*mCamera, mPipeline->getVertexShader("EdgeFilter"),
  568. mPipeline->getPixelShader("EdgeFilter"), false);
  569. }
  570. }