OGLGraphics.cpp 64 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198
  1. //
  2. // Urho3D Engine
  3. // Copyright (c) 2008-2012 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 "AnimatedModel.h"
  25. #include "Animation.h"
  26. #include "AnimationController.h"
  27. #include "BillboardSet.h"
  28. #include "Camera.h"
  29. #include "Context.h"
  30. #include "DebugRenderer.h"
  31. #include "Graphics.h"
  32. #include "GraphicsEvents.h"
  33. #include "GraphicsImpl.h"
  34. #include "IndexBuffer.h"
  35. #include "Light.h"
  36. #include "Log.h"
  37. #include "Material.h"
  38. #include "Mutex.h"
  39. #include "Octree.h"
  40. #include "ParticleEmitter.h"
  41. #include "ProcessUtils.h"
  42. #include "Profiler.h"
  43. #include "RenderSurface.h"
  44. #include "Shader.h"
  45. #include "ShaderProgram.h"
  46. #include "ShaderVariation.h"
  47. #include "Skybox.h"
  48. #include "StringUtils.h"
  49. #include "Technique.h"
  50. #include "Texture2D.h"
  51. #include "TextureCube.h"
  52. #include "VertexBuffer.h"
  53. #include "Zone.h"
  54. #include <stdio.h>
  55. #include "DebugNew.h"
  56. static const unsigned glCmpFunc[] =
  57. {
  58. GL_ALWAYS,
  59. GL_EQUAL,
  60. GL_NOTEQUAL,
  61. GL_LESS,
  62. GL_LEQUAL,
  63. GL_GREATER,
  64. GL_GEQUAL
  65. };
  66. static const unsigned glSrcBlend[] =
  67. {
  68. GL_ONE,
  69. GL_ONE,
  70. GL_DST_COLOR,
  71. GL_SRC_ALPHA,
  72. GL_SRC_ALPHA,
  73. GL_ONE,
  74. GL_ONE_MINUS_DST_ALPHA
  75. };
  76. static const unsigned glDestBlend[] =
  77. {
  78. GL_ZERO,
  79. GL_ONE,
  80. GL_ZERO,
  81. GL_ONE_MINUS_SRC_ALPHA,
  82. GL_ONE,
  83. GL_ONE_MINUS_SRC_ALPHA,
  84. GL_DST_ALPHA
  85. };
  86. static const unsigned glStencilOps[] =
  87. {
  88. GL_KEEP,
  89. GL_ZERO,
  90. GL_REPLACE,
  91. GL_INCR_WRAP,
  92. GL_DECR_WRAP
  93. };
  94. static unsigned numInstances = 0;
  95. static const String noParameter;
  96. static const unsigned MAX_FRAMEBUFFER_AGE = 2000;
  97. int CloseCallback(GLFWwindow window)
  98. {
  99. Context* context = GetWindowContext(window);
  100. if (context)
  101. {
  102. Graphics* graphics = context->GetSubsystem<Graphics>();
  103. // Do not close the window: GLFW will do it for us
  104. if (graphics)
  105. graphics->Release(true, false);
  106. }
  107. return GL_TRUE;
  108. }
  109. OBJECTTYPESTATIC(Graphics);
  110. Graphics::Graphics(Context* context_) :
  111. Object(context_),
  112. impl_(new GraphicsImpl()),
  113. width_(0),
  114. height_(0),
  115. multiSample_(1),
  116. fullscreen_(false),
  117. vsync_(false),
  118. tripleBuffer_(false),
  119. lightPrepassSupport_(false),
  120. deferredSupport_(false),
  121. hardwareDepthSupport_(false),
  122. numPrimitives_(0),
  123. numBatches_(0),
  124. defaultTextureFilterMode_(FILTER_BILINEAR),
  125. shadowMapFormat_(GL_DEPTH_COMPONENT16),
  126. hiresShadowMapFormat_(GL_DEPTH_COMPONENT24),
  127. shaderParameterFrame_(0)
  128. {
  129. ResetCachedState();
  130. SetTextureUnitMappings();
  131. {
  132. MutexLock lock(GetStaticMutex());
  133. if (!numInstances)
  134. glfwInit();
  135. ++numInstances;
  136. }
  137. }
  138. Graphics::~Graphics()
  139. {
  140. Close();
  141. delete impl_;
  142. impl_ = 0;
  143. {
  144. MutexLock lock(GetStaticMutex());
  145. --numInstances;
  146. if (!numInstances)
  147. glfwTerminate();
  148. }
  149. }
  150. void Graphics::SetWindowTitle(const String& windowTitle)
  151. {
  152. windowTitle_ = windowTitle;
  153. if (impl_->window_)
  154. glfwSetWindowTitle(impl_->window_, windowTitle_.CString());
  155. }
  156. bool Graphics::SetMode(int width, int height, bool fullscreen, bool vsync, bool tripleBuffer, int multiSample)
  157. {
  158. PROFILE(SetScreenMode);
  159. multiSample = Clamp(multiSample, 1, 16);
  160. if (IsInitialized() && width == width_ && height == height_ && fullscreen == fullscreen_ &&
  161. vsync == vsync_ && tripleBuffer == tripleBuffer_ && multiSample == multiSample_)
  162. return true;
  163. // If only vsync changes, do not destroy/recreate the context
  164. if (IsInitialized() && width == width_ && height == height_ && fullscreen == fullscreen_ &&
  165. tripleBuffer == tripleBuffer_ && multiSample == multiSample_ && vsync != vsync_)
  166. {
  167. glfwSwapInterval(vsync ? 1 : 0);
  168. vsync_ = vsync;
  169. return true;
  170. }
  171. // If zero dimensions in windowed mode, set default. If zero in fullscreen, use desktop mode
  172. if (!width || !height)
  173. {
  174. if (!fullscreen)
  175. {
  176. width = 800;
  177. height = 600;
  178. }
  179. else
  180. {
  181. GLFWvidmode mode;
  182. glfwGetDesktopMode(&mode);
  183. width = mode.width;
  184. height = mode.height;
  185. }
  186. }
  187. // Close the existing window, mark GPU objects as lost
  188. Release(false, true);
  189. {
  190. // GLFW window parameters and the window list are static, so need to operate under static lock
  191. MutexLock lock(GetStaticMutex());
  192. glfwOpenWindowHint(GLFW_RED_BITS, 8);
  193. glfwOpenWindowHint(GLFW_GREEN_BITS, 8);
  194. glfwOpenWindowHint(GLFW_BLUE_BITS, 8);
  195. glfwOpenWindowHint(GLFW_ALPHA_BITS, 0);
  196. glfwOpenWindowHint(GLFW_DEPTH_BITS, 24);
  197. glfwOpenWindowHint(GLFW_STENCIL_BITS, 8);
  198. glfwOpenWindowHint(GLFW_WINDOW_RESIZABLE, GL_FALSE);
  199. if (multiSample > 1)
  200. glfwOpenWindowHint(GLFW_FSAA_SAMPLES, multiSample);
  201. else
  202. glfwOpenWindowHint(GLFW_FSAA_SAMPLES, 0);
  203. impl_->window_ = glfwOpenWindow(width, height, fullscreen ? GLFW_FULLSCREEN : GLFW_WINDOWED, windowTitle_.CString(), 0);
  204. if (!impl_->window_)
  205. {
  206. LOGERROR("Could not open window");
  207. return false;
  208. }
  209. // If OpenGL extensions not yet initialized, initialize now
  210. if (!GLeeInitialized())
  211. GLeeInit();
  212. if (!_GLEE_VERSION_2_0)
  213. {
  214. LOGERROR("OpenGL 2.0 is required");
  215. glfwCloseWindow(impl_->window_);
  216. return false;
  217. }
  218. if (!_GLEE_EXT_framebuffer_object || !_GLEE_EXT_packed_depth_stencil || !_GLEE_EXT_texture_compression_s3tc ||
  219. !_GLEE_EXT_texture_filter_anisotropic)
  220. {
  221. LOGERROR("EXT_framebuffer_object, EXT_packed_depth_stencil, EXT_texture_compression_s3tc and "
  222. "EXT_texture_filter_anisotropic OpenGL extensions are required");
  223. glfwCloseWindow(impl_->window_);
  224. return false;
  225. }
  226. // Set window close callback
  227. glfwSetWindowCloseCallback(CloseCallback);
  228. // Associate GLFW window with the execution context
  229. SetWindowContext(impl_->window_, context_);
  230. }
  231. // Set vsync
  232. glfwSwapInterval(vsync ? 1 : 0);
  233. // Query for system backbuffer depth
  234. glGetIntegerv(GL_DEPTH_BITS, &impl_->windowDepthBits_);
  235. impl_->depthBits_ = impl_->windowDepthBits_;
  236. // Set initial state to match Direct3D
  237. glEnable(GL_DEPTH_TEST);
  238. SetCullMode(CULL_CCW);
  239. SetDepthTest(CMP_LESSEQUAL);
  240. glfwGetWindowSize(impl_->window_, &width_, &height_);
  241. fullscreen_ = fullscreen;
  242. vsync_ = vsync;
  243. tripleBuffer_ = tripleBuffer;
  244. multiSample_ = multiSample;
  245. // Reset rendertargets and viewport for the new screen mode
  246. ResetRenderTargets();
  247. // Clear the window to black now, because GPU object restore may take time
  248. Clear(CLEAR_COLOR);
  249. glfwSwapBuffers();
  250. // Let GPU objects restore themselves
  251. for (Vector<GPUObject*>::Iterator i = gpuObjects_.Begin(); i != gpuObjects_.End(); ++i)
  252. (*i)->OnDeviceReset();
  253. CheckFeatureSupport();
  254. if (multiSample > 1)
  255. LOGINFO("Set screen mode " + String(width_) + "x" + String(height_) + " " + (fullscreen_ ? "fullscreen" : "windowed") +
  256. " multisample " + String(multiSample));
  257. else
  258. LOGINFO("Set screen mode " + String(width_) + "x" + String(height_) + " " + (fullscreen_ ? "fullscreen" : "windowed"));
  259. using namespace ScreenMode;
  260. VariantMap eventData;
  261. eventData[P_WIDTH] = width_;
  262. eventData[P_HEIGHT] = height_;
  263. eventData[P_FULLSCREEN] = fullscreen_;
  264. SendEvent(E_SCREENMODE, eventData);
  265. return true;
  266. }
  267. bool Graphics::SetMode(int width, int height)
  268. {
  269. return SetMode(width, height, fullscreen_, vsync_, tripleBuffer_, multiSample_);
  270. }
  271. bool Graphics::ToggleFullscreen()
  272. {
  273. return SetMode(width_, height_, !fullscreen_, vsync_, tripleBuffer_, multiSample_);
  274. }
  275. void Graphics::Close()
  276. {
  277. if (!IsInitialized())
  278. return;
  279. // Actually close the window
  280. Release(true, true);
  281. }
  282. bool Graphics::TakeScreenShot(Image& destImage)
  283. {
  284. PROFILE(TakeScreenShot);
  285. ResetRenderTargets();
  286. destImage.SetSize(width_, height_, 3);
  287. glReadPixels(0, 0, width_, height_, GL_RGB, GL_UNSIGNED_BYTE, destImage.GetData());
  288. return true;
  289. }
  290. bool Graphics::BeginFrame()
  291. {
  292. PROFILE(BeginRendering);
  293. if (!IsInitialized())
  294. return false;
  295. // If we should be fullscreen, but are not currently active, do not render
  296. if (fullscreen_ && (!glfwGetWindowParam(impl_->window_, GLFW_ACTIVE) || glfwGetWindowParam(impl_->window_, GLFW_ICONIFIED)))
  297. return false;
  298. // Set default rendertarget and depth buffer
  299. ResetRenderTargets();
  300. // Cleanup textures from previous frame
  301. for (unsigned i = 0; i < MAX_TEXTURE_UNITS; ++i)
  302. SetTexture(i, 0);
  303. // Enable color and depth write
  304. SetColorWrite(true);
  305. SetDepthWrite(true);
  306. numPrimitives_ = 0;
  307. numBatches_ = 0;
  308. SendEvent(E_BEGINRENDERING);
  309. return true;
  310. }
  311. void Graphics::EndFrame()
  312. {
  313. PROFILE(EndRendering);
  314. if (!IsInitialized())
  315. return;
  316. SendEvent(E_ENDRENDERING);
  317. glfwSwapBuffers();
  318. // Clean up FBO's that have not been used for a long time
  319. CleanupFramebuffers(false);
  320. }
  321. void Graphics::Clear(unsigned flags, const Color& color, float depth, unsigned stencil)
  322. {
  323. if (impl_->fboDirty_)
  324. CommitFramebuffer();
  325. bool oldColorWrite = colorWrite_;
  326. bool oldDepthWrite = depthWrite_;
  327. if (flags & CLEAR_COLOR && !oldColorWrite)
  328. SetColorWrite(true);
  329. if (flags & CLEAR_DEPTH && !oldDepthWrite)
  330. SetDepthWrite(true);
  331. if (flags & CLEAR_STENCIL && stencilWriteMask_ != M_MAX_UNSIGNED)
  332. glStencilMask(M_MAX_UNSIGNED);
  333. unsigned glFlags = 0;
  334. if (flags & CLEAR_COLOR)
  335. {
  336. glFlags |= GL_COLOR_BUFFER_BIT;
  337. glClearColor(color.r_, color.g_, color.b_, color.a_);
  338. }
  339. if (flags & CLEAR_DEPTH)
  340. {
  341. glFlags |= GL_DEPTH_BUFFER_BIT;
  342. glClearDepth(depth);
  343. }
  344. if (flags & CLEAR_STENCIL)
  345. {
  346. glFlags |= GL_STENCIL_BUFFER_BIT;
  347. glClearStencil(stencil);
  348. }
  349. // If viewport is less than full screen, set a scissor to limit the clear
  350. /// \todo Any user-set scissor test will be lost
  351. IntVector2 viewSize = GetRenderTargetDimensions();
  352. if (viewport_.left_ != 0 || viewport_.top_ != 0 || viewport_.right_ != viewSize.x_ || viewport_.bottom_ != viewSize.y_)
  353. SetScissorTest(true, IntRect(0, 0, viewport_.right_ - viewport_.left_, viewport_.bottom_ - viewport_.top_));
  354. else
  355. SetScissorTest(false);
  356. glClear(glFlags);
  357. SetScissorTest(false);
  358. SetColorWrite(oldColorWrite);
  359. SetDepthWrite(oldDepthWrite);
  360. if (flags & CLEAR_STENCIL && stencilWriteMask_ != M_MAX_UNSIGNED)
  361. glStencilMask(stencilWriteMask_);
  362. }
  363. bool Graphics::ResolveToTexture(Texture2D* destination, const IntRect& viewport)
  364. {
  365. if (!destination || !destination->GetRenderSurface() || destination->GetWidth() != width_ ||
  366. destination->GetHeight() != height_)
  367. return false;
  368. IntRect vpCopy = viewport;
  369. if (vpCopy.right_ <= vpCopy.left_)
  370. vpCopy.right_ = vpCopy.left_ + 1;
  371. if (vpCopy.bottom_ <= vpCopy.top_)
  372. vpCopy.bottom_ = vpCopy.top_ + 1;
  373. vpCopy.left_ = Clamp(vpCopy.left_, 0, width_);
  374. vpCopy.top_ = Clamp(vpCopy.top_, 0, height_);
  375. vpCopy.right_ = Clamp(vpCopy.right_, 0, width_);
  376. vpCopy.bottom_ = Clamp(vpCopy.bottom_, 0, height_);
  377. // Make sure the FBO is not in use
  378. ResetRenderTargets();
  379. // Use Direct3D convention with the vertical coordinates ie. 0 is top
  380. SetTextureForUpdate(destination);
  381. glCopyTexSubImage2D(GL_TEXTURE_2D, 0, vpCopy.left_, height_ - vpCopy.bottom_, vpCopy.left_, height_ - vpCopy.bottom_,
  382. vpCopy.right_ - vpCopy.left_, vpCopy.bottom_ - vpCopy.top_);
  383. SetTexture(0, 0);
  384. return true;
  385. }
  386. void Graphics::Draw(PrimitiveType type, unsigned vertexStart, unsigned vertexCount)
  387. {
  388. if (!vertexCount)
  389. return;
  390. if (impl_->fboDirty_)
  391. CommitFramebuffer();
  392. unsigned primitiveCount = 0;
  393. switch (type)
  394. {
  395. case TRIANGLE_LIST:
  396. primitiveCount = vertexCount / 3;
  397. glDrawArrays(GL_TRIANGLES, vertexStart, vertexCount);
  398. break;
  399. case LINE_LIST:
  400. primitiveCount = vertexCount / 2;
  401. glDrawArrays(GL_LINES, vertexStart, vertexCount);
  402. break;
  403. }
  404. numPrimitives_ += primitiveCount;
  405. ++numBatches_;
  406. }
  407. void Graphics::Draw(PrimitiveType type, unsigned indexStart, unsigned indexCount, unsigned minVertex, unsigned vertexCount)
  408. {
  409. if (!indexCount || !indexBuffer_)
  410. return;
  411. if (impl_->fboDirty_)
  412. CommitFramebuffer();
  413. unsigned primitiveCount = 0;
  414. unsigned indexSize = indexBuffer_->GetIndexSize();
  415. switch (type)
  416. {
  417. case TRIANGLE_LIST:
  418. primitiveCount = indexCount / 3;
  419. if (indexSize == sizeof(unsigned short))
  420. glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_SHORT, (const GLvoid*)(indexStart * indexSize));
  421. else
  422. glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, (const GLvoid*)(indexStart * indexSize));
  423. break;
  424. case LINE_LIST:
  425. primitiveCount = indexCount / 2;
  426. if (indexSize == sizeof(unsigned short))
  427. glDrawElements(GL_LINES, indexCount, GL_UNSIGNED_SHORT, (const GLvoid*)(indexStart * indexSize));
  428. else
  429. glDrawElements(GL_LINES, indexCount, GL_UNSIGNED_INT, (const GLvoid*)(indexStart * indexSize));
  430. break;
  431. }
  432. numPrimitives_ += primitiveCount;
  433. ++numBatches_;
  434. }
  435. void Graphics::DrawInstanced(PrimitiveType type, unsigned indexStart, unsigned indexCount, unsigned minVertex, unsigned vertexCount, unsigned instanceCount)
  436. {
  437. }
  438. void Graphics::SetVertexBuffer(VertexBuffer* buffer)
  439. {
  440. Vector<VertexBuffer*> vertexBuffers(1);
  441. PODVector<unsigned> elementMasks(1);
  442. vertexBuffers[0] = buffer;
  443. elementMasks[0] = MASK_DEFAULT;
  444. SetVertexBuffers(vertexBuffers, elementMasks);
  445. }
  446. bool Graphics::SetVertexBuffers(const Vector<VertexBuffer*>& buffers, const PODVector<unsigned>& elementMasks,
  447. unsigned instanceOffset)
  448. {
  449. if (buffers.Size() > MAX_VERTEX_STREAMS)
  450. {
  451. LOGERROR("Too many vertex buffers");
  452. return false;
  453. }
  454. if (buffers.Size() != elementMasks.Size())
  455. {
  456. LOGERROR("Amount of element masks and vertex buffers does not match");
  457. return false;
  458. }
  459. // If no valid shader to determine the attribute bindings, can not set vertex buffers
  460. if (!shaderProgram_)
  461. return false;
  462. const int* attributeLocations = shaderProgram_->GetAttributeLocations();
  463. bool changed = false;
  464. unsigned newAttributes = 0;
  465. for (unsigned i = 0; i < MAX_VERTEX_STREAMS; ++i)
  466. {
  467. VertexBuffer* buffer = 0;
  468. unsigned elementMask = 0;
  469. if (i < buffers.Size())
  470. {
  471. buffer = buffers[i];
  472. elementMask = elementMasks[i];
  473. if (elementMask == MASK_DEFAULT && buffer)
  474. elementMask = buffers[i]->GetElementMask();
  475. }
  476. // If buffer and element mask have stayed the same, skip to the next buffer
  477. if (buffer == vertexBuffers_[i] && elementMask == elementMasks_[i])
  478. continue;
  479. vertexBuffers_[i] = buffer;
  480. elementMasks_[i] = elementMask;
  481. changed = true;
  482. if (!buffer)
  483. continue;
  484. glBindBuffer(GL_ARRAY_BUFFER, buffer->GetGPUObject());
  485. unsigned vertexSize = buffer->GetVertexSize();
  486. for (unsigned j = 0; j < MAX_VERTEX_ELEMENTS; ++j)
  487. {
  488. // If shader does not use the attribute, do not bind it (bandwidth optimization)
  489. int attributeIndex = attributeLocations[j];
  490. if (attributeIndex < 0)
  491. continue;
  492. unsigned elementBit = 1 << j;
  493. unsigned attributeBit = 1 << attributeIndex;
  494. if (elementMask & elementBit)
  495. {
  496. newAttributes |= attributeBit;
  497. // Enable attribute if not enabled yet
  498. if ((impl_->enabledAttributes_ & attributeBit) == 0)
  499. {
  500. glEnableVertexAttribArray(attributeIndex);
  501. impl_->enabledAttributes_ |= attributeBit;
  502. }
  503. // Set the attribute pointer
  504. glVertexAttribPointer(attributeIndex, VertexBuffer::elementComponents[j], VertexBuffer::elementType[j],
  505. VertexBuffer::elementNormalize[j], vertexSize, (const GLvoid*)(buffer->GetElementOffset((VertexElement)j)));
  506. }
  507. }
  508. }
  509. if (!changed)
  510. return true;
  511. // Now check which vertex attributes should be disabled
  512. unsigned disableAttributes = impl_->enabledAttributes_ & (~newAttributes);
  513. int disableIndex = 0;
  514. while (disableAttributes)
  515. {
  516. if (disableAttributes & 1)
  517. {
  518. glDisableVertexAttribArray(disableIndex);
  519. impl_->enabledAttributes_ &= ~(1 << disableIndex);
  520. }
  521. disableAttributes >>= 1;
  522. ++disableIndex;
  523. }
  524. return true;
  525. }
  526. bool Graphics::SetVertexBuffers(const Vector<SharedPtr<VertexBuffer> >& buffers, const PODVector<unsigned>&
  527. elementMasks, unsigned instanceOffset)
  528. {
  529. if (buffers.Size() > MAX_VERTEX_STREAMS)
  530. {
  531. LOGERROR("Too many vertex buffers");
  532. return false;
  533. }
  534. if (buffers.Size() != elementMasks.Size())
  535. {
  536. LOGERROR("Amount of element masks and vertex buffers does not match");
  537. return false;
  538. }
  539. // If no valid shader to determine the attribute bindings, can not set vertex buffers
  540. if (!shaderProgram_)
  541. return false;
  542. const int* attributeLocations = shaderProgram_->GetAttributeLocations();
  543. bool changed = false;
  544. unsigned newAttributes = 0;
  545. for (unsigned i = 0; i < MAX_VERTEX_STREAMS; ++i)
  546. {
  547. VertexBuffer* buffer = 0;
  548. unsigned elementMask = 0;
  549. if (i < buffers.Size())
  550. {
  551. buffer = buffers[i];
  552. elementMask = elementMasks[i];
  553. if (elementMask == MASK_DEFAULT && buffer)
  554. elementMask = buffers[i]->GetElementMask();
  555. }
  556. // If buffer and element mask have stayed the same, skip to the next buffer
  557. if (buffer == vertexBuffers_[i] && elementMask == elementMasks_[i])
  558. continue;
  559. vertexBuffers_[i] = buffer;
  560. elementMasks_[i] = elementMask;
  561. changed = true;
  562. if (!buffer)
  563. continue;
  564. glBindBuffer(GL_ARRAY_BUFFER, buffer->GetGPUObject());
  565. unsigned vertexSize = buffer->GetVertexSize();
  566. for (unsigned j = 0; j < MAX_VERTEX_ELEMENTS; ++j)
  567. {
  568. // If shader does not use the attribute, do not bind it (bandwidth optimization)
  569. int attributeIndex = attributeLocations[j];
  570. if (attributeIndex < 0)
  571. continue;
  572. unsigned elementBit = 1 << j;
  573. unsigned attributeBit = 1 << attributeIndex;
  574. if (elementMask & elementBit)
  575. {
  576. newAttributes |= attributeBit;
  577. // Enable attribute if not enabled yet
  578. if ((impl_->enabledAttributes_ & attributeBit) == 0)
  579. {
  580. glEnableVertexAttribArray(attributeIndex);
  581. impl_->enabledAttributes_ |= attributeBit;
  582. }
  583. // Set the attribute pointer
  584. glVertexAttribPointer(attributeIndex, VertexBuffer::elementComponents[j], VertexBuffer::elementType[j],
  585. VertexBuffer::elementNormalize[j], vertexSize, (const GLvoid*)(buffer->GetElementOffset((VertexElement)j)));
  586. }
  587. }
  588. }
  589. if (!changed)
  590. return true;
  591. // Now check which vertex attributes should be disabled
  592. unsigned disableAttributes = impl_->enabledAttributes_ & (~newAttributes);
  593. int disableIndex = 0;
  594. while (disableAttributes)
  595. {
  596. if (disableAttributes & 1)
  597. {
  598. glDisableVertexAttribArray(disableIndex);
  599. impl_->enabledAttributes_ &= ~(1 << disableIndex);
  600. }
  601. disableAttributes >>= 1;
  602. ++disableIndex;
  603. }
  604. return true;
  605. }
  606. void Graphics::SetIndexBuffer(IndexBuffer* buffer)
  607. {
  608. if (indexBuffer_ == buffer)
  609. return;
  610. if (buffer)
  611. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer->GetGPUObject());
  612. else
  613. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  614. indexBuffer_ = buffer;
  615. }
  616. void Graphics::SetShaders(ShaderVariation* vs, ShaderVariation* ps)
  617. {
  618. if (vs == vertexShader_ && ps == pixelShader_)
  619. return;
  620. // Compile the shaders now if not yet compiled. If already attempted, do not retry
  621. if (vs && !vs->IsCompiled())
  622. {
  623. if (vs->GetCompilerOutput().Empty())
  624. {
  625. PROFILE(CompileVertexShader);
  626. bool success = vs->Create();
  627. if (success)
  628. LOGDEBUG("Compiled vertex shader " + vs->GetName());
  629. else
  630. {
  631. LOGERROR("Failed to compile vertex shader " + vs->GetName() + ":\n" + vs->GetCompilerOutput());
  632. vs = 0;
  633. }
  634. }
  635. else
  636. vs = 0;
  637. }
  638. if (ps && !ps->IsCompiled())
  639. {
  640. if (ps->GetCompilerOutput().Empty())
  641. {
  642. PROFILE(CompilePixelShader);
  643. bool success = ps->Create();
  644. if (success)
  645. LOGDEBUG("Compiled pixel shader " + ps->GetName());
  646. else
  647. {
  648. LOGERROR("Failed to compile pixel shader " + ps->GetName() + ":\n" + ps->GetCompilerOutput());
  649. ps = 0;
  650. }
  651. }
  652. else
  653. ps = 0;
  654. }
  655. for (unsigned i = 0; i < MAX_VERTEX_STREAMS; ++i)
  656. {
  657. vertexBuffers_[i] = 0;
  658. elementMasks_[i] = 0;
  659. }
  660. if (!vs || !ps)
  661. {
  662. glUseProgram(0);
  663. vertexShader_ = 0;
  664. pixelShader_ = 0;
  665. shaderProgram_ = 0;
  666. }
  667. else
  668. {
  669. vertexShader_ = vs;
  670. pixelShader_ = ps;
  671. Pair<ShaderVariation*, ShaderVariation*> combination(vs, ps);
  672. ShaderProgramMap::Iterator i = shaderPrograms_.Find(combination);
  673. if (i != shaderPrograms_.End())
  674. {
  675. // Use the existing linked program
  676. if (i->second_->IsLinked())
  677. {
  678. glUseProgram(i->second_->GetGPUObject());
  679. shaderProgram_ = i->second_;
  680. }
  681. else
  682. {
  683. glUseProgram(0);
  684. shaderProgram_ = 0;
  685. }
  686. }
  687. else
  688. {
  689. // Link a new combination
  690. SharedPtr<ShaderProgram> newProgram(new ShaderProgram(this, vs, ps));
  691. if (newProgram->Link())
  692. {
  693. LOGDEBUG("Linked vertex shader " + vs->GetName() + " and pixel shader " + ps->GetName());
  694. // Note: Link() calls glUseProgram() to set the texture sampler uniforms,
  695. // so it is not necessary to call it again
  696. shaderProgram_ = newProgram;
  697. }
  698. else
  699. {
  700. LOGERROR("Failed to link vertex shader " + vs->GetName() + " and pixel shader " + ps->GetName() + ":\n" +
  701. newProgram->GetLinkerOutput());
  702. glUseProgram(0);
  703. shaderProgram_ = 0;
  704. }
  705. shaderPrograms_[combination] = newProgram;
  706. }
  707. }
  708. }
  709. void Graphics::SetShaderParameter(StringHash param, const float* data, unsigned count)
  710. {
  711. if (shaderProgram_)
  712. {
  713. const ShaderParameter* info = shaderProgram_->GetParameter(param);
  714. if (info)
  715. {
  716. switch (info->type_)
  717. {
  718. case GL_FLOAT:
  719. glUniform1fv(info->location_, count, data);
  720. break;
  721. case GL_FLOAT_VEC2:
  722. glUniform2fv(info->location_, count / 2, data);
  723. break;
  724. case GL_FLOAT_VEC3:
  725. glUniform3fv(info->location_, count / 3, data);
  726. break;
  727. case GL_FLOAT_VEC4:
  728. glUniform4fv(info->location_, count / 4, data);
  729. break;
  730. case GL_FLOAT_MAT3:
  731. glUniformMatrix3fv(info->location_, count / 9, GL_TRUE, data);
  732. break;
  733. case GL_FLOAT_MAT4:
  734. glUniformMatrix4fv(info->location_, count / 16, GL_TRUE, data);
  735. break;
  736. }
  737. }
  738. }
  739. }
  740. void Graphics::SetShaderParameter(StringHash param, float value)
  741. {
  742. if (shaderProgram_)
  743. {
  744. const ShaderParameter* info = shaderProgram_->GetParameter(param);
  745. if (info)
  746. glUniform1fv(info->location_, 1, &value);
  747. }
  748. }
  749. void Graphics::SetShaderParameter(StringHash param, const Color& color)
  750. {
  751. SetShaderParameter(param, color.Data(), 4);
  752. }
  753. void Graphics::SetShaderParameter(StringHash param, const Matrix3& matrix)
  754. {
  755. if (shaderProgram_)
  756. {
  757. const ShaderParameter* info = shaderProgram_->GetParameter(param);
  758. if (info)
  759. glUniformMatrix3fv(info->location_, 1, GL_TRUE, matrix.Data());
  760. }
  761. }
  762. void Graphics::SetShaderParameter(StringHash param, const Vector3& vector)
  763. {
  764. if (shaderProgram_)
  765. {
  766. const ShaderParameter* info = shaderProgram_->GetParameter(param);
  767. if (info)
  768. {
  769. // Check the uniform type to avoid mismatch
  770. switch (info->type_)
  771. {
  772. case GL_FLOAT:
  773. glUniform1fv(info->location_, 1, vector.Data());
  774. break;
  775. case GL_FLOAT_VEC2:
  776. glUniform2fv(info->location_, 1, vector.Data());
  777. break;
  778. case GL_FLOAT_VEC3:
  779. glUniform3fv(info->location_, 1, vector.Data());
  780. break;
  781. }
  782. }
  783. }
  784. }
  785. void Graphics::SetShaderParameter(StringHash param, const Matrix4& matrix)
  786. {
  787. if (shaderProgram_)
  788. {
  789. const ShaderParameter* info = shaderProgram_->GetParameter(param);
  790. if (info)
  791. glUniformMatrix4fv(info->location_, 1, GL_TRUE, matrix.Data());
  792. }
  793. }
  794. void Graphics::SetShaderParameter(StringHash param, const Vector4& vector)
  795. {
  796. if (shaderProgram_)
  797. {
  798. const ShaderParameter* info = shaderProgram_->GetParameter(param);
  799. if (info)
  800. {
  801. // Check the uniform type to avoid mismatch
  802. switch (info->type_)
  803. {
  804. case GL_FLOAT:
  805. glUniform1fv(info->location_, 1, vector.Data());
  806. break;
  807. case GL_FLOAT_VEC2:
  808. glUniform2fv(info->location_, 1, vector.Data());
  809. break;
  810. case GL_FLOAT_VEC3:
  811. glUniform3fv(info->location_, 1, vector.Data());
  812. break;
  813. case GL_FLOAT_VEC4:
  814. glUniform4fv(info->location_, 1, vector.Data());
  815. break;
  816. }
  817. }
  818. }
  819. }
  820. void Graphics::SetShaderParameter(StringHash param, const Matrix3x4& matrix)
  821. {
  822. if (shaderProgram_)
  823. {
  824. const ShaderParameter* info = shaderProgram_->GetParameter(param);
  825. if (info)
  826. {
  827. float data[16];
  828. data[0] = matrix.m00_;
  829. data[1] = matrix.m01_;
  830. data[2] = matrix.m02_;
  831. data[3] = matrix.m03_;
  832. data[4] = matrix.m10_;
  833. data[5] = matrix.m11_;
  834. data[6] = matrix.m12_;
  835. data[7] = matrix.m13_;
  836. data[8] = matrix.m20_;
  837. data[9] = matrix.m21_;
  838. data[10] = matrix.m22_;
  839. data[11] = matrix.m23_;
  840. data[12] = 0.0f;
  841. data[13] = 0.0f;
  842. data[14] = 0.0f;
  843. data[15] = 1.0f;
  844. glUniformMatrix4fv(info->location_, 1, GL_TRUE, data);
  845. }
  846. }
  847. }
  848. bool Graphics::NeedParameterUpdate(StringHash param, const void* source)
  849. {
  850. if (shaderProgram_)
  851. return shaderProgram_->NeedParameterUpdate(param, source, shaderParameterFrame_);
  852. return false;
  853. }
  854. bool Graphics::NeedTextureUnit(TextureUnit unit)
  855. {
  856. if (shaderProgram_ && shaderProgram_->HasTextureUnit(unit))
  857. return true;
  858. return false;
  859. }
  860. void Graphics::ClearParameterSource(StringHash param)
  861. {
  862. if (shaderProgram_)
  863. shaderProgram_->ClearParameterSource(param);
  864. }
  865. void Graphics::ClearParameterSources()
  866. {
  867. ++shaderParameterFrame_;
  868. }
  869. void Graphics::ClearTransformSources()
  870. {
  871. if (shaderProgram_)
  872. {
  873. shaderProgram_->ClearParameterSource(VSP_MODEL);
  874. shaderProgram_->ClearParameterSource(VSP_VIEWPROJ);
  875. }
  876. }
  877. void Graphics::CleanupShaderPrograms()
  878. {
  879. for (ShaderProgramMap::Iterator i = shaderPrograms_.Begin(); i != shaderPrograms_.End();)
  880. {
  881. ShaderProgramMap::Iterator current = i++;
  882. ShaderVariation* vs = current->second_->GetVertexShader();
  883. ShaderVariation* ps = current->second_->GetPixelShader();
  884. if (!vs || !ps || !vs->GetGPUObject() || !ps->GetGPUObject())
  885. shaderPrograms_.Erase(current);
  886. }
  887. }
  888. void Graphics::SetTexture(unsigned index, Texture* texture)
  889. {
  890. if (index >= MAX_TEXTURE_UNITS)
  891. return;
  892. // Check if texture is currently bound as a rendertarget. In that case, use its backup texture, or blank if not defined
  893. if (texture)
  894. {
  895. if (texture == viewTexture_ || (renderTargets_[0] && renderTargets_[0]->GetParentTexture() == texture))
  896. texture = texture->GetBackupTexture();
  897. }
  898. if (textures_[index] != texture)
  899. {
  900. if (impl_->activeTexture_ != index)
  901. {
  902. glActiveTexture(GL_TEXTURE0 + index);
  903. impl_->activeTexture_ = index;
  904. }
  905. if (texture)
  906. {
  907. unsigned glType = texture->GetTarget();
  908. if (glType != textureTypes_[index])
  909. {
  910. if (textureTypes_[index])
  911. glDisable(textureTypes_[index]);
  912. glEnable(glType);
  913. textureTypes_[index] = glType;
  914. }
  915. glBindTexture(glType, texture->GetGPUObject());
  916. if (texture->GetParametersDirty())
  917. texture->UpdateParameters();
  918. }
  919. else
  920. {
  921. if (textureTypes_[index])
  922. glBindTexture(textureTypes_[index], 0);
  923. }
  924. textures_[index] = texture;
  925. }
  926. else
  927. {
  928. if (texture && texture->GetParametersDirty())
  929. {
  930. if (impl_->activeTexture_ != index)
  931. {
  932. glActiveTexture(GL_TEXTURE0 + index);
  933. impl_->activeTexture_ = index;
  934. }
  935. glBindTexture(texture->GetTarget(), texture->GetGPUObject());
  936. texture->UpdateParameters();
  937. }
  938. }
  939. }
  940. void Graphics::SetTextureForUpdate(Texture* texture)
  941. {
  942. if (impl_->activeTexture_ != 0)
  943. {
  944. glActiveTexture(GL_TEXTURE0);
  945. impl_->activeTexture_ = 0;
  946. }
  947. glBindTexture(texture->GetTarget(), texture->GetGPUObject());
  948. textures_[0] = texture;
  949. }
  950. void Graphics::SetDefaultTextureFilterMode(TextureFilterMode mode)
  951. {
  952. if (mode != defaultTextureFilterMode_)
  953. {
  954. defaultTextureFilterMode_ = mode;
  955. SetTextureParametersDirty();
  956. }
  957. }
  958. void Graphics::SetTextureAnisotropy(unsigned level)
  959. {
  960. if (level != textureAnisotropy_)
  961. {
  962. textureAnisotropy_ = level;
  963. SetTextureParametersDirty();
  964. }
  965. }
  966. void Graphics::SetTextureParametersDirty()
  967. {
  968. for (Vector<GPUObject*>::Iterator i = gpuObjects_.Begin(); i != gpuObjects_.End(); ++i)
  969. {
  970. Texture* texture = dynamic_cast<Texture*>(*i);
  971. if (texture)
  972. texture->SetParametersDirty();
  973. }
  974. }
  975. void Graphics::ResetRenderTargets()
  976. {
  977. for (unsigned i = 0; i < MAX_RENDERTARGETS; ++i)
  978. SetRenderTarget(i, (RenderSurface*)0);
  979. SetDepthStencil((RenderSurface*)0);
  980. SetViewport(IntRect(0, 0, width_, height_));
  981. }
  982. void Graphics::ResetRenderTarget(unsigned index)
  983. {
  984. SetRenderTarget(index, (RenderSurface*)0);
  985. }
  986. void Graphics::ResetDepthStencil()
  987. {
  988. SetDepthStencil((RenderSurface*)0);
  989. }
  990. void Graphics::SetRenderTarget(unsigned index, RenderSurface* renderTarget)
  991. {
  992. if (index >= MAX_RENDERTARGETS)
  993. return;
  994. if (renderTarget != renderTargets_[index])
  995. {
  996. renderTargets_[index] = renderTarget;
  997. // If the rendertarget is also bound as a texture, replace with backup texture or null
  998. if (renderTarget)
  999. {
  1000. Texture* parentTexture = renderTarget->GetParentTexture();
  1001. for (unsigned i = 0; i < MAX_TEXTURE_UNITS; ++i)
  1002. {
  1003. if (textures_[i] == parentTexture)
  1004. SetTexture(i, textures_[i]->GetBackupTexture());
  1005. }
  1006. }
  1007. impl_->fboDirty_ = true;
  1008. }
  1009. }
  1010. void Graphics::SetRenderTarget(unsigned index, Texture2D* texture)
  1011. {
  1012. RenderSurface* renderTarget = 0;
  1013. if (texture)
  1014. renderTarget = texture->GetRenderSurface();
  1015. SetRenderTarget(index, renderTarget);
  1016. }
  1017. void Graphics::SetDepthStencil(RenderSurface* depthStencil)
  1018. {
  1019. // If we are using a rendertarget texture, it is required in OpenGL to also have an own depth-stencil
  1020. // Create a new depth-stencil texture as necessary to be able to provide similar behaviour as Direct3D9
  1021. if (renderTargets_[0] && !depthStencil)
  1022. {
  1023. int width = renderTargets_[0]->GetWidth();
  1024. int height = renderTargets_[0]->GetHeight();
  1025. // Direct3D9 default depth-stencil can not be used when rendertarget is larger than the window.
  1026. // Check size similarly
  1027. if (width <= width_ && height <= height_)
  1028. {
  1029. int searchKey = (width << 16) | height;
  1030. HashMap<int, SharedPtr<Texture2D> >::Iterator i = depthTextures_.Find(searchKey);
  1031. if (i != depthTextures_.End())
  1032. depthStencil = i->second_->GetRenderSurface();
  1033. else
  1034. {
  1035. SharedPtr<Texture2D> newDepthTexture(new Texture2D(context_));
  1036. newDepthTexture->SetSize(width, height, GetDepthStencilFormat(), TEXTURE_DEPTHSTENCIL);
  1037. depthTextures_[searchKey] = newDepthTexture;
  1038. depthStencil = newDepthTexture->GetRenderSurface();
  1039. }
  1040. }
  1041. }
  1042. if (depthStencil != depthStencil_)
  1043. {
  1044. depthStencil_ = depthStencil;
  1045. impl_->fboDirty_ = true;
  1046. }
  1047. }
  1048. void Graphics::SetDepthStencil(Texture2D* texture)
  1049. {
  1050. RenderSurface* depthStencil = 0;
  1051. if (texture)
  1052. depthStencil = texture->GetRenderSurface();
  1053. SetDepthStencil(depthStencil);
  1054. }
  1055. void Graphics::SetViewTexture(Texture* texture)
  1056. {
  1057. viewTexture_ = texture;
  1058. if (viewTexture_)
  1059. {
  1060. for (unsigned i = 0; i < MAX_TEXTURE_UNITS; ++i)
  1061. {
  1062. if (textures_[i] == viewTexture_)
  1063. SetTexture(i, textures_[i]->GetBackupTexture());
  1064. }
  1065. }
  1066. }
  1067. void Graphics::SetViewport(const IntRect& rect)
  1068. {
  1069. if (impl_->fboDirty_)
  1070. CommitFramebuffer();
  1071. IntVector2 rtSize = GetRenderTargetDimensions();
  1072. IntRect rectCopy = rect;
  1073. if (rectCopy.right_ <= rectCopy.left_)
  1074. rectCopy.right_ = rectCopy.left_ + 1;
  1075. if (rectCopy.bottom_ <= rectCopy.top_)
  1076. rectCopy.bottom_ = rectCopy.top_ + 1;
  1077. rectCopy.left_ = Clamp(rectCopy.left_, 0, rtSize.x_);
  1078. rectCopy.top_ = Clamp(rectCopy.top_, 0, rtSize.y_);
  1079. rectCopy.right_ = Clamp(rectCopy.right_, 0, rtSize.x_);
  1080. rectCopy.bottom_ = Clamp(rectCopy.bottom_, 0, rtSize.y_);
  1081. // Use Direct3D convention with the vertical coordinates ie. 0 is top
  1082. glViewport(rectCopy.left_, rtSize.y_ - rectCopy.bottom_, rectCopy.right_ - rectCopy.left_, rectCopy.bottom_ - rectCopy.top_);
  1083. viewport_ = rectCopy;
  1084. // Disable scissor test, needs to be re-enabled by the user
  1085. SetScissorTest(false);
  1086. }
  1087. void Graphics::SetAlphaTest(bool enable, CompareMode mode, float alphaRef)
  1088. {
  1089. if (enable != alphaTest_)
  1090. {
  1091. if (enable)
  1092. glEnable(GL_ALPHA_TEST);
  1093. else
  1094. glDisable(GL_ALPHA_TEST);
  1095. alphaTest_ = enable;
  1096. }
  1097. if (enable)
  1098. {
  1099. alphaRef = Clamp(alphaRef, 0.0f, 1.0f);
  1100. if (mode != alphaTestMode_ || alphaRef != alphaRef_)
  1101. {
  1102. glAlphaFunc(glCmpFunc[mode], alphaRef);
  1103. alphaTestMode_ = mode;
  1104. alphaRef_ = alphaRef;
  1105. }
  1106. }
  1107. }
  1108. void Graphics::SetBlendMode(BlendMode mode)
  1109. {
  1110. if (mode != blendMode_)
  1111. {
  1112. if (mode == BLEND_REPLACE)
  1113. glDisable(GL_BLEND);
  1114. else
  1115. {
  1116. glEnable(GL_BLEND);
  1117. glBlendFunc(glSrcBlend[mode], glDestBlend[mode]);
  1118. }
  1119. blendMode_ = mode;
  1120. }
  1121. }
  1122. void Graphics::SetColorWrite(bool enable)
  1123. {
  1124. if (enable != colorWrite_)
  1125. {
  1126. if (enable)
  1127. glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  1128. else
  1129. glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
  1130. colorWrite_ = enable;
  1131. }
  1132. }
  1133. void Graphics::SetCullMode(CullMode mode)
  1134. {
  1135. if (mode != cullMode_)
  1136. {
  1137. if (mode == CULL_NONE)
  1138. glDisable(GL_CULL_FACE);
  1139. else
  1140. {
  1141. // Use Direct3D convention, ie. clockwise vertices define a front face
  1142. glEnable(GL_CULL_FACE);
  1143. glCullFace(mode == CULL_CCW ? GL_FRONT : GL_BACK);
  1144. }
  1145. cullMode_ = mode;
  1146. }
  1147. }
  1148. void Graphics::SetDepthBias(float constantBias, float slopeScaledBias)
  1149. {
  1150. if (constantBias != constantDepthBias_ || slopeScaledBias != slopeScaledDepthBias_)
  1151. {
  1152. if (constantBias != 0.0f || slopeScaledBias != 0.0f)
  1153. {
  1154. // Bring the constant bias from Direct3D9 scale to OpenGL (depends on depth buffer bitdepth)
  1155. // Zero depth bits may be returned if using the packed depth-stencil format. Assume 24bit in that case
  1156. int depthBits = Min(impl_->depthBits_, 23);
  1157. if (!depthBits)
  1158. depthBits = 23;
  1159. float adjustedConstantBias = constantBias * (float)(1 << (depthBits - 1));
  1160. float adjustedSlopeScaledBias = slopeScaledBias + 1.0f;
  1161. glEnable(GL_POLYGON_OFFSET_FILL);
  1162. glEnable(GL_POLYGON_OFFSET_LINE);
  1163. glPolygonOffset(adjustedSlopeScaledBias, adjustedConstantBias);
  1164. }
  1165. else
  1166. {
  1167. glDisable(GL_POLYGON_OFFSET_FILL);
  1168. glDisable(GL_POLYGON_OFFSET_LINE);
  1169. }
  1170. constantDepthBias_ = constantBias;
  1171. slopeScaledDepthBias_ = slopeScaledBias;
  1172. }
  1173. }
  1174. void Graphics::SetDepthTest(CompareMode mode)
  1175. {
  1176. if (mode != depthTestMode_)
  1177. {
  1178. glDepthFunc(glCmpFunc[mode]);
  1179. depthTestMode_ = mode;
  1180. }
  1181. }
  1182. void Graphics::SetDepthWrite(bool enable)
  1183. {
  1184. if (enable != depthWrite_)
  1185. {
  1186. glDepthMask(enable ? GL_TRUE : GL_FALSE);
  1187. depthWrite_ = enable;
  1188. }
  1189. }
  1190. void Graphics::SetFillMode(FillMode mode)
  1191. {
  1192. if (mode != fillMode_)
  1193. {
  1194. glPolygonMode(GL_FRONT_AND_BACK, mode == FILL_SOLID ? GL_FILL : GL_LINE);
  1195. fillMode_ = mode;
  1196. }
  1197. }
  1198. void Graphics::SetScissorTest(bool enable, const Rect& rect, bool borderInclusive)
  1199. {
  1200. // During some light rendering loops, a full rect is toggled on/off repeatedly.
  1201. // Disable scissor in that case to reduce state changes
  1202. if (rect.min_.x_ <= 0.0f && rect.min_.y_ <= 0.0f && rect.max_.x_ >= 1.0f && rect.max_.y_ >= 1.0f)
  1203. enable = false;
  1204. if (enable)
  1205. {
  1206. IntVector2 rtSize(GetRenderTargetDimensions());
  1207. IntVector2 viewSize(viewport_.right_ - viewport_.left_, viewport_.bottom_ - viewport_.top_);
  1208. IntVector2 viewPos(viewport_.left_, viewport_.top_);
  1209. IntRect intRect;
  1210. int expand = borderInclusive ? 1 : 0;
  1211. intRect.left_ = Clamp((int)((rect.min_.x_ + 1.0f) * 0.5f * viewSize.x_) + viewPos.x_, 0, rtSize.x_ - 1);
  1212. intRect.top_ = Clamp((int)((-rect.max_.y_ + 1.0f) * 0.5f * viewSize.y_) + viewPos.y_, 0, rtSize.y_ - 1);
  1213. intRect.right_ = Clamp((int)((rect.max_.x_ + 1.0f) * 0.5f * viewSize.x_) + viewPos.x_ + expand, 0, rtSize.x_);
  1214. intRect.bottom_ = Clamp((int)((-rect.min_.y_ + 1.0f) * 0.5f * viewSize.y_) + viewPos.y_ + expand, 0, rtSize.y_);
  1215. if (intRect.right_ == intRect.left_)
  1216. intRect.right_++;
  1217. if (intRect.bottom_ == intRect.top_)
  1218. intRect.bottom_++;
  1219. if (intRect.right_ < intRect.left_ || intRect.bottom_ < intRect.top_)
  1220. enable = false;
  1221. if (enable && scissorRect_ != intRect)
  1222. {
  1223. // Use Direct3D convention with the vertical coordinates ie. 0 is top
  1224. glScissor(intRect.left_, rtSize.y_ - intRect.bottom_, intRect.right_ - intRect.left_, intRect.bottom_ - intRect.top_);
  1225. scissorRect_ = intRect;
  1226. }
  1227. }
  1228. else
  1229. scissorRect_ = IntRect::ZERO;
  1230. if (enable != scissorTest_)
  1231. {
  1232. if (enable)
  1233. glEnable(GL_SCISSOR_TEST);
  1234. else
  1235. glDisable(GL_SCISSOR_TEST);
  1236. scissorTest_ = enable;
  1237. }
  1238. }
  1239. void Graphics::SetScissorTest(bool enable, const IntRect& rect)
  1240. {
  1241. IntVector2 rtSize(GetRenderTargetDimensions());
  1242. IntVector2 viewSize(viewport_.right_ - viewport_.left_, viewport_.bottom_ - viewport_.top_);
  1243. IntVector2 viewPos(viewport_.left_, viewport_.top_);
  1244. if (enable)
  1245. {
  1246. IntRect intRect;
  1247. intRect.left_ = Clamp(rect.left_ + viewPos.x_, 0, rtSize.x_ - 1);
  1248. intRect.top_ = Clamp(rect.top_ + viewPos.y_, 0, rtSize.y_ - 1);
  1249. intRect.right_ = Clamp(rect.right_ + viewPos.x_, 0, rtSize.x_);
  1250. intRect.bottom_ = Clamp(rect.bottom_ + viewPos.y_, 0, rtSize.y_);
  1251. if (intRect.right_ == intRect.left_)
  1252. intRect.right_++;
  1253. if (intRect.bottom_ == intRect.top_)
  1254. intRect.bottom_++;
  1255. if (intRect.right_ < intRect.left_ || intRect.bottom_ < intRect.top_)
  1256. enable = false;
  1257. if (enable && scissorRect_ != intRect)
  1258. {
  1259. // Use Direct3D convention with the vertical coordinates ie. 0 is top
  1260. glScissor(intRect.left_, rtSize.y_ - intRect.bottom_, intRect.right_ - intRect.left_, intRect.bottom_ - intRect.top_);
  1261. scissorRect_ = intRect;
  1262. }
  1263. }
  1264. else
  1265. scissorRect_ = IntRect::ZERO;
  1266. if (enable != scissorTest_)
  1267. {
  1268. if (enable)
  1269. glEnable(GL_SCISSOR_TEST);
  1270. else
  1271. glDisable(GL_SCISSOR_TEST);
  1272. scissorTest_ = enable;
  1273. }
  1274. }
  1275. void Graphics::SetStreamFrequency(unsigned index, unsigned frequency)
  1276. {
  1277. }
  1278. void Graphics::ResetStreamFrequencies()
  1279. {
  1280. }
  1281. void Graphics::SetStencilTest(bool enable, CompareMode mode, StencilOp pass, StencilOp fail, StencilOp zFail, unsigned stencilRef, unsigned compareMask, unsigned writeMask)
  1282. {
  1283. if (enable != stencilTest_)
  1284. {
  1285. if (enable)
  1286. glEnable(GL_STENCIL_TEST);
  1287. else
  1288. glDisable(GL_STENCIL_TEST);
  1289. stencilTest_ = enable;
  1290. }
  1291. if (enable)
  1292. {
  1293. if (mode != stencilTestMode_ || stencilRef != stencilRef_ || compareMask != stencilCompareMask_)
  1294. {
  1295. glStencilFunc(glCmpFunc[mode], stencilRef, compareMask);
  1296. stencilTestMode_ = mode;
  1297. stencilRef_ = stencilRef;
  1298. stencilCompareMask_ = compareMask;
  1299. }
  1300. if (writeMask != stencilWriteMask_)
  1301. {
  1302. glStencilMask(writeMask);
  1303. stencilWriteMask_ = writeMask;
  1304. }
  1305. if (pass != stencilPass_ || fail != stencilFail_ || zFail != stencilZFail_)
  1306. {
  1307. glStencilOp(glStencilOps[fail], glStencilOps[zFail], glStencilOps[pass]);
  1308. stencilPass_ = pass;
  1309. stencilFail_ = fail;
  1310. stencilZFail_ = zFail;
  1311. }
  1312. }
  1313. }
  1314. void Graphics::SetForceSM2(bool enable)
  1315. {
  1316. }
  1317. bool Graphics::IsInitialized() const
  1318. {
  1319. return impl_->window_ != 0;
  1320. }
  1321. void* Graphics::GetWindowHandle() const
  1322. {
  1323. return impl_->window_;
  1324. }
  1325. PODVector<IntVector2> Graphics::GetResolutions() const
  1326. {
  1327. static const unsigned MAX_MODES = 256;
  1328. GLFWvidmode modes[MAX_MODES];
  1329. unsigned count = glfwGetVideoModes(modes, MAX_MODES);
  1330. PODVector<IntVector2> ret;
  1331. for (unsigned i = 0; i < count; ++i)
  1332. {
  1333. int width = modes[i].width;
  1334. int height = modes[i].height;
  1335. // Store mode if unique
  1336. bool unique = true;
  1337. for (unsigned j = 0; j < ret.Size(); ++i)
  1338. {
  1339. if (ret[j].x_ == width && ret[j].y_ == height)
  1340. {
  1341. unique = false;
  1342. break;
  1343. }
  1344. }
  1345. if (unique)
  1346. ret.Push(IntVector2(width, height));
  1347. }
  1348. return ret;
  1349. }
  1350. PODVector<int> Graphics::GetMultiSampleLevels() const
  1351. {
  1352. PODVector<int> ret;
  1353. // No multisampling always supported
  1354. ret.Push(1);
  1355. /// \todo Implement properly, if possible
  1356. return ret;
  1357. }
  1358. VertexBuffer* Graphics::GetVertexBuffer(unsigned index) const
  1359. {
  1360. return index < MAX_VERTEX_STREAMS ? vertexBuffers_[index] : 0;
  1361. }
  1362. TextureUnit Graphics::GetTextureUnit(const String& name)
  1363. {
  1364. Map<String, TextureUnit>::Iterator i = textureUnits_.Find(name);
  1365. if (i != textureUnits_.End())
  1366. return i->second_;
  1367. else
  1368. return MAX_TEXTURE_UNITS;
  1369. }
  1370. const String& Graphics::GetTextureUnitName(TextureUnit unit)
  1371. {
  1372. for (Map<String, TextureUnit>::Iterator i = textureUnits_.Begin(); i != textureUnits_.End(); ++i)
  1373. {
  1374. if (i->second_ == unit)
  1375. return i->first_;
  1376. }
  1377. return noParameter;
  1378. }
  1379. Texture* Graphics::GetTexture(unsigned index) const
  1380. {
  1381. return index < MAX_TEXTURE_UNITS ? textures_[index] : 0;
  1382. }
  1383. RenderSurface* Graphics::GetRenderTarget(unsigned index) const
  1384. {
  1385. return index < MAX_RENDERTARGETS ? renderTargets_[index] : 0;
  1386. }
  1387. IntVector2 Graphics::GetRenderTargetDimensions() const
  1388. {
  1389. int width, height;
  1390. if (renderTargets_[0])
  1391. {
  1392. width = renderTargets_[0]->GetWidth();
  1393. height = renderTargets_[0]->GetHeight();
  1394. }
  1395. else if (depthStencil_)
  1396. {
  1397. width = depthStencil_->GetWidth();
  1398. height = depthStencil_->GetHeight();
  1399. }
  1400. else
  1401. {
  1402. width = width_;
  1403. height = height_;
  1404. }
  1405. return IntVector2(width, height);
  1406. }
  1407. void Graphics::AddGPUObject(GPUObject* object)
  1408. {
  1409. gpuObjects_.Push(object);
  1410. }
  1411. void Graphics::RemoveGPUObject(GPUObject* object)
  1412. {
  1413. Vector<GPUObject*>::Iterator i = gpuObjects_.Find(object);
  1414. if (i != gpuObjects_.End())
  1415. gpuObjects_.Erase(i);
  1416. }
  1417. void* Graphics::ReserveDiscardLockBuffer(unsigned size)
  1418. {
  1419. // First check for a free buffer that is large enough
  1420. for (Vector<DiscardLockBuffer>::Iterator i = discardLockBuffers_.Begin(); i != discardLockBuffers_.End(); ++i)
  1421. {
  1422. if (!i->reserved_ && i->size_ >= size)
  1423. {
  1424. i->reserved_ = true;
  1425. return i->data_.Get();
  1426. }
  1427. }
  1428. // Then check if a free buffer can be resized
  1429. for (Vector<DiscardLockBuffer>::Iterator i = discardLockBuffers_.Begin(); i != discardLockBuffers_.End(); ++i)
  1430. {
  1431. if (!i->reserved_)
  1432. {
  1433. i->data_ = new unsigned char[size];
  1434. i->size_ = size;
  1435. i->reserved_ = true;
  1436. return i->data_.Get();
  1437. }
  1438. }
  1439. // Finally allocate a new buffer
  1440. DiscardLockBuffer newBuffer;
  1441. newBuffer.data_ = new unsigned char[size];
  1442. newBuffer.size_ = size;
  1443. newBuffer.reserved_ = true;
  1444. discardLockBuffers_.Push(newBuffer);
  1445. return newBuffer.data_.Get();
  1446. }
  1447. void Graphics::FreeDiscardLockBuffer(void* buffer)
  1448. {
  1449. for (Vector<DiscardLockBuffer>::Iterator i = discardLockBuffers_.Begin(); i != discardLockBuffers_.End(); ++i)
  1450. {
  1451. if (i->reserved_ && i->data_.Get() == buffer)
  1452. {
  1453. i->reserved_ = false;
  1454. return;
  1455. }
  1456. }
  1457. LOGWARNING("Reserved discard lock buffer " + ToStringHex((unsigned)buffer) + " not found");
  1458. }
  1459. void Graphics::Release(bool clearGPUObjects, bool closeWindow)
  1460. {
  1461. if (!impl_->window_)
  1462. return;
  1463. CleanupFramebuffers(true);
  1464. depthTextures_.Clear();
  1465. if (clearGPUObjects)
  1466. {
  1467. // Shutting down: release all GPU objects that still exist
  1468. for (Vector<GPUObject*>::Iterator i = gpuObjects_.Begin(); i != gpuObjects_.End(); ++i)
  1469. (*i)->Release();
  1470. gpuObjects_.Clear();
  1471. }
  1472. else
  1473. {
  1474. // We are not shutting down, but recreating the context: mark GPU objects lost
  1475. for (Vector<GPUObject*>::Iterator i = gpuObjects_.Begin(); i != gpuObjects_.End(); ++i)
  1476. (*i)->OnDeviceLost();
  1477. }
  1478. // When the new context is initialized, it will have default state again
  1479. ResetCachedState();
  1480. ClearParameterSources();
  1481. {
  1482. MutexLock lock(GetStaticMutex());
  1483. SetWindowContext(impl_->window_, 0);
  1484. // If in close callback, GLFW will close the window for us, so skip it
  1485. if (closeWindow)
  1486. glfwCloseWindow(impl_->window_);
  1487. impl_->window_ = 0;
  1488. }
  1489. }
  1490. void Graphics::CleanupRenderSurface(RenderSurface* surface)
  1491. {
  1492. if (!surface)
  1493. return;
  1494. // Flush pending FBO changes first if any
  1495. CommitFramebuffer();
  1496. unsigned currentFbo = impl_->boundFbo_;
  1497. // Go through all FBOs and clean up the surface from them
  1498. for (Map<unsigned long long, FrameBufferObject>::Iterator i = impl_->frameBuffers_.Begin(); i != impl_->frameBuffers_.End();
  1499. ++i)
  1500. {
  1501. for (unsigned j = 0; j < MAX_RENDERTARGETS; ++j)
  1502. {
  1503. if (i->second_.colorAttachments_[j] == surface)
  1504. {
  1505. if (currentFbo != i->second_.fbo_)
  1506. {
  1507. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, i->second_.fbo_);
  1508. currentFbo = i->second_.fbo_;
  1509. }
  1510. glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + j, GL_TEXTURE_2D, 0, 0);
  1511. i->second_.colorAttachments_[j] = 0;
  1512. // Mark drawbuffer bits to need recalculation
  1513. i->second_.drawBuffers_ = M_MAX_UNSIGNED;
  1514. }
  1515. }
  1516. if (i->second_.depthAttachment_ == surface)
  1517. {
  1518. if (currentFbo != i->second_.fbo_)
  1519. {
  1520. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, i->second_.fbo_);
  1521. currentFbo = i->second_.fbo_;
  1522. }
  1523. glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0);
  1524. glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0);
  1525. i->second_.depthAttachment_ = 0;
  1526. }
  1527. }
  1528. // Restore previously bound FBO now if needed
  1529. if (currentFbo != impl_->boundFbo_)
  1530. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, impl_->boundFbo_);
  1531. }
  1532. unsigned Graphics::GetAlphaFormat()
  1533. {
  1534. return GL_ALPHA;
  1535. }
  1536. unsigned Graphics::GetLuminanceFormat()
  1537. {
  1538. return GL_LUMINANCE;
  1539. }
  1540. unsigned Graphics::GetLuminanceAlphaFormat()
  1541. {
  1542. return GL_LUMINANCE_ALPHA;
  1543. }
  1544. unsigned Graphics::GetRGBFormat()
  1545. {
  1546. return GL_RGB;
  1547. }
  1548. unsigned Graphics::GetRGBAFormat()
  1549. {
  1550. return GL_RGBA;
  1551. }
  1552. unsigned Graphics::GetFloatFormat()
  1553. {
  1554. return GL_LUMINANCE32F_ARB;
  1555. }
  1556. unsigned Graphics::GetLinearDepthFormat()
  1557. {
  1558. // OpenGL FBO specs state that color attachments must have the same format; therefore must encode linear depth to RGBA
  1559. // manually if not using a readable hardware depth texture
  1560. return GL_RGBA;
  1561. }
  1562. unsigned Graphics::GetDepthStencilFormat()
  1563. {
  1564. return GL_DEPTH24_STENCIL8_EXT;
  1565. }
  1566. void Graphics::CheckFeatureSupport()
  1567. {
  1568. // Check supported features: light pre-pass, deferred rendering and hardware depth texture
  1569. lightPrepassSupport_ = false;
  1570. deferredSupport_ = false;
  1571. hardwareDepthSupport_ = false;
  1572. int numSupportedRTs = 1;
  1573. glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &numSupportedRTs);
  1574. // For now hardware depth texture is only tested for on NVIDIA hardware because of visual artifacts and slowdown on ATI
  1575. String vendorString = String((const char*)glGetString(GL_VENDOR)).ToUpper();
  1576. if (vendorString.Find("NVIDIA") != String::NPOS)
  1577. {
  1578. SharedPtr<Texture2D> depthTexture(new Texture2D(context_));
  1579. hardwareDepthSupport_ = true;
  1580. // Note: Texture2D::SetSize() requires hardwareDepthSupport_ == true to create a texture instead of a renderbuffer
  1581. depthTexture->SetSize(256, 256, GetDepthStencilFormat(), TEXTURE_DEPTHSTENCIL);
  1582. SetDepthStencil(depthTexture);
  1583. // If hardware depth textures work, this means also light pre-pass is automatically supported
  1584. if (CheckFramebuffer())
  1585. {
  1586. lightPrepassSupport_ = true;
  1587. if (numSupportedRTs >= 3)
  1588. deferredSupport_ = true;
  1589. }
  1590. else
  1591. hardwareDepthSupport_ = false;
  1592. ResetDepthStencil();
  1593. }
  1594. if (!hardwareDepthSupport_)
  1595. {
  1596. // If hardware depth is not supported, must support 2 rendertargets for light pre-pass, and 4 for deferred
  1597. if (numSupportedRTs >= 2)
  1598. lightPrepassSupport_ = true;
  1599. if (numSupportedRTs >= 4)
  1600. deferredSupport_ = true;
  1601. }
  1602. }
  1603. void Graphics::CommitFramebuffer()
  1604. {
  1605. if (!impl_->fboDirty_)
  1606. return;
  1607. impl_->fboDirty_ = false;
  1608. // First check if no framebuffer is needed. In that case simply return to backbuffer rendering
  1609. bool noFbo = !depthStencil_;
  1610. if (noFbo)
  1611. {
  1612. for (unsigned i = 0; i < MAX_RENDERTARGETS; ++i)
  1613. {
  1614. if (renderTargets_[i])
  1615. {
  1616. noFbo = false;
  1617. break;
  1618. }
  1619. }
  1620. }
  1621. if (noFbo)
  1622. {
  1623. if (impl_->boundFbo_)
  1624. {
  1625. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  1626. impl_->boundFbo_ = 0;
  1627. }
  1628. return;
  1629. }
  1630. // Search for a new framebuffer based on format & size, or create new
  1631. IntVector2 rtSize = Graphics::GetRenderTargetDimensions();
  1632. unsigned format = 0;
  1633. if (renderTargets_[0])
  1634. format = renderTargets_[0]->GetParentTexture()->GetFormat();
  1635. else if (depthStencil_)
  1636. format = depthStencil_->GetParentTexture()->GetFormat();
  1637. unsigned long long fboKey = (rtSize.x_ << 16 | rtSize.y_) | (((unsigned long long)format) << 32);
  1638. Map<unsigned long long, FrameBufferObject>::Iterator i = impl_->frameBuffers_.Find(fboKey);
  1639. if (i == impl_->frameBuffers_.End())
  1640. {
  1641. FrameBufferObject newFbo;
  1642. glGenFramebuffersEXT(1, &newFbo.fbo_);
  1643. i = impl_->frameBuffers_.Insert(MakePair(fboKey, newFbo));
  1644. }
  1645. i->second_.useTimer_.Reset();
  1646. if (impl_->boundFbo_ != i->second_.fbo_)
  1647. {
  1648. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, i->second_.fbo_);
  1649. impl_->boundFbo_ = i->second_.fbo_;
  1650. }
  1651. // Setup readbuffers & drawbuffers if needed
  1652. if (i->second_.readBuffers_ != GL_NONE)
  1653. {
  1654. glReadBuffer(GL_NONE);
  1655. i->second_.readBuffers_ = GL_NONE;
  1656. }
  1657. // Calculate the bit combination of non-zero color rendertargets to first check if the combination changed
  1658. unsigned newDrawBuffers = 0;
  1659. for (unsigned i = 0; i < MAX_RENDERTARGETS; ++i)
  1660. {
  1661. if (renderTargets_[i])
  1662. newDrawBuffers |= 1 << i;
  1663. }
  1664. if (newDrawBuffers != i->second_.drawBuffers_)
  1665. {
  1666. // Check for no color rendertargets (depth rendering only)
  1667. if (!newDrawBuffers)
  1668. glDrawBuffer(GL_NONE);
  1669. else
  1670. {
  1671. int drawBufferIds[4];
  1672. unsigned drawBufferCount = 0;
  1673. for (unsigned i = 0; i < MAX_RENDERTARGETS; ++i)
  1674. {
  1675. if (renderTargets_[i])
  1676. drawBufferIds[drawBufferCount++] = GL_COLOR_ATTACHMENT0_EXT + i;
  1677. }
  1678. glDrawBuffers(drawBufferCount, (const GLenum*)drawBufferIds);
  1679. }
  1680. i->second_.drawBuffers_ = newDrawBuffers;
  1681. }
  1682. for (unsigned j = 0; j < MAX_RENDERTARGETS; ++j)
  1683. {
  1684. if (renderTargets_[j])
  1685. {
  1686. Texture* texture = renderTargets_[j]->GetParentTexture();
  1687. // If texture's parameters are dirty, update before attaching
  1688. if (texture->GetParametersDirty())
  1689. {
  1690. SetTextureForUpdate(texture);
  1691. texture->UpdateParameters();
  1692. SetTexture(0, 0);
  1693. }
  1694. if (i->second_.colorAttachments_[j] != renderTargets_[j])
  1695. {
  1696. glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + j, renderTargets_[j]->GetTarget(),
  1697. texture->GetGPUObject(), 0);
  1698. i->second_.colorAttachments_[j] = renderTargets_[j];
  1699. }
  1700. }
  1701. else
  1702. {
  1703. if (i->second_.colorAttachments_[j])
  1704. {
  1705. glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + j, GL_TEXTURE_2D, 0, 0);
  1706. i->second_.colorAttachments_[j] = 0;
  1707. }
  1708. }
  1709. }
  1710. if (depthStencil_)
  1711. {
  1712. // Bind either a renderbuffer or a depth texture, depending on what is available
  1713. Texture* texture = depthStencil_->GetParentTexture();
  1714. bool hasStencil = texture->GetFormat() == GetDepthStencilFormat();
  1715. unsigned renderBufferID = depthStencil_->GetRenderBuffer();
  1716. if (!renderBufferID)
  1717. {
  1718. // If texture's parameters are dirty, update before attaching
  1719. if (texture->GetParametersDirty())
  1720. {
  1721. SetTextureForUpdate(texture);
  1722. texture->UpdateParameters();
  1723. SetTexture(0, 0);
  1724. }
  1725. if (i->second_.depthAttachment_ != depthStencil_)
  1726. {
  1727. glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, texture->GetGPUObject(), 0);
  1728. if (hasStencil)
  1729. {
  1730. glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D,
  1731. texture->GetGPUObject(), 0);
  1732. }
  1733. else
  1734. glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0);
  1735. i->second_.depthAttachment_ = depthStencil_;
  1736. }
  1737. }
  1738. else
  1739. {
  1740. if (i->second_.depthAttachment_ != depthStencil_)
  1741. {
  1742. glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, renderBufferID);
  1743. if (hasStencil)
  1744. {
  1745. glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT,
  1746. renderBufferID);
  1747. }
  1748. else
  1749. glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0);
  1750. i->second_.depthAttachment_ = depthStencil_;
  1751. }
  1752. }
  1753. impl_->depthBits_ = texture->GetDepthBits();
  1754. }
  1755. else
  1756. {
  1757. if (i->second_.depthAttachment_)
  1758. {
  1759. glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0);
  1760. glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0);
  1761. i->second_.depthAttachment_ = 0;
  1762. impl_->depthBits_ = impl_->windowDepthBits_;
  1763. }
  1764. }
  1765. }
  1766. bool Graphics::CheckFramebuffer()
  1767. {
  1768. return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT;
  1769. }
  1770. void Graphics::CleanupFramebuffers(bool deleteAll)
  1771. {
  1772. if (deleteAll && impl_->boundFbo_)
  1773. {
  1774. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  1775. impl_->boundFbo_ = 0;
  1776. }
  1777. for (Map<unsigned long long, FrameBufferObject>::Iterator i = impl_->frameBuffers_.Begin(); i != impl_->frameBuffers_.End();)
  1778. {
  1779. Map<unsigned long long, FrameBufferObject>::Iterator current = i++;
  1780. if (deleteAll || (current->second_.fbo_ != impl_->boundFbo_ && current->second_.useTimer_.GetMSec(false) > MAX_FRAMEBUFFER_AGE))
  1781. {
  1782. glDeleteFramebuffersEXT(1, &current->second_.fbo_);
  1783. impl_->frameBuffers_.Erase(current);
  1784. }
  1785. }
  1786. }
  1787. void Graphics::ResetCachedState()
  1788. {
  1789. for (unsigned i = 0; i < MAX_VERTEX_STREAMS; ++i)
  1790. {
  1791. vertexBuffers_[i] = 0;
  1792. elementMasks_[i] = 0;
  1793. }
  1794. for (unsigned i = 0; i < MAX_TEXTURE_UNITS; ++i)
  1795. {
  1796. textures_[i] = 0;
  1797. textureTypes_[i] = 0;
  1798. }
  1799. for (unsigned i = 0; i < MAX_RENDERTARGETS; ++i)
  1800. renderTargets_[i] = 0;
  1801. depthStencil_ = 0;
  1802. viewTexture_ = 0;
  1803. viewport_ = IntRect(0, 0, 0, 0);
  1804. indexBuffer_ = 0;
  1805. vertexShader_ = 0;
  1806. pixelShader_ = 0;
  1807. shaderProgram_ = 0;
  1808. blendMode_ = BLEND_REPLACE;
  1809. alphaTest_ = false;
  1810. alphaTestMode_ = CMP_ALWAYS;
  1811. alphaRef_ = 0.0f;
  1812. textureAnisotropy_ = 1;
  1813. colorWrite_ = true;
  1814. cullMode_ = CULL_NONE;
  1815. constantDepthBias_ = 0.0f;
  1816. slopeScaledDepthBias_ = 0.0f;
  1817. depthTestMode_ = CMP_ALWAYS;
  1818. depthWrite_ = true;
  1819. fillMode_ = FILL_SOLID;
  1820. scissorTest_ = false;
  1821. scissorRect_ = IntRect::ZERO;
  1822. stencilTest_ = false;
  1823. stencilTestMode_ = CMP_ALWAYS;
  1824. stencilPass_ = OP_KEEP;
  1825. stencilFail_ = OP_KEEP;
  1826. stencilZFail_ = OP_KEEP;
  1827. stencilRef_ = 0;
  1828. stencilCompareMask_ = M_MAX_UNSIGNED;
  1829. stencilWriteMask_ = M_MAX_UNSIGNED;
  1830. impl_->activeTexture_ = 0;
  1831. impl_->enabledAttributes_ = 0;
  1832. }
  1833. void Graphics::SetTextureUnitMappings()
  1834. {
  1835. textureUnits_["DiffMap"] = TU_DIFFUSE;
  1836. textureUnits_["DiffCubeMap"] = TU_DIFFUSE;
  1837. textureUnits_["NormalMap"] = TU_NORMAL;
  1838. textureUnits_["EmissiveMap"] = TU_EMISSIVE;
  1839. textureUnits_["DetailMap"] = TU_DETAIL;
  1840. textureUnits_["EnvironmentMap"] = TU_ENVIRONMENT;
  1841. textureUnits_["EnvironmentCubeMap"] = TU_ENVIRONMENT;
  1842. textureUnits_["LightRampMap"] = TU_LIGHTRAMP;
  1843. textureUnits_["LightSpotMap"] = TU_LIGHTSHAPE;
  1844. textureUnits_["LightCubeMap"] = TU_LIGHTSHAPE;
  1845. textureUnits_["ShadowMap"] = TU_SHADOWMAP;
  1846. textureUnits_["FaceSelectCubeMap"] = TU_FACESELECT;
  1847. textureUnits_["IndirectionCubeMap"] = TU_INDIRECTION;
  1848. textureUnits_["AlbedoBuffer"] = TU_ALBEDOBUFFER;
  1849. textureUnits_["NormalBuffer"] = TU_NORMALBUFFER;
  1850. textureUnits_["DepthBuffer"] = TU_DEPTHBUFFER;
  1851. textureUnits_["LightBuffer"] = TU_LIGHTBUFFER;
  1852. }
  1853. void RegisterGraphicsLibrary(Context* context)
  1854. {
  1855. Animation::RegisterObject(context);
  1856. Material::RegisterObject(context);
  1857. Model::RegisterObject(context);
  1858. Shader::RegisterObject(context);
  1859. Technique::RegisterObject(context);
  1860. Texture2D::RegisterObject(context);
  1861. TextureCube::RegisterObject(context);
  1862. Camera::RegisterObject(context);
  1863. Drawable::RegisterObject(context);
  1864. Light::RegisterObject(context);
  1865. StaticModel::RegisterObject(context);
  1866. Skybox::RegisterObject(context);
  1867. AnimatedModel::RegisterObject(context);
  1868. AnimationController::RegisterObject(context);
  1869. BillboardSet::RegisterObject(context);
  1870. ParticleEmitter::RegisterObject(context);
  1871. DebugRenderer::RegisterObject(context);
  1872. Octree::RegisterObject(context);
  1873. Zone::RegisterObject(context);
  1874. }