OGLGraphics.cpp 75 KB

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