OGLGraphics.cpp 78 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589
  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. #include <GLee.h>
  54. #ifdef _MSC_VER
  55. #include <float.h>
  56. #endif
  57. #include "DebugNew.h"
  58. #ifdef _MSC_VER
  59. #pragma warning(disable:4355)
  60. #endif
  61. static const unsigned glCmpFunc[] =
  62. {
  63. GL_ALWAYS,
  64. GL_EQUAL,
  65. GL_NOTEQUAL,
  66. GL_LESS,
  67. GL_LEQUAL,
  68. GL_GREATER,
  69. GL_GEQUAL
  70. };
  71. static const unsigned glSrcBlend[] =
  72. {
  73. GL_ONE,
  74. GL_ONE,
  75. GL_DST_COLOR,
  76. GL_SRC_ALPHA,
  77. GL_SRC_ALPHA,
  78. GL_ONE,
  79. GL_ONE_MINUS_DST_ALPHA
  80. };
  81. static const unsigned glDestBlend[] =
  82. {
  83. GL_ZERO,
  84. GL_ONE,
  85. GL_ZERO,
  86. GL_ONE_MINUS_SRC_ALPHA,
  87. GL_ONE,
  88. GL_ONE_MINUS_SRC_ALPHA,
  89. GL_DST_ALPHA
  90. };
  91. static const unsigned glStencilOps[] =
  92. {
  93. GL_KEEP,
  94. GL_ZERO,
  95. GL_REPLACE,
  96. GL_INCR,
  97. GL_DECR
  98. };
  99. static const String noParameter;
  100. static const DWORD windowStyle = WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX;
  101. static LRESULT CALLBACK wndProc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam);
  102. OBJECTTYPESTATIC(Graphics);
  103. Graphics::Graphics(Context* context_) :
  104. Object(context_),
  105. impl_(new GraphicsImpl()),
  106. mode_(RENDER_FORWARD),
  107. width_(0),
  108. height_(0),
  109. multiSample_(1),
  110. inModeChange_(0),
  111. windowPosX_(0),
  112. windowPosY_(0),
  113. fullscreen_(false),
  114. vsync_(false),
  115. flushGPU_(true),
  116. fullscreenModeSet_(false),
  117. renderTargetSupport_(false),
  118. deferredSupport_(false),
  119. numPrimitives_(0),
  120. numBatches_(0),
  121. immediateVertexCount_(0),
  122. defaultTextureFilterMode_(FILTER_BILINEAR),
  123. shadowMapFormat_(0),
  124. hiresShadowMapFormat_(0),
  125. shaderParameterFrame_(0)
  126. {
  127. ResetCachedState();
  128. InitializeShaderParameters();
  129. SubscribeToEvent(E_WINDOWMESSAGE, HANDLER(Graphics, HandleWindowMessage));
  130. SubscribeToEvent(E_ACTIVATION, HANDLER(Graphics, HandleActivation));
  131. }
  132. Graphics::~Graphics()
  133. {
  134. Close();
  135. delete impl_;
  136. impl_ = 0;
  137. }
  138. void Graphics::MessagePump()
  139. {
  140. MSG msg;
  141. while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
  142. {
  143. TranslateMessage(&msg);
  144. DispatchMessage(&msg);
  145. }
  146. }
  147. void Graphics::SetWindowTitle(const String& windowTitle)
  148. {
  149. windowTitle_ = windowTitle;
  150. if (impl_->window_)
  151. SetWindowText(impl_->window_, windowTitle_.CString());
  152. }
  153. bool Graphics::SetMode(RenderMode mode, int width, int height, bool fullscreen, bool vsync, int multiSample)
  154. {
  155. PROFILE(SetScreenMode);
  156. // If OpenGL extensions not yet initialized, initialize now
  157. InitializeExtensions();
  158. if (!_GLEE_VERSION_2_0)
  159. {
  160. LOGERROR("OpenGL 2.0 is required");
  161. return false;
  162. }
  163. if (multiSample < 1)
  164. multiSample = 1;
  165. // If zero dimensions, use the desktop default
  166. if ((width <= 0) || (height <= 0))
  167. {
  168. if (fullscreen)
  169. {
  170. IntVector2 desktopResolution = impl_->GetDesktopResolution();
  171. width = desktopResolution.x_;
  172. height = desktopResolution.y_;
  173. }
  174. else
  175. {
  176. width = 800;
  177. height = 600;
  178. }
  179. }
  180. if ((mode == mode_) && (width == width_) && (height == height_) && (fullscreen == fullscreen_) && (vsync == vsync_)
  181. && (multiSample == multiSample_))
  182. return true;
  183. if (!impl_->window_)
  184. {
  185. if (!OpenWindow(width, height))
  186. return false;
  187. }
  188. if (!fullscreen_)
  189. {
  190. // Save the window placement if not fullscreen
  191. WINDOWPLACEMENT wndpl;
  192. wndpl.length = sizeof wndpl;
  193. if (SUCCEEDED(GetWindowPlacement(impl_->window_, &wndpl)))
  194. {
  195. windowPosX_ = wndpl.rcNormalPosition.left;
  196. windowPosY_ = wndpl.rcNormalPosition.top;
  197. }
  198. }
  199. // Choose pixel format
  200. int pixelFormat = GetPixelFormat(mode, multiSample);
  201. if (!pixelFormat)
  202. {
  203. LOGERROR("Failed to choose pixel format");
  204. return false;
  205. }
  206. // Check fullscreen mode validity. If not valid, revert to windowed
  207. if (fullscreen)
  208. {
  209. PODVector<IntVector2> resolutions = GetResolutions();
  210. fullscreen = false;
  211. for (unsigned i = 0; i < resolutions.Size(); ++i)
  212. {
  213. if ((width == resolutions[i].x_) && (height == resolutions[i].y_))
  214. {
  215. fullscreen = true;
  216. break;
  217. }
  218. }
  219. }
  220. // Clear any additional depth buffers now, as they are possibly not needed any more
  221. depthTextures_.Clear();
  222. // Create context if not created yet, or if the pixel format or fullscreen mode changes
  223. // (it is not strictly necessary to recreate context just because the fullscreen mode changes, but on some ATI cards
  224. // there seem to be corruption or wrong client area bugs)
  225. if ((!impl_->renderContext_) || (pixelFormat != impl_->pixelFormat_) || (fullscreen != fullscreen_))
  226. {
  227. // Mimic Direct3D way of setting FPU into round-to-nearest, single precision mode
  228. if (!impl_->renderContext_)
  229. {
  230. #ifdef _MSC_VER
  231. _controlfp(_RC_NEAR | _PC_24, _MCW_RC | _MCW_PC);
  232. #endif
  233. }
  234. else
  235. {
  236. // Existing context needs to be destroyed, and the window closed and reopened
  237. Release();
  238. if (!OpenWindow(width, height))
  239. return false;
  240. }
  241. if (SetPixelFormat(impl_->deviceContext_, pixelFormat, 0) == FALSE)
  242. {
  243. LOGERROR("Failed to set pixel format");
  244. return false;
  245. }
  246. impl_->pixelFormat_ = pixelFormat;
  247. impl_->renderContext_ = wglCreateContext(impl_->deviceContext_);
  248. wglMakeCurrent(impl_->deviceContext_, impl_->renderContext_);
  249. LOGINFO("Created OpenGL context");
  250. // Create the FBO if fully supported
  251. if ((_GLEE_EXT_framebuffer_object) && (_GLEE_EXT_packed_depth_stencil))
  252. {
  253. glGenFramebuffersEXT(1, &impl_->fbo_);
  254. // Shadows, render targets and deferred rendering all depend on FBO & packed depth stencil
  255. shadowMapFormat_ = GL_DEPTH_COMPONENT16;
  256. hiresShadowMapFormat_ = GL_DEPTH_COMPONENT24;
  257. renderTargetSupport_ = true;
  258. deferredSupport_ = true;
  259. }
  260. // Set initial state to match Direct3D
  261. glEnable(GL_DEPTH_TEST);
  262. SetCullMode(CULL_CCW);
  263. SetDepthTest(CMP_LESSEQUAL);
  264. }
  265. // Change/restore desktop resolution as necessary
  266. if (fullscreen)
  267. {
  268. if (!SetScreenMode(width, height))
  269. fullscreen = false;
  270. }
  271. else
  272. RestoreScreenMode();
  273. AdjustWindow(width, height, fullscreen);
  274. #ifdef WIN32
  275. if (wglSwapIntervalEXT)
  276. wglSwapIntervalEXT(vsync ? 1 : 0);
  277. #endif
  278. glGetIntegerv(GL_DEPTH_BITS, &impl_->windowDepthBits_);
  279. impl_->depthBits_ = impl_->windowDepthBits_;
  280. width_ = width;
  281. height_ = height;
  282. fullscreen_ = fullscreen;
  283. vsync_ = vsync;
  284. mode_ = mode;
  285. multiSample_ = multiSample;
  286. // Reset rendertargets and viewport for the new screen mode
  287. ResetRenderTargets();
  288. viewTexture_ = 0;
  289. // Get the system depth buffer's bit depth
  290. glGetIntegerv(GL_DEPTH_BITS, &impl_->depthBits_);
  291. // Clear the window to black now, because GPU object restore may take time
  292. Clear(CLEAR_COLOR);
  293. SwapBuffers(impl_->deviceContext_);
  294. // Let GPU objects restore themselves
  295. for (Vector<GPUObject*>::Iterator i = gpuObjects_.Begin(); i != gpuObjects_.End(); ++i)
  296. (*i)->OnDeviceReset();
  297. // Create deferred rendering buffers as necessary
  298. CreateRenderTargets();
  299. if (multiSample > 1)
  300. LOGINFO("Set screen mode " + String(width_) + "x" + String(height_) + " " + (fullscreen_ ? "fullscreen" : "windowed") +
  301. " multisample " + String(multiSample));
  302. else
  303. LOGINFO("Set screen mode " + String(width_) + "x" + String(height_) + " " + (fullscreen_ ? "fullscreen" : "windowed"));
  304. using namespace ScreenMode;
  305. VariantMap eventData;
  306. eventData[P_WIDTH] = width_;
  307. eventData[P_HEIGHT] = height_;
  308. eventData[P_FULLSCREEN] = fullscreen_;
  309. SendEvent(E_SCREENMODE, eventData);
  310. return true;
  311. }
  312. bool Graphics::SetMode(int width, int height)
  313. {
  314. return SetMode(mode_, width, height, fullscreen_, vsync_, multiSample_);
  315. }
  316. bool Graphics::SetMode(RenderMode mode)
  317. {
  318. return SetMode(mode, width_, height_, fullscreen_, vsync_, multiSample_);
  319. }
  320. bool Graphics::ToggleFullscreen()
  321. {
  322. return SetMode(mode_, width_, height_, !fullscreen_, vsync_, multiSample_);
  323. }
  324. void Graphics::Close()
  325. {
  326. // Release all GPU objects that still exist
  327. for (Vector<GPUObject*>::Iterator i = gpuObjects_.Begin(); i != gpuObjects_.End(); ++i)
  328. (*i)->Release();
  329. gpuObjects_.Clear();
  330. Release();
  331. }
  332. bool Graphics::TakeScreenShot(Image& destImage)
  333. {
  334. PROFILE(TakeScreenShot);
  335. ResetRenderTargets();
  336. destImage.SetSize(width_, height_, 3);
  337. glReadPixels(0, 0, width_, height_, GL_RGB, GL_UNSIGNED_BYTE, destImage.GetData());
  338. return true;
  339. }
  340. void Graphics::SetFlushGPU(bool enable)
  341. {
  342. flushGPU_ = enable;
  343. }
  344. bool Graphics::BeginFrame()
  345. {
  346. PROFILE(BeginRendering);
  347. if (!IsInitialized())
  348. return false;
  349. // If we should be fullscreen, but the screen mode is not currently set, do not render
  350. if ((fullscreen_) && (!fullscreenModeSet_))
  351. return false;
  352. // Set default rendertarget and depth buffer
  353. ResetRenderTargets();
  354. viewTexture_ = 0;
  355. // Cleanup textures from previous frame
  356. for (unsigned i = 0; i < MAX_TEXTURE_UNITS; ++i)
  357. SetTexture(i, 0);
  358. // Enable color and depth write
  359. SetColorWrite(true);
  360. SetDepthWrite(true);
  361. numPrimitives_ = 0;
  362. numBatches_ = 0;
  363. SendEvent(E_BEGINRENDER);
  364. return true;
  365. }
  366. void Graphics::EndFrame()
  367. {
  368. PROFILE(EndRendering);
  369. if (!IsInitialized())
  370. return;
  371. SendEvent(E_ENDRENDER);
  372. SwapBuffers(impl_->deviceContext_);
  373. }
  374. void Graphics::Clear(unsigned flags, const Color& color, float depth, unsigned stencil)
  375. {
  376. bool oldColorWrite = colorWrite_;
  377. bool oldDepthWrite = depthWrite_;
  378. if ((flags & CLEAR_COLOR) && (!oldColorWrite))
  379. SetColorWrite(true);
  380. if ((flags & CLEAR_DEPTH) && (!oldDepthWrite))
  381. SetDepthWrite(true);
  382. unsigned glFlags = 0;
  383. if (flags & CLEAR_COLOR)
  384. {
  385. glFlags |= GL_COLOR_BUFFER_BIT;
  386. glClearColor(color.r_, color.g_, color.b_, color.a_);
  387. }
  388. if (flags & CLEAR_DEPTH)
  389. {
  390. glFlags |= GL_DEPTH_BUFFER_BIT;
  391. glClearDepth(depth);
  392. }
  393. if (flags & CLEAR_STENCIL)
  394. {
  395. glFlags |= GL_STENCIL_BUFFER_BIT;
  396. glClearStencil(stencil);
  397. }
  398. glClear(glFlags);
  399. SetColorWrite(oldColorWrite);
  400. SetDepthWrite(oldDepthWrite);
  401. }
  402. void Graphics::Draw(PrimitiveType type, unsigned vertexStart, unsigned vertexCount)
  403. {
  404. if (!vertexCount)
  405. return;
  406. unsigned primitiveCount = 0;
  407. switch (type)
  408. {
  409. case TRIANGLE_LIST:
  410. primitiveCount = vertexCount / 3;
  411. glDrawArrays(GL_TRIANGLES, vertexStart, vertexCount);
  412. break;
  413. case LINE_LIST:
  414. primitiveCount = vertexCount / 2;
  415. glDrawArrays(GL_LINES, vertexStart, vertexCount);
  416. break;
  417. }
  418. numPrimitives_ += primitiveCount;
  419. ++numBatches_;
  420. }
  421. void Graphics::Draw(PrimitiveType type, unsigned indexStart, unsigned indexCount, unsigned minVertex, unsigned vertexCount)
  422. {
  423. if ((!indexCount) || (!indexBuffer_))
  424. return;
  425. unsigned primitiveCount = 0;
  426. unsigned indexSize = indexBuffer_->GetIndexSize();
  427. switch (type)
  428. {
  429. case TRIANGLE_LIST:
  430. primitiveCount = indexCount / 3;
  431. if (indexSize == sizeof(unsigned short))
  432. glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_SHORT, (const GLvoid*)(indexStart * indexSize));
  433. else
  434. glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, (const GLvoid*)(indexStart * indexSize));
  435. break;
  436. case LINE_LIST:
  437. primitiveCount = indexCount / 2;
  438. if (indexSize == sizeof(unsigned short))
  439. glDrawElements(GL_LINES, indexCount, GL_UNSIGNED_SHORT, (const GLvoid*)(indexStart * indexSize));
  440. else
  441. glDrawElements(GL_LINES, indexCount, GL_UNSIGNED_INT, (const GLvoid*)(indexStart * indexSize));
  442. break;
  443. }
  444. numPrimitives_ += primitiveCount;
  445. ++numBatches_;
  446. }
  447. void Graphics::DrawInstanced(PrimitiveType type, unsigned indexStart, unsigned indexCount, unsigned minVertex, unsigned vertexCount, unsigned instanceCount)
  448. {
  449. }
  450. void Graphics::SetVertexBuffer(VertexBuffer* buffer)
  451. {
  452. Vector<VertexBuffer*> vertexBuffers(1);
  453. PODVector<unsigned> elementMasks(1);
  454. vertexBuffers[0] = buffer;
  455. elementMasks[0] = MASK_DEFAULT;
  456. SetVertexBuffers(vertexBuffers, elementMasks);
  457. }
  458. bool Graphics::SetVertexBuffers(const Vector<VertexBuffer*>& buffers, const PODVector<unsigned>& elementMasks,
  459. unsigned instanceOffset)
  460. {
  461. if (buffers.Size() > MAX_VERTEX_STREAMS)
  462. {
  463. LOGERROR("Too many vertex buffers");
  464. return false;
  465. }
  466. if (buffers.Size() != elementMasks.Size())
  467. {
  468. LOGERROR("Amount of element masks and vertex buffers does not match");
  469. return false;
  470. }
  471. // If no valid shader to determine the attribute bindings, can not set vertex buffers
  472. if (!shaderProgram_)
  473. return false;
  474. const int* attributeLocations = shaderProgram_->GetAttributeLocations();
  475. bool changed = false;
  476. unsigned newAttributes = 0;
  477. for (unsigned i = 0; i < MAX_VERTEX_STREAMS; ++i)
  478. {
  479. VertexBuffer* buffer = 0;
  480. unsigned elementMask = 0;
  481. if (i < buffers.Size())
  482. {
  483. buffer = buffers[i];
  484. elementMask = elementMasks[i];
  485. if ((elementMask == MASK_DEFAULT) && (buffer))
  486. elementMask = buffers[i]->GetElementMask();
  487. }
  488. // If buffer and element mask have stayed the same, skip to the next buffer
  489. if ((buffer == vertexBuffers_[i]) && (elementMask == elementMasks_[i]))
  490. continue;
  491. vertexBuffers_[i] = buffer;
  492. elementMasks_[i] = elementMask;
  493. changed = true;
  494. if (!buffer)
  495. continue;
  496. glBindBuffer(GL_ARRAY_BUFFER, buffer->GetGPUObject());
  497. unsigned vertexSize = buffer->GetVertexSize();
  498. for (unsigned j = 0; j < MAX_VERTEX_ELEMENTS; ++j)
  499. {
  500. // If shader does not use the attribute, do not bind it (bandwidth optimization)
  501. int attributeIndex = attributeLocations[j];
  502. if (attributeIndex < 0)
  503. continue;
  504. unsigned elementBit = 1 << j;
  505. unsigned attributeBit = 1 << attributeIndex;
  506. if (elementMask & elementBit)
  507. {
  508. newAttributes |= attributeBit;
  509. // Enable attribute if not enabled yet
  510. if ((impl_->enabledAttributes_ & attributeBit) == 0)
  511. {
  512. glEnableVertexAttribArray(attributeIndex);
  513. impl_->enabledAttributes_ |= attributeBit;
  514. }
  515. // Set the attribute pointer
  516. glVertexAttribPointer(attributeIndex, VertexBuffer::elementComponents[j], VertexBuffer::elementType[j],
  517. VertexBuffer::elementNormalize[j], vertexSize, (const GLvoid*)(buffer->GetElementOffset((VertexElement)j)));
  518. }
  519. }
  520. }
  521. if (!changed)
  522. return true;
  523. // Now check which vertex attributes should be disabled
  524. unsigned disableAttributes = impl_->enabledAttributes_ & (~newAttributes);
  525. int disableIndex = 0;
  526. while (disableAttributes)
  527. {
  528. if (disableAttributes & 1)
  529. {
  530. glDisableVertexAttribArray(disableIndex);
  531. impl_->enabledAttributes_ &= ~(1 << disableIndex);
  532. }
  533. disableAttributes >>= 1;
  534. ++disableIndex;
  535. }
  536. return true;
  537. }
  538. bool Graphics::SetVertexBuffers(const Vector<SharedPtr<VertexBuffer> >& buffers, const PODVector<unsigned>&
  539. elementMasks, unsigned instanceOffset)
  540. {
  541. if (buffers.Size() > MAX_VERTEX_STREAMS)
  542. {
  543. LOGERROR("Too many vertex buffers");
  544. return false;
  545. }
  546. if (buffers.Size() != elementMasks.Size())
  547. {
  548. LOGERROR("Amount of element masks and vertex buffers does not match");
  549. return false;
  550. }
  551. // If no valid shader to determine the attribute bindings, can not set vertex buffers
  552. if (!shaderProgram_)
  553. return false;
  554. const int* attributeLocations = shaderProgram_->GetAttributeLocations();
  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())
  562. {
  563. buffer = buffers[i];
  564. elementMask = elementMasks[i];
  565. if ((elementMask == MASK_DEFAULT) && (buffer))
  566. elementMask = buffers[i]->GetElementMask();
  567. }
  568. // If buffer and element mask have stayed the same, skip to the next buffer
  569. if ((buffer == vertexBuffers_[i]) && (elementMask == elementMasks_[i]))
  570. continue;
  571. vertexBuffers_[i] = buffer;
  572. elementMasks_[i] = elementMask;
  573. changed = true;
  574. if (!buffer)
  575. continue;
  576. glBindBuffer(GL_ARRAY_BUFFER, buffer->GetGPUObject());
  577. unsigned vertexSize = buffer->GetVertexSize();
  578. for (unsigned j = 0; j < MAX_VERTEX_ELEMENTS; ++j)
  579. {
  580. // If shader does not use the attribute, do not bind it (bandwidth optimization)
  581. int attributeIndex = attributeLocations[j];
  582. if (attributeIndex < 0)
  583. continue;
  584. unsigned elementBit = 1 << j;
  585. unsigned attributeBit = 1 << attributeIndex;
  586. if (elementMask & elementBit)
  587. {
  588. newAttributes |= attributeBit;
  589. // Enable attribute if not enabled yet
  590. if ((impl_->enabledAttributes_ & attributeBit) == 0)
  591. {
  592. glEnableVertexAttribArray(attributeIndex);
  593. impl_->enabledAttributes_ |= attributeBit;
  594. }
  595. // Set the attribute pointer
  596. glVertexAttribPointer(attributeIndex, VertexBuffer::elementComponents[j], VertexBuffer::elementType[j],
  597. VertexBuffer::elementNormalize[j], vertexSize, (const GLvoid*)(buffer->GetElementOffset((VertexElement)j)));
  598. }
  599. }
  600. }
  601. if (!changed)
  602. return true;
  603. // Now check which vertex attributes should be disabled
  604. unsigned disableAttributes = impl_->enabledAttributes_ & (~newAttributes);
  605. int disableIndex = 0;
  606. while (disableAttributes)
  607. {
  608. if (disableAttributes & 1)
  609. {
  610. glDisableVertexAttribArray(disableIndex);
  611. impl_->enabledAttributes_ &= ~(1 << disableIndex);
  612. }
  613. disableAttributes >>= 1;
  614. ++disableIndex;
  615. }
  616. return true;
  617. }
  618. void Graphics::SetIndexBuffer(IndexBuffer* buffer)
  619. {
  620. if (indexBuffer_ == buffer)
  621. return;
  622. if (buffer)
  623. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer->GetGPUObject());
  624. else
  625. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  626. indexBuffer_ = buffer;
  627. }
  628. void Graphics::SetShaders(ShaderVariation* vs, ShaderVariation* ps)
  629. {
  630. if ((vs == vertexShader_) && (ps == pixelShader_))
  631. return;
  632. // Compile the shaders now if not yet compiled. If already attempted, do not retry
  633. if ((vs) && (!vs->IsCompiled()))
  634. {
  635. if (vs->GetCompilerOutput().Empty())
  636. {
  637. PROFILE(CompileVertexShader);
  638. bool success = vs->Create();
  639. if (success)
  640. LOGDEBUG("Compiled vertex shader " + vs->GetName());
  641. else
  642. {
  643. LOGERROR("Failed to compile vertex shader " + vs->GetName() + ":\n" + vs->GetCompilerOutput());
  644. vs = 0;
  645. }
  646. }
  647. else
  648. vs = 0;
  649. }
  650. if ((ps) && (!ps->IsCompiled()))
  651. {
  652. if (ps->GetCompilerOutput().Empty())
  653. {
  654. PROFILE(CompilePixelShader);
  655. bool success = ps->Create();
  656. if (success)
  657. LOGDEBUG("Compiled pixel shader " + ps->GetName());
  658. else
  659. {
  660. LOGERROR("Failed to compile pixel shader " + ps->GetName() + ":\n" + ps->GetCompilerOutput());
  661. ps = 0;
  662. }
  663. }
  664. else
  665. ps = 0;
  666. }
  667. for (unsigned i = 0; i < MAX_VERTEX_STREAMS; ++i)
  668. {
  669. vertexBuffers_[i] = 0;
  670. elementMasks_[i] = 0;
  671. }
  672. if ((!vs) || (!ps))
  673. {
  674. glUseProgram(0);
  675. vertexShader_ = 0;
  676. pixelShader_ = 0;
  677. shaderProgram_ = 0;
  678. }
  679. else
  680. {
  681. vertexShader_ = vs;
  682. pixelShader_ = ps;
  683. Pair<ShaderVariation*, ShaderVariation*> combination(vs, ps);
  684. ShaderProgramMap::Iterator i = shaderPrograms_.Find(combination);
  685. if (i != shaderPrograms_.End())
  686. {
  687. // Use the existing linked program
  688. if (i->second_->IsLinked())
  689. {
  690. glUseProgram(i->second_->GetGPUObject());
  691. shaderProgram_ = i->second_;
  692. }
  693. else
  694. {
  695. glUseProgram(0);
  696. shaderProgram_ = 0;
  697. }
  698. }
  699. else
  700. {
  701. // Link a new combination
  702. SharedPtr<ShaderProgram> newProgram(new ShaderProgram(this, vs, ps));
  703. if (newProgram->Link())
  704. {
  705. LOGDEBUG("Linked vertex shader " + vs->GetName() + " and pixel shader " + ps->GetName());
  706. // Note: Link() calls glUseProgram() to set the texture sampler uniforms,
  707. // so it is not necessary to call it again
  708. shaderProgram_ = newProgram;
  709. }
  710. else
  711. {
  712. LOGERROR("Failed to link vertex shader " + vs->GetName() + " and pixel shader " + ps->GetName() + ":\n" +
  713. newProgram->GetLinkerOutput());
  714. glUseProgram(0);
  715. shaderProgram_ = 0;
  716. }
  717. shaderPrograms_[combination] = newProgram;
  718. }
  719. }
  720. }
  721. void Graphics::SetShaderParameter(ShaderParameter param, const bool* data, unsigned count)
  722. {
  723. // Not supported
  724. }
  725. void Graphics::SetShaderParameter(ShaderParameter param, const float* data, unsigned count)
  726. {
  727. if (shaderProgram_)
  728. {
  729. const UniformInfo* info = shaderProgram_->GetUniformInfo(param);
  730. if (info)
  731. {
  732. switch (info->type_)
  733. {
  734. case GL_FLOAT:
  735. glUniform1fv(info->location_, count, data);
  736. break;
  737. case GL_FLOAT_VEC2:
  738. glUniform2fv(info->location_, count / 2, data);
  739. break;
  740. case GL_FLOAT_VEC3:
  741. glUniform3fv(info->location_, count / 3, data);
  742. break;
  743. case GL_FLOAT_VEC4:
  744. glUniform4fv(info->location_, count / 4, data);
  745. break;
  746. case GL_FLOAT_MAT3:
  747. glUniformMatrix3fv(info->location_, count / 9, GL_TRUE, data);
  748. break;
  749. case GL_FLOAT_MAT4:
  750. glUniformMatrix4fv(info->location_, count / 16, GL_TRUE, data);
  751. break;
  752. }
  753. }
  754. }
  755. }
  756. void Graphics::SetShaderParameter(ShaderParameter param, const int* data, unsigned count)
  757. {
  758. if (shaderProgram_)
  759. {
  760. const UniformInfo* info = shaderProgram_->GetUniformInfo(param);
  761. if (info)
  762. {
  763. switch (info->type_)
  764. {
  765. case GL_INT:
  766. glUniform1iv(info->location_, count, data);
  767. break;
  768. case GL_INT_VEC2:
  769. glUniform2iv(info->location_, count / 2, data);
  770. break;
  771. case GL_INT_VEC3:
  772. glUniform3iv(info->location_, count / 3, data);
  773. break;
  774. case GL_INT_VEC4:
  775. glUniform4iv(info->location_, count / 4, data);
  776. break;
  777. }
  778. }
  779. }
  780. }
  781. void Graphics::SetShaderParameter(ShaderParameter param, float value)
  782. {
  783. if (shaderProgram_)
  784. {
  785. const UniformInfo* info = shaderProgram_->GetUniformInfo(param);
  786. if (info)
  787. glUniform1fv(info->location_, 1, &value);
  788. }
  789. }
  790. void Graphics::SetShaderParameter(ShaderParameter param, const Color& color)
  791. {
  792. SetShaderParameter(param, color.GetData(), 4);
  793. }
  794. void Graphics::SetShaderParameter(ShaderParameter param, const Matrix3& matrix)
  795. {
  796. if (shaderProgram_)
  797. {
  798. const UniformInfo* info = shaderProgram_->GetUniformInfo(param);
  799. if (info)
  800. glUniformMatrix3fv(info->location_, 1, GL_TRUE, matrix.GetData());
  801. }
  802. }
  803. void Graphics::SetShaderParameter(ShaderParameter param, const Vector3& vector)
  804. {
  805. if (shaderProgram_)
  806. {
  807. const UniformInfo* info = shaderProgram_->GetUniformInfo(param);
  808. if (info)
  809. {
  810. // Check the uniform type to avoid mismatch
  811. switch (info->type_)
  812. {
  813. case GL_FLOAT:
  814. glUniform1fv(info->location_, 1, vector.GetData());
  815. break;
  816. case GL_FLOAT_VEC2:
  817. glUniform2fv(info->location_, 1, vector.GetData());
  818. break;
  819. case GL_FLOAT_VEC3:
  820. glUniform3fv(info->location_, 1, vector.GetData());
  821. break;
  822. }
  823. }
  824. }
  825. }
  826. void Graphics::SetShaderParameter(ShaderParameter param, const Matrix4& matrix)
  827. {
  828. if (shaderProgram_)
  829. {
  830. const UniformInfo* info = shaderProgram_->GetUniformInfo(param);
  831. if (info)
  832. glUniformMatrix4fv(info->location_, 1, GL_TRUE, matrix.GetData());
  833. }
  834. }
  835. void Graphics::SetShaderParameter(ShaderParameter param, const Vector4& vector)
  836. {
  837. if (shaderProgram_)
  838. {
  839. const UniformInfo* info = shaderProgram_->GetUniformInfo(param);
  840. if (info)
  841. {
  842. // Check the uniform type to avoid mismatch
  843. switch (info->type_)
  844. {
  845. case GL_FLOAT:
  846. glUniform1fv(info->location_, 1, vector.GetData());
  847. break;
  848. case GL_FLOAT_VEC2:
  849. glUniform2fv(info->location_, 1, vector.GetData());
  850. break;
  851. case GL_FLOAT_VEC3:
  852. glUniform3fv(info->location_, 1, vector.GetData());
  853. break;
  854. case GL_FLOAT_VEC4:
  855. glUniform4fv(info->location_, 1, vector.GetData());
  856. break;
  857. }
  858. }
  859. }
  860. }
  861. void Graphics::SetShaderParameter(ShaderParameter param, const Matrix3x4& matrix)
  862. {
  863. if (shaderProgram_)
  864. {
  865. const UniformInfo* info = shaderProgram_->GetUniformInfo(param);
  866. if (info)
  867. {
  868. float data[16];
  869. data[0] = matrix.m00_;
  870. data[1] = matrix.m01_;
  871. data[2] = matrix.m02_;
  872. data[3] = matrix.m03_;
  873. data[4] = matrix.m10_;
  874. data[5] = matrix.m11_;
  875. data[6] = matrix.m12_;
  876. data[7] = matrix.m13_;
  877. data[8] = matrix.m20_;
  878. data[9] = matrix.m21_;
  879. data[10] = matrix.m22_;
  880. data[11] = matrix.m23_;
  881. data[12] = 0.0f;
  882. data[13] = 0.0f;
  883. data[14] = 0.0f;
  884. data[15] = 1.0f;
  885. glUniformMatrix4fv(info->location_, 1, GL_TRUE, data);
  886. }
  887. }
  888. }
  889. bool Graphics::NeedParameterUpdate(ShaderParameter param, const void* source)
  890. {
  891. if (shaderProgram_)
  892. return shaderProgram_->NeedParameterUpdate(param, source, shaderParameterFrame_);
  893. return false;
  894. }
  895. bool Graphics::NeedTextureUnit(TextureUnit unit)
  896. {
  897. if ((shaderProgram_) && (shaderProgram_->HasTextureUnit(unit)))
  898. return true;
  899. return false;
  900. }
  901. void Graphics::ClearParameterSources()
  902. {
  903. ++shaderParameterFrame_;
  904. }
  905. void Graphics::ClearTransformSources()
  906. {
  907. if (shaderProgram_)
  908. {
  909. shaderProgram_->ClearParameterSource(VSP_MODEL);
  910. shaderProgram_->ClearParameterSource(VSP_VIEWPROJ);
  911. }
  912. }
  913. void Graphics::CleanupShaderPrograms()
  914. {
  915. for (ShaderProgramMap::Iterator i = shaderPrograms_.Begin(); i != shaderPrograms_.End();)
  916. {
  917. ShaderProgramMap::Iterator current = i++;
  918. ShaderVariation* vs = current->second_->GetVertexShader();
  919. ShaderVariation* ps = current->second_->GetPixelShader();
  920. if ((!vs) || (!ps) || (!vs->GetGPUObject()) || (!ps->GetGPUObject()))
  921. shaderPrograms_.Erase(current);
  922. }
  923. }
  924. void Graphics::SetTexture(unsigned index, Texture* texture)
  925. {
  926. if (index >= MAX_TEXTURE_UNITS)
  927. return;
  928. // Check if texture is currently bound as a render target. In that case, use its backup texture, or blank if not defined
  929. if (texture)
  930. {
  931. if ((renderTargets_[0]) && (renderTargets_[0]->GetParentTexture() == texture))
  932. texture = texture->GetBackupTexture();
  933. // Check also for the view texture, in case a specific rendering pass does not bind the destination render target,
  934. // but should still not sample it either
  935. else if (texture == viewTexture_)
  936. texture = texture->GetBackupTexture();
  937. }
  938. if (textures_[index] != texture)
  939. {
  940. if (impl_->activeTexture_ != index)
  941. {
  942. glActiveTexture(GL_TEXTURE0 + index);
  943. impl_->activeTexture_ = index;
  944. }
  945. if (texture)
  946. {
  947. unsigned glType = texture->GetTarget();
  948. if (glType != textureTypes_[index])
  949. {
  950. if (textureTypes_[index])
  951. glDisable(textureTypes_[index]);
  952. glEnable(glType);
  953. textureTypes_[index] = glType;
  954. }
  955. glBindTexture(glType, texture->GetGPUObject());
  956. if (texture->GetParametersDirty())
  957. texture->UpdateParameters();
  958. }
  959. else
  960. {
  961. if (textureTypes_[index])
  962. glBindTexture(textureTypes_[index], 0);
  963. }
  964. textures_[index] = texture;
  965. }
  966. else
  967. {
  968. if ((texture) && (texture->GetParametersDirty()))
  969. {
  970. if (impl_->activeTexture_ != index)
  971. {
  972. glActiveTexture(GL_TEXTURE0 + index);
  973. impl_->activeTexture_ = index;
  974. }
  975. glBindTexture(texture->GetTarget(), texture->GetGPUObject());
  976. texture->UpdateParameters();
  977. }
  978. }
  979. }
  980. void Graphics::SetTextureForUpdate(Texture* texture)
  981. {
  982. if (impl_->activeTexture_ != 0)
  983. {
  984. glActiveTexture(GL_TEXTURE0);
  985. impl_->activeTexture_ = 0;
  986. }
  987. glBindTexture(texture->GetTarget(), texture->GetGPUObject());
  988. textures_[0] = texture;
  989. }
  990. void Graphics::SetDefaultTextureFilterMode(TextureFilterMode mode)
  991. {
  992. if (mode != defaultTextureFilterMode_)
  993. {
  994. defaultTextureFilterMode_ = mode;
  995. SetTextureParametersDirty();
  996. }
  997. }
  998. void Graphics::SetTextureAnisotropy(unsigned level)
  999. {
  1000. if (level != textureAnisotropy_)
  1001. {
  1002. textureAnisotropy_ = level;
  1003. SetTextureParametersDirty();
  1004. }
  1005. }
  1006. void Graphics::SetTextureParametersDirty()
  1007. {
  1008. for (Vector<GPUObject*>::Iterator i = gpuObjects_.Begin(); i != gpuObjects_.End(); ++i)
  1009. {
  1010. Texture* texture = dynamic_cast<Texture*>(*i);
  1011. if (texture)
  1012. texture->SetParametersDirty();
  1013. }
  1014. }
  1015. void Graphics::ResetRenderTargets()
  1016. {
  1017. for (unsigned i = 0; i < MAX_RENDERTARGETS; ++i)
  1018. SetRenderTarget(i, (RenderSurface*)0);
  1019. SetDepthStencil((RenderSurface*)0);
  1020. }
  1021. void Graphics::ResetRenderTarget(unsigned index)
  1022. {
  1023. SetRenderTarget(index, (RenderSurface*)0);
  1024. }
  1025. void Graphics::ResetDepthStencil()
  1026. {
  1027. SetDepthStencil((RenderSurface*)0);
  1028. }
  1029. void Graphics::SetRenderTarget(unsigned index, RenderSurface* renderTarget)
  1030. {
  1031. if ((index >= MAX_RENDERTARGETS) || (!impl_->fbo_))
  1032. return;
  1033. if (renderTarget != renderTargets_[index])
  1034. {
  1035. renderTargets_[index] = renderTarget;
  1036. // If the rendertarget is also bound as a texture, replace with backup texture or null
  1037. if (renderTarget)
  1038. {
  1039. Texture* parentTexture = renderTarget->GetParentTexture();
  1040. for (unsigned i = 0; i < MAX_TEXTURE_UNITS; ++i)
  1041. {
  1042. if (textures_[i] == parentTexture)
  1043. SetTexture(i, textures_[i]->GetBackupTexture());
  1044. }
  1045. }
  1046. // Bind the FBO to be able to make changes to it
  1047. if (!impl_->fboBound_)
  1048. {
  1049. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, impl_->fbo_);
  1050. impl_->fboBound_ = true;
  1051. }
  1052. if (renderTarget)
  1053. {
  1054. Texture* texture = renderTarget->GetParentTexture();
  1055. // If texture's parameters are dirty, update before attaching
  1056. if (texture->GetParametersDirty())
  1057. {
  1058. SetTextureForUpdate(texture);
  1059. texture->UpdateParameters();
  1060. SetTexture(0, 0);
  1061. }
  1062. glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + index, renderTarget->GetTarget(), texture->GetGPUObject(), 0);
  1063. }
  1064. else
  1065. glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + index, GL_TEXTURE_2D, 0, 0);
  1066. // Disable color buffer writing/reading if only a depth texture is to be used:
  1067. // otherwise it is an OpenGL error (incomplete framebuffer)
  1068. SetDrawBuffers();
  1069. // If all rendertargets and the depth buffer are not textures, revert to backbuffer rendering
  1070. bool noFBO = (depthStencil_ == 0);
  1071. for (unsigned i = 0; i < MAX_RENDERTARGETS; ++i)
  1072. {
  1073. if (renderTargets_[i])
  1074. {
  1075. noFBO = false;
  1076. break;
  1077. }
  1078. }
  1079. if ((noFBO) && (impl_->fboBound_))
  1080. {
  1081. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  1082. impl_->fboBound_ = false;
  1083. }
  1084. }
  1085. }
  1086. void Graphics::SetRenderTarget(unsigned index, Texture2D* renderTexture)
  1087. {
  1088. RenderSurface* renderTarget = 0;
  1089. if (renderTexture)
  1090. renderTarget = renderTexture->GetRenderSurface();
  1091. SetRenderTarget(index, renderTarget);
  1092. }
  1093. void Graphics::SetDepthStencil(RenderSurface* depthStencil)
  1094. {
  1095. if ((impl_->fbo_) && (depthStencil != depthStencil_))
  1096. {
  1097. // If we are using a rendertarget texture, it is required in OpenGL to also have an own depth stencil
  1098. // Create a new depth stencil texture as necessary to be able to provide similar behaviour.
  1099. if ((renderTargets_[0]) && (!depthStencil))
  1100. {
  1101. int width = renderTargets_[0]->GetWidth();
  1102. int height = renderTargets_[0]->GetHeight();
  1103. int searchKey = (width << 16) | height;
  1104. HashMap<int, SharedPtr<Texture2D> >::Iterator i = depthTextures_.Find(searchKey);
  1105. if (i != depthTextures_.End())
  1106. depthStencil = i->second_->GetRenderSurface();
  1107. else
  1108. {
  1109. SharedPtr<Texture2D> newDepthTexture(new Texture2D(context_));
  1110. newDepthTexture->SetSize(width, height, GetDepthStencilFormat(), TEXTURE_DEPTHSTENCIL);
  1111. depthTextures_[searchKey] = newDepthTexture;
  1112. depthStencil = newDepthTexture->GetRenderSurface();
  1113. }
  1114. }
  1115. /// \todo Should check that the texture actually is in depth format
  1116. depthStencil_ = depthStencil;
  1117. // Bind the FBO to be able to make changes to it
  1118. if (!impl_->fboBound_)
  1119. {
  1120. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, impl_->fbo_);
  1121. impl_->fboBound_ = true;
  1122. }
  1123. if (depthStencil)
  1124. {
  1125. // Bind either a renderbuffer or a depth texture, depending on what is available
  1126. unsigned renderBufferID = depthStencil->GetRenderBuffer();
  1127. if (!renderBufferID)
  1128. {
  1129. Texture* texture = depthStencil->GetParentTexture();
  1130. // If texture's parameters are dirty, update before attaching
  1131. if (texture->GetParametersDirty())
  1132. {
  1133. SetTextureForUpdate(texture);
  1134. texture->UpdateParameters();
  1135. SetTexture(0, 0);
  1136. }
  1137. glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, texture->GetGPUObject(), 0);
  1138. glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0);
  1139. impl_->depthBits_ = texture->GetDepthBits();
  1140. }
  1141. else
  1142. {
  1143. glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, renderBufferID);
  1144. glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, renderBufferID);
  1145. impl_->depthBits_ = 24;
  1146. }
  1147. }
  1148. else
  1149. {
  1150. glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0);
  1151. glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0);
  1152. impl_->depthBits_ = impl_->windowDepthBits_;
  1153. }
  1154. // Disable color buffer writing/reading if only a depth texture is to be used:
  1155. // otherwise it is an OpenGL error (incomplete framebuffer)
  1156. SetDrawBuffers();
  1157. // If all rendertargets and the depth buffer are not textures, revert to backbuffer rendering
  1158. bool noFBO = (depthStencil_ == 0);
  1159. for (unsigned i = 0; i < MAX_RENDERTARGETS; ++i)
  1160. {
  1161. if (renderTargets_[i])
  1162. {
  1163. noFBO = false;
  1164. break;
  1165. }
  1166. }
  1167. if ((noFBO) && (impl_->fboBound_))
  1168. {
  1169. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  1170. impl_->fboBound_ = false;
  1171. }
  1172. }
  1173. // Reset viewport and scissor test
  1174. IntVector2 viewSize = GetRenderTargetDimensions();
  1175. SetViewport(IntRect(0, 0, viewSize.x_, viewSize.y_));
  1176. SetScissorTest(false);
  1177. }
  1178. void Graphics::SetDepthStencil(Texture2D* depthTexture)
  1179. {
  1180. RenderSurface* depthStencil = 0;
  1181. if (depthTexture)
  1182. depthStencil = depthTexture->GetRenderSurface();
  1183. SetDepthStencil(depthStencil);
  1184. }
  1185. void Graphics::SetViewport(const IntRect& rect)
  1186. {
  1187. IntVector2 rtSize = GetRenderTargetDimensions();
  1188. IntRect rectCopy = rect;
  1189. if (rectCopy.right_ <= rectCopy.left_)
  1190. rectCopy.right_ = rectCopy.left_ + 1;
  1191. if (rectCopy.bottom_ <= rectCopy.top_)
  1192. rectCopy.bottom_ = rectCopy.top_ + 1;
  1193. rectCopy.left_ = Clamp(rectCopy.left_, 0, rtSize.x_);
  1194. rectCopy.top_ = Clamp(rectCopy.top_, 0, rtSize.y_);
  1195. rectCopy.right_ = Clamp(rectCopy.right_, 0, rtSize.x_);
  1196. rectCopy.bottom_ = Clamp(rectCopy.bottom_, 0, rtSize.y_);
  1197. if (rectCopy != viewport_)
  1198. {
  1199. // Use Direct3D convention with the vertical coordinates ie. 0 is top
  1200. glViewport(rectCopy.left_, rtSize.y_ - rectCopy.bottom_, rectCopy.right_ - rectCopy.left_, rectCopy.bottom_ - rectCopy.top_);
  1201. viewport_ = rectCopy;
  1202. }
  1203. // Disable scissor test, needs to be re-enabled by the user
  1204. SetScissorTest(false);
  1205. }
  1206. void Graphics::SetViewTexture(Texture* texture)
  1207. {
  1208. viewTexture_ = texture;
  1209. // Check for the view texture being currently bound
  1210. if (texture)
  1211. {
  1212. for (unsigned i = 0; i < MAX_TEXTURE_UNITS; ++i)
  1213. {
  1214. if (textures_[i] == texture)
  1215. SetTexture(i, textures_[i]->GetBackupTexture());
  1216. }
  1217. }
  1218. }
  1219. void Graphics::SetAlphaTest(bool enable, CompareMode mode, float alphaRef)
  1220. {
  1221. if (enable != alphaTest_)
  1222. {
  1223. if (enable)
  1224. glEnable(GL_ALPHA_TEST);
  1225. else
  1226. glDisable(GL_ALPHA_TEST);
  1227. alphaTest_ = enable;
  1228. }
  1229. if (enable)
  1230. {
  1231. alphaRef = Clamp(alphaRef, 0.0f, 1.0f);
  1232. if ((mode != alphaTestMode_) || (alphaRef != alphaRef_))
  1233. {
  1234. glAlphaFunc(glCmpFunc[mode], alphaRef);
  1235. alphaTestMode_ = mode;
  1236. alphaRef_ = alphaRef;
  1237. }
  1238. }
  1239. }
  1240. void Graphics::SetBlendMode(BlendMode mode)
  1241. {
  1242. if (mode != blendMode_)
  1243. {
  1244. if (mode == BLEND_REPLACE)
  1245. glDisable(GL_BLEND);
  1246. else
  1247. {
  1248. glEnable(GL_BLEND);
  1249. glBlendFunc(glSrcBlend[mode], glDestBlend[mode]);
  1250. }
  1251. blendMode_ = mode;
  1252. }
  1253. }
  1254. void Graphics::SetColorWrite(bool enable)
  1255. {
  1256. if (enable != colorWrite_)
  1257. {
  1258. if (enable)
  1259. glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  1260. else
  1261. glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
  1262. colorWrite_ = enable;
  1263. }
  1264. }
  1265. void Graphics::SetCullMode(CullMode mode)
  1266. {
  1267. if (mode != cullMode_)
  1268. {
  1269. if (mode == CULL_NONE)
  1270. glDisable(GL_CULL_FACE);
  1271. else
  1272. {
  1273. // Use Direct3D convention, ie. clockwise vertices define a front face
  1274. glEnable(GL_CULL_FACE);
  1275. glCullFace(mode == CULL_CCW ? GL_FRONT : GL_BACK);
  1276. }
  1277. cullMode_ = mode;
  1278. }
  1279. }
  1280. void Graphics::SetDepthBias(float constantBias, float slopeScaledBias)
  1281. {
  1282. if ((constantBias != constantDepthBias_) || (slopeScaledBias != slopeScaledDepthBias_))
  1283. {
  1284. if ((constantBias != 0.0f) || (slopeScaledBias != 0.0f))
  1285. {
  1286. // Bring the constant bias from Direct3D9 scale to OpenGL (depends on depth buffer bitdepth)
  1287. // Zero depth bits may be returned if using the packed depth stencil format. Assume 24bit in that case
  1288. int depthBits = min(impl_->depthBits_, 23);
  1289. if (!depthBits)
  1290. depthBits = 23;
  1291. float adjustedConstantBias = constantBias * (float)(1 << (depthBits - 1));
  1292. float adjustedSlopeScaledBias = slopeScaledBias + 1.0f;
  1293. glEnable(GL_POLYGON_OFFSET_FILL);
  1294. glEnable(GL_POLYGON_OFFSET_LINE);
  1295. glPolygonOffset(adjustedSlopeScaledBias, adjustedConstantBias);
  1296. }
  1297. else
  1298. {
  1299. glDisable(GL_POLYGON_OFFSET_FILL);
  1300. glDisable(GL_POLYGON_OFFSET_LINE);
  1301. }
  1302. constantDepthBias_ = constantBias;
  1303. slopeScaledDepthBias_ = slopeScaledBias;
  1304. }
  1305. }
  1306. void Graphics::SetDepthTest(CompareMode mode)
  1307. {
  1308. if (mode != depthTestMode_)
  1309. {
  1310. glDepthFunc(glCmpFunc[mode]);
  1311. depthTestMode_ = mode;
  1312. }
  1313. }
  1314. void Graphics::SetDepthWrite(bool enable)
  1315. {
  1316. if (enable != depthWrite_)
  1317. {
  1318. glDepthMask(enable ? GL_TRUE : GL_FALSE);
  1319. depthWrite_ = enable;
  1320. }
  1321. }
  1322. void Graphics::SetFillMode(FillMode mode)
  1323. {
  1324. if (mode != fillMode_)
  1325. {
  1326. glPolygonMode(GL_FRONT_AND_BACK, mode == FILL_SOLID ? GL_FILL : GL_LINE);
  1327. fillMode_ = mode;
  1328. }
  1329. }
  1330. void Graphics::SetScissorTest(bool enable, const Rect& rect, bool borderInclusive)
  1331. {
  1332. // During some light rendering loops, a full rect is toggled on/off repeatedly.
  1333. // Disable scissor in that case to reduce state changes
  1334. if ((rect.min_.x_ <= 0.0f) && (rect.min_.y_ <= 0.0f) && (rect.max_.y_ >= 1.0f) && (rect.max_.y_ >= 1.0f))
  1335. enable = false;
  1336. // Check for illegal rect, disable in that case
  1337. if ((rect.max_.x_ < rect.min_.x_) || (rect.max_.y_ < rect.min_.y_))
  1338. enable = false;
  1339. if (enable)
  1340. {
  1341. IntVector2 rtSize(GetRenderTargetDimensions());
  1342. IntVector2 viewSize(viewport_.right_ - viewport_.left_, viewport_.bottom_ - viewport_.top_);
  1343. IntVector2 viewPos(viewport_.left_, viewport_.top_);
  1344. IntRect intRect;
  1345. int expand = borderInclusive ? 1 : 0;
  1346. intRect.left_ = Clamp((int)((rect.min_.x_ + 1.0f) * 0.5f * viewSize.x_) + viewPos.x_, 0, rtSize.x_ - 1);
  1347. intRect.top_ = Clamp((int)((-rect.max_.y_ + 1.0f) * 0.5f * viewSize.y_) + viewPos.y_, 0, rtSize.y_ - 1);
  1348. intRect.right_ = Clamp((int)((rect.max_.x_ + 1.0f) * 0.5f * viewSize.x_) + viewPos.x_ + expand, 0, rtSize.x_);
  1349. intRect.bottom_ = Clamp((int)((-rect.min_.y_ + 1.0f) * 0.5f * viewSize.y_) + viewPos.y_ + expand, 0, rtSize.y_);
  1350. if (intRect.right_ == intRect.left_)
  1351. intRect.right_++;
  1352. if (intRect.bottom_ == intRect.top_)
  1353. intRect.bottom_++;
  1354. if ((intRect.right_ < intRect.left_) || (intRect.bottom_ < intRect.top_))
  1355. enable = false;
  1356. if ((enable) && (scissorRect_ != intRect))
  1357. {
  1358. // Use Direct3D convention with the vertical coordinates ie. 0 is top
  1359. glScissor(intRect.left_, rtSize.y_ - intRect.bottom_, intRect.right_ - intRect.left_, intRect.bottom_ - intRect.top_);
  1360. scissorRect_ = intRect;
  1361. }
  1362. }
  1363. else
  1364. scissorRect_ = IntRect::ZERO;
  1365. if (enable != scissorTest_)
  1366. {
  1367. if (enable)
  1368. glEnable(GL_SCISSOR_TEST);
  1369. else
  1370. glDisable(GL_SCISSOR_TEST);
  1371. scissorTest_ = enable;
  1372. }
  1373. }
  1374. void Graphics::SetScissorTest(bool enable, const IntRect& rect)
  1375. {
  1376. IntVector2 rtSize(GetRenderTargetDimensions());
  1377. IntVector2 viewSize(viewport_.right_ - viewport_.left_, viewport_.bottom_ - viewport_.top_);
  1378. IntVector2 viewPos(viewport_.left_, viewport_.top_);
  1379. // Full scissor is same as disabling the test
  1380. if ((rect.left_ <= 0) && (rect.right_ >= viewSize.x_) && (rect.top_ <= 0) && (rect.bottom_ >= viewSize.y_))
  1381. enable = false;
  1382. // Check for illegal rect, disable in that case
  1383. if ((rect.right_ < rect.left_) || (rect.bottom_ < rect.top_))
  1384. enable = false;
  1385. if (enable)
  1386. {
  1387. IntRect intRect;
  1388. intRect.left_ = Clamp(rect.left_ + viewPos.x_, 0, rtSize.x_ - 1);
  1389. intRect.top_ = Clamp(rect.top_ + viewPos.y_, 0, rtSize.y_ - 1);
  1390. intRect.right_ = Clamp(rect.right_ + viewPos.x_, 0, rtSize.x_);
  1391. intRect.bottom_ = Clamp(rect.bottom_ + viewPos.y_, 0, rtSize.y_);
  1392. if (intRect.right_ == intRect.left_)
  1393. intRect.right_++;
  1394. if (intRect.bottom_ == intRect.top_)
  1395. intRect.bottom_++;
  1396. if ((intRect.right_ < intRect.left_) || (intRect.bottom_ < intRect.top_))
  1397. enable = false;
  1398. if ((enable) && (scissorRect_ != intRect))
  1399. {
  1400. // Use Direct3D convention with the vertical coordinates ie. 0 is top
  1401. glScissor(intRect.left_, rtSize.y_ - intRect.bottom_, intRect.right_ - intRect.left_, intRect.bottom_ - intRect.top_);
  1402. scissorRect_ = intRect;
  1403. }
  1404. }
  1405. else
  1406. scissorRect_ = IntRect::ZERO;
  1407. if (enable != scissorTest_)
  1408. {
  1409. if (enable)
  1410. glEnable(GL_SCISSOR_TEST);
  1411. else
  1412. glDisable(GL_SCISSOR_TEST);
  1413. scissorTest_ = enable;
  1414. }
  1415. }
  1416. void Graphics::SetStreamFrequency(unsigned index, unsigned frequency)
  1417. {
  1418. }
  1419. void Graphics::ResetStreamFrequencies()
  1420. {
  1421. }
  1422. void Graphics::SetStencilTest(bool enable, CompareMode mode, StencilOp pass, StencilOp fail, StencilOp zFail, unsigned stencilRef, unsigned stencilMask)
  1423. {
  1424. if (enable != stencilTest_)
  1425. {
  1426. if (enable)
  1427. glEnable(GL_STENCIL_TEST);
  1428. else
  1429. glDisable(GL_STENCIL_TEST);
  1430. stencilTest_ = enable;
  1431. }
  1432. if (enable)
  1433. {
  1434. if ((mode != stencilTestMode_) || (stencilRef != stencilRef_) || (stencilMask != stencilMask_))
  1435. {
  1436. glStencilFunc(glCmpFunc[mode], stencilRef, stencilMask);
  1437. stencilTestMode_ = mode;
  1438. stencilRef_ = stencilRef;
  1439. stencilMask_ = stencilMask;
  1440. }
  1441. if ((pass != stencilPass_) || (fail != stencilFail_) || (!zFail != stencilZFail_))
  1442. {
  1443. glStencilOp(glStencilOps[fail], glStencilOps[zFail], glStencilOps[pass]);
  1444. stencilPass_ = pass;
  1445. stencilFail_ = fail;
  1446. stencilZFail_ = zFail;
  1447. }
  1448. }
  1449. }
  1450. bool Graphics::BeginImmediate(PrimitiveType type, unsigned vertexCount, unsigned elementMask)
  1451. {
  1452. if (immediateVertexCount_)
  1453. {
  1454. LOGERROR("New immediate draw operation started before ending the last one");
  1455. return false;
  1456. }
  1457. if (!(elementMask & MASK_POSITION))
  1458. {
  1459. LOGERROR("Immediate draw operation must contain vertex positions");
  1460. return false;
  1461. }
  1462. if (!vertexCount)
  1463. return true;
  1464. // Resize the buffer if it is too small
  1465. unsigned vertexSize = VertexBuffer::GetVertexSize(elementMask);
  1466. if (immediateVertexData_.Size() < vertexCount * vertexSize)
  1467. immediateVertexData_.Resize(vertexCount * vertexSize);
  1468. // Note: the data pointer gets pre-decremented here, because the first call to DefineVertex() will increment it
  1469. immediateDataPtr_ = &immediateVertexData_[0] - vertexSize;
  1470. immediateType_= type;
  1471. immediateVertexCount_ = vertexCount;
  1472. immediateVertexSize_ = vertexSize;
  1473. immediateElementMask_ = elementMask;
  1474. immediateCurrentVertex_ = 0;
  1475. unsigned dataOffset = 0;
  1476. for (unsigned i = ELEMENT_POSITION; i <= ELEMENT_TEXCOORD1; ++i)
  1477. {
  1478. immediateElementOffsets_[i] = dataOffset;
  1479. if (elementMask & (1 << i))
  1480. dataOffset += VertexBuffer::elementSize[i];
  1481. }
  1482. return true;
  1483. }
  1484. bool Graphics::DefineVertex(const Vector3& vertex)
  1485. {
  1486. if ((!immediateVertexCount_) || (immediateCurrentVertex_ >= immediateVertexCount_))
  1487. return false;
  1488. immediateDataPtr_ += immediateVertexSize_;
  1489. ++immediateCurrentVertex_;
  1490. float* dest = (float*)(immediateDataPtr_ + immediateElementOffsets_[ELEMENT_POSITION]);
  1491. const float* src = vertex.GetData();
  1492. dest[0] = src[0];
  1493. dest[1] = src[1];
  1494. dest[2] = src[2];
  1495. return true;
  1496. }
  1497. bool Graphics::DefineNormal(const Vector3& normal)
  1498. {
  1499. if ((!immediateVertexCount_) || (!(immediateElementMask_ & MASK_NORMAL)) || (!immediateCurrentVertex_))
  1500. return false;
  1501. float* dest = (float*)(immediateDataPtr_ + immediateElementOffsets_[ELEMENT_NORMAL]);
  1502. const float* src = normal.GetData();
  1503. dest[0] = src[0];
  1504. dest[1] = src[1];
  1505. dest[2] = src[2];
  1506. return true;
  1507. }
  1508. bool Graphics::DefineTexCoord(const Vector2& texCoord)
  1509. {
  1510. if ((!immediateVertexCount_) || (!(immediateElementMask_ & MASK_TEXCOORD1)) || (!immediateCurrentVertex_))
  1511. return false;
  1512. float* dest = (float*)(immediateDataPtr_ + immediateElementOffsets_[ELEMENT_TEXCOORD1]);
  1513. const float* src = texCoord.GetData();
  1514. dest[0] = src[0];
  1515. dest[1] = src[1];
  1516. return true;
  1517. }
  1518. bool Graphics::DefineColor(const Color& color)
  1519. {
  1520. if ((!immediateVertexCount_) || (!(immediateElementMask_ & MASK_COLOR)) || (!immediateCurrentVertex_))
  1521. return false;
  1522. unsigned* dest = (unsigned*)(immediateDataPtr_ + immediateElementOffsets_[ELEMENT_COLOR]);
  1523. *dest = color.ToUInt();
  1524. return true;
  1525. }
  1526. bool Graphics::DefineColor(unsigned color)
  1527. {
  1528. if ((!immediateVertexCount_) || (!(immediateElementMask_ & MASK_COLOR)) || (!immediateCurrentVertex_))
  1529. return false;
  1530. unsigned* dest = (unsigned*)(immediateDataPtr_ + immediateElementOffsets_[ELEMENT_COLOR]);
  1531. *dest = color;
  1532. return true;
  1533. }
  1534. void Graphics::EndImmediate()
  1535. {
  1536. if (immediateVertexCount_)
  1537. {
  1538. SetVertexBuffer(0);
  1539. SetIndexBuffer(0);
  1540. if (shaderProgram_)
  1541. {
  1542. const int* attributeLocations = shaderProgram_->GetAttributeLocations();
  1543. unsigned vertexSize = VertexBuffer::GetVertexSize(immediateElementMask_);
  1544. glBindBuffer(GL_ARRAY_BUFFER, 0);
  1545. for (unsigned i = ELEMENT_POSITION; i <= ELEMENT_TEXCOORD1; ++i)
  1546. {
  1547. unsigned attributeIndex = attributeLocations[i];
  1548. unsigned attributeBit = 1 << attributeIndex;
  1549. unsigned elementBit = 1 << i;
  1550. if (immediateElementMask_ & elementBit)
  1551. {
  1552. if ((impl_->enabledAttributes_ & attributeBit) == 0)
  1553. {
  1554. glEnableVertexAttribArray(attributeIndex);
  1555. impl_->enabledAttributes_ |= attributeBit;
  1556. }
  1557. glVertexAttribPointer(attributeIndex, VertexBuffer::elementComponents[i], VertexBuffer::elementType[i],
  1558. VertexBuffer::elementNormalize[i], vertexSize, (const GLvoid*)&immediateVertexData_[immediateElementOffsets_[i]]);
  1559. }
  1560. else if (impl_->enabledAttributes_ & attributeBit)
  1561. {
  1562. glDisableVertexAttribArray(attributeIndex);
  1563. impl_->enabledAttributes_ &= ~attributeBit;
  1564. }
  1565. }
  1566. Draw(immediateType_, 0, immediateVertexCount_);
  1567. }
  1568. immediateVertexCount_ = 0;
  1569. }
  1570. }
  1571. void Graphics::SetForceSM2(bool enable)
  1572. {
  1573. }
  1574. unsigned char* Graphics::GetImmediateDataPtr() const
  1575. {
  1576. if (!immediateVertexCount_)
  1577. {
  1578. LOGERROR("Immediate draw operation not started");
  1579. return 0;
  1580. }
  1581. return const_cast<unsigned char*>(&immediateVertexData_[0]);
  1582. }
  1583. PODVector<IntVector2> Graphics::GetResolutions() const
  1584. {
  1585. PODVector<IntVector2> ret;
  1586. DEVMODE displayMode;
  1587. unsigned index = 0;
  1588. for (unsigned index = 0;; ++index)
  1589. {
  1590. if (!EnumDisplaySettings(NULL, index, &displayMode))
  1591. break;
  1592. if (displayMode.dmBitsPerPel < 16)
  1593. continue;
  1594. IntVector2 newMode(displayMode.dmPelsWidth, displayMode.dmPelsHeight);
  1595. // Check for duplicate before storing
  1596. bool unique = true;
  1597. for (unsigned j = 0; j < ret.Size(); ++j)
  1598. {
  1599. if (ret[j] == newMode)
  1600. {
  1601. unique = false;
  1602. break;
  1603. }
  1604. }
  1605. if (unique)
  1606. ret.Push(newMode);
  1607. }
  1608. return ret;
  1609. }
  1610. PODVector<int> Graphics::GetMultiSampleLevels() const
  1611. {
  1612. PODVector<int> ret;
  1613. // No multisampling always supported
  1614. ret.Push(1);
  1615. if ((_GLEE_WGL_ARB_pixel_format) && (impl_->deviceContext_))
  1616. {
  1617. int attributes[] = {
  1618. WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
  1619. WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
  1620. WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
  1621. WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
  1622. WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
  1623. WGL_SAMPLES_ARB, 2,
  1624. 0, 0
  1625. };
  1626. int pixelFormats[256];
  1627. unsigned numPixelFormats;
  1628. wglChoosePixelFormatARB(impl_->deviceContext_, attributes, 0, 256, pixelFormats, &numPixelFormats);
  1629. for (unsigned i = 0; i < numPixelFormats; ++i)
  1630. {
  1631. int multiSampleQuery = WGL_SAMPLES_ARB;
  1632. int multiSampleLevel;
  1633. wglGetPixelFormatAttribivARB(impl_->deviceContext_, pixelFormats[i], 0, 1, &multiSampleQuery, &multiSampleLevel);
  1634. if (multiSampleLevel > 1)
  1635. {
  1636. bool unique = true;
  1637. for (unsigned j = 0; j < ret.Size(); ++j)
  1638. {
  1639. if (ret[j] == multiSampleLevel)
  1640. {
  1641. unique = false;
  1642. break;
  1643. }
  1644. }
  1645. if (unique)
  1646. ret.Push(multiSampleLevel);
  1647. }
  1648. }
  1649. }
  1650. return ret;
  1651. }
  1652. VertexBuffer* Graphics::GetVertexBuffer(unsigned index) const
  1653. {
  1654. return index < MAX_VERTEX_STREAMS ? vertexBuffers_[index] : 0;
  1655. }
  1656. ShaderParameter Graphics::GetShaderParameter(const String& name)
  1657. {
  1658. Map<String, ShaderParameter>::Iterator i = shaderParameters_.Find(name);
  1659. if (i != shaderParameters_.End())
  1660. return i->second_;
  1661. else
  1662. return MAX_SHADER_PARAMETERS;
  1663. }
  1664. TextureUnit Graphics::GetTextureUnit(const String& name)
  1665. {
  1666. Map<String, TextureUnit>::Iterator i = textureUnits_.Find(name);
  1667. if (i != textureUnits_.End())
  1668. return i->second_;
  1669. else
  1670. return MAX_TEXTURE_UNITS;
  1671. }
  1672. const String& Graphics::GetShaderParameterName(ShaderParameter parameter)
  1673. {
  1674. for (Map<String, ShaderParameter>::Iterator i = shaderParameters_.Begin(); i != shaderParameters_.End(); ++i)
  1675. {
  1676. if (i->second_ == parameter)
  1677. return i->first_;
  1678. }
  1679. return noParameter;
  1680. }
  1681. const String& Graphics::GetTextureUnitName(TextureUnit unit)
  1682. {
  1683. for (Map<String, TextureUnit>::Iterator i = textureUnits_.Begin(); i != textureUnits_.End(); ++i)
  1684. {
  1685. if (i->second_ == unit)
  1686. return i->first_;
  1687. }
  1688. return noParameter;
  1689. }
  1690. Texture* Graphics::GetTexture(unsigned index) const
  1691. {
  1692. return index < MAX_TEXTURE_UNITS ? textures_[index] : 0;
  1693. }
  1694. RenderSurface* Graphics::GetRenderTarget(unsigned index) const
  1695. {
  1696. return index < MAX_RENDERTARGETS ? renderTargets_[index] : 0;
  1697. }
  1698. IntVector2 Graphics::GetRenderTargetDimensions() const
  1699. {
  1700. int width, height;
  1701. if (renderTargets_[0])
  1702. {
  1703. width = renderTargets_[0]->GetWidth();
  1704. height = renderTargets_[0]->GetHeight();
  1705. }
  1706. else if (depthStencil_)
  1707. {
  1708. width = depthStencil_->GetWidth();
  1709. height = depthStencil_->GetHeight();
  1710. }
  1711. else
  1712. {
  1713. width = width_;
  1714. height = height_;
  1715. }
  1716. return IntVector2(width, height);
  1717. }
  1718. void Graphics::AddGPUObject(GPUObject* object)
  1719. {
  1720. gpuObjects_.Push(object);
  1721. }
  1722. void Graphics::RemoveGPUObject(GPUObject* object)
  1723. {
  1724. for (Vector<GPUObject*>::Iterator i = gpuObjects_.Begin(); i != gpuObjects_.End(); ++i)
  1725. {
  1726. if ((*i) == object)
  1727. {
  1728. gpuObjects_.Erase(i);
  1729. return;
  1730. }
  1731. }
  1732. }
  1733. unsigned Graphics::GetAlphaFormat()
  1734. {
  1735. return GL_ALPHA;
  1736. }
  1737. unsigned Graphics::GetLuminanceFormat()
  1738. {
  1739. return GL_LUMINANCE;
  1740. }
  1741. unsigned Graphics::GetLuminanceAlphaFormat()
  1742. {
  1743. return GL_LUMINANCE_ALPHA;
  1744. }
  1745. unsigned Graphics::GetRGBFormat()
  1746. {
  1747. return GL_RGB;
  1748. }
  1749. unsigned Graphics::GetRGBAFormat()
  1750. {
  1751. return GL_RGBA;
  1752. }
  1753. unsigned Graphics::GetDepthFormat()
  1754. {
  1755. return GL_DEPTH_COMPONENT24;
  1756. }
  1757. unsigned Graphics::GetDepthStencilFormat()
  1758. {
  1759. return GL_DEPTH24_STENCIL8_EXT;
  1760. }
  1761. bool Graphics::IsInitialized() const
  1762. {
  1763. return ((impl_->window_ != 0) && (impl_->renderContext_ != 0));
  1764. }
  1765. unsigned Graphics::GetWindowHandle() const
  1766. {
  1767. return (unsigned)impl_->window_;
  1768. }
  1769. bool Graphics::OpenWindow(int width, int height)
  1770. {
  1771. WNDCLASS wc;
  1772. wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
  1773. wc.lpfnWndProc = wndProc;
  1774. wc.cbClsExtra = 0;
  1775. wc.cbWndExtra = 0;
  1776. wc.hInstance = impl_->instance_;
  1777. wc.hIcon = LoadIcon(0, IDI_APPLICATION);
  1778. wc.hCursor = LoadCursor(0, IDC_ARROW);
  1779. wc.hbrBackground = 0;
  1780. wc.lpszMenuName = 0;
  1781. wc.lpszClassName = "OpenGL";
  1782. RegisterClass(&wc);
  1783. RECT rect = {0, 0, width, height};
  1784. AdjustWindowRect(&rect, windowStyle, FALSE);
  1785. impl_->window_ = CreateWindow("OpenGL", windowTitle_.CString(), windowStyle, CW_USEDEFAULT, CW_USEDEFAULT,
  1786. rect.right, rect.bottom, 0, 0, impl_->instance_, 0);
  1787. if (!impl_->window_)
  1788. {
  1789. LOGERROR("Could not create window");
  1790. return false;
  1791. }
  1792. SetWindowLongPtr(impl_->window_, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
  1793. // Save the device context
  1794. impl_->deviceContext_ = GetDC(impl_->window_);
  1795. LOGINFO("Created application window");
  1796. return true;
  1797. }
  1798. int Graphics::GetPixelFormat(RenderMode mode, int multiSample)
  1799. {
  1800. PIXELFORMATDESCRIPTOR format;
  1801. ZeroMemory(&format, sizeof(format));
  1802. format.nSize = sizeof(format);
  1803. format.nVersion = 1;
  1804. format.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_GENERIC_ACCELERATED | PFD_DOUBLEBUFFER;
  1805. format.iPixelType = PFD_TYPE_RGBA;
  1806. format.cColorBits = impl_->GetDesktopBitsPerPixel();
  1807. format.cDepthBits = 24;
  1808. format.cStencilBits = 8;
  1809. int pixelFormat = 0;
  1810. unsigned numFormats;
  1811. // Use the extended pixel format if multisampling requested in forward rendering mode
  1812. if ((_GLEE_WGL_ARB_pixel_format) && (multiSample > 1) && (mode == RENDER_FORWARD))
  1813. {
  1814. int attributes[] = {
  1815. WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
  1816. WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
  1817. WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
  1818. WGL_COLOR_BITS_ARB, impl_->GetDesktopBitsPerPixel(),
  1819. WGL_DEPTH_BITS_ARB, 24,
  1820. WGL_STENCIL_BITS_ARB, 8,
  1821. WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
  1822. WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
  1823. WGL_SAMPLES_ARB, multiSample,
  1824. 0, 0
  1825. };
  1826. // If multisample fails, switch to non-multisampled pixel format
  1827. if ((!wglChoosePixelFormatARB(impl_->deviceContext_, attributes, 0, 1, &pixelFormat, &numFormats)) || (!pixelFormat))
  1828. pixelFormat = ChoosePixelFormat(impl_->deviceContext_, &format);
  1829. }
  1830. else
  1831. pixelFormat = ChoosePixelFormat(impl_->deviceContext_, &format);
  1832. return pixelFormat;
  1833. }
  1834. bool Graphics::SetScreenMode(int newWidth, int newHeight)
  1835. {
  1836. ++inModeChange_;
  1837. DEVMODE displayMode;
  1838. ZeroMemory(&displayMode, sizeof(displayMode));
  1839. displayMode.dmSize = sizeof(displayMode);
  1840. displayMode.dmPelsWidth = newWidth;
  1841. displayMode.dmPelsHeight = newHeight;
  1842. displayMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
  1843. bool success = ChangeDisplaySettings(&displayMode, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL;
  1844. if (success)
  1845. fullscreenModeSet_ = true;
  1846. --inModeChange_;
  1847. return success;
  1848. }
  1849. void Graphics::RestoreScreenMode()
  1850. {
  1851. if (fullscreenModeSet_)
  1852. {
  1853. ++inModeChange_;
  1854. ChangeDisplaySettings(NULL, 0);
  1855. fullscreenModeSet_ = false;
  1856. --inModeChange_;
  1857. }
  1858. }
  1859. void Graphics::AdjustWindow(int newWidth, int newHeight, bool newFullscreen)
  1860. {
  1861. ++inModeChange_;
  1862. if (newFullscreen)
  1863. {
  1864. SetWindowLongPtr(impl_->window_, GWL_STYLE, WS_POPUP);
  1865. SetWindowPos(impl_->window_, HWND_TOP, 0, 0, newWidth, newHeight, SWP_SHOWWINDOW | SWP_NOCOPYBITS);
  1866. }
  1867. else
  1868. {
  1869. RECT rect = {0, 0, newWidth, newHeight};
  1870. AdjustWindowRect(&rect, windowStyle, FALSE);
  1871. SetWindowLongPtr(impl_->window_, GWL_STYLE, windowStyle);
  1872. SetWindowPos(impl_->window_, HWND_TOP, windowPosX_, windowPosY_, rect.right - rect.left, rect.bottom - rect.top,
  1873. SWP_SHOWWINDOW | SWP_NOCOPYBITS);
  1874. // Clean up the desktop of old window contents
  1875. InvalidateRect(0, 0, TRUE);
  1876. }
  1877. --inModeChange_;
  1878. }
  1879. void Graphics::CreateRenderTargets()
  1880. {
  1881. if (mode_ != RENDER_FORWARD)
  1882. {
  1883. if (!diffBuffer_)
  1884. {
  1885. diffBuffer_ = new Texture2D(context_);
  1886. diffBuffer_->SetSize(0, 0, GetRGBAFormat(), TEXTURE_RENDERTARGET);
  1887. }
  1888. if (!normalBuffer_)
  1889. {
  1890. normalBuffer_ = new Texture2D(context_);
  1891. normalBuffer_->SetSize(0, 0, GetRGBAFormat(), TEXTURE_RENDERTARGET);
  1892. }
  1893. if (!depthBuffer_)
  1894. {
  1895. depthBuffer_ = new Texture2D(context_);
  1896. depthBuffer_->SetSize(0, 0, GetDepthFormat(), TEXTURE_DEPTHSTENCIL);
  1897. }
  1898. // If deferred antialiasing is used, reserve screen buffer
  1899. // (later we will probably want the screen buffer reserved in any case, to do for example distortion effects,
  1900. // which will also be useful in forward rendering)
  1901. if (multiSample_ > 1)
  1902. {
  1903. screenBuffer_ = new Texture2D(context_);
  1904. screenBuffer_->SetSize(0, 0, GetRGBAFormat(), TEXTURE_RENDERTARGET);
  1905. screenBuffer_->SetFilterMode(FILTER_BILINEAR);
  1906. }
  1907. else
  1908. screenBuffer_.Reset();
  1909. }
  1910. else
  1911. {
  1912. diffBuffer_.Reset();
  1913. normalBuffer_.Reset();
  1914. depthBuffer_.Reset();
  1915. screenBuffer_.Reset();
  1916. }
  1917. }
  1918. void Graphics::ResetCachedState()
  1919. {
  1920. for (unsigned i = 0; i < MAX_VERTEX_STREAMS; ++i)
  1921. {
  1922. vertexBuffers_[i] = 0;
  1923. elementMasks_[i] = 0;
  1924. }
  1925. for (unsigned i = 0; i < MAX_TEXTURE_UNITS; ++i)
  1926. {
  1927. textures_[i] = 0;
  1928. textureTypes_[i] = 0;
  1929. }
  1930. for (unsigned i = 0; i < MAX_RENDERTARGETS; ++i)
  1931. renderTargets_[i] = 0;
  1932. depthStencil_ = 0;
  1933. viewport_ = IntRect(0, 0, 0, 0);
  1934. viewTexture_ = 0;
  1935. indexBuffer_ = 0;
  1936. vertexShader_ = 0;
  1937. pixelShader_ = 0;
  1938. shaderProgram_ = 0;
  1939. blendMode_ = BLEND_REPLACE;
  1940. alphaTest_ = false;
  1941. alphaTestMode_ = CMP_ALWAYS;
  1942. alphaRef_ = 0.0f;
  1943. textureAnisotropy_ = 1;
  1944. colorWrite_ = true;
  1945. cullMode_ = CULL_NONE;
  1946. constantDepthBias_ = 0.0f;
  1947. slopeScaledDepthBias_ = 0.0f;
  1948. depthTestMode_ = CMP_ALWAYS;
  1949. depthWrite_ = true;
  1950. fillMode_ = FILL_SOLID;
  1951. scissorTest_ = false;
  1952. scissorRect_ = IntRect::ZERO;
  1953. stencilTest_ = false;
  1954. stencilTestMode_ = CMP_ALWAYS;
  1955. stencilPass_ = OP_KEEP;
  1956. stencilFail_ = OP_KEEP;
  1957. stencilZFail_ = OP_KEEP;
  1958. stencilRef_ = 0;
  1959. stencilMask_ = M_MAX_UNSIGNED;
  1960. impl_->activeTexture_ = 0;
  1961. impl_->drawBuffers_ = M_MAX_UNSIGNED;
  1962. impl_->enabledAttributes_ = 0;
  1963. impl_->fboBound_ = false;
  1964. }
  1965. void Graphics::SetDrawBuffers()
  1966. {
  1967. // Calculate the bit combination of non-zero color rendertargets to first check if the combination changed
  1968. unsigned newDrawBuffers = 0;
  1969. for (unsigned i = 0; i < MAX_RENDERTARGETS; ++i)
  1970. {
  1971. if (renderTargets_[i])
  1972. newDrawBuffers |= 1 << i;
  1973. }
  1974. if (newDrawBuffers == impl_->drawBuffers_)
  1975. return;
  1976. // Check for no color rendertargets (depth rendering only)
  1977. if (!newDrawBuffers)
  1978. glDrawBuffer(GL_NONE);
  1979. else
  1980. {
  1981. int drawBufferIds[4];
  1982. unsigned drawBufferCount = 0;
  1983. for (unsigned i = 0; i < MAX_RENDERTARGETS; ++i)
  1984. {
  1985. if (renderTargets_[i])
  1986. drawBufferIds[drawBufferCount++] = GL_COLOR_ATTACHMENT0_EXT + i;
  1987. }
  1988. glDrawBuffers(drawBufferCount, (const GLenum*)drawBufferIds);
  1989. }
  1990. glReadBuffer(GL_NONE);
  1991. }
  1992. void Graphics::Release()
  1993. {
  1994. diffBuffer_.Reset();
  1995. normalBuffer_.Reset();
  1996. depthBuffer_.Reset();
  1997. screenBuffer_.Reset();
  1998. // If GPU objects exist ie. it's a context delete/recreate, not Close(), tell the GPU objects to save and release themselves
  1999. for (Vector<GPUObject*>::Iterator i = gpuObjects_.Begin(); i != gpuObjects_.End(); ++i)
  2000. (*i)->OnDeviceLost();
  2001. if (impl_->renderContext_)
  2002. {
  2003. if (impl_->fbo_)
  2004. {
  2005. glDeleteFramebuffersEXT(1, &impl_->fbo_);
  2006. impl_->fbo_ = 0;
  2007. }
  2008. wglMakeCurrent(NULL, NULL);
  2009. wglDeleteContext(impl_->renderContext_);
  2010. impl_->renderContext_ = 0;
  2011. }
  2012. if (impl_->deviceContext_)
  2013. {
  2014. ReleaseDC(impl_->window_, impl_->deviceContext_);
  2015. impl_->deviceContext_ = 0;
  2016. }
  2017. if (impl_->window_)
  2018. {
  2019. RestoreScreenMode();
  2020. DestroyWindow(impl_->window_);
  2021. impl_->window_ = 0;
  2022. }
  2023. // When the new context is initialized, it will have default state again
  2024. ResetCachedState();
  2025. ClearParameterSources();
  2026. }
  2027. void Graphics::InitializeExtensions()
  2028. {
  2029. // Query for extensions needs to happen under lock as the function pointers are static
  2030. MutexLock lock(GetStaticMutex());
  2031. if (GLeeInitialized())
  2032. return;
  2033. WNDCLASS wc;
  2034. wc.style = CS_OWNDC;
  2035. wc.lpfnWndProc = wndProc;
  2036. wc.cbClsExtra = 0;
  2037. wc.cbWndExtra = 0;
  2038. wc.hInstance = impl_->instance_;
  2039. wc.hIcon = NULL;
  2040. wc.hCursor = NULL;
  2041. wc.hbrBackground = 0;
  2042. wc.lpszMenuName = 0;
  2043. wc.lpszClassName = "DummyOpenGL";
  2044. RegisterClass(&wc);
  2045. HWND dummyWindow = CreateWindow("DummyOpenGL", "Urho3D", WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT,
  2046. 32, 32, 0, 0, impl_->instance_, 0);
  2047. SetWindowLongPtr(dummyWindow, GWLP_USERDATA, 0);
  2048. // Save the device context, then set the pixel format
  2049. HDC deviceContext = GetDC(dummyWindow);
  2050. PIXELFORMATDESCRIPTOR format;
  2051. ZeroMemory(&format, sizeof(format));
  2052. format.nSize = sizeof(format);
  2053. format.nVersion = 1;
  2054. format.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
  2055. format.iPixelType = PFD_TYPE_RGBA;
  2056. format.cColorBits = 16;
  2057. format.cDepthBits = 15;
  2058. int iFormat = ChoosePixelFormat(deviceContext, &format);
  2059. SetPixelFormat(deviceContext, iFormat, &format);
  2060. HGLRC renderContext = wglCreateContext(deviceContext);
  2061. wglMakeCurrent(deviceContext, renderContext);
  2062. GLeeInit();
  2063. wglMakeCurrent(NULL, NULL);
  2064. wglDeleteContext(renderContext);
  2065. ReleaseDC(dummyWindow, deviceContext);
  2066. DestroyWindow(dummyWindow);
  2067. }
  2068. void Graphics::InitializeShaderParameters()
  2069. {
  2070. // Map parameter names
  2071. shaderParameters_["CameraPos"] = VSP_CAMERAPOS;
  2072. shaderParameters_["CameraRot"] = VSP_CAMERAROT;
  2073. shaderParameters_["DepthMode"] = VSP_DEPTHMODE;
  2074. shaderParameters_["ElapsedTime"] = VSP_ELAPSEDTIME;
  2075. shaderParameters_["FrustumSize"] = VSP_FRUSTUMSIZE;
  2076. shaderParameters_["GBufferOffsets"] = VSP_GBUFFEROFFSETS;
  2077. shaderParameters_["Model"] = VSP_MODEL;
  2078. shaderParameters_["ShadowProj"] = VSP_SHADOWPROJ;
  2079. shaderParameters_["SpotProj"] = VSP_SPOTPROJ;
  2080. shaderParameters_["ViewProj"] = VSP_VIEWPROJ;
  2081. shaderParameters_["UOffset"] = VSP_UOFFSET;
  2082. shaderParameters_["VOffset"] = VSP_VOFFSET;
  2083. shaderParameters_["ViewRightVector"] = VSP_VIEWRIGHTVECTOR;
  2084. shaderParameters_["ViewUpVector"] = VSP_VIEWUPVECTOR;
  2085. shaderParameters_["SkinMatrices"] = VSP_SKINMATRICES;
  2086. shaderParameters_["AmbientColor"] = PSP_AMBIENTCOLOR;
  2087. shaderParameters_["DepthReconstruct"] = PSP_DEPTHRECONSTRUCT;
  2088. shaderParameters_["EdgeFilterParams"] = PSP_EDGEFILTERPARAMS;
  2089. shaderParameters_["ElapsedTimePS"] = PSP_ELAPSEDTIME;
  2090. shaderParameters_["FogColor"] = PSP_FOGCOLOR;
  2091. shaderParameters_["FogParams"] = PSP_FOGPARAMS;
  2092. shaderParameters_["LightAtten"] = PSP_LIGHTATTEN;
  2093. shaderParameters_["LightColor"] = PSP_LIGHTCOLOR;
  2094. shaderParameters_["LightDir"] = PSP_LIGHTDIR;
  2095. shaderParameters_["LightPos"] = PSP_LIGHTPOS;
  2096. shaderParameters_["LightSplits"] = PSP_LIGHTSPLITS;
  2097. shaderParameters_["LightVecRot"] = PSP_LIGHTVECROT;
  2098. shaderParameters_["MatDiffColor"] = PSP_MATDIFFCOLOR;
  2099. shaderParameters_["MatEmissiveColor"] = PSP_MATEMISSIVECOLOR;
  2100. shaderParameters_["MatSpecProperties"] = PSP_MATSPECPROPERTIES;
  2101. shaderParameters_["SampleOffsets"] = PSP_SAMPLEOFFSETS;
  2102. shaderParameters_["ShadowIntensity"] = PSP_SHADOWINTENSITY;
  2103. shaderParameters_["ShadowProjPS"] = PSP_SHADOWPROJ;
  2104. shaderParameters_["SpotProjPS"] = PSP_SPOTPROJ;
  2105. // Map texture units
  2106. textureUnits_["NormalMap"] = TU_NORMAL;
  2107. textureUnits_["DiffMap"] = TU_DIFFUSE;
  2108. textureUnits_["DiffCubeMap"] = TU_DIFFUSE;
  2109. textureUnits_["SpecMap"] = TU_SPECULAR;
  2110. textureUnits_["EmissiveMap"] = TU_EMISSIVE;
  2111. textureUnits_["DetailMap"] = TU_DETAIL;
  2112. textureUnits_["EnvironmentMap"] = TU_ENVIRONMENT;
  2113. textureUnits_["EnvironmentCubeMap"] = TU_ENVIRONMENT;
  2114. textureUnits_["LightRampMap"] = TU_LIGHTRAMP;
  2115. textureUnits_["LightSpotMap"] = TU_LIGHTSPOT;
  2116. textureUnits_["LightCubeMap"] = TU_LIGHTSPOT;
  2117. textureUnits_["ShadowMap"] = TU_SHADOWMAP;
  2118. textureUnits_["DiffBuffer"] = TU_DIFFBUFFER;
  2119. textureUnits_["NormalBuffer"] = TU_NORMALBUFFER;
  2120. textureUnits_["DepthBuffer"] = TU_DEPTHBUFFER;
  2121. }
  2122. void Graphics::HandleWindowMessage(StringHash eventType, VariantMap& eventData)
  2123. {
  2124. using namespace WindowMessage;
  2125. if (eventData[P_WINDOW].GetInt() != (int)impl_->window_)
  2126. return;
  2127. switch (eventData[P_MSG].GetInt())
  2128. {
  2129. case WM_CLOSE:
  2130. Close();
  2131. eventData[P_HANDLED] = true;
  2132. break;
  2133. case WM_DESTROY:
  2134. eventData[P_HANDLED] = true;
  2135. break;
  2136. }
  2137. }
  2138. void Graphics::HandleActivation(StringHash eventType, VariantMap& eventData)
  2139. {
  2140. if ((inModeChange_) || (!impl_->window_) || (!fullscreen_))
  2141. return;
  2142. using namespace Activation;
  2143. if (eventData[P_ACTIVE].GetBool())
  2144. {
  2145. // If we were activated and are not minimized, change back to the custom mode
  2146. if ((!eventData[P_MINIMIZED].GetBool()) && (!fullscreenModeSet_))
  2147. {
  2148. if (!SetScreenMode(width_, height_))
  2149. fullscreen_ = false;
  2150. AdjustWindow(width_, height_, fullscreen_);
  2151. }
  2152. }
  2153. else
  2154. {
  2155. // Reset to desktop resolution on inactivation
  2156. ++inModeChange_;
  2157. ShowWindow(impl_->window_, SW_MINIMIZE);
  2158. --inModeChange_;
  2159. RestoreScreenMode();
  2160. }
  2161. }
  2162. LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  2163. {
  2164. using namespace WindowMessage;
  2165. Graphics* graphics = reinterpret_cast<Graphics*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
  2166. if ((graphics) && (graphics->IsInitialized()))
  2167. {
  2168. VariantMap eventData;
  2169. eventData[P_WINDOW] = (int)hwnd;
  2170. eventData[P_MSG] = (int)msg;
  2171. eventData[P_WPARAM] = (int)wParam;
  2172. eventData[P_LPARAM] = (int)lParam;
  2173. eventData[P_HANDLED] = false;
  2174. graphics->SendEvent(E_WINDOWMESSAGE, eventData);
  2175. if (eventData[P_HANDLED].GetBool())
  2176. return 0;
  2177. }
  2178. return DefWindowProc(hwnd, msg, wParam, lParam);
  2179. }
  2180. void RegisterGraphicsLibrary(Context* context)
  2181. {
  2182. Animation::RegisterObject(context);
  2183. Material::RegisterObject(context);
  2184. Model::RegisterObject(context);
  2185. Shader::RegisterObject(context);
  2186. Technique::RegisterObject(context);
  2187. Texture2D::RegisterObject(context);
  2188. TextureCube::RegisterObject(context);
  2189. Camera::RegisterObject(context);
  2190. Drawable::RegisterObject(context);
  2191. Light::RegisterObject(context);
  2192. StaticModel::RegisterObject(context);
  2193. Skybox::RegisterObject(context);
  2194. AnimatedModel::RegisterObject(context);
  2195. AnimationController::RegisterObject(context);
  2196. BillboardSet::RegisterObject(context);
  2197. ParticleEmitter::RegisterObject(context);
  2198. DebugRenderer::RegisterObject(context);
  2199. Octree::RegisterObject(context);
  2200. Zone::RegisterObject(context);
  2201. }