OGLGraphics.cpp 67 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232
  1. //
  2. // Urho3D Engine
  3. // Copyright (c) 2008-2011 Lasse Öörni
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. //
  23. #include "Precompiled.h"
  24. #include "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 "Technique.h"
  49. #include "Texture2D.h"
  50. #include "TextureCube.h"
  51. #include "VertexBuffer.h"
  52. #include "Zone.h"
  53. #ifdef _MSC_VER
  54. #include <float.h>
  55. #else
  56. // From http://stereopsis.com/FPU.html
  57. #define FPU_CW_PREC_MASK 0x0300
  58. #define FPU_CW_PREC_SINGLE 0x0000
  59. #define FPU_CW_PREC_DOUBLE 0x0200
  60. #define FPU_CW_PREC_EXTENDED 0x0300
  61. #define FPU_CW_ROUND_MASK 0x0c00
  62. #define FPU_CW_ROUND_NEAR 0x0000
  63. #define FPU_CW_ROUND_DOWN 0x0400
  64. #define FPU_CW_ROUND_UP 0x0800
  65. #define FPU_CW_ROUND_CHOP 0x0c00
  66. inline unsigned GetFPUState()
  67. {
  68. unsigned control = 0;
  69. __asm__ __volatile__ ("fnstcw %0" : "=m" (control));
  70. return control;
  71. }
  72. inline void SetFPUState(unsigned control)
  73. {
  74. __asm__ __volatile__ ("fldcw %0" : : "m" (control));
  75. }
  76. #endif
  77. #include "DebugNew.h"
  78. static const unsigned glCmpFunc[] =
  79. {
  80. GL_ALWAYS,
  81. GL_EQUAL,
  82. GL_NOTEQUAL,
  83. GL_LESS,
  84. GL_LEQUAL,
  85. GL_GREATER,
  86. GL_GEQUAL
  87. };
  88. static const unsigned glSrcBlend[] =
  89. {
  90. GL_ONE,
  91. GL_ONE,
  92. GL_DST_COLOR,
  93. GL_SRC_ALPHA,
  94. GL_SRC_ALPHA,
  95. GL_ONE,
  96. GL_ONE_MINUS_DST_ALPHA
  97. };
  98. static const unsigned glDestBlend[] =
  99. {
  100. GL_ZERO,
  101. GL_ONE,
  102. GL_ZERO,
  103. GL_ONE_MINUS_SRC_ALPHA,
  104. GL_ONE,
  105. GL_ONE_MINUS_SRC_ALPHA,
  106. GL_DST_ALPHA
  107. };
  108. static const unsigned glStencilOps[] =
  109. {
  110. GL_KEEP,
  111. GL_ZERO,
  112. GL_REPLACE,
  113. GL_INCR,
  114. GL_DECR
  115. };
  116. static const String noParameter;
  117. OBJECTTYPESTATIC(Graphics);
  118. Graphics::Graphics(Context* context_) :
  119. Object(context_),
  120. impl_(new GraphicsImpl()),
  121. mode_(RENDER_FORWARD),
  122. width_(0),
  123. height_(0),
  124. multiSample_(1),
  125. initialized_(false),
  126. fullscreen_(false),
  127. vsync_(false),
  128. flushGPU_(true),
  129. renderTargetSupport_(false),
  130. deferredSupport_(false),
  131. numPrimitives_(0),
  132. numBatches_(0),
  133. immediateVertexCount_(0),
  134. defaultTextureFilterMode_(FILTER_BILINEAR),
  135. shadowMapFormat_(0),
  136. hiresShadowMapFormat_(0),
  137. shaderParameterFrame_(0)
  138. {
  139. ResetCachedState();
  140. InitializeShaderParameters();
  141. }
  142. Graphics::~Graphics()
  143. {
  144. Close();
  145. delete impl_;
  146. impl_ = 0;
  147. }
  148. void Graphics::SetWindowTitle(const String& windowTitle)
  149. {
  150. SDL_WM_SetCaption(windowTitle.CString(), 0);
  151. }
  152. bool Graphics::SetMode(RenderMode mode, int width, int height, bool fullscreen, bool vsync, int multiSample)
  153. {
  154. PROFILE(SetScreenMode);
  155. if ((initialized_) && (mode == mode_) && (width == width_) && (height == height_) && (fullscreen == fullscreen_) && (vsync == vsync_)
  156. && (multiSample == multiSample_))
  157. return true;
  158. multiSample = Clamp(multiSample, 1, 16);
  159. // If zero dimensions in windowed mode, set default. If zero in fullscreen, use desktop mode
  160. if ((!width) || (!height))
  161. {
  162. if (!fullscreen)
  163. {
  164. width = 800;
  165. height = 600;
  166. }
  167. else
  168. {
  169. width = 0;
  170. height = 0;
  171. }
  172. }
  173. /// \todo Reimplement using SDL 1.3 functionality, which allows multiple windows
  174. if (!initialized_)
  175. {
  176. if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
  177. {
  178. LOGERROR("SDL video subsystem initialization failed");
  179. return false;
  180. }
  181. }
  182. SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
  183. SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
  184. SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
  185. SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
  186. SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
  187. SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 0);
  188. SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
  189. if ((multiSample > 1) && (mode == RENDER_FORWARD))
  190. {
  191. SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
  192. SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, multiSample);
  193. }
  194. else
  195. {
  196. SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
  197. SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
  198. }
  199. // Lose the existing OpenGL context now
  200. Release();
  201. unsigned sdlFlags = SDL_OPENGL;
  202. if (fullscreen)
  203. sdlFlags |= SDL_FULLSCREEN;
  204. SDL_Surface* surface = SDL_SetVideoMode(width, height, 0, sdlFlags);
  205. if (!surface)
  206. {
  207. // If fullscreen mode fails, retry windowed
  208. if (fullscreen)
  209. {
  210. fullscreen = false;
  211. unsigned sdlFlags = SDL_OPENGL;
  212. surface = SDL_SetVideoMode(width, height, 0, sdlFlags);
  213. }
  214. if (!surface)
  215. {
  216. LOGERROR("Could not set screen mode");
  217. return false;
  218. }
  219. }
  220. // Mimic Direct3D way of setting FPU into round-to-nearest, single precision mode
  221. // This is actually needed for ODE to behave predictably in float mode
  222. #ifdef _MSC_VER
  223. _controlfp(_RC_NEAR | _PC_24, _MCW_RC | _MCW_PC);
  224. #else
  225. unsigned control = GetFPUState();
  226. control &= ~(FPU_CW_PREC_MASK | FPU_CW_ROUND_MASK);
  227. control |= (FPU_CW_PREC_SINGLE | FPU_CW_ROUND_NEAR);
  228. SetFPUState(control);
  229. #endif
  230. // If OpenGL extensions not yet initialized, initialize now
  231. // Query needs to happen under lock as the function pointers are static
  232. {
  233. MutexLock lock(GetStaticMutex());
  234. if (!GLeeInitialized())
  235. GLeeInit();
  236. }
  237. if (!_GLEE_VERSION_2_0)
  238. {
  239. LOGERROR("OpenGL 2.0 is required");
  240. SDL_Quit();
  241. return false;
  242. }
  243. // Set vsync
  244. SDL_GL_SetSwapInterval(vsync ? 1 : 0);
  245. // Query for system backbuffer depth
  246. glGetIntegerv(GL_DEPTH_BITS, &impl_->windowDepthBits_);
  247. impl_->depthBits_ = impl_->windowDepthBits_;
  248. // Create the FBO if fully supported
  249. if ((_GLEE_EXT_framebuffer_object) && (_GLEE_EXT_packed_depth_stencil))
  250. {
  251. glGenFramebuffersEXT(1, &impl_->fbo_);
  252. // Shadows, render targets and deferred rendering all depend on FBO & packed depth stencil
  253. shadowMapFormat_ = GL_DEPTH_COMPONENT16;
  254. hiresShadowMapFormat_ = GL_DEPTH_COMPONENT24;
  255. renderTargetSupport_ = true;
  256. deferredSupport_ = true;
  257. }
  258. // Set initial state to match Direct3D
  259. glEnable(GL_DEPTH_TEST);
  260. SetCullMode(CULL_CCW);
  261. SetDepthTest(CMP_LESSEQUAL);
  262. width_ = surface->w;
  263. height_ = surface->h;
  264. fullscreen_ = fullscreen;
  265. vsync_ = vsync;
  266. mode_ = mode;
  267. multiSample_ = multiSample;
  268. initialized_ = true;
  269. // Reset rendertargets and viewport for the new screen mode
  270. ResetRenderTargets();
  271. viewTexture_ = 0;
  272. // Clear the window to black now, because GPU object restore may take time
  273. Clear(CLEAR_COLOR);
  274. SDL_GL_SwapBuffers();
  275. // Create deferred rendering buffers as necessary
  276. CreateRenderTargets();
  277. // Let GPU objects restore themselves
  278. for (Vector<GPUObject*>::Iterator i = gpuObjects_.Begin(); i != gpuObjects_.End(); ++i)
  279. (*i)->OnDeviceReset();
  280. if (multiSample > 1)
  281. LOGINFO("Set screen mode " + String(width_) + "x" + String(height_) + " " + (fullscreen_ ? "fullscreen" : "windowed") +
  282. " multisample " + String(multiSample));
  283. else
  284. LOGINFO("Set screen mode " + String(width_) + "x" + String(height_) + " " + (fullscreen_ ? "fullscreen" : "windowed"));
  285. using namespace ScreenMode;
  286. VariantMap eventData;
  287. eventData[P_WIDTH] = width_;
  288. eventData[P_HEIGHT] = height_;
  289. eventData[P_FULLSCREEN] = fullscreen_;
  290. SendEvent(E_SCREENMODE, eventData);
  291. return true;
  292. }
  293. bool Graphics::SetMode(int width, int height)
  294. {
  295. return SetMode(mode_, width, height, fullscreen_, vsync_, multiSample_);
  296. }
  297. bool Graphics::SetMode(RenderMode mode)
  298. {
  299. return SetMode(mode, width_, height_, fullscreen_, vsync_, multiSample_);
  300. }
  301. bool Graphics::ToggleFullscreen()
  302. {
  303. return SetMode(mode_, width_, height_, !fullscreen_, vsync_, multiSample_);
  304. }
  305. void Graphics::Close()
  306. {
  307. if (initialized_)
  308. {
  309. // Release all GPU objects that still exist
  310. for (Vector<GPUObject*>::Iterator i = gpuObjects_.Begin(); i != gpuObjects_.End(); ++i)
  311. (*i)->Release();
  312. gpuObjects_.Clear();
  313. Release();
  314. SDL_QuitSubSystem(SDL_INIT_VIDEO);
  315. initialized_ = false;
  316. }
  317. }
  318. bool Graphics::TakeScreenShot(Image& destImage)
  319. {
  320. PROFILE(TakeScreenShot);
  321. ResetRenderTargets();
  322. destImage.SetSize(width_, height_, 3);
  323. glReadPixels(0, 0, width_, height_, GL_RGB, GL_UNSIGNED_BYTE, destImage.GetData());
  324. return true;
  325. }
  326. void Graphics::SetFlushGPU(bool enable)
  327. {
  328. flushGPU_ = enable;
  329. }
  330. bool Graphics::BeginFrame()
  331. {
  332. PROFILE(BeginRendering);
  333. if (!IsInitialized())
  334. return false;
  335. // If we should be fullscreen, but are not currently active, do not render
  336. if (fullscreen_)
  337. {
  338. unsigned state = SDL_GetAppState();
  339. if (!(state & SDL_APPACTIVE))
  340. return false;
  341. }
  342. // Set default rendertarget and depth buffer
  343. ResetRenderTargets();
  344. viewTexture_ = 0;
  345. // Cleanup textures from previous frame
  346. for (unsigned i = 0; i < MAX_TEXTURE_UNITS; ++i)
  347. SetTexture(i, 0);
  348. // Enable color and depth write
  349. SetColorWrite(true);
  350. SetDepthWrite(true);
  351. numPrimitives_ = 0;
  352. numBatches_ = 0;
  353. SendEvent(E_BEGINRENDER);
  354. return true;
  355. }
  356. void Graphics::EndFrame()
  357. {
  358. PROFILE(EndRendering);
  359. if (!IsInitialized())
  360. return;
  361. SendEvent(E_ENDRENDER);
  362. SDL_GL_SwapBuffers();
  363. }
  364. void Graphics::Clear(unsigned flags, const Color& color, float depth, unsigned stencil)
  365. {
  366. bool oldColorWrite = colorWrite_;
  367. bool oldDepthWrite = depthWrite_;
  368. if ((flags & CLEAR_COLOR) && (!oldColorWrite))
  369. SetColorWrite(true);
  370. if ((flags & CLEAR_DEPTH) && (!oldDepthWrite))
  371. SetDepthWrite(true);
  372. unsigned glFlags = 0;
  373. if (flags & CLEAR_COLOR)
  374. {
  375. glFlags |= GL_COLOR_BUFFER_BIT;
  376. glClearColor(color.r_, color.g_, color.b_, color.a_);
  377. }
  378. if (flags & CLEAR_DEPTH)
  379. {
  380. glFlags |= GL_DEPTH_BUFFER_BIT;
  381. glClearDepth(depth);
  382. }
  383. if (flags & CLEAR_STENCIL)
  384. {
  385. glFlags |= GL_STENCIL_BUFFER_BIT;
  386. glClearStencil(stencil);
  387. }
  388. glClear(glFlags);
  389. SetColorWrite(oldColorWrite);
  390. SetDepthWrite(oldDepthWrite);
  391. }
  392. void Graphics::Draw(PrimitiveType type, unsigned vertexStart, unsigned vertexCount)
  393. {
  394. if (!vertexCount)
  395. return;
  396. unsigned primitiveCount = 0;
  397. switch (type)
  398. {
  399. case TRIANGLE_LIST:
  400. primitiveCount = vertexCount / 3;
  401. glDrawArrays(GL_TRIANGLES, vertexStart, vertexCount);
  402. break;
  403. case LINE_LIST:
  404. primitiveCount = vertexCount / 2;
  405. glDrawArrays(GL_LINES, vertexStart, vertexCount);
  406. break;
  407. }
  408. numPrimitives_ += primitiveCount;
  409. ++numBatches_;
  410. }
  411. void Graphics::Draw(PrimitiveType type, unsigned indexStart, unsigned indexCount, unsigned minVertex, unsigned vertexCount)
  412. {
  413. if ((!indexCount) || (!indexBuffer_))
  414. return;
  415. unsigned primitiveCount = 0;
  416. unsigned indexSize = indexBuffer_->GetIndexSize();
  417. switch (type)
  418. {
  419. case TRIANGLE_LIST:
  420. primitiveCount = indexCount / 3;
  421. if (indexSize == sizeof(unsigned short))
  422. glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_SHORT, (const GLvoid*)(indexStart * indexSize));
  423. else
  424. glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, (const GLvoid*)(indexStart * indexSize));
  425. break;
  426. case LINE_LIST:
  427. primitiveCount = indexCount / 2;
  428. if (indexSize == sizeof(unsigned short))
  429. glDrawElements(GL_LINES, indexCount, GL_UNSIGNED_SHORT, (const GLvoid*)(indexStart * indexSize));
  430. else
  431. glDrawElements(GL_LINES, indexCount, GL_UNSIGNED_INT, (const GLvoid*)(indexStart * indexSize));
  432. break;
  433. }
  434. numPrimitives_ += primitiveCount;
  435. ++numBatches_;
  436. }
  437. void Graphics::DrawInstanced(PrimitiveType type, unsigned indexStart, unsigned indexCount, unsigned minVertex, unsigned vertexCount, unsigned instanceCount)
  438. {
  439. }
  440. void Graphics::SetVertexBuffer(VertexBuffer* buffer)
  441. {
  442. Vector<VertexBuffer*> vertexBuffers(1);
  443. PODVector<unsigned> elementMasks(1);
  444. vertexBuffers[0] = buffer;
  445. elementMasks[0] = MASK_DEFAULT;
  446. SetVertexBuffers(vertexBuffers, elementMasks);
  447. }
  448. bool Graphics::SetVertexBuffers(const Vector<VertexBuffer*>& buffers, const PODVector<unsigned>& elementMasks,
  449. unsigned instanceOffset)
  450. {
  451. if (buffers.Size() > MAX_VERTEX_STREAMS)
  452. {
  453. LOGERROR("Too many vertex buffers");
  454. return false;
  455. }
  456. if (buffers.Size() != elementMasks.Size())
  457. {
  458. LOGERROR("Amount of element masks and vertex buffers does not match");
  459. return false;
  460. }
  461. // If no valid shader to determine the attribute bindings, can not set vertex buffers
  462. if (!shaderProgram_)
  463. return false;
  464. const int* attributeLocations = shaderProgram_->GetAttributeLocations();
  465. bool changed = false;
  466. unsigned newAttributes = 0;
  467. for (unsigned i = 0; i < MAX_VERTEX_STREAMS; ++i)
  468. {
  469. VertexBuffer* buffer = 0;
  470. unsigned elementMask = 0;
  471. if (i < buffers.Size())
  472. {
  473. buffer = buffers[i];
  474. elementMask = elementMasks[i];
  475. if ((elementMask == MASK_DEFAULT) && (buffer))
  476. elementMask = buffers[i]->GetElementMask();
  477. }
  478. // If buffer and element mask have stayed the same, skip to the next buffer
  479. if ((buffer == vertexBuffers_[i]) && (elementMask == elementMasks_[i]))
  480. continue;
  481. vertexBuffers_[i] = buffer;
  482. elementMasks_[i] = elementMask;
  483. changed = true;
  484. if (!buffer)
  485. continue;
  486. glBindBuffer(GL_ARRAY_BUFFER, buffer->GetGPUObject());
  487. unsigned vertexSize = buffer->GetVertexSize();
  488. for (unsigned j = 0; j < MAX_VERTEX_ELEMENTS; ++j)
  489. {
  490. // If shader does not use the attribute, do not bind it (bandwidth optimization)
  491. int attributeIndex = attributeLocations[j];
  492. if (attributeIndex < 0)
  493. continue;
  494. unsigned elementBit = 1 << j;
  495. unsigned attributeBit = 1 << attributeIndex;
  496. if (elementMask & elementBit)
  497. {
  498. newAttributes |= attributeBit;
  499. // Enable attribute if not enabled yet
  500. if ((impl_->enabledAttributes_ & attributeBit) == 0)
  501. {
  502. glEnableVertexAttribArray(attributeIndex);
  503. impl_->enabledAttributes_ |= attributeBit;
  504. }
  505. // Set the attribute pointer
  506. glVertexAttribPointer(attributeIndex, VertexBuffer::elementComponents[j], VertexBuffer::elementType[j],
  507. VertexBuffer::elementNormalize[j], vertexSize, (const GLvoid*)(buffer->GetElementOffset((VertexElement)j)));
  508. }
  509. }
  510. }
  511. if (!changed)
  512. return true;
  513. // Now check which vertex attributes should be disabled
  514. unsigned disableAttributes = impl_->enabledAttributes_ & (~newAttributes);
  515. int disableIndex = 0;
  516. while (disableAttributes)
  517. {
  518. if (disableAttributes & 1)
  519. {
  520. glDisableVertexAttribArray(disableIndex);
  521. impl_->enabledAttributes_ &= ~(1 << disableIndex);
  522. }
  523. disableAttributes >>= 1;
  524. ++disableIndex;
  525. }
  526. return true;
  527. }
  528. bool Graphics::SetVertexBuffers(const Vector<SharedPtr<VertexBuffer> >& buffers, const PODVector<unsigned>&
  529. elementMasks, unsigned instanceOffset)
  530. {
  531. if (buffers.Size() > MAX_VERTEX_STREAMS)
  532. {
  533. LOGERROR("Too many vertex buffers");
  534. return false;
  535. }
  536. if (buffers.Size() != elementMasks.Size())
  537. {
  538. LOGERROR("Amount of element masks and vertex buffers does not match");
  539. return false;
  540. }
  541. // If no valid shader to determine the attribute bindings, can not set vertex buffers
  542. if (!shaderProgram_)
  543. return false;
  544. const int* attributeLocations = shaderProgram_->GetAttributeLocations();
  545. bool changed = false;
  546. unsigned newAttributes = 0;
  547. for (unsigned i = 0; i < MAX_VERTEX_STREAMS; ++i)
  548. {
  549. VertexBuffer* buffer = 0;
  550. unsigned elementMask = 0;
  551. if (i < buffers.Size())
  552. {
  553. buffer = buffers[i];
  554. elementMask = elementMasks[i];
  555. if ((elementMask == MASK_DEFAULT) && (buffer))
  556. elementMask = buffers[i]->GetElementMask();
  557. }
  558. // If buffer and element mask have stayed the same, skip to the next buffer
  559. if ((buffer == vertexBuffers_[i]) && (elementMask == elementMasks_[i]))
  560. continue;
  561. vertexBuffers_[i] = buffer;
  562. elementMasks_[i] = elementMask;
  563. changed = true;
  564. if (!buffer)
  565. continue;
  566. glBindBuffer(GL_ARRAY_BUFFER, buffer->GetGPUObject());
  567. unsigned vertexSize = buffer->GetVertexSize();
  568. for (unsigned j = 0; j < MAX_VERTEX_ELEMENTS; ++j)
  569. {
  570. // If shader does not use the attribute, do not bind it (bandwidth optimization)
  571. int attributeIndex = attributeLocations[j];
  572. if (attributeIndex < 0)
  573. continue;
  574. unsigned elementBit = 1 << j;
  575. unsigned attributeBit = 1 << attributeIndex;
  576. if (elementMask & elementBit)
  577. {
  578. newAttributes |= attributeBit;
  579. // Enable attribute if not enabled yet
  580. if ((impl_->enabledAttributes_ & attributeBit) == 0)
  581. {
  582. glEnableVertexAttribArray(attributeIndex);
  583. impl_->enabledAttributes_ |= attributeBit;
  584. }
  585. // Set the attribute pointer
  586. glVertexAttribPointer(attributeIndex, VertexBuffer::elementComponents[j], VertexBuffer::elementType[j],
  587. VertexBuffer::elementNormalize[j], vertexSize, (const GLvoid*)(buffer->GetElementOffset((VertexElement)j)));
  588. }
  589. }
  590. }
  591. if (!changed)
  592. return true;
  593. // Now check which vertex attributes should be disabled
  594. unsigned disableAttributes = impl_->enabledAttributes_ & (~newAttributes);
  595. int disableIndex = 0;
  596. while (disableAttributes)
  597. {
  598. if (disableAttributes & 1)
  599. {
  600. glDisableVertexAttribArray(disableIndex);
  601. impl_->enabledAttributes_ &= ~(1 << disableIndex);
  602. }
  603. disableAttributes >>= 1;
  604. ++disableIndex;
  605. }
  606. return true;
  607. }
  608. void Graphics::SetIndexBuffer(IndexBuffer* buffer)
  609. {
  610. if (indexBuffer_ == buffer)
  611. return;
  612. if (buffer)
  613. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer->GetGPUObject());
  614. else
  615. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  616. indexBuffer_ = buffer;
  617. }
  618. void Graphics::SetShaders(ShaderVariation* vs, ShaderVariation* ps)
  619. {
  620. if ((vs == vertexShader_) && (ps == pixelShader_))
  621. return;
  622. // Compile the shaders now if not yet compiled. If already attempted, do not retry
  623. if ((vs) && (!vs->IsCompiled()))
  624. {
  625. if (vs->GetCompilerOutput().Empty())
  626. {
  627. PROFILE(CompileVertexShader);
  628. bool success = vs->Create();
  629. if (success)
  630. LOGDEBUG("Compiled vertex shader " + vs->GetName());
  631. else
  632. {
  633. LOGERROR("Failed to compile vertex shader " + vs->GetName() + ":\n" + vs->GetCompilerOutput());
  634. vs = 0;
  635. }
  636. }
  637. else
  638. vs = 0;
  639. }
  640. if ((ps) && (!ps->IsCompiled()))
  641. {
  642. if (ps->GetCompilerOutput().Empty())
  643. {
  644. PROFILE(CompilePixelShader);
  645. bool success = ps->Create();
  646. if (success)
  647. LOGDEBUG("Compiled pixel shader " + ps->GetName());
  648. else
  649. {
  650. LOGERROR("Failed to compile pixel shader " + ps->GetName() + ":\n" + ps->GetCompilerOutput());
  651. ps = 0;
  652. }
  653. }
  654. else
  655. ps = 0;
  656. }
  657. for (unsigned i = 0; i < MAX_VERTEX_STREAMS; ++i)
  658. {
  659. vertexBuffers_[i] = 0;
  660. elementMasks_[i] = 0;
  661. }
  662. if ((!vs) || (!ps))
  663. {
  664. glUseProgram(0);
  665. vertexShader_ = 0;
  666. pixelShader_ = 0;
  667. shaderProgram_ = 0;
  668. }
  669. else
  670. {
  671. vertexShader_ = vs;
  672. pixelShader_ = ps;
  673. Pair<ShaderVariation*, ShaderVariation*> combination(vs, ps);
  674. ShaderProgramMap::Iterator i = shaderPrograms_.Find(combination);
  675. if (i != shaderPrograms_.End())
  676. {
  677. // Use the existing linked program
  678. if (i->second_->IsLinked())
  679. {
  680. glUseProgram(i->second_->GetGPUObject());
  681. shaderProgram_ = i->second_;
  682. }
  683. else
  684. {
  685. glUseProgram(0);
  686. shaderProgram_ = 0;
  687. }
  688. }
  689. else
  690. {
  691. // Link a new combination
  692. SharedPtr<ShaderProgram> newProgram(new ShaderProgram(this, vs, ps));
  693. if (newProgram->Link())
  694. {
  695. LOGDEBUG("Linked vertex shader " + vs->GetName() + " and pixel shader " + ps->GetName());
  696. // Note: Link() calls glUseProgram() to set the texture sampler uniforms,
  697. // so it is not necessary to call it again
  698. shaderProgram_ = newProgram;
  699. }
  700. else
  701. {
  702. LOGERROR("Failed to link vertex shader " + vs->GetName() + " and pixel shader " + ps->GetName() + ":\n" +
  703. newProgram->GetLinkerOutput());
  704. glUseProgram(0);
  705. shaderProgram_ = 0;
  706. }
  707. shaderPrograms_[combination] = newProgram;
  708. }
  709. }
  710. }
  711. void Graphics::SetShaderParameter(ShaderParameter param, const bool* data, unsigned count)
  712. {
  713. // Not supported
  714. }
  715. void Graphics::SetShaderParameter(ShaderParameter param, const float* data, unsigned count)
  716. {
  717. if (shaderProgram_)
  718. {
  719. const UniformInfo* info = shaderProgram_->GetUniformInfo(param);
  720. if (info)
  721. {
  722. switch (info->type_)
  723. {
  724. case GL_FLOAT:
  725. glUniform1fv(info->location_, count, data);
  726. break;
  727. case GL_FLOAT_VEC2:
  728. glUniform2fv(info->location_, count / 2, data);
  729. break;
  730. case GL_FLOAT_VEC3:
  731. glUniform3fv(info->location_, count / 3, data);
  732. break;
  733. case GL_FLOAT_VEC4:
  734. glUniform4fv(info->location_, count / 4, data);
  735. break;
  736. case GL_FLOAT_MAT3:
  737. glUniformMatrix3fv(info->location_, count / 9, GL_TRUE, data);
  738. break;
  739. case GL_FLOAT_MAT4:
  740. glUniformMatrix4fv(info->location_, count / 16, GL_TRUE, data);
  741. break;
  742. }
  743. }
  744. }
  745. }
  746. void Graphics::SetShaderParameter(ShaderParameter param, const int* data, unsigned count)
  747. {
  748. if (shaderProgram_)
  749. {
  750. const UniformInfo* info = shaderProgram_->GetUniformInfo(param);
  751. if (info)
  752. {
  753. switch (info->type_)
  754. {
  755. case GL_INT:
  756. glUniform1iv(info->location_, count, data);
  757. break;
  758. case GL_INT_VEC2:
  759. glUniform2iv(info->location_, count / 2, data);
  760. break;
  761. case GL_INT_VEC3:
  762. glUniform3iv(info->location_, count / 3, data);
  763. break;
  764. case GL_INT_VEC4:
  765. glUniform4iv(info->location_, count / 4, data);
  766. break;
  767. }
  768. }
  769. }
  770. }
  771. void Graphics::SetShaderParameter(ShaderParameter param, float value)
  772. {
  773. if (shaderProgram_)
  774. {
  775. const UniformInfo* info = shaderProgram_->GetUniformInfo(param);
  776. if (info)
  777. glUniform1fv(info->location_, 1, &value);
  778. }
  779. }
  780. void Graphics::SetShaderParameter(ShaderParameter param, const Color& color)
  781. {
  782. SetShaderParameter(param, color.GetData(), 4);
  783. }
  784. void Graphics::SetShaderParameter(ShaderParameter param, const Matrix3& matrix)
  785. {
  786. if (shaderProgram_)
  787. {
  788. const UniformInfo* info = shaderProgram_->GetUniformInfo(param);
  789. if (info)
  790. glUniformMatrix3fv(info->location_, 1, GL_TRUE, matrix.GetData());
  791. }
  792. }
  793. void Graphics::SetShaderParameter(ShaderParameter param, const Vector3& vector)
  794. {
  795. if (shaderProgram_)
  796. {
  797. const UniformInfo* info = shaderProgram_->GetUniformInfo(param);
  798. if (info)
  799. {
  800. // Check the uniform type to avoid mismatch
  801. switch (info->type_)
  802. {
  803. case GL_FLOAT:
  804. glUniform1fv(info->location_, 1, vector.GetData());
  805. break;
  806. case GL_FLOAT_VEC2:
  807. glUniform2fv(info->location_, 1, vector.GetData());
  808. break;
  809. case GL_FLOAT_VEC3:
  810. glUniform3fv(info->location_, 1, vector.GetData());
  811. break;
  812. }
  813. }
  814. }
  815. }
  816. void Graphics::SetShaderParameter(ShaderParameter param, const Matrix4& matrix)
  817. {
  818. if (shaderProgram_)
  819. {
  820. const UniformInfo* info = shaderProgram_->GetUniformInfo(param);
  821. if (info)
  822. glUniformMatrix4fv(info->location_, 1, GL_TRUE, matrix.GetData());
  823. }
  824. }
  825. void Graphics::SetShaderParameter(ShaderParameter param, const Vector4& vector)
  826. {
  827. if (shaderProgram_)
  828. {
  829. const UniformInfo* info = shaderProgram_->GetUniformInfo(param);
  830. if (info)
  831. {
  832. // Check the uniform type to avoid mismatch
  833. switch (info->type_)
  834. {
  835. case GL_FLOAT:
  836. glUniform1fv(info->location_, 1, vector.GetData());
  837. break;
  838. case GL_FLOAT_VEC2:
  839. glUniform2fv(info->location_, 1, vector.GetData());
  840. break;
  841. case GL_FLOAT_VEC3:
  842. glUniform3fv(info->location_, 1, vector.GetData());
  843. break;
  844. case GL_FLOAT_VEC4:
  845. glUniform4fv(info->location_, 1, vector.GetData());
  846. break;
  847. }
  848. }
  849. }
  850. }
  851. void Graphics::SetShaderParameter(ShaderParameter param, const Matrix3x4& matrix)
  852. {
  853. if (shaderProgram_)
  854. {
  855. const UniformInfo* info = shaderProgram_->GetUniformInfo(param);
  856. if (info)
  857. {
  858. float data[16];
  859. data[0] = matrix.m00_;
  860. data[1] = matrix.m01_;
  861. data[2] = matrix.m02_;
  862. data[3] = matrix.m03_;
  863. data[4] = matrix.m10_;
  864. data[5] = matrix.m11_;
  865. data[6] = matrix.m12_;
  866. data[7] = matrix.m13_;
  867. data[8] = matrix.m20_;
  868. data[9] = matrix.m21_;
  869. data[10] = matrix.m22_;
  870. data[11] = matrix.m23_;
  871. data[12] = 0.0f;
  872. data[13] = 0.0f;
  873. data[14] = 0.0f;
  874. data[15] = 1.0f;
  875. glUniformMatrix4fv(info->location_, 1, GL_TRUE, data);
  876. }
  877. }
  878. }
  879. bool Graphics::NeedParameterUpdate(ShaderParameter param, const void* source)
  880. {
  881. if (shaderProgram_)
  882. return shaderProgram_->NeedParameterUpdate(param, source, shaderParameterFrame_);
  883. return false;
  884. }
  885. bool Graphics::NeedTextureUnit(TextureUnit unit)
  886. {
  887. if ((shaderProgram_) && (shaderProgram_->HasTextureUnit(unit)))
  888. return true;
  889. return false;
  890. }
  891. void Graphics::ClearParameterSources()
  892. {
  893. ++shaderParameterFrame_;
  894. }
  895. void Graphics::ClearTransformSources()
  896. {
  897. if (shaderProgram_)
  898. {
  899. shaderProgram_->ClearParameterSource(VSP_MODEL);
  900. shaderProgram_->ClearParameterSource(VSP_VIEWPROJ);
  901. }
  902. }
  903. void Graphics::CleanupShaderPrograms()
  904. {
  905. for (ShaderProgramMap::Iterator i = shaderPrograms_.Begin(); i != shaderPrograms_.End();)
  906. {
  907. ShaderProgramMap::Iterator current = i++;
  908. ShaderVariation* vs = current->second_->GetVertexShader();
  909. ShaderVariation* ps = current->second_->GetPixelShader();
  910. if ((!vs) || (!ps) || (!vs->GetGPUObject()) || (!ps->GetGPUObject()))
  911. shaderPrograms_.Erase(current);
  912. }
  913. }
  914. void Graphics::SetTexture(unsigned index, Texture* texture)
  915. {
  916. if (index >= MAX_TEXTURE_UNITS)
  917. return;
  918. // Check if texture is currently bound as a render target. In that case, use its backup texture, or blank if not defined
  919. if (texture)
  920. {
  921. if ((renderTargets_[0]) && (renderTargets_[0]->GetParentTexture() == texture))
  922. texture = texture->GetBackupTexture();
  923. // Check also for the view texture, in case a specific rendering pass does not bind the destination render target,
  924. // but should still not sample it either
  925. else if (texture == viewTexture_)
  926. texture = texture->GetBackupTexture();
  927. }
  928. if (textures_[index] != texture)
  929. {
  930. if (impl_->activeTexture_ != index)
  931. {
  932. glActiveTexture(GL_TEXTURE0 + index);
  933. impl_->activeTexture_ = index;
  934. }
  935. if (texture)
  936. {
  937. unsigned glType = texture->GetTarget();
  938. if (glType != textureTypes_[index])
  939. {
  940. if (textureTypes_[index])
  941. glDisable(textureTypes_[index]);
  942. glEnable(glType);
  943. textureTypes_[index] = glType;
  944. }
  945. glBindTexture(glType, texture->GetGPUObject());
  946. if (texture->GetParametersDirty())
  947. texture->UpdateParameters();
  948. }
  949. else
  950. {
  951. if (textureTypes_[index])
  952. glBindTexture(textureTypes_[index], 0);
  953. }
  954. textures_[index] = texture;
  955. }
  956. else
  957. {
  958. if ((texture) && (texture->GetParametersDirty()))
  959. {
  960. if (impl_->activeTexture_ != index)
  961. {
  962. glActiveTexture(GL_TEXTURE0 + index);
  963. impl_->activeTexture_ = index;
  964. }
  965. glBindTexture(texture->GetTarget(), texture->GetGPUObject());
  966. texture->UpdateParameters();
  967. }
  968. }
  969. }
  970. void Graphics::SetTextureForUpdate(Texture* texture)
  971. {
  972. if (impl_->activeTexture_ != 0)
  973. {
  974. glActiveTexture(GL_TEXTURE0);
  975. impl_->activeTexture_ = 0;
  976. }
  977. glBindTexture(texture->GetTarget(), texture->GetGPUObject());
  978. textures_[0] = texture;
  979. }
  980. void Graphics::SetDefaultTextureFilterMode(TextureFilterMode mode)
  981. {
  982. if (mode != defaultTextureFilterMode_)
  983. {
  984. defaultTextureFilterMode_ = mode;
  985. SetTextureParametersDirty();
  986. }
  987. }
  988. void Graphics::SetTextureAnisotropy(unsigned level)
  989. {
  990. if (level != textureAnisotropy_)
  991. {
  992. textureAnisotropy_ = level;
  993. SetTextureParametersDirty();
  994. }
  995. }
  996. void Graphics::SetTextureParametersDirty()
  997. {
  998. for (Vector<GPUObject*>::Iterator i = gpuObjects_.Begin(); i != gpuObjects_.End(); ++i)
  999. {
  1000. Texture* texture = dynamic_cast<Texture*>(*i);
  1001. if (texture)
  1002. texture->SetParametersDirty();
  1003. }
  1004. }
  1005. void Graphics::ResetRenderTargets()
  1006. {
  1007. for (unsigned i = 0; i < MAX_RENDERTARGETS; ++i)
  1008. SetRenderTarget(i, (RenderSurface*)0);
  1009. SetDepthStencil((RenderSurface*)0);
  1010. }
  1011. void Graphics::ResetRenderTarget(unsigned index)
  1012. {
  1013. SetRenderTarget(index, (RenderSurface*)0);
  1014. }
  1015. void Graphics::ResetDepthStencil()
  1016. {
  1017. SetDepthStencil((RenderSurface*)0);
  1018. }
  1019. void Graphics::SetRenderTarget(unsigned index, RenderSurface* renderTarget)
  1020. {
  1021. if ((index >= MAX_RENDERTARGETS) || (!impl_->fbo_))
  1022. return;
  1023. if (renderTarget != renderTargets_[index])
  1024. {
  1025. renderTargets_[index] = renderTarget;
  1026. // If the rendertarget is also bound as a texture, replace with backup texture or null
  1027. if (renderTarget)
  1028. {
  1029. Texture* parentTexture = renderTarget->GetParentTexture();
  1030. for (unsigned i = 0; i < MAX_TEXTURE_UNITS; ++i)
  1031. {
  1032. if (textures_[i] == parentTexture)
  1033. SetTexture(i, textures_[i]->GetBackupTexture());
  1034. }
  1035. }
  1036. // Bind the FBO to be able to make changes to it
  1037. if (!impl_->fboBound_)
  1038. {
  1039. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, impl_->fbo_);
  1040. impl_->fboBound_ = true;
  1041. }
  1042. if (renderTarget)
  1043. {
  1044. Texture* texture = renderTarget->GetParentTexture();
  1045. // If texture's parameters are dirty, update before attaching
  1046. if (texture->GetParametersDirty())
  1047. {
  1048. SetTextureForUpdate(texture);
  1049. texture->UpdateParameters();
  1050. SetTexture(0, 0);
  1051. }
  1052. glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + index, renderTarget->GetTarget(), texture->GetGPUObject(), 0);
  1053. }
  1054. else
  1055. glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + index, GL_TEXTURE_2D, 0, 0);
  1056. // Disable color buffer writing/reading if only a depth texture is to be used:
  1057. // otherwise it is an OpenGL error (incomplete framebuffer)
  1058. SetDrawBuffers();
  1059. // If all rendertargets and the depth buffer are not textures, revert to backbuffer rendering
  1060. bool noFBO = (depthStencil_ == 0);
  1061. for (unsigned i = 0; i < MAX_RENDERTARGETS; ++i)
  1062. {
  1063. if (renderTargets_[i])
  1064. {
  1065. noFBO = false;
  1066. break;
  1067. }
  1068. }
  1069. if ((noFBO) && (impl_->fboBound_))
  1070. {
  1071. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  1072. impl_->fboBound_ = false;
  1073. }
  1074. }
  1075. }
  1076. void Graphics::SetRenderTarget(unsigned index, Texture2D* renderTexture)
  1077. {
  1078. RenderSurface* renderTarget = 0;
  1079. if (renderTexture)
  1080. renderTarget = renderTexture->GetRenderSurface();
  1081. SetRenderTarget(index, renderTarget);
  1082. }
  1083. void Graphics::SetDepthStencil(RenderSurface* depthStencil)
  1084. {
  1085. if ((impl_->fbo_) && (depthStencil != depthStencil_))
  1086. {
  1087. // If we are using a rendertarget texture, it is required in OpenGL to also have an own depth stencil
  1088. // Create a new depth stencil texture as necessary to be able to provide similar behaviour.
  1089. if ((renderTargets_[0]) && (!depthStencil))
  1090. {
  1091. int width = renderTargets_[0]->GetWidth();
  1092. int height = renderTargets_[0]->GetHeight();
  1093. int searchKey = (width << 16) | height;
  1094. HashMap<int, SharedPtr<Texture2D> >::Iterator i = depthTextures_.Find(searchKey);
  1095. if (i != depthTextures_.End())
  1096. depthStencil = i->second_->GetRenderSurface();
  1097. else
  1098. {
  1099. SharedPtr<Texture2D> newDepthTexture(new Texture2D(context_));
  1100. newDepthTexture->SetSize(width, height, GetDepthStencilFormat(), TEXTURE_DEPTHSTENCIL);
  1101. depthTextures_[searchKey] = newDepthTexture;
  1102. depthStencil = newDepthTexture->GetRenderSurface();
  1103. }
  1104. }
  1105. /// \todo Should check that the texture actually is in depth format
  1106. depthStencil_ = depthStencil;
  1107. // Bind the FBO to be able to make changes to it
  1108. if (!impl_->fboBound_)
  1109. {
  1110. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, impl_->fbo_);
  1111. impl_->fboBound_ = true;
  1112. }
  1113. if (depthStencil)
  1114. {
  1115. // Bind either a renderbuffer or a depth texture, depending on what is available
  1116. unsigned renderBufferID = depthStencil->GetRenderBuffer();
  1117. if (!renderBufferID)
  1118. {
  1119. Texture* texture = depthStencil->GetParentTexture();
  1120. // If texture's parameters are dirty, update before attaching
  1121. if (texture->GetParametersDirty())
  1122. {
  1123. SetTextureForUpdate(texture);
  1124. texture->UpdateParameters();
  1125. SetTexture(0, 0);
  1126. }
  1127. glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, texture->GetGPUObject(), 0);
  1128. glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0);
  1129. impl_->depthBits_ = texture->GetDepthBits();
  1130. }
  1131. else
  1132. {
  1133. glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, renderBufferID);
  1134. glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, renderBufferID);
  1135. impl_->depthBits_ = 24;
  1136. }
  1137. }
  1138. else
  1139. {
  1140. glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0);
  1141. glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0);
  1142. impl_->depthBits_ = impl_->windowDepthBits_;
  1143. }
  1144. // Disable color buffer writing/reading if only a depth texture is to be used:
  1145. // otherwise it is an OpenGL error (incomplete framebuffer)
  1146. SetDrawBuffers();
  1147. // If all rendertargets and the depth buffer are not textures, revert to backbuffer rendering
  1148. bool noFBO = (depthStencil_ == 0);
  1149. for (unsigned i = 0; i < MAX_RENDERTARGETS; ++i)
  1150. {
  1151. if (renderTargets_[i])
  1152. {
  1153. noFBO = false;
  1154. break;
  1155. }
  1156. }
  1157. if ((noFBO) && (impl_->fboBound_))
  1158. {
  1159. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  1160. impl_->fboBound_ = false;
  1161. }
  1162. }
  1163. // Reset viewport and scissor test
  1164. IntVector2 viewSize = GetRenderTargetDimensions();
  1165. SetViewport(IntRect(0, 0, viewSize.x_, viewSize.y_));
  1166. SetScissorTest(false);
  1167. }
  1168. void Graphics::SetDepthStencil(Texture2D* depthTexture)
  1169. {
  1170. RenderSurface* depthStencil = 0;
  1171. if (depthTexture)
  1172. depthStencil = depthTexture->GetRenderSurface();
  1173. SetDepthStencil(depthStencil);
  1174. }
  1175. void Graphics::SetViewport(const IntRect& rect)
  1176. {
  1177. IntVector2 rtSize = GetRenderTargetDimensions();
  1178. IntRect rectCopy = rect;
  1179. if (rectCopy.right_ <= rectCopy.left_)
  1180. rectCopy.right_ = rectCopy.left_ + 1;
  1181. if (rectCopy.bottom_ <= rectCopy.top_)
  1182. rectCopy.bottom_ = rectCopy.top_ + 1;
  1183. rectCopy.left_ = Clamp(rectCopy.left_, 0, rtSize.x_);
  1184. rectCopy.top_ = Clamp(rectCopy.top_, 0, rtSize.y_);
  1185. rectCopy.right_ = Clamp(rectCopy.right_, 0, rtSize.x_);
  1186. rectCopy.bottom_ = Clamp(rectCopy.bottom_, 0, rtSize.y_);
  1187. if (rectCopy != viewport_)
  1188. {
  1189. // Use Direct3D convention with the vertical coordinates ie. 0 is top
  1190. glViewport(rectCopy.left_, rtSize.y_ - rectCopy.bottom_, rectCopy.right_ - rectCopy.left_, rectCopy.bottom_ - rectCopy.top_);
  1191. viewport_ = rectCopy;
  1192. }
  1193. // Disable scissor test, needs to be re-enabled by the user
  1194. SetScissorTest(false);
  1195. }
  1196. void Graphics::SetViewTexture(Texture* texture)
  1197. {
  1198. viewTexture_ = texture;
  1199. // Check for the view texture being currently bound
  1200. if (texture)
  1201. {
  1202. for (unsigned i = 0; i < MAX_TEXTURE_UNITS; ++i)
  1203. {
  1204. if (textures_[i] == texture)
  1205. SetTexture(i, textures_[i]->GetBackupTexture());
  1206. }
  1207. }
  1208. }
  1209. void Graphics::SetAlphaTest(bool enable, CompareMode mode, float alphaRef)
  1210. {
  1211. if (enable != alphaTest_)
  1212. {
  1213. if (enable)
  1214. glEnable(GL_ALPHA_TEST);
  1215. else
  1216. glDisable(GL_ALPHA_TEST);
  1217. alphaTest_ = enable;
  1218. }
  1219. if (enable)
  1220. {
  1221. alphaRef = Clamp(alphaRef, 0.0f, 1.0f);
  1222. if ((mode != alphaTestMode_) || (alphaRef != alphaRef_))
  1223. {
  1224. glAlphaFunc(glCmpFunc[mode], alphaRef);
  1225. alphaTestMode_ = mode;
  1226. alphaRef_ = alphaRef;
  1227. }
  1228. }
  1229. }
  1230. void Graphics::SetBlendMode(BlendMode mode)
  1231. {
  1232. if (mode != blendMode_)
  1233. {
  1234. if (mode == BLEND_REPLACE)
  1235. glDisable(GL_BLEND);
  1236. else
  1237. {
  1238. glEnable(GL_BLEND);
  1239. glBlendFunc(glSrcBlend[mode], glDestBlend[mode]);
  1240. }
  1241. blendMode_ = mode;
  1242. }
  1243. }
  1244. void Graphics::SetColorWrite(bool enable)
  1245. {
  1246. if (enable != colorWrite_)
  1247. {
  1248. if (enable)
  1249. glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  1250. else
  1251. glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
  1252. colorWrite_ = enable;
  1253. }
  1254. }
  1255. void Graphics::SetCullMode(CullMode mode)
  1256. {
  1257. if (mode != cullMode_)
  1258. {
  1259. if (mode == CULL_NONE)
  1260. glDisable(GL_CULL_FACE);
  1261. else
  1262. {
  1263. // Use Direct3D convention, ie. clockwise vertices define a front face
  1264. glEnable(GL_CULL_FACE);
  1265. glCullFace(mode == CULL_CCW ? GL_FRONT : GL_BACK);
  1266. }
  1267. cullMode_ = mode;
  1268. }
  1269. }
  1270. void Graphics::SetDepthBias(float constantBias, float slopeScaledBias)
  1271. {
  1272. if ((constantBias != constantDepthBias_) || (slopeScaledBias != slopeScaledDepthBias_))
  1273. {
  1274. if ((constantBias != 0.0f) || (slopeScaledBias != 0.0f))
  1275. {
  1276. // Bring the constant bias from Direct3D9 scale to OpenGL (depends on depth buffer bitdepth)
  1277. // Zero depth bits may be returned if using the packed depth stencil format. Assume 24bit in that case
  1278. int depthBits = Min(impl_->depthBits_, 23);
  1279. if (!depthBits)
  1280. depthBits = 23;
  1281. float adjustedConstantBias = constantBias * (float)(1 << (depthBits - 1));
  1282. float adjustedSlopeScaledBias = slopeScaledBias + 1.0f;
  1283. glEnable(GL_POLYGON_OFFSET_FILL);
  1284. glEnable(GL_POLYGON_OFFSET_LINE);
  1285. glPolygonOffset(adjustedSlopeScaledBias, adjustedConstantBias);
  1286. }
  1287. else
  1288. {
  1289. glDisable(GL_POLYGON_OFFSET_FILL);
  1290. glDisable(GL_POLYGON_OFFSET_LINE);
  1291. }
  1292. constantDepthBias_ = constantBias;
  1293. slopeScaledDepthBias_ = slopeScaledBias;
  1294. }
  1295. }
  1296. void Graphics::SetDepthTest(CompareMode mode)
  1297. {
  1298. if (mode != depthTestMode_)
  1299. {
  1300. glDepthFunc(glCmpFunc[mode]);
  1301. depthTestMode_ = mode;
  1302. }
  1303. }
  1304. void Graphics::SetDepthWrite(bool enable)
  1305. {
  1306. if (enable != depthWrite_)
  1307. {
  1308. glDepthMask(enable ? GL_TRUE : GL_FALSE);
  1309. depthWrite_ = enable;
  1310. }
  1311. }
  1312. void Graphics::SetFillMode(FillMode mode)
  1313. {
  1314. if (mode != fillMode_)
  1315. {
  1316. glPolygonMode(GL_FRONT_AND_BACK, mode == FILL_SOLID ? GL_FILL : GL_LINE);
  1317. fillMode_ = mode;
  1318. }
  1319. }
  1320. void Graphics::SetScissorTest(bool enable, const Rect& rect, bool borderInclusive)
  1321. {
  1322. // During some light rendering loops, a full rect is toggled on/off repeatedly.
  1323. // Disable scissor in that case to reduce state changes
  1324. if ((rect.min_.x_ <= 0.0f) && (rect.min_.y_ <= 0.0f) && (rect.max_.y_ >= 1.0f) && (rect.max_.y_ >= 1.0f))
  1325. enable = false;
  1326. // Check for illegal rect, disable in that case
  1327. if ((rect.max_.x_ < rect.min_.x_) || (rect.max_.y_ < rect.min_.y_))
  1328. enable = false;
  1329. if (enable)
  1330. {
  1331. IntVector2 rtSize(GetRenderTargetDimensions());
  1332. IntVector2 viewSize(viewport_.right_ - viewport_.left_, viewport_.bottom_ - viewport_.top_);
  1333. IntVector2 viewPos(viewport_.left_, viewport_.top_);
  1334. IntRect intRect;
  1335. int expand = borderInclusive ? 1 : 0;
  1336. intRect.left_ = Clamp((int)((rect.min_.x_ + 1.0f) * 0.5f * viewSize.x_) + viewPos.x_, 0, rtSize.x_ - 1);
  1337. intRect.top_ = Clamp((int)((-rect.max_.y_ + 1.0f) * 0.5f * viewSize.y_) + viewPos.y_, 0, rtSize.y_ - 1);
  1338. intRect.right_ = Clamp((int)((rect.max_.x_ + 1.0f) * 0.5f * viewSize.x_) + viewPos.x_ + expand, 0, rtSize.x_);
  1339. intRect.bottom_ = Clamp((int)((-rect.min_.y_ + 1.0f) * 0.5f * viewSize.y_) + viewPos.y_ + expand, 0, rtSize.y_);
  1340. if (intRect.right_ == intRect.left_)
  1341. intRect.right_++;
  1342. if (intRect.bottom_ == intRect.top_)
  1343. intRect.bottom_++;
  1344. if ((intRect.right_ < intRect.left_) || (intRect.bottom_ < intRect.top_))
  1345. enable = false;
  1346. if ((enable) && (scissorRect_ != intRect))
  1347. {
  1348. // Use Direct3D convention with the vertical coordinates ie. 0 is top
  1349. glScissor(intRect.left_, rtSize.y_ - intRect.bottom_, intRect.right_ - intRect.left_, intRect.bottom_ - intRect.top_);
  1350. scissorRect_ = intRect;
  1351. }
  1352. }
  1353. else
  1354. scissorRect_ = IntRect::ZERO;
  1355. if (enable != scissorTest_)
  1356. {
  1357. if (enable)
  1358. glEnable(GL_SCISSOR_TEST);
  1359. else
  1360. glDisable(GL_SCISSOR_TEST);
  1361. scissorTest_ = enable;
  1362. }
  1363. }
  1364. void Graphics::SetScissorTest(bool enable, const IntRect& rect)
  1365. {
  1366. IntVector2 rtSize(GetRenderTargetDimensions());
  1367. IntVector2 viewSize(viewport_.right_ - viewport_.left_, viewport_.bottom_ - viewport_.top_);
  1368. IntVector2 viewPos(viewport_.left_, viewport_.top_);
  1369. // Full scissor is same as disabling the test
  1370. if ((rect.left_ <= 0) && (rect.right_ >= viewSize.x_) && (rect.top_ <= 0) && (rect.bottom_ >= viewSize.y_))
  1371. enable = false;
  1372. // Check for illegal rect, disable in that case
  1373. if ((rect.right_ < rect.left_) || (rect.bottom_ < rect.top_))
  1374. enable = false;
  1375. if (enable)
  1376. {
  1377. IntRect intRect;
  1378. intRect.left_ = Clamp(rect.left_ + viewPos.x_, 0, rtSize.x_ - 1);
  1379. intRect.top_ = Clamp(rect.top_ + viewPos.y_, 0, rtSize.y_ - 1);
  1380. intRect.right_ = Clamp(rect.right_ + viewPos.x_, 0, rtSize.x_);
  1381. intRect.bottom_ = Clamp(rect.bottom_ + viewPos.y_, 0, rtSize.y_);
  1382. if (intRect.right_ == intRect.left_)
  1383. intRect.right_++;
  1384. if (intRect.bottom_ == intRect.top_)
  1385. intRect.bottom_++;
  1386. if ((intRect.right_ < intRect.left_) || (intRect.bottom_ < intRect.top_))
  1387. enable = false;
  1388. if ((enable) && (scissorRect_ != intRect))
  1389. {
  1390. // Use Direct3D convention with the vertical coordinates ie. 0 is top
  1391. glScissor(intRect.left_, rtSize.y_ - intRect.bottom_, intRect.right_ - intRect.left_, intRect.bottom_ - intRect.top_);
  1392. scissorRect_ = intRect;
  1393. }
  1394. }
  1395. else
  1396. scissorRect_ = IntRect::ZERO;
  1397. if (enable != scissorTest_)
  1398. {
  1399. if (enable)
  1400. glEnable(GL_SCISSOR_TEST);
  1401. else
  1402. glDisable(GL_SCISSOR_TEST);
  1403. scissorTest_ = enable;
  1404. }
  1405. }
  1406. void Graphics::SetStreamFrequency(unsigned index, unsigned frequency)
  1407. {
  1408. }
  1409. void Graphics::ResetStreamFrequencies()
  1410. {
  1411. }
  1412. void Graphics::SetStencilTest(bool enable, CompareMode mode, StencilOp pass, StencilOp fail, StencilOp zFail, unsigned stencilRef, unsigned stencilMask)
  1413. {
  1414. if (enable != stencilTest_)
  1415. {
  1416. if (enable)
  1417. glEnable(GL_STENCIL_TEST);
  1418. else
  1419. glDisable(GL_STENCIL_TEST);
  1420. stencilTest_ = enable;
  1421. }
  1422. if (enable)
  1423. {
  1424. if ((mode != stencilTestMode_) || (stencilRef != stencilRef_) || (stencilMask != stencilMask_))
  1425. {
  1426. glStencilFunc(glCmpFunc[mode], stencilRef, stencilMask);
  1427. stencilTestMode_ = mode;
  1428. stencilRef_ = stencilRef;
  1429. stencilMask_ = stencilMask;
  1430. }
  1431. if ((pass != stencilPass_) || (fail != stencilFail_) || (!zFail != stencilZFail_))
  1432. {
  1433. glStencilOp(glStencilOps[fail], glStencilOps[zFail], glStencilOps[pass]);
  1434. stencilPass_ = pass;
  1435. stencilFail_ = fail;
  1436. stencilZFail_ = zFail;
  1437. }
  1438. }
  1439. }
  1440. bool Graphics::BeginImmediate(PrimitiveType type, unsigned vertexCount, unsigned elementMask)
  1441. {
  1442. if (immediateVertexCount_)
  1443. {
  1444. LOGERROR("New immediate draw operation started before ending the last one");
  1445. return false;
  1446. }
  1447. if (!(elementMask & MASK_POSITION))
  1448. {
  1449. LOGERROR("Immediate draw operation must contain vertex positions");
  1450. return false;
  1451. }
  1452. if (!vertexCount)
  1453. return true;
  1454. // Resize the buffer if it is too small
  1455. unsigned vertexSize = VertexBuffer::GetVertexSize(elementMask);
  1456. if (immediateVertexData_.Size() < vertexCount * vertexSize)
  1457. immediateVertexData_.Resize(vertexCount * vertexSize);
  1458. // Note: the data pointer gets pre-decremented here, because the first call to DefineVertex() will increment it
  1459. immediateDataPtr_ = &immediateVertexData_[0] - vertexSize;
  1460. immediateType_= type;
  1461. immediateVertexCount_ = vertexCount;
  1462. immediateVertexSize_ = vertexSize;
  1463. immediateElementMask_ = elementMask;
  1464. immediateCurrentVertex_ = 0;
  1465. unsigned dataOffset = 0;
  1466. for (unsigned i = ELEMENT_POSITION; i <= ELEMENT_TEXCOORD1; ++i)
  1467. {
  1468. immediateElementOffsets_[i] = dataOffset;
  1469. if (elementMask & (1 << i))
  1470. dataOffset += VertexBuffer::elementSize[i];
  1471. }
  1472. return true;
  1473. }
  1474. bool Graphics::DefineVertex(const Vector3& vertex)
  1475. {
  1476. if ((!immediateVertexCount_) || (immediateCurrentVertex_ >= immediateVertexCount_))
  1477. return false;
  1478. immediateDataPtr_ += immediateVertexSize_;
  1479. ++immediateCurrentVertex_;
  1480. float* dest = (float*)(immediateDataPtr_ + immediateElementOffsets_[ELEMENT_POSITION]);
  1481. const float* src = vertex.GetData();
  1482. dest[0] = src[0];
  1483. dest[1] = src[1];
  1484. dest[2] = src[2];
  1485. return true;
  1486. }
  1487. bool Graphics::DefineNormal(const Vector3& normal)
  1488. {
  1489. if ((!immediateVertexCount_) || (!(immediateElementMask_ & MASK_NORMAL)) || (!immediateCurrentVertex_))
  1490. return false;
  1491. float* dest = (float*)(immediateDataPtr_ + immediateElementOffsets_[ELEMENT_NORMAL]);
  1492. const float* src = normal.GetData();
  1493. dest[0] = src[0];
  1494. dest[1] = src[1];
  1495. dest[2] = src[2];
  1496. return true;
  1497. }
  1498. bool Graphics::DefineTexCoord(const Vector2& texCoord)
  1499. {
  1500. if ((!immediateVertexCount_) || (!(immediateElementMask_ & MASK_TEXCOORD1)) || (!immediateCurrentVertex_))
  1501. return false;
  1502. float* dest = (float*)(immediateDataPtr_ + immediateElementOffsets_[ELEMENT_TEXCOORD1]);
  1503. const float* src = texCoord.GetData();
  1504. dest[0] = src[0];
  1505. dest[1] = src[1];
  1506. return true;
  1507. }
  1508. bool Graphics::DefineColor(const Color& color)
  1509. {
  1510. if ((!immediateVertexCount_) || (!(immediateElementMask_ & MASK_COLOR)) || (!immediateCurrentVertex_))
  1511. return false;
  1512. unsigned* dest = (unsigned*)(immediateDataPtr_ + immediateElementOffsets_[ELEMENT_COLOR]);
  1513. *dest = color.ToUInt();
  1514. return true;
  1515. }
  1516. bool Graphics::DefineColor(unsigned color)
  1517. {
  1518. if ((!immediateVertexCount_) || (!(immediateElementMask_ & MASK_COLOR)) || (!immediateCurrentVertex_))
  1519. return false;
  1520. unsigned* dest = (unsigned*)(immediateDataPtr_ + immediateElementOffsets_[ELEMENT_COLOR]);
  1521. *dest = color;
  1522. return true;
  1523. }
  1524. void Graphics::EndImmediate()
  1525. {
  1526. if (immediateVertexCount_)
  1527. {
  1528. SetVertexBuffer(0);
  1529. SetIndexBuffer(0);
  1530. if (shaderProgram_)
  1531. {
  1532. const int* attributeLocations = shaderProgram_->GetAttributeLocations();
  1533. unsigned vertexSize = VertexBuffer::GetVertexSize(immediateElementMask_);
  1534. glBindBuffer(GL_ARRAY_BUFFER, 0);
  1535. for (unsigned i = ELEMENT_POSITION; i <= ELEMENT_TEXCOORD1; ++i)
  1536. {
  1537. unsigned attributeIndex = attributeLocations[i];
  1538. unsigned attributeBit = 1 << attributeIndex;
  1539. unsigned elementBit = 1 << i;
  1540. if (immediateElementMask_ & elementBit)
  1541. {
  1542. if ((impl_->enabledAttributes_ & attributeBit) == 0)
  1543. {
  1544. glEnableVertexAttribArray(attributeIndex);
  1545. impl_->enabledAttributes_ |= attributeBit;
  1546. }
  1547. glVertexAttribPointer(attributeIndex, VertexBuffer::elementComponents[i], VertexBuffer::elementType[i],
  1548. VertexBuffer::elementNormalize[i], vertexSize, (const GLvoid*)&immediateVertexData_[immediateElementOffsets_[i]]);
  1549. }
  1550. else if (impl_->enabledAttributes_ & attributeBit)
  1551. {
  1552. glDisableVertexAttribArray(attributeIndex);
  1553. impl_->enabledAttributes_ &= ~attributeBit;
  1554. }
  1555. }
  1556. Draw(immediateType_, 0, immediateVertexCount_);
  1557. }
  1558. immediateVertexCount_ = 0;
  1559. }
  1560. }
  1561. void Graphics::SetForceSM2(bool enable)
  1562. {
  1563. }
  1564. unsigned char* Graphics::GetImmediateDataPtr() const
  1565. {
  1566. if (!immediateVertexCount_)
  1567. {
  1568. LOGERROR("Immediate draw operation not started");
  1569. return 0;
  1570. }
  1571. return const_cast<unsigned char*>(&immediateVertexData_[0]);
  1572. }
  1573. PODVector<IntVector2> Graphics::GetResolutions() const
  1574. {
  1575. PODVector<IntVector2> ret;
  1576. SDL_Rect** rects = SDL_ListModes(0, SDL_OPENGL | SDL_FULLSCREEN);
  1577. if ((rects) && (rects != (SDL_Rect**)-1))
  1578. {
  1579. for (unsigned i = 0; rects[i]; ++i)
  1580. ret.Push(IntVector2(rects[i]->w, rects[i]->h));
  1581. }
  1582. return ret;
  1583. }
  1584. PODVector<int> Graphics::GetMultiSampleLevels() const
  1585. {
  1586. PODVector<int> ret;
  1587. // No multisampling always supported
  1588. ret.Push(1);
  1589. /// \todo Implement properly using SDL, if possible
  1590. return ret;
  1591. }
  1592. VertexBuffer* Graphics::GetVertexBuffer(unsigned index) const
  1593. {
  1594. return index < MAX_VERTEX_STREAMS ? vertexBuffers_[index] : 0;
  1595. }
  1596. ShaderParameter Graphics::GetShaderParameter(const String& name)
  1597. {
  1598. Map<String, ShaderParameter>::Iterator i = shaderParameters_.Find(name);
  1599. if (i != shaderParameters_.End())
  1600. return i->second_;
  1601. else
  1602. return MAX_SHADER_PARAMETERS;
  1603. }
  1604. TextureUnit Graphics::GetTextureUnit(const String& name)
  1605. {
  1606. Map<String, TextureUnit>::Iterator i = textureUnits_.Find(name);
  1607. if (i != textureUnits_.End())
  1608. return i->second_;
  1609. else
  1610. return MAX_TEXTURE_UNITS;
  1611. }
  1612. const String& Graphics::GetShaderParameterName(ShaderParameter parameter)
  1613. {
  1614. for (Map<String, ShaderParameter>::Iterator i = shaderParameters_.Begin(); i != shaderParameters_.End(); ++i)
  1615. {
  1616. if (i->second_ == parameter)
  1617. return i->first_;
  1618. }
  1619. return noParameter;
  1620. }
  1621. const String& Graphics::GetTextureUnitName(TextureUnit unit)
  1622. {
  1623. for (Map<String, TextureUnit>::Iterator i = textureUnits_.Begin(); i != textureUnits_.End(); ++i)
  1624. {
  1625. if (i->second_ == unit)
  1626. return i->first_;
  1627. }
  1628. return noParameter;
  1629. }
  1630. Texture* Graphics::GetTexture(unsigned index) const
  1631. {
  1632. return index < MAX_TEXTURE_UNITS ? textures_[index] : 0;
  1633. }
  1634. RenderSurface* Graphics::GetRenderTarget(unsigned index) const
  1635. {
  1636. return index < MAX_RENDERTARGETS ? renderTargets_[index] : 0;
  1637. }
  1638. IntVector2 Graphics::GetRenderTargetDimensions() const
  1639. {
  1640. int width, height;
  1641. if (renderTargets_[0])
  1642. {
  1643. width = renderTargets_[0]->GetWidth();
  1644. height = renderTargets_[0]->GetHeight();
  1645. }
  1646. else if (depthStencil_)
  1647. {
  1648. width = depthStencil_->GetWidth();
  1649. height = depthStencil_->GetHeight();
  1650. }
  1651. else
  1652. {
  1653. width = width_;
  1654. height = height_;
  1655. }
  1656. return IntVector2(width, height);
  1657. }
  1658. void Graphics::AddGPUObject(GPUObject* object)
  1659. {
  1660. gpuObjects_.Push(object);
  1661. }
  1662. void Graphics::RemoveGPUObject(GPUObject* object)
  1663. {
  1664. for (Vector<GPUObject*>::Iterator i = gpuObjects_.Begin(); i != gpuObjects_.End(); ++i)
  1665. {
  1666. if ((*i) == object)
  1667. {
  1668. gpuObjects_.Erase(i);
  1669. return;
  1670. }
  1671. }
  1672. }
  1673. unsigned Graphics::GetAlphaFormat()
  1674. {
  1675. return GL_ALPHA;
  1676. }
  1677. unsigned Graphics::GetLuminanceFormat()
  1678. {
  1679. return GL_LUMINANCE;
  1680. }
  1681. unsigned Graphics::GetLuminanceAlphaFormat()
  1682. {
  1683. return GL_LUMINANCE_ALPHA;
  1684. }
  1685. unsigned Graphics::GetRGBFormat()
  1686. {
  1687. return GL_RGB;
  1688. }
  1689. unsigned Graphics::GetRGBAFormat()
  1690. {
  1691. return GL_RGBA;
  1692. }
  1693. unsigned Graphics::GetDepthFormat()
  1694. {
  1695. return GL_DEPTH_COMPONENT24;
  1696. }
  1697. unsigned Graphics::GetDepthStencilFormat()
  1698. {
  1699. return GL_DEPTH24_STENCIL8_EXT;
  1700. }
  1701. void Graphics::CreateRenderTargets()
  1702. {
  1703. if (mode_ != RENDER_FORWARD)
  1704. {
  1705. if (!diffBuffer_)
  1706. {
  1707. diffBuffer_ = new Texture2D(context_);
  1708. diffBuffer_->SetSize(0, 0, GetRGBAFormat(), TEXTURE_RENDERTARGET);
  1709. }
  1710. if (!normalBuffer_)
  1711. {
  1712. normalBuffer_ = new Texture2D(context_);
  1713. normalBuffer_->SetSize(0, 0, GetRGBAFormat(), TEXTURE_RENDERTARGET);
  1714. }
  1715. if (!depthBuffer_)
  1716. {
  1717. depthBuffer_ = new Texture2D(context_);
  1718. depthBuffer_->SetSize(0, 0, GetDepthFormat(), TEXTURE_DEPTHSTENCIL);
  1719. }
  1720. // If deferred antialiasing is used, reserve screen buffer
  1721. // (later we will probably want the screen buffer reserved in any case, to do for example distortion effects,
  1722. // which will also be useful in forward rendering)
  1723. if (multiSample_ > 1)
  1724. {
  1725. screenBuffer_ = new Texture2D(context_);
  1726. screenBuffer_->SetSize(0, 0, GetRGBAFormat(), TEXTURE_RENDERTARGET);
  1727. screenBuffer_->SetFilterMode(FILTER_BILINEAR);
  1728. }
  1729. else
  1730. screenBuffer_.Reset();
  1731. }
  1732. else
  1733. {
  1734. diffBuffer_.Reset();
  1735. normalBuffer_.Reset();
  1736. depthBuffer_.Reset();
  1737. screenBuffer_.Reset();
  1738. }
  1739. }
  1740. void Graphics::ResetCachedState()
  1741. {
  1742. for (unsigned i = 0; i < MAX_VERTEX_STREAMS; ++i)
  1743. {
  1744. vertexBuffers_[i] = 0;
  1745. elementMasks_[i] = 0;
  1746. }
  1747. for (unsigned i = 0; i < MAX_TEXTURE_UNITS; ++i)
  1748. {
  1749. textures_[i] = 0;
  1750. textureTypes_[i] = 0;
  1751. }
  1752. for (unsigned i = 0; i < MAX_RENDERTARGETS; ++i)
  1753. renderTargets_[i] = 0;
  1754. depthStencil_ = 0;
  1755. viewport_ = IntRect(0, 0, 0, 0);
  1756. viewTexture_ = 0;
  1757. indexBuffer_ = 0;
  1758. vertexShader_ = 0;
  1759. pixelShader_ = 0;
  1760. shaderProgram_ = 0;
  1761. blendMode_ = BLEND_REPLACE;
  1762. alphaTest_ = false;
  1763. alphaTestMode_ = CMP_ALWAYS;
  1764. alphaRef_ = 0.0f;
  1765. textureAnisotropy_ = 1;
  1766. colorWrite_ = true;
  1767. cullMode_ = CULL_NONE;
  1768. constantDepthBias_ = 0.0f;
  1769. slopeScaledDepthBias_ = 0.0f;
  1770. depthTestMode_ = CMP_ALWAYS;
  1771. depthWrite_ = true;
  1772. fillMode_ = FILL_SOLID;
  1773. scissorTest_ = false;
  1774. scissorRect_ = IntRect::ZERO;
  1775. stencilTest_ = false;
  1776. stencilTestMode_ = CMP_ALWAYS;
  1777. stencilPass_ = OP_KEEP;
  1778. stencilFail_ = OP_KEEP;
  1779. stencilZFail_ = OP_KEEP;
  1780. stencilRef_ = 0;
  1781. stencilMask_ = M_MAX_UNSIGNED;
  1782. impl_->activeTexture_ = 0;
  1783. impl_->drawBuffers_ = M_MAX_UNSIGNED;
  1784. impl_->enabledAttributes_ = 0;
  1785. impl_->fboBound_ = false;
  1786. }
  1787. void Graphics::SetDrawBuffers()
  1788. {
  1789. // Calculate the bit combination of non-zero color rendertargets to first check if the combination changed
  1790. unsigned newDrawBuffers = 0;
  1791. for (unsigned i = 0; i < MAX_RENDERTARGETS; ++i)
  1792. {
  1793. if (renderTargets_[i])
  1794. newDrawBuffers |= 1 << i;
  1795. }
  1796. if (newDrawBuffers == impl_->drawBuffers_)
  1797. return;
  1798. // Check for no color rendertargets (depth rendering only)
  1799. if (!newDrawBuffers)
  1800. glDrawBuffer(GL_NONE);
  1801. else
  1802. {
  1803. int drawBufferIds[4];
  1804. unsigned drawBufferCount = 0;
  1805. for (unsigned i = 0; i < MAX_RENDERTARGETS; ++i)
  1806. {
  1807. if (renderTargets_[i])
  1808. drawBufferIds[drawBufferCount++] = GL_COLOR_ATTACHMENT0_EXT + i;
  1809. }
  1810. glDrawBuffers(drawBufferCount, (const GLenum*)drawBufferIds);
  1811. }
  1812. glReadBuffer(GL_NONE);
  1813. }
  1814. void Graphics::Release()
  1815. {
  1816. diffBuffer_.Reset();
  1817. normalBuffer_.Reset();
  1818. depthBuffer_.Reset();
  1819. screenBuffer_.Reset();
  1820. depthTextures_.Clear();
  1821. // If GPU objects exist ie. it's a context delete/recreate, not Close(), tell them to save and release themselves
  1822. for (Vector<GPUObject*>::Iterator i = gpuObjects_.Begin(); i != gpuObjects_.End(); ++i)
  1823. (*i)->OnDeviceLost();
  1824. if (impl_->fbo_)
  1825. {
  1826. glDeleteFramebuffersEXT(1, &impl_->fbo_);
  1827. impl_->fbo_ = 0;
  1828. }
  1829. // When the new context is initialized, it will have default state again
  1830. ResetCachedState();
  1831. ClearParameterSources();
  1832. }
  1833. void Graphics::InitializeShaderParameters()
  1834. {
  1835. // Map parameter names
  1836. shaderParameters_["CameraPos"] = VSP_CAMERAPOS;
  1837. shaderParameters_["CameraRot"] = VSP_CAMERAROT;
  1838. shaderParameters_["DepthMode"] = VSP_DEPTHMODE;
  1839. shaderParameters_["ElapsedTime"] = VSP_ELAPSEDTIME;
  1840. shaderParameters_["FrustumSize"] = VSP_FRUSTUMSIZE;
  1841. shaderParameters_["GBufferOffsets"] = VSP_GBUFFEROFFSETS;
  1842. shaderParameters_["Model"] = VSP_MODEL;
  1843. shaderParameters_["ShadowProj"] = VSP_SHADOWPROJ;
  1844. shaderParameters_["SpotProj"] = VSP_SPOTPROJ;
  1845. shaderParameters_["ViewProj"] = VSP_VIEWPROJ;
  1846. shaderParameters_["UOffset"] = VSP_UOFFSET;
  1847. shaderParameters_["VOffset"] = VSP_VOFFSET;
  1848. shaderParameters_["ViewRightVector"] = VSP_VIEWRIGHTVECTOR;
  1849. shaderParameters_["ViewUpVector"] = VSP_VIEWUPVECTOR;
  1850. shaderParameters_["SkinMatrices"] = VSP_SKINMATRICES;
  1851. shaderParameters_["AmbientColor"] = PSP_AMBIENTCOLOR;
  1852. shaderParameters_["DepthReconstruct"] = PSP_DEPTHRECONSTRUCT;
  1853. shaderParameters_["EdgeFilterParams"] = PSP_EDGEFILTERPARAMS;
  1854. shaderParameters_["ElapsedTimePS"] = PSP_ELAPSEDTIME;
  1855. shaderParameters_["FogColor"] = PSP_FOGCOLOR;
  1856. shaderParameters_["FogParams"] = PSP_FOGPARAMS;
  1857. shaderParameters_["LightAtten"] = PSP_LIGHTATTEN;
  1858. shaderParameters_["LightColor"] = PSP_LIGHTCOLOR;
  1859. shaderParameters_["LightDir"] = PSP_LIGHTDIR;
  1860. shaderParameters_["LightPos"] = PSP_LIGHTPOS;
  1861. shaderParameters_["LightSplits"] = PSP_LIGHTSPLITS;
  1862. shaderParameters_["LightVecRot"] = PSP_LIGHTVECROT;
  1863. shaderParameters_["MatDiffColor"] = PSP_MATDIFFCOLOR;
  1864. shaderParameters_["MatEmissiveColor"] = PSP_MATEMISSIVECOLOR;
  1865. shaderParameters_["MatSpecProperties"] = PSP_MATSPECPROPERTIES;
  1866. shaderParameters_["SampleOffsets"] = PSP_SAMPLEOFFSETS;
  1867. shaderParameters_["ShadowIntensity"] = PSP_SHADOWINTENSITY;
  1868. shaderParameters_["ShadowProjPS"] = PSP_SHADOWPROJ;
  1869. shaderParameters_["SpotProjPS"] = PSP_SPOTPROJ;
  1870. // Map texture units
  1871. textureUnits_["NormalMap"] = TU_NORMAL;
  1872. textureUnits_["DiffMap"] = TU_DIFFUSE;
  1873. textureUnits_["DiffCubeMap"] = TU_DIFFUSE;
  1874. textureUnits_["SpecMap"] = TU_SPECULAR;
  1875. textureUnits_["EmissiveMap"] = TU_EMISSIVE;
  1876. textureUnits_["DetailMap"] = TU_DETAIL;
  1877. textureUnits_["EnvironmentMap"] = TU_ENVIRONMENT;
  1878. textureUnits_["EnvironmentCubeMap"] = TU_ENVIRONMENT;
  1879. textureUnits_["LightRampMap"] = TU_LIGHTRAMP;
  1880. textureUnits_["LightSpotMap"] = TU_LIGHTSPOT;
  1881. textureUnits_["LightCubeMap"] = TU_LIGHTSPOT;
  1882. textureUnits_["ShadowMap"] = TU_SHADOWMAP;
  1883. textureUnits_["DiffBuffer"] = TU_DIFFBUFFER;
  1884. textureUnits_["NormalBuffer"] = TU_NORMALBUFFER;
  1885. textureUnits_["DepthBuffer"] = TU_DEPTHBUFFER;
  1886. }
  1887. void RegisterGraphicsLibrary(Context* context)
  1888. {
  1889. Animation::RegisterObject(context);
  1890. Material::RegisterObject(context);
  1891. Model::RegisterObject(context);
  1892. Shader::RegisterObject(context);
  1893. Technique::RegisterObject(context);
  1894. Texture2D::RegisterObject(context);
  1895. TextureCube::RegisterObject(context);
  1896. Camera::RegisterObject(context);
  1897. Drawable::RegisterObject(context);
  1898. Light::RegisterObject(context);
  1899. StaticModel::RegisterObject(context);
  1900. Skybox::RegisterObject(context);
  1901. AnimatedModel::RegisterObject(context);
  1902. AnimationController::RegisterObject(context);
  1903. BillboardSet::RegisterObject(context);
  1904. ParticleEmitter::RegisterObject(context);
  1905. DebugRenderer::RegisterObject(context);
  1906. Octree::RegisterObject(context);
  1907. Zone::RegisterObject(context);
  1908. }