OGLGraphics.cpp 62 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061
  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. int CloseCallback(GLFWwindow window)
  97. {
  98. Context* context = GetWindowContext(window);
  99. if (context)
  100. {
  101. Graphics* graphics = context->GetSubsystem<Graphics>();
  102. // Do not close the window: GLFW will do it for us
  103. if (graphics)
  104. graphics->Release(true, false);
  105. }
  106. return GL_TRUE;
  107. }
  108. OBJECTTYPESTATIC(Graphics);
  109. Graphics::Graphics(Context* context_) :
  110. Object(context_),
  111. impl_(new GraphicsImpl()),
  112. width_(0),
  113. height_(0),
  114. multiSample_(1),
  115. fullscreen_(false),
  116. vsync_(false),
  117. tripleBuffer_(false),
  118. lightPrepassSupport_(false),
  119. deferredSupport_(false),
  120. hardwareDepthSupport_(false),
  121. numPrimitives_(0),
  122. numBatches_(0),
  123. defaultTextureFilterMode_(FILTER_BILINEAR),
  124. shadowMapFormat_(GL_DEPTH_COMPONENT16),
  125. hiresShadowMapFormat_(GL_DEPTH_COMPONENT24),
  126. shaderParameterFrame_(0)
  127. {
  128. ResetCachedState();
  129. SetTextureUnitMappings();
  130. {
  131. MutexLock lock(GetStaticMutex());
  132. if (!numInstances)
  133. glfwInit();
  134. ++numInstances;
  135. }
  136. }
  137. Graphics::~Graphics()
  138. {
  139. Close();
  140. delete impl_;
  141. impl_ = 0;
  142. {
  143. MutexLock lock(GetStaticMutex());
  144. --numInstances;
  145. if (!numInstances)
  146. glfwTerminate();
  147. }
  148. }
  149. void Graphics::SetWindowTitle(const String& windowTitle)
  150. {
  151. windowTitle_ = windowTitle;
  152. if (impl_->window_)
  153. glfwSetWindowTitle(impl_->window_, windowTitle_.CString());
  154. }
  155. bool Graphics::SetMode(int width, int height, bool fullscreen, bool vsync, bool tripleBuffer, int multiSample)
  156. {
  157. PROFILE(SetScreenMode);
  158. multiSample = Clamp(multiSample, 1, 16);
  159. if (IsInitialized() && width == width_ && height == height_ && fullscreen == fullscreen_ &&
  160. vsync == vsync_ && tripleBuffer == tripleBuffer_ && multiSample == multiSample_)
  161. return true;
  162. // If only vsync changes, do not destroy/recreate the context
  163. if (IsInitialized() && width == width_ && height == height_ && fullscreen == fullscreen_ &&
  164. tripleBuffer == tripleBuffer_ && multiSample == multiSample_ && vsync != vsync_)
  165. {
  166. glfwSwapInterval(vsync ? 1 : 0);
  167. vsync_ = vsync;
  168. return true;
  169. }
  170. // If zero dimensions in windowed mode, set default. If zero in fullscreen, use desktop mode
  171. if (!width || !height)
  172. {
  173. if (!fullscreen)
  174. {
  175. width = 800;
  176. height = 600;
  177. }
  178. else
  179. {
  180. GLFWvidmode mode;
  181. glfwGetDesktopMode(&mode);
  182. width = mode.width;
  183. height = mode.height;
  184. }
  185. }
  186. // Close the existing window, mark GPU objects as lost
  187. Release(false, true);
  188. {
  189. // GLFW window parameters and the window list are static, so need to operate under static lock
  190. MutexLock lock(GetStaticMutex());
  191. glfwOpenWindowHint(GLFW_RED_BITS, 8);
  192. glfwOpenWindowHint(GLFW_GREEN_BITS, 8);
  193. glfwOpenWindowHint(GLFW_BLUE_BITS, 8);
  194. glfwOpenWindowHint(GLFW_ALPHA_BITS, 0);
  195. glfwOpenWindowHint(GLFW_DEPTH_BITS, 24);
  196. glfwOpenWindowHint(GLFW_STENCIL_BITS, 8);
  197. glfwOpenWindowHint(GLFW_WINDOW_RESIZABLE, GL_FALSE);
  198. if (multiSample > 1)
  199. glfwOpenWindowHint(GLFW_FSAA_SAMPLES, multiSample);
  200. else
  201. glfwOpenWindowHint(GLFW_FSAA_SAMPLES, 0);
  202. impl_->window_ = glfwOpenWindow(width, height, fullscreen ? GLFW_FULLSCREEN : GLFW_WINDOWED, windowTitle_.CString(), 0);
  203. if (!impl_->window_)
  204. {
  205. LOGERROR("Could not open window");
  206. return false;
  207. }
  208. // If OpenGL extensions not yet initialized, initialize now
  209. if (!GLeeInitialized())
  210. GLeeInit();
  211. if (!_GLEE_VERSION_2_0)
  212. {
  213. LOGERROR("OpenGL 2.0 is required");
  214. glfwCloseWindow(impl_->window_);
  215. return false;
  216. }
  217. if (!_GLEE_EXT_framebuffer_object || !_GLEE_EXT_packed_depth_stencil || !_GLEE_EXT_texture_compression_s3tc ||
  218. !_GLEE_EXT_texture_filter_anisotropic)
  219. {
  220. LOGERROR("EXT_framebuffer_object, EXT_packed_depth_stencil, EXT_texture_compression_s3tc and "
  221. "EXT_texture_filter_anisotropic OpenGL extensions are required");
  222. glfwCloseWindow(impl_->window_);
  223. return false;
  224. }
  225. // Set window close callback
  226. glfwSetWindowCloseCallback(CloseCallback);
  227. // Associate GLFW window with the execution context
  228. SetWindowContext(impl_->window_, context_);
  229. }
  230. // Set vsync
  231. glfwSwapInterval(vsync ? 1 : 0);
  232. // Query for system backbuffer depth
  233. glGetIntegerv(GL_DEPTH_BITS, &impl_->windowDepthBits_);
  234. impl_->depthBits_ = impl_->windowDepthBits_;
  235. // Create the FBOs and set the read buffer once (FBO will not be read)
  236. glGenFramebuffersEXT(1, &impl_->fbo_);
  237. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, impl_->fbo_);
  238. glReadBuffer(GL_NONE);
  239. glGenFramebuffersEXT(1, &impl_->depthOnlyFbo_);
  240. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, impl_->depthOnlyFbo_);
  241. glReadBuffer(GL_NONE);
  242. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  243. impl_->boundFbo_ = 0;
  244. // Set initial state to match Direct3D
  245. glEnable(GL_DEPTH_TEST);
  246. SetCullMode(CULL_CCW);
  247. SetDepthTest(CMP_LESSEQUAL);
  248. glfwGetWindowSize(impl_->window_, &width_, &height_);
  249. fullscreen_ = fullscreen;
  250. vsync_ = vsync;
  251. tripleBuffer_ = tripleBuffer;
  252. multiSample_ = multiSample;
  253. // Reset rendertargets and viewport for the new screen mode
  254. ResetRenderTargets();
  255. // Clear the window to black now, because GPU object restore may take time
  256. Clear(CLEAR_COLOR);
  257. glfwSwapBuffers();
  258. // Let GPU objects restore themselves
  259. for (Vector<GPUObject*>::Iterator i = gpuObjects_.Begin(); i != gpuObjects_.End(); ++i)
  260. (*i)->OnDeviceReset();
  261. CheckFeatureSupport();
  262. if (multiSample > 1)
  263. LOGINFO("Set screen mode " + String(width_) + "x" + String(height_) + " " + (fullscreen_ ? "fullscreen" : "windowed") +
  264. " multisample " + String(multiSample));
  265. else
  266. LOGINFO("Set screen mode " + String(width_) + "x" + String(height_) + " " + (fullscreen_ ? "fullscreen" : "windowed"));
  267. using namespace ScreenMode;
  268. VariantMap eventData;
  269. eventData[P_WIDTH] = width_;
  270. eventData[P_HEIGHT] = height_;
  271. eventData[P_FULLSCREEN] = fullscreen_;
  272. SendEvent(E_SCREENMODE, eventData);
  273. return true;
  274. }
  275. bool Graphics::SetMode(int width, int height)
  276. {
  277. return SetMode(width, height, fullscreen_, vsync_, tripleBuffer_, multiSample_);
  278. }
  279. bool Graphics::ToggleFullscreen()
  280. {
  281. return SetMode(width_, height_, !fullscreen_, vsync_, tripleBuffer_, multiSample_);
  282. }
  283. void Graphics::Close()
  284. {
  285. if (!IsInitialized())
  286. return;
  287. // Actually close the window
  288. Release(true, true);
  289. }
  290. bool Graphics::TakeScreenShot(Image& destImage)
  291. {
  292. PROFILE(TakeScreenShot);
  293. ResetRenderTargets();
  294. destImage.SetSize(width_, height_, 3);
  295. glReadPixels(0, 0, width_, height_, GL_RGB, GL_UNSIGNED_BYTE, destImage.GetData());
  296. return true;
  297. }
  298. bool Graphics::BeginFrame()
  299. {
  300. PROFILE(BeginRendering);
  301. if (!IsInitialized())
  302. return false;
  303. // If we should be fullscreen, but are not currently active, do not render
  304. if (fullscreen_ && (!glfwGetWindowParam(impl_->window_, GLFW_ACTIVE) || glfwGetWindowParam(impl_->window_, GLFW_ICONIFIED)))
  305. return false;
  306. // Set default rendertarget and depth buffer
  307. ResetRenderTargets();
  308. // Cleanup textures from previous frame
  309. for (unsigned i = 0; i < MAX_TEXTURE_UNITS; ++i)
  310. SetTexture(i, 0);
  311. // Enable color and depth write
  312. SetColorWrite(true);
  313. SetDepthWrite(true);
  314. numPrimitives_ = 0;
  315. numBatches_ = 0;
  316. SendEvent(E_BEGINRENDERING);
  317. return true;
  318. }
  319. void Graphics::EndFrame()
  320. {
  321. PROFILE(EndRendering);
  322. if (!IsInitialized())
  323. return;
  324. SendEvent(E_ENDRENDERING);
  325. glfwSwapBuffers();
  326. }
  327. void Graphics::Clear(unsigned flags, const Color& color, float depth, unsigned stencil)
  328. {
  329. bool oldColorWrite = colorWrite_;
  330. bool oldDepthWrite = depthWrite_;
  331. if (flags & CLEAR_COLOR && !oldColorWrite)
  332. SetColorWrite(true);
  333. if (flags & CLEAR_DEPTH && !oldDepthWrite)
  334. SetDepthWrite(true);
  335. if (flags & CLEAR_STENCIL && stencilWriteMask_ != M_MAX_UNSIGNED)
  336. glStencilMask(M_MAX_UNSIGNED);
  337. unsigned glFlags = 0;
  338. if (flags & CLEAR_COLOR)
  339. {
  340. glFlags |= GL_COLOR_BUFFER_BIT;
  341. glClearColor(color.r_, color.g_, color.b_, color.a_);
  342. }
  343. if (flags & CLEAR_DEPTH)
  344. {
  345. glFlags |= GL_DEPTH_BUFFER_BIT;
  346. glClearDepth(depth);
  347. }
  348. if (flags & CLEAR_STENCIL)
  349. {
  350. glFlags |= GL_STENCIL_BUFFER_BIT;
  351. glClearStencil(stencil);
  352. }
  353. // If viewport is less than full screen, set a scissor to limit the clear
  354. /// \todo Any user-set scissor test will be lost
  355. IntVector2 viewSize = GetRenderTargetDimensions();
  356. if (viewport_.left_ != 0 || viewport_.top_ != 0 || viewport_.right_ != viewSize.x_ || viewport_.bottom_ != viewSize.y_)
  357. SetScissorTest(true, IntRect(0, 0, viewport_.right_ - viewport_.left_, viewport_.bottom_ - viewport_.top_));
  358. else
  359. SetScissorTest(false);
  360. glClear(glFlags);
  361. SetScissorTest(false);
  362. SetColorWrite(oldColorWrite);
  363. SetDepthWrite(oldDepthWrite);
  364. if (flags & CLEAR_STENCIL && stencilWriteMask_ != M_MAX_UNSIGNED)
  365. glStencilMask(stencilWriteMask_);
  366. }
  367. bool Graphics::ResolveToTexture(Texture2D* destination, const IntRect& viewport)
  368. {
  369. if (!destination || !destination->GetRenderSurface() || destination->GetWidth() != width_ ||
  370. destination->GetHeight() != height_)
  371. return false;
  372. IntRect vpCopy = viewport;
  373. if (vpCopy.right_ <= vpCopy.left_)
  374. vpCopy.right_ = vpCopy.left_ + 1;
  375. if (vpCopy.bottom_ <= vpCopy.top_)
  376. vpCopy.bottom_ = vpCopy.top_ + 1;
  377. vpCopy.left_ = Clamp(vpCopy.left_, 0, width_);
  378. vpCopy.top_ = Clamp(vpCopy.top_, 0, height_);
  379. vpCopy.right_ = Clamp(vpCopy.right_, 0, width_);
  380. vpCopy.bottom_ = Clamp(vpCopy.bottom_, 0, height_);
  381. // Make sure the FBO is not in use
  382. ResetRenderTargets();
  383. // Use Direct3D convention with the vertical coordinates ie. 0 is top
  384. SetTextureForUpdate(destination);
  385. glCopyTexSubImage2D(GL_TEXTURE_2D, 0, vpCopy.left_, height_ - vpCopy.bottom_, vpCopy.left_, height_ - vpCopy.bottom_,
  386. vpCopy.right_ - vpCopy.left_, vpCopy.bottom_ - vpCopy.top_);
  387. SetTexture(0, 0);
  388. return true;
  389. }
  390. void Graphics::Draw(PrimitiveType type, unsigned vertexStart, unsigned vertexCount)
  391. {
  392. if (!vertexCount)
  393. return;
  394. unsigned primitiveCount = 0;
  395. switch (type)
  396. {
  397. case TRIANGLE_LIST:
  398. primitiveCount = vertexCount / 3;
  399. glDrawArrays(GL_TRIANGLES, vertexStart, vertexCount);
  400. break;
  401. case LINE_LIST:
  402. primitiveCount = vertexCount / 2;
  403. glDrawArrays(GL_LINES, vertexStart, vertexCount);
  404. break;
  405. }
  406. numPrimitives_ += primitiveCount;
  407. ++numBatches_;
  408. }
  409. void Graphics::Draw(PrimitiveType type, unsigned indexStart, unsigned indexCount, unsigned minVertex, unsigned vertexCount)
  410. {
  411. if (!indexCount || !indexBuffer_)
  412. return;
  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. }
  1008. // Note: the rendertargets are actually committed during SetDepthStencil()
  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. depthStencil_ = depthStencil;
  1020. unsigned targetFbo = 0;
  1021. if (renderTargets_[0])
  1022. targetFbo = impl_->fbo_;
  1023. else if (depthStencil_)
  1024. targetFbo = impl_->depthOnlyFbo_;
  1025. if (impl_->boundFbo_ != targetFbo)
  1026. {
  1027. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, targetFbo);
  1028. impl_->boundFbo_ = targetFbo;
  1029. }
  1030. // If we are returning to backbuffer rendering, no further operations necessary
  1031. if (!targetFbo)
  1032. {
  1033. impl_->depthBits_ = impl_->windowDepthBits_;
  1034. return;
  1035. }
  1036. // If we are using a rendertarget texture, it is required in OpenGL to also have an own depth-stencil
  1037. // Create a new depth-stencil texture as necessary to be able to provide similar behaviour as Direct3D9
  1038. if (renderTargets_[0] && !depthStencil_)
  1039. {
  1040. int width = renderTargets_[0]->GetWidth();
  1041. int height = renderTargets_[0]->GetHeight();
  1042. // Direct3D9 default depth-stencil can not be used when rendertarget is larger than the window.
  1043. // Check size similarly
  1044. if (width <= width_ && height <= height_)
  1045. {
  1046. int searchKey = (width << 16) | height;
  1047. HashMap<int, SharedPtr<Texture2D> >::Iterator i = depthTextures_.Find(searchKey);
  1048. if (i != depthTextures_.End())
  1049. depthStencil_ = i->second_->GetRenderSurface();
  1050. else
  1051. {
  1052. SharedPtr<Texture2D> newDepthTexture(new Texture2D(context_));
  1053. newDepthTexture->SetSize(width, height, GetDepthStencilFormat(), TEXTURE_DEPTHSTENCIL);
  1054. depthTextures_[searchKey] = newDepthTexture;
  1055. depthStencil_ = newDepthTexture->GetRenderSurface();
  1056. }
  1057. }
  1058. }
  1059. if (targetFbo == impl_->fbo_)
  1060. {
  1061. for (unsigned i = 0; i < MAX_RENDERTARGETS; ++i)
  1062. {
  1063. if (renderTargets_[i])
  1064. {
  1065. Texture* texture = renderTargets_[i]->GetParentTexture();
  1066. // If texture's parameters are dirty, update before attaching
  1067. if (texture->GetParametersDirty())
  1068. {
  1069. SetTextureForUpdate(texture);
  1070. texture->UpdateParameters();
  1071. SetTexture(0, 0);
  1072. }
  1073. glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + i, renderTargets_[i]->GetTarget(),
  1074. texture->GetGPUObject(), 0);
  1075. }
  1076. else
  1077. glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + i, GL_TEXTURE_2D, 0, 0);
  1078. }
  1079. SetDrawBuffers();
  1080. }
  1081. if (depthStencil_)
  1082. {
  1083. // Bind either a renderbuffer or a depth texture, depending on what is available
  1084. Texture* texture = depthStencil_->GetParentTexture();
  1085. bool hasStencil = texture->GetFormat() == GetDepthStencilFormat();
  1086. unsigned renderBufferID = depthStencil_->GetRenderBuffer();
  1087. if (!renderBufferID)
  1088. {
  1089. // If texture's parameters are dirty, update before attaching
  1090. if (texture->GetParametersDirty())
  1091. {
  1092. SetTextureForUpdate(texture);
  1093. texture->UpdateParameters();
  1094. SetTexture(0, 0);
  1095. }
  1096. glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, texture->GetGPUObject(), 0);
  1097. if (hasStencil)
  1098. glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, texture->GetGPUObject(), 0);
  1099. else
  1100. glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0);
  1101. impl_->depthBits_ = texture->GetDepthBits();
  1102. }
  1103. else
  1104. {
  1105. glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, renderBufferID);
  1106. if (hasStencil)
  1107. glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, renderBufferID);
  1108. else
  1109. glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0);
  1110. impl_->depthBits_ = 24;
  1111. }
  1112. }
  1113. else
  1114. {
  1115. glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0);
  1116. glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0);
  1117. impl_->depthBits_ = impl_->windowDepthBits_;
  1118. }
  1119. }
  1120. void Graphics::SetDepthStencil(Texture2D* texture)
  1121. {
  1122. RenderSurface* depthStencil = 0;
  1123. if (texture)
  1124. depthStencil = texture->GetRenderSurface();
  1125. SetDepthStencil(depthStencil);
  1126. }
  1127. void Graphics::SetViewTexture(Texture* texture)
  1128. {
  1129. viewTexture_ = texture;
  1130. if (viewTexture_)
  1131. {
  1132. for (unsigned i = 0; i < MAX_TEXTURE_UNITS; ++i)
  1133. {
  1134. if (textures_[i] == viewTexture_)
  1135. SetTexture(i, textures_[i]->GetBackupTexture());
  1136. }
  1137. }
  1138. }
  1139. void Graphics::SetViewport(const IntRect& rect)
  1140. {
  1141. IntVector2 rtSize = GetRenderTargetDimensions();
  1142. IntRect rectCopy = rect;
  1143. if (rectCopy.right_ <= rectCopy.left_)
  1144. rectCopy.right_ = rectCopy.left_ + 1;
  1145. if (rectCopy.bottom_ <= rectCopy.top_)
  1146. rectCopy.bottom_ = rectCopy.top_ + 1;
  1147. rectCopy.left_ = Clamp(rectCopy.left_, 0, rtSize.x_);
  1148. rectCopy.top_ = Clamp(rectCopy.top_, 0, rtSize.y_);
  1149. rectCopy.right_ = Clamp(rectCopy.right_, 0, rtSize.x_);
  1150. rectCopy.bottom_ = Clamp(rectCopy.bottom_, 0, rtSize.y_);
  1151. // Use Direct3D convention with the vertical coordinates ie. 0 is top
  1152. glViewport(rectCopy.left_, rtSize.y_ - rectCopy.bottom_, rectCopy.right_ - rectCopy.left_, rectCopy.bottom_ - rectCopy.top_);
  1153. viewport_ = rectCopy;
  1154. // Disable scissor test, needs to be re-enabled by the user
  1155. SetScissorTest(false);
  1156. }
  1157. void Graphics::SetAlphaTest(bool enable, CompareMode mode, float alphaRef)
  1158. {
  1159. if (enable != alphaTest_)
  1160. {
  1161. if (enable)
  1162. glEnable(GL_ALPHA_TEST);
  1163. else
  1164. glDisable(GL_ALPHA_TEST);
  1165. alphaTest_ = enable;
  1166. }
  1167. if (enable)
  1168. {
  1169. alphaRef = Clamp(alphaRef, 0.0f, 1.0f);
  1170. if (mode != alphaTestMode_ || alphaRef != alphaRef_)
  1171. {
  1172. glAlphaFunc(glCmpFunc[mode], alphaRef);
  1173. alphaTestMode_ = mode;
  1174. alphaRef_ = alphaRef;
  1175. }
  1176. }
  1177. }
  1178. void Graphics::SetBlendMode(BlendMode mode)
  1179. {
  1180. if (mode != blendMode_)
  1181. {
  1182. if (mode == BLEND_REPLACE)
  1183. glDisable(GL_BLEND);
  1184. else
  1185. {
  1186. glEnable(GL_BLEND);
  1187. glBlendFunc(glSrcBlend[mode], glDestBlend[mode]);
  1188. }
  1189. blendMode_ = mode;
  1190. }
  1191. }
  1192. void Graphics::SetColorWrite(bool enable)
  1193. {
  1194. if (enable != colorWrite_)
  1195. {
  1196. if (enable)
  1197. glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  1198. else
  1199. glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
  1200. colorWrite_ = enable;
  1201. }
  1202. }
  1203. void Graphics::SetCullMode(CullMode mode)
  1204. {
  1205. if (mode != cullMode_)
  1206. {
  1207. if (mode == CULL_NONE)
  1208. glDisable(GL_CULL_FACE);
  1209. else
  1210. {
  1211. // Use Direct3D convention, ie. clockwise vertices define a front face
  1212. glEnable(GL_CULL_FACE);
  1213. glCullFace(mode == CULL_CCW ? GL_FRONT : GL_BACK);
  1214. }
  1215. cullMode_ = mode;
  1216. }
  1217. }
  1218. void Graphics::SetDepthBias(float constantBias, float slopeScaledBias)
  1219. {
  1220. if (constantBias != constantDepthBias_ || slopeScaledBias != slopeScaledDepthBias_)
  1221. {
  1222. if (constantBias != 0.0f || slopeScaledBias != 0.0f)
  1223. {
  1224. // Bring the constant bias from Direct3D9 scale to OpenGL (depends on depth buffer bitdepth)
  1225. // Zero depth bits may be returned if using the packed depth-stencil format. Assume 24bit in that case
  1226. int depthBits = Min(impl_->depthBits_, 23);
  1227. if (!depthBits)
  1228. depthBits = 23;
  1229. float adjustedConstantBias = constantBias * (float)(1 << (depthBits - 1));
  1230. float adjustedSlopeScaledBias = slopeScaledBias + 1.0f;
  1231. glEnable(GL_POLYGON_OFFSET_FILL);
  1232. glEnable(GL_POLYGON_OFFSET_LINE);
  1233. glPolygonOffset(adjustedSlopeScaledBias, adjustedConstantBias);
  1234. }
  1235. else
  1236. {
  1237. glDisable(GL_POLYGON_OFFSET_FILL);
  1238. glDisable(GL_POLYGON_OFFSET_LINE);
  1239. }
  1240. constantDepthBias_ = constantBias;
  1241. slopeScaledDepthBias_ = slopeScaledBias;
  1242. }
  1243. }
  1244. void Graphics::SetDepthTest(CompareMode mode)
  1245. {
  1246. if (mode != depthTestMode_)
  1247. {
  1248. glDepthFunc(glCmpFunc[mode]);
  1249. depthTestMode_ = mode;
  1250. }
  1251. }
  1252. void Graphics::SetDepthWrite(bool enable)
  1253. {
  1254. if (enable != depthWrite_)
  1255. {
  1256. glDepthMask(enable ? GL_TRUE : GL_FALSE);
  1257. depthWrite_ = enable;
  1258. }
  1259. }
  1260. void Graphics::SetFillMode(FillMode mode)
  1261. {
  1262. if (mode != fillMode_)
  1263. {
  1264. glPolygonMode(GL_FRONT_AND_BACK, mode == FILL_SOLID ? GL_FILL : GL_LINE);
  1265. fillMode_ = mode;
  1266. }
  1267. }
  1268. void Graphics::SetScissorTest(bool enable, const Rect& rect, bool borderInclusive)
  1269. {
  1270. // During some light rendering loops, a full rect is toggled on/off repeatedly.
  1271. // Disable scissor in that case to reduce state changes
  1272. if (rect.min_.x_ <= 0.0f && rect.min_.y_ <= 0.0f && rect.max_.x_ >= 1.0f && rect.max_.y_ >= 1.0f)
  1273. enable = false;
  1274. if (enable)
  1275. {
  1276. IntVector2 rtSize(GetRenderTargetDimensions());
  1277. IntVector2 viewSize(viewport_.right_ - viewport_.left_, viewport_.bottom_ - viewport_.top_);
  1278. IntVector2 viewPos(viewport_.left_, viewport_.top_);
  1279. IntRect intRect;
  1280. int expand = borderInclusive ? 1 : 0;
  1281. intRect.left_ = Clamp((int)((rect.min_.x_ + 1.0f) * 0.5f * viewSize.x_) + viewPos.x_, 0, rtSize.x_ - 1);
  1282. intRect.top_ = Clamp((int)((-rect.max_.y_ + 1.0f) * 0.5f * viewSize.y_) + viewPos.y_, 0, rtSize.y_ - 1);
  1283. intRect.right_ = Clamp((int)((rect.max_.x_ + 1.0f) * 0.5f * viewSize.x_) + viewPos.x_ + expand, 0, rtSize.x_);
  1284. intRect.bottom_ = Clamp((int)((-rect.min_.y_ + 1.0f) * 0.5f * viewSize.y_) + viewPos.y_ + expand, 0, rtSize.y_);
  1285. if (intRect.right_ == intRect.left_)
  1286. intRect.right_++;
  1287. if (intRect.bottom_ == intRect.top_)
  1288. intRect.bottom_++;
  1289. if (intRect.right_ < intRect.left_ || intRect.bottom_ < intRect.top_)
  1290. enable = false;
  1291. if (enable && scissorRect_ != intRect)
  1292. {
  1293. // Use Direct3D convention with the vertical coordinates ie. 0 is top
  1294. glScissor(intRect.left_, rtSize.y_ - intRect.bottom_, intRect.right_ - intRect.left_, intRect.bottom_ - intRect.top_);
  1295. scissorRect_ = intRect;
  1296. }
  1297. }
  1298. else
  1299. scissorRect_ = IntRect::ZERO;
  1300. if (enable != scissorTest_)
  1301. {
  1302. if (enable)
  1303. glEnable(GL_SCISSOR_TEST);
  1304. else
  1305. glDisable(GL_SCISSOR_TEST);
  1306. scissorTest_ = enable;
  1307. }
  1308. }
  1309. void Graphics::SetScissorTest(bool enable, const IntRect& rect)
  1310. {
  1311. IntVector2 rtSize(GetRenderTargetDimensions());
  1312. IntVector2 viewSize(viewport_.right_ - viewport_.left_, viewport_.bottom_ - viewport_.top_);
  1313. IntVector2 viewPos(viewport_.left_, viewport_.top_);
  1314. if (enable)
  1315. {
  1316. IntRect intRect;
  1317. intRect.left_ = Clamp(rect.left_ + viewPos.x_, 0, rtSize.x_ - 1);
  1318. intRect.top_ = Clamp(rect.top_ + viewPos.y_, 0, rtSize.y_ - 1);
  1319. intRect.right_ = Clamp(rect.right_ + viewPos.x_, 0, rtSize.x_);
  1320. intRect.bottom_ = Clamp(rect.bottom_ + viewPos.y_, 0, rtSize.y_);
  1321. if (intRect.right_ == intRect.left_)
  1322. intRect.right_++;
  1323. if (intRect.bottom_ == intRect.top_)
  1324. intRect.bottom_++;
  1325. if (intRect.right_ < intRect.left_ || intRect.bottom_ < intRect.top_)
  1326. enable = false;
  1327. if (enable && scissorRect_ != intRect)
  1328. {
  1329. // Use Direct3D convention with the vertical coordinates ie. 0 is top
  1330. glScissor(intRect.left_, rtSize.y_ - intRect.bottom_, intRect.right_ - intRect.left_, intRect.bottom_ - intRect.top_);
  1331. scissorRect_ = intRect;
  1332. }
  1333. }
  1334. else
  1335. scissorRect_ = IntRect::ZERO;
  1336. if (enable != scissorTest_)
  1337. {
  1338. if (enable)
  1339. glEnable(GL_SCISSOR_TEST);
  1340. else
  1341. glDisable(GL_SCISSOR_TEST);
  1342. scissorTest_ = enable;
  1343. }
  1344. }
  1345. void Graphics::SetStreamFrequency(unsigned index, unsigned frequency)
  1346. {
  1347. }
  1348. void Graphics::ResetStreamFrequencies()
  1349. {
  1350. }
  1351. void Graphics::SetStencilTest(bool enable, CompareMode mode, StencilOp pass, StencilOp fail, StencilOp zFail, unsigned stencilRef, unsigned compareMask, unsigned writeMask)
  1352. {
  1353. if (enable != stencilTest_)
  1354. {
  1355. if (enable)
  1356. glEnable(GL_STENCIL_TEST);
  1357. else
  1358. glDisable(GL_STENCIL_TEST);
  1359. stencilTest_ = enable;
  1360. }
  1361. if (enable)
  1362. {
  1363. if (mode != stencilTestMode_ || stencilRef != stencilRef_ || compareMask != stencilCompareMask_)
  1364. {
  1365. glStencilFunc(glCmpFunc[mode], stencilRef, compareMask);
  1366. stencilTestMode_ = mode;
  1367. stencilRef_ = stencilRef;
  1368. stencilCompareMask_ = compareMask;
  1369. }
  1370. if (writeMask != stencilWriteMask_)
  1371. {
  1372. glStencilMask(writeMask);
  1373. stencilWriteMask_ = writeMask;
  1374. }
  1375. if (pass != stencilPass_ || fail != stencilFail_ || zFail != stencilZFail_)
  1376. {
  1377. glStencilOp(glStencilOps[fail], glStencilOps[zFail], glStencilOps[pass]);
  1378. stencilPass_ = pass;
  1379. stencilFail_ = fail;
  1380. stencilZFail_ = zFail;
  1381. }
  1382. }
  1383. }
  1384. void Graphics::SetForceSM2(bool enable)
  1385. {
  1386. }
  1387. bool Graphics::IsInitialized() const
  1388. {
  1389. return impl_->window_ != 0;
  1390. }
  1391. void* Graphics::GetWindowHandle() const
  1392. {
  1393. return impl_->window_;
  1394. }
  1395. PODVector<IntVector2> Graphics::GetResolutions() const
  1396. {
  1397. static const unsigned MAX_MODES = 256;
  1398. GLFWvidmode modes[MAX_MODES];
  1399. unsigned count = glfwGetVideoModes(modes, MAX_MODES);
  1400. PODVector<IntVector2> ret;
  1401. for (unsigned i = 0; i < count; ++i)
  1402. {
  1403. int width = modes[i].width;
  1404. int height = modes[i].height;
  1405. // Store mode if unique
  1406. bool unique = true;
  1407. for (unsigned j = 0; j < ret.Size(); ++i)
  1408. {
  1409. if (ret[j].x_ == width && ret[j].y_ == height)
  1410. {
  1411. unique = false;
  1412. break;
  1413. }
  1414. }
  1415. if (unique)
  1416. ret.Push(IntVector2(width, height));
  1417. }
  1418. return ret;
  1419. }
  1420. PODVector<int> Graphics::GetMultiSampleLevels() const
  1421. {
  1422. PODVector<int> ret;
  1423. // No multisampling always supported
  1424. ret.Push(1);
  1425. /// \todo Implement properly, if possible
  1426. return ret;
  1427. }
  1428. VertexBuffer* Graphics::GetVertexBuffer(unsigned index) const
  1429. {
  1430. return index < MAX_VERTEX_STREAMS ? vertexBuffers_[index] : 0;
  1431. }
  1432. TextureUnit Graphics::GetTextureUnit(const String& name)
  1433. {
  1434. Map<String, TextureUnit>::Iterator i = textureUnits_.Find(name);
  1435. if (i != textureUnits_.End())
  1436. return i->second_;
  1437. else
  1438. return MAX_TEXTURE_UNITS;
  1439. }
  1440. const String& Graphics::GetTextureUnitName(TextureUnit unit)
  1441. {
  1442. for (Map<String, TextureUnit>::Iterator i = textureUnits_.Begin(); i != textureUnits_.End(); ++i)
  1443. {
  1444. if (i->second_ == unit)
  1445. return i->first_;
  1446. }
  1447. return noParameter;
  1448. }
  1449. Texture* Graphics::GetTexture(unsigned index) const
  1450. {
  1451. return index < MAX_TEXTURE_UNITS ? textures_[index] : 0;
  1452. }
  1453. RenderSurface* Graphics::GetRenderTarget(unsigned index) const
  1454. {
  1455. return index < MAX_RENDERTARGETS ? renderTargets_[index] : 0;
  1456. }
  1457. IntVector2 Graphics::GetRenderTargetDimensions() const
  1458. {
  1459. int width, height;
  1460. if (renderTargets_[0])
  1461. {
  1462. width = renderTargets_[0]->GetWidth();
  1463. height = renderTargets_[0]->GetHeight();
  1464. }
  1465. else if (depthStencil_)
  1466. {
  1467. width = depthStencil_->GetWidth();
  1468. height = depthStencil_->GetHeight();
  1469. }
  1470. else
  1471. {
  1472. width = width_;
  1473. height = height_;
  1474. }
  1475. return IntVector2(width, height);
  1476. }
  1477. void Graphics::AddGPUObject(GPUObject* object)
  1478. {
  1479. gpuObjects_.Push(object);
  1480. }
  1481. void Graphics::RemoveGPUObject(GPUObject* object)
  1482. {
  1483. Vector<GPUObject*>::Iterator i = gpuObjects_.Find(object);
  1484. if (i != gpuObjects_.End())
  1485. gpuObjects_.Erase(i);
  1486. }
  1487. void* Graphics::ReserveDiscardLockBuffer(unsigned size)
  1488. {
  1489. // First check for a free buffer that is large enough
  1490. for (Vector<DiscardLockBuffer>::Iterator i = discardLockBuffers_.Begin(); i != discardLockBuffers_.End(); ++i)
  1491. {
  1492. if (!i->reserved_ && i->size_ >= size)
  1493. {
  1494. i->reserved_ = true;
  1495. return i->data_.Get();
  1496. }
  1497. }
  1498. // Then check if a free buffer can be resized
  1499. for (Vector<DiscardLockBuffer>::Iterator i = discardLockBuffers_.Begin(); i != discardLockBuffers_.End(); ++i)
  1500. {
  1501. if (!i->reserved_)
  1502. {
  1503. i->data_ = new unsigned char[size];
  1504. i->size_ = size;
  1505. i->reserved_ = true;
  1506. return i->data_.Get();
  1507. }
  1508. }
  1509. // Finally allocate a new buffer
  1510. DiscardLockBuffer newBuffer;
  1511. newBuffer.data_ = new unsigned char[size];
  1512. newBuffer.size_ = size;
  1513. newBuffer.reserved_ = true;
  1514. discardLockBuffers_.Push(newBuffer);
  1515. return newBuffer.data_.Get();
  1516. }
  1517. void Graphics::FreeDiscardLockBuffer(void* buffer)
  1518. {
  1519. for (Vector<DiscardLockBuffer>::Iterator i = discardLockBuffers_.Begin(); i != discardLockBuffers_.End(); ++i)
  1520. {
  1521. if (i->reserved_ && i->data_.Get() == buffer)
  1522. {
  1523. i->reserved_ = false;
  1524. return;
  1525. }
  1526. }
  1527. LOGWARNING("Reserved discard lock buffer " + ToStringHex((unsigned)buffer) + " not found");
  1528. }
  1529. void Graphics::Release(bool clearGPUObjects, bool closeWindow)
  1530. {
  1531. if (!impl_->window_)
  1532. return;
  1533. depthTextures_.Clear();
  1534. if (clearGPUObjects)
  1535. {
  1536. // Shutting down: release all GPU objects that still exist
  1537. for (Vector<GPUObject*>::Iterator i = gpuObjects_.Begin(); i != gpuObjects_.End(); ++i)
  1538. (*i)->Release();
  1539. gpuObjects_.Clear();
  1540. }
  1541. else
  1542. {
  1543. // We are not shutting down, but recreating the context: mark GPU objects lost
  1544. for (Vector<GPUObject*>::Iterator i = gpuObjects_.Begin(); i != gpuObjects_.End(); ++i)
  1545. (*i)->OnDeviceLost();
  1546. }
  1547. if (impl_->fbo_)
  1548. {
  1549. glDeleteFramebuffersEXT(1, &impl_->fbo_);
  1550. glDeleteFramebuffersEXT(1, &impl_->depthOnlyFbo_);
  1551. impl_->fbo_ = 0;
  1552. impl_->depthOnlyFbo_ = 0;
  1553. }
  1554. // When the new context is initialized, it will have default state again
  1555. ResetCachedState();
  1556. ClearParameterSources();
  1557. {
  1558. MutexLock lock(GetStaticMutex());
  1559. SetWindowContext(impl_->window_, 0);
  1560. // If in close callback, GLFW will close the window for us, so skip it
  1561. if (closeWindow)
  1562. glfwCloseWindow(impl_->window_);
  1563. impl_->window_ = 0;
  1564. }
  1565. }
  1566. unsigned Graphics::GetAlphaFormat()
  1567. {
  1568. return GL_ALPHA;
  1569. }
  1570. unsigned Graphics::GetLuminanceFormat()
  1571. {
  1572. return GL_LUMINANCE;
  1573. }
  1574. unsigned Graphics::GetLuminanceAlphaFormat()
  1575. {
  1576. return GL_LUMINANCE_ALPHA;
  1577. }
  1578. unsigned Graphics::GetRGBFormat()
  1579. {
  1580. return GL_RGB;
  1581. }
  1582. unsigned Graphics::GetRGBAFormat()
  1583. {
  1584. return GL_RGBA;
  1585. }
  1586. unsigned Graphics::GetFloatFormat()
  1587. {
  1588. return GL_LUMINANCE32F_ARB;
  1589. }
  1590. unsigned Graphics::GetLinearDepthFormat()
  1591. {
  1592. // OpenGL FBO specs state that color attachments must have the same format; therefore must encode linear depth to RGBA
  1593. // manually if not using a readable hardware depth texture
  1594. return GL_RGBA;
  1595. }
  1596. unsigned Graphics::GetDepthStencilFormat()
  1597. {
  1598. return GL_DEPTH24_STENCIL8_EXT;
  1599. }
  1600. void Graphics::CheckFeatureSupport()
  1601. {
  1602. // Check supported features: light pre-pass, deferred rendering and hardware depth texture
  1603. lightPrepassSupport_ = false;
  1604. deferredSupport_ = false;
  1605. hardwareDepthSupport_ = false;
  1606. int numSupportedRTs = 1;
  1607. glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &numSupportedRTs);
  1608. // For now hardware depth texture is only tested for on NVIDIA hardware because of visual artifacts and slowdown on ATI
  1609. String vendorString = String((const char*)glGetString(GL_VENDOR)).ToUpper();
  1610. if (vendorString.Find("NVIDIA") != String::NPOS)
  1611. {
  1612. SharedPtr<Texture2D> depthTexture(new Texture2D(context_));
  1613. hardwareDepthSupport_ = true;
  1614. // Note: Texture2D::SetSize() requires hardwareDepthSupport_ == true to create a texture instead of a renderbuffer
  1615. depthTexture->SetSize(256, 256, GetDepthStencilFormat(), TEXTURE_DEPTHSTENCIL);
  1616. SetDepthStencil(depthTexture);
  1617. // If hardware depth textures work, this means also light pre-pass is automatically supported
  1618. if (CheckFramebuffer())
  1619. {
  1620. lightPrepassSupport_ = true;
  1621. if (numSupportedRTs >= 3)
  1622. deferredSupport_ = true;
  1623. }
  1624. else
  1625. hardwareDepthSupport_ = false;
  1626. ResetDepthStencil();
  1627. }
  1628. if (!hardwareDepthSupport_)
  1629. {
  1630. // If hardware depth is not supported, must support 2 rendertargets for light pre-pass, and 4 for deferred
  1631. if (numSupportedRTs >= 2)
  1632. lightPrepassSupport_ = true;
  1633. if (numSupportedRTs >= 4)
  1634. deferredSupport_ = true;
  1635. }
  1636. }
  1637. void Graphics::SetDrawBuffers()
  1638. {
  1639. // Calculate the bit combination of non-zero color rendertargets to first check if the combination changed
  1640. unsigned newDrawBuffers = 0;
  1641. for (unsigned i = 0; i < MAX_RENDERTARGETS; ++i)
  1642. {
  1643. if (renderTargets_[i])
  1644. newDrawBuffers |= 1 << i;
  1645. }
  1646. if (newDrawBuffers == impl_->drawBuffers_)
  1647. return;
  1648. // Check for no color rendertargets (depth rendering only)
  1649. if (!newDrawBuffers)
  1650. glDrawBuffer(GL_NONE);
  1651. else
  1652. {
  1653. int drawBufferIds[4];
  1654. unsigned drawBufferCount = 0;
  1655. for (unsigned i = 0; i < MAX_RENDERTARGETS; ++i)
  1656. {
  1657. if (renderTargets_[i])
  1658. drawBufferIds[drawBufferCount++] = GL_COLOR_ATTACHMENT0_EXT + i;
  1659. }
  1660. glDrawBuffers(drawBufferCount, (const GLenum*)drawBufferIds);
  1661. }
  1662. impl_->drawBuffers_ = newDrawBuffers;
  1663. }
  1664. bool Graphics::CheckFramebuffer()
  1665. {
  1666. return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT;
  1667. }
  1668. void Graphics::ResetCachedState()
  1669. {
  1670. for (unsigned i = 0; i < MAX_VERTEX_STREAMS; ++i)
  1671. {
  1672. vertexBuffers_[i] = 0;
  1673. elementMasks_[i] = 0;
  1674. }
  1675. for (unsigned i = 0; i < MAX_TEXTURE_UNITS; ++i)
  1676. {
  1677. textures_[i] = 0;
  1678. textureTypes_[i] = 0;
  1679. }
  1680. for (unsigned i = 0; i < MAX_RENDERTARGETS; ++i)
  1681. renderTargets_[i] = 0;
  1682. depthStencil_ = 0;
  1683. viewTexture_ = 0;
  1684. viewport_ = IntRect(0, 0, 0, 0);
  1685. indexBuffer_ = 0;
  1686. vertexShader_ = 0;
  1687. pixelShader_ = 0;
  1688. shaderProgram_ = 0;
  1689. blendMode_ = BLEND_REPLACE;
  1690. alphaTest_ = false;
  1691. alphaTestMode_ = CMP_ALWAYS;
  1692. alphaRef_ = 0.0f;
  1693. textureAnisotropy_ = 1;
  1694. colorWrite_ = true;
  1695. cullMode_ = CULL_NONE;
  1696. constantDepthBias_ = 0.0f;
  1697. slopeScaledDepthBias_ = 0.0f;
  1698. depthTestMode_ = CMP_ALWAYS;
  1699. depthWrite_ = true;
  1700. fillMode_ = FILL_SOLID;
  1701. scissorTest_ = false;
  1702. scissorRect_ = IntRect::ZERO;
  1703. stencilTest_ = false;
  1704. stencilTestMode_ = CMP_ALWAYS;
  1705. stencilPass_ = OP_KEEP;
  1706. stencilFail_ = OP_KEEP;
  1707. stencilZFail_ = OP_KEEP;
  1708. stencilRef_ = 0;
  1709. stencilCompareMask_ = M_MAX_UNSIGNED;
  1710. stencilWriteMask_ = M_MAX_UNSIGNED;
  1711. impl_->activeTexture_ = 0;
  1712. impl_->drawBuffers_ = M_MAX_UNSIGNED;
  1713. impl_->enabledAttributes_ = 0;
  1714. }
  1715. void Graphics::SetTextureUnitMappings()
  1716. {
  1717. textureUnits_["DiffMap"] = TU_DIFFUSE;
  1718. textureUnits_["DiffCubeMap"] = TU_DIFFUSE;
  1719. textureUnits_["NormalMap"] = TU_NORMAL;
  1720. textureUnits_["EmissiveMap"] = TU_EMISSIVE;
  1721. textureUnits_["DetailMap"] = TU_DETAIL;
  1722. textureUnits_["EnvironmentMap"] = TU_ENVIRONMENT;
  1723. textureUnits_["EnvironmentCubeMap"] = TU_ENVIRONMENT;
  1724. textureUnits_["LightRampMap"] = TU_LIGHTRAMP;
  1725. textureUnits_["LightSpotMap"] = TU_LIGHTSHAPE;
  1726. textureUnits_["LightCubeMap"] = TU_LIGHTSHAPE;
  1727. textureUnits_["ShadowMap"] = TU_SHADOWMAP;
  1728. textureUnits_["FaceSelectCubeMap"] = TU_FACESELECT;
  1729. textureUnits_["IndirectionCubeMap"] = TU_INDIRECTION;
  1730. textureUnits_["AlbedoBuffer"] = TU_ALBEDOBUFFER;
  1731. textureUnits_["NormalBuffer"] = TU_NORMALBUFFER;
  1732. textureUnits_["DepthBuffer"] = TU_DEPTHBUFFER;
  1733. textureUnits_["LightBuffer"] = TU_LIGHTBUFFER;
  1734. }
  1735. void RegisterGraphicsLibrary(Context* context)
  1736. {
  1737. Animation::RegisterObject(context);
  1738. Material::RegisterObject(context);
  1739. Model::RegisterObject(context);
  1740. Shader::RegisterObject(context);
  1741. Technique::RegisterObject(context);
  1742. Texture2D::RegisterObject(context);
  1743. TextureCube::RegisterObject(context);
  1744. Camera::RegisterObject(context);
  1745. Drawable::RegisterObject(context);
  1746. Light::RegisterObject(context);
  1747. StaticModel::RegisterObject(context);
  1748. Skybox::RegisterObject(context);
  1749. AnimatedModel::RegisterObject(context);
  1750. AnimationController::RegisterObject(context);
  1751. BillboardSet::RegisterObject(context);
  1752. ParticleEmitter::RegisterObject(context);
  1753. DebugRenderer::RegisterObject(context);
  1754. Octree::RegisterObject(context);
  1755. Zone::RegisterObject(context);
  1756. }