1
1

app.d 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130
  1. import std.stdio;
  2. import std.typecons;
  3. import derelict.opengl3.gl3;
  4. import derelict.glfw3.glfw3;
  5. import derelict.anttweakbar.anttweakbar;
  6. import derelict.freeimage.freeimage;
  7. import derelict.freetype.ft;
  8. import derelict.assimp3.assimp;
  9. import std.string;
  10. import std.experimental.logger;
  11. //======================================================================================================================
  12. //
  13. //======================================================================================================================
  14. import std.traits : ReturnType;
  15. ReturnType!func glCheck(alias func, string file = __FILE__, size_t line = __LINE__, string mod = __MODULE__, string funcd = __FUNCTION__, string pretty = __PRETTY_FUNCTION__, Args...)(Args args) nothrow {
  16. import std.stdio;
  17. import std.stdio : stderr;
  18. import std.array : join;
  19. import std.range : repeat;
  20. import std.string : format;
  21. try{
  22. debug scope(exit) {
  23. GLenum err = glGetError();
  24. if(err != GL_NO_ERROR) {
  25. stderr.writeln("\n===============================");
  26. stderr.writeln("File: ", file, "\nLine: ", line, "\nModule: ",mod, "\nFunction: ",funcd, "\n",pretty);
  27. stderr.writeln("-------------------------------");
  28. stderr.writefln(`OpenGL function "%s(%s)" failed: "%s."`, func.stringof, format("%s".repeat(Args.length).join(", "), args), glErrorString(err));
  29. stderr.writeln("=============================== \n");
  30. assert(false);
  31. }
  32. }
  33. }
  34. catch(Exception e){
  35. }
  36. debug if(func is null) {
  37. try{
  38. stderr.writefln("%s is null! OpenGL loaded? Required OpenGL version not supported?".format(func.stringof));
  39. }
  40. catch(Exception e){
  41. assert(false);
  42. }
  43. assert(false);
  44. }
  45. return func(args);
  46. }
  47. string glErrorString(GLenum error) pure @safe nothrow @nogc {
  48. final switch(error) {
  49. case GL_NO_ERROR: return "no error";
  50. case GL_INVALID_ENUM: return "invalid enum";
  51. case GL_INVALID_VALUE: return "invalid value";
  52. case GL_INVALID_OPERATION: return "invalid operation";
  53. //case GL_STACK_OVERFLOW: return "stack overflow";
  54. //case GL_STACK_UNDERFLOW: return "stack underflow";
  55. case GL_INVALID_FRAMEBUFFER_OPERATION: return "invalid framebuffer operation";
  56. case GL_OUT_OF_MEMORY: return "out of memory";
  57. }
  58. assert(false, "invalid enum");
  59. }
  60. //======================================================================================================================
  61. //
  62. //======================================================================================================================
  63. alias SoA(T) = T[];
  64. //======================================================================================================================
  65. //
  66. //======================================================================================================================
  67. struct SOAVector3 {
  68. SoA!float x;
  69. SoA!float y;
  70. SoA!float z;
  71. }
  72. struct SOAQuaternion {
  73. SoA!float x;
  74. SoA!float y;
  75. SoA!float z;
  76. SoA!float w;
  77. }
  78. //======================================================================================================================
  79. //
  80. //======================================================================================================================
  81. struct Window {
  82. private:
  83. GLFWwindow* glfwWindow = null;
  84. string title;
  85. uint x, y, width, height;
  86. KeyAction[int] keyStates;
  87. ButtonAction[int] buttonStates;
  88. }
  89. alias ScanCode = int;
  90. enum IconifyAction {
  91. Iconified,
  92. Restored
  93. }
  94. enum FocusAction {
  95. Focused,
  96. Defocused
  97. }
  98. enum CursorAction {
  99. Entered,
  100. Leaved
  101. }
  102. enum ButtonAction {
  103. Pressed,
  104. Released
  105. }
  106. enum KeyAction {
  107. Pressed,
  108. Released,
  109. Repeated
  110. }
  111. enum KeyMod {
  112. Shift = 0x0001,
  113. Control = 0x0002,
  114. Alt = 0x0004,
  115. Super = 0x0008,
  116. }
  117. enum Key {
  118. Unknown = -1,
  119. Space = 32,
  120. Apostrophe = 39,
  121. Comma = 44,
  122. Minus = 45,
  123. Period = 46,
  124. Slash = 47,
  125. Key0 = 48,
  126. Key1 = 49,
  127. Key2 = 50,
  128. Key3 = 51,
  129. Key4 = 52,
  130. Key5 = 53,
  131. Key6 = 54,
  132. Key7 = 55,
  133. Key8 = 56,
  134. Key9 = 57,
  135. Semicolon = 59,
  136. Equal = 61,
  137. KeyA = 65,
  138. KeyB = 66,
  139. KeyC = 67,
  140. KeyD = 68,
  141. KeyE = 69,
  142. KeyF = 70,
  143. KeyG = 71,
  144. KeyH = 72,
  145. KeyI = 73,
  146. KeyJ = 74,
  147. KeyK = 75,
  148. Keyl = 76,
  149. KeyM = 77,
  150. KeyN = 78,
  151. KeyO = 79,
  152. KeyP = 80,
  153. KeyQ = 81,
  154. KeyR = 82,
  155. KeyS = 83,
  156. KeyT = 84,
  157. KeyU = 85,
  158. KeyV = 86,
  159. KeyW = 87,
  160. KeyX = 88,
  161. KeyY = 89,
  162. KeyZ = 90,
  163. LeftBracket = 91,
  164. Backslash = 92,
  165. RightBracket = 93,
  166. GraveAccent = 96,
  167. World1 = 161,
  168. World2 = 162,
  169. Escape = 256,
  170. Enter = 257,
  171. Tab = 258,
  172. Backspace = 259,
  173. Insert = 260,
  174. Delete = 261,
  175. Right = 262,
  176. Left = 263,
  177. Down = 264,
  178. Up = 265,
  179. PageUp = 266,
  180. PageDown = 267,
  181. Home = 268,
  182. End = 269,
  183. CapsLock = 280,
  184. ScrollLock = 281,
  185. NumLock = 282,
  186. PrintScreen = 283,
  187. Pause = 284,
  188. F1 = 290,
  189. F2 = 291,
  190. F3 = 292,
  191. F4 = 293,
  192. F5 = 294,
  193. F6 = 295,
  194. F7 = 296,
  195. F8 = 297,
  196. F9 = 298,
  197. F10 = 299,
  198. F11 = 300,
  199. F12 = 301,
  200. F13 = 302,
  201. F14 = 303,
  202. F15 = 304,
  203. F16 = 305,
  204. F17 = 306,
  205. F18 = 307,
  206. F19 = 308,
  207. F20 = 309,
  208. F21 = 310,
  209. F22 = 311,
  210. F23 = 312,
  211. F24 = 313,
  212. F25 = 314,
  213. NumBlock0 = 320,
  214. NumBlock1 = 321,
  215. NumBlock2 = 322,
  216. NumBlock3 = 323,
  217. NumBlock4 = 324,
  218. NumBlock5 = 325,
  219. NumBlock6 = 326,
  220. NumBlock7 = 327,
  221. NumBlock8 = 328,
  222. NumBlock9 = 329,
  223. KpDecimal = 330,
  224. KpDivide = 331,
  225. KpMultiply = 332,
  226. KpSubtract = 333,
  227. KpAdd = 334,
  228. KpEnter = 335,
  229. KpEqual = 336,
  230. LeftShift = 340,
  231. LeftControl = 341,
  232. LeftAlt = 342,
  233. LeftSuper = 343,
  234. RightShift = 344,
  235. RightControl = 345,
  236. RightAlt = 346,
  237. RightSuper = 347,
  238. Menu = 348
  239. }
  240. void construct(out Window window, string title, uint width, uint height) nothrow {
  241. window.x = 0;
  242. window.y = 0;
  243. window.width = width;
  244. window.height = height;
  245. glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
  246. glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
  247. glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4);
  248. glfwDefaultWindowHints();
  249. glfwWindowHint(GLFW_RED_BITS, 8);
  250. glfwWindowHint(GLFW_GREEN_BITS, 8);
  251. glfwWindowHint(GLFW_BLUE_BITS, 8);
  252. glfwWindowHint(GLFW_ALPHA_BITS, 0);
  253. glfwWindowHint(GLFW_DEPTH_BITS, 24);
  254. glfwWindowHint(GLFW_STENCIL_BITS, 8);
  255. window.glfwWindow = glfwCreateWindow(width, height, title.toStringz(), null, null);
  256. assert(window.glfwWindow !is null);
  257. // glfwSetWindowUserPointer(window.glfwWindow, cast(void*)&window);
  258. // glfwSetWindowPosCallback(window.glfwWindow, cast(GLFWwindowposfun)&_GLFWwindowposfun);
  259. // glfwSetWindowSizeCallback(window.glfwWindow, cast(GLFWwindowsizefun)&_GLFWwindowsizefun);
  260. // glfwSetWindowCloseCallback(window.glfwWindow, cast(GLFWwindowclosefun)&_GLFWwindowclosefun);
  261. // glfwSetWindowRefreshCallback(window.glfwWindow, cast(GLFWwindowrefreshfun)&_GLFWwindowrefreshfun);
  262. // glfwSetWindowIconifyCallback(window.glfwWindow, cast(GLFWwindowiconifyfun)&_GLFWwindowiconifyfun);
  263. // glfwSetMouseButtonCallback(window.glfwWindow, cast(GLFWmousebuttonfun)&_GLFWmousebuttonfun);
  264. // glfwSetCursorPosCallback(window.glfwWindow, cast(GLFWcursorposfun)&_GLFWcursorposfun);
  265. // //glfwSetCursorEnterCallback(window.glfwWindow, cast(GLFWcursorenterfunfun)&_GLFWcursorenterfunfun);
  266. // glfwSetScrollCallback(window.glfwWindow, cast(GLFWscrollfun)&_GLFWscrollfun);
  267. // glfwSetKeyCallback(window.glfwWindow, cast(GLFWkeyfun)&_GLFWkeyfun);
  268. // glfwSetCharCallback(window.glfwWindow, cast(GLFWcharfun)&_GLFWcharfun);
  269. glfwMakeContextCurrent(window.glfwWindow);
  270. }
  271. void destruct(ref Window window) nothrow @nogc {
  272. // glfwSetWindowPosCallback(window.glfwWindow, null);
  273. // glfwSetWindowSizeCallback(window.glfwWindow, null);
  274. // glfwSetWindowCloseCallback(window.glfwWindow, null);
  275. // glfwSetWindowRefreshCallback(window.glfwWindow, null);
  276. // glfwSetWindowIconifyCallback(window.glfwWindow, null);
  277. // glfwSetMouseButtonCallback(window.glfwWindow, null);
  278. // glfwSetCursorPosCallback(window.glfwWindow, null);
  279. // //glfwSetCursorEnterCallback(this._glfwWindow, null);
  280. // glfwSetScrollCallback(window.glfwWindow, null);
  281. // glfwSetKeyCallback(window.glfwWindow, null);
  282. // glfwSetCharCallback(window.glfwWindow, null);
  283. glfwDestroyWindow(window.glfwWindow);
  284. window = Window.init;
  285. }
  286. void makeAktiveRenderWindow(ref Window window) nothrow @nogc {
  287. glfwMakeContextCurrent(window.glfwWindow);
  288. }
  289. void swapBuffers(ref Window window) nothrow @nogc {
  290. glfwSwapBuffers(window.glfwWindow);
  291. }
  292. void pollEvents(ref Window window) nothrow @nogc {
  293. glfwPollEvents();
  294. }
  295. @property void setTitle(ref Window window, string title) nothrow {
  296. glfwSetWindowTitle(window.glfwWindow, title.toStringz());
  297. }
  298. KeyAction keyState(ref Window window, int key) pure @safe nothrow {
  299. try {
  300. return window.keyStates.get(key, KeyAction.Released);
  301. }
  302. catch(Exception) {
  303. return KeyAction.Released;
  304. }
  305. }
  306. ButtonAction buttonState(ref Window window, int button) pure @safe nothrow {
  307. try {
  308. return window.buttonStates.get(button, ButtonAction.Released);
  309. }
  310. catch(Exception) {
  311. return ButtonAction.Released;
  312. }
  313. }
  314. //======================================================================================================================
  315. //
  316. //======================================================================================================================
  317. struct Viewport {
  318. }
  319. void construct(out Viewport viewport) pure @safe nothrow @nogc {
  320. }
  321. void destruct(ref Viewport viewport) pure @safe nothrow @nogc {
  322. viewport = Viewport.init;
  323. }
  324. //======================================================================================================================
  325. //
  326. //======================================================================================================================
  327. struct Scene {
  328. SOAMesh mesh;
  329. }
  330. void construct(out Scene scene) pure @safe nothrow @nogc {
  331. }
  332. void destruct(ref Scene scene) pure @safe nothrow @nogc {
  333. scene = Scene.init;
  334. }
  335. //======================================================================================================================
  336. //
  337. //======================================================================================================================
  338. struct Camera {
  339. }
  340. void construct(out Camera camera) pure @safe nothrow @nogc {
  341. }
  342. void destruct(ref Camera camera) pure @safe nothrow @nogc {
  343. camera = Camera.init;
  344. }
  345. //======================================================================================================================
  346. //
  347. //======================================================================================================================
  348. struct RenderTarget {
  349. uint width;
  350. uint height;
  351. GLuint textureTarget;
  352. }
  353. void construct(out RenderTarget renderTarget, uint width, uint height) nothrow {
  354. renderTarget.width = width;
  355. renderTarget.height = height;
  356. glCheck!glGenTextures(1, &renderTarget.textureTarget);
  357. glCheck!glBindTexture(GL_TEXTURE_2D, renderTarget.textureTarget);
  358. glCheck!glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, width, height);
  359. glCheck!glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_FLOAT, null);
  360. glCheck!glBindTexture(GL_TEXTURE_2D, 0);
  361. }
  362. void destruct(ref RenderTarget renderTarget) nothrow {
  363. glCheck!glDeleteTextures(1, &renderTarget.textureTarget);
  364. renderTarget = RenderTarget.init;
  365. }
  366. //======================================================================================================================
  367. //
  368. //======================================================================================================================
  369. struct GBuffer {
  370. uint width;
  371. uint height;
  372. GLuint textureDepth;
  373. GLuint textureNormal;
  374. GLuint textureColor;
  375. GLuint textureDepthStencil;
  376. GLuint fbo;
  377. }
  378. void construct(out GBuffer gBuffer, uint width, uint height) nothrow {
  379. gBuffer.width = width;
  380. gBuffer.width = height;
  381. glCheck!glGenTextures(1, &gBuffer.textureDepth);
  382. glCheck!glBindTexture(GL_TEXTURE_2D, gBuffer.textureDepth);
  383. glCheck!glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  384. glCheck!glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  385. // glCheck!glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  386. // glCheck!glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  387. // glCheck!glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
  388. glCheck!glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH_COMPONENT32F, width, height);
  389. glCheck!glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_DEPTH_COMPONENT, GL_FLOAT, null);
  390. glCheck!glBindTexture(GL_TEXTURE_2D, 0);
  391. glCheck!glGenTextures(1, &gBuffer.textureNormal);
  392. glCheck!glBindTexture(GL_TEXTURE_2D, gBuffer.textureNormal);
  393. glCheck!glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  394. glCheck!glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  395. // glCheck!glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  396. // glCheck!glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  397. glCheck!glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB10_A2, width, height);
  398. glCheck!glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_FLOAT, null);
  399. glCheck!glBindTexture(GL_TEXTURE_2D, 0);
  400. glCheck!glGenTextures(1, &gBuffer.textureColor);
  401. glCheck!glBindTexture(GL_TEXTURE_2D, gBuffer.textureColor);
  402. glCheck!glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
  403. glCheck!glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_FLOAT, null);
  404. glCheck!glBindTexture(GL_TEXTURE_2D, 0);
  405. glCheck!glGenTextures(1, &gBuffer.textureDepthStencil);
  406. glCheck!glBindTexture(GL_TEXTURE_2D, gBuffer.textureDepthStencil);
  407. glCheck!glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, width, height);
  408. glCheck!glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, null);
  409. glCheck!glBindTexture(GL_TEXTURE_2D, 0);
  410. glCheck!glGenFramebuffers(1, &gBuffer.fbo);
  411. glCheck!glBindFramebuffer(GL_DRAW_FRAMEBUFFER, gBuffer.fbo);
  412. glCheck!glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + 0, GL_TEXTURE_2D, gBuffer.textureDepth, 0);
  413. glCheck!glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + 1, GL_TEXTURE_2D, gBuffer.textureNormal, 0);
  414. glCheck!glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + 2, GL_TEXTURE_2D, gBuffer.textureColor, 0);
  415. glCheck!glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, gBuffer.textureDepthStencil, 0);
  416. glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
  417. }
  418. void destruct(ref GBuffer gBuffer) nothrow {
  419. glCheck!glDeleteFramebuffers(1, &gBuffer.fbo);
  420. glCheck!glDeleteTextures(1, &gBuffer.textureDepthStencil);
  421. glCheck!glDeleteTextures(1, &gBuffer.textureColor);
  422. glCheck!glDeleteTextures(1, &gBuffer.textureNormal);
  423. glCheck!glDeleteTextures(1, &gBuffer.textureDepth);
  424. gBuffer = GBuffer.init;
  425. }
  426. struct Pipeline {
  427. GLuint pipeline;
  428. GLuint vertexShaderGeometryPass;
  429. GLuint fragmentShaderGeometryPass;
  430. }
  431. void construct(out Pipeline pipeline) nothrow {
  432. glGenProgramPipelines(1, &pipeline.pipeline);
  433. }
  434. void destruct(ref Pipeline pipeline) nothrow {
  435. glDeleteProgramPipelines(1, &pipeline.pipeline);
  436. pipeline = Pipeline.init;
  437. }
  438. struct OpenGlTiledDeferredRenderer {
  439. GBuffer gBuffer;
  440. Pipeline pipeline;
  441. }
  442. void construct(out OpenGlTiledDeferredRenderer deferredRenderer, uint width, uint height) nothrow {
  443. deferredRenderer.gBuffer.construct(width, height);
  444. }
  445. void destruct(ref OpenGlTiledDeferredRenderer deferredRenderer) nothrow {
  446. deferredRenderer.gBuffer.destruct();
  447. deferredRenderer = OpenGlTiledDeferredRenderer.init;
  448. }
  449. // draw the scene supersampled with renderer's with+height onto renderTarget at position+size of viewport
  450. void renderOneFrame(ref OpenGlTiledDeferredRenderer renderer, ref Scene scene, ref Camera camera, ref RenderTarget renderTarget, ref Viewport viewport) nothrow {
  451. // 1. Render the (opaque) geometry into the G-Buffers.
  452. // 2. Construct a screen space grid, covering the frame buffer, with some fixed tile
  453. // size, t = (x, y), e.g. 32 × 32 pixels.
  454. // 3. For each light: find the screen space extents of the light volume and append the
  455. // light ID to each affected grid cell.
  456. // 4. For each fragment in the frame buffer, with location f = (x, y).
  457. // (a) sample the G-Buffers at f.
  458. // (b) accumulate light contributions from all lights in tile at ⌊f /t⌋
  459. // (c) output total light contributions to frame buffer at f
  460. with(renderer.gBuffer) glCheck!glViewport(0, 0, width, height);
  461. //enable depth mask _before_ glClear ing the depth buffer!
  462. glCheck!glDepthMask(GL_TRUE); scope(exit) glCheck!glDepthMask(GL_FALSE);
  463. glCheck!glEnable(GL_DEPTH_TEST); scope(exit) glCheck!glDisable(GL_DEPTH_TEST);
  464. glCheck!glDepthFunc(GL_LEQUAL);
  465. //bind gBuffer
  466. glCheck!glBindFramebuffer(GL_DRAW_FRAMEBUFFER, renderer.gBuffer.fbo); scope(exit) glCheck!glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
  467. glCheck!glDrawBuffer(GL_COLOR_ATTACHMENT0 + 0);
  468. glCheck!glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
  469. GLenum[] drawBuffers = [GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2];
  470. glCheck!glDrawBuffers(drawBuffers.length, drawBuffers.ptr);
  471. glCheck!glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
  472. //bind pipeline
  473. glCheck!glBindProgramPipeline(renderer.pipeline.pipeline); scope(exit) glCheck!glBindProgramPipeline(0);
  474. {// Draw Geometry
  475. scope(exit) glCheck!glBindVertexArray(0);
  476. scope(exit) glCheck!glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); // TODO: GL_ELEMENT_ARRAY_BUFFER should be vao state, but bugs might make this necessary
  477. for(size_t meshIdx = 0; meshIdx < scene.mesh.cnt; ++meshIdx) {
  478. glCheck!glBindVertexArray(scene.mesh.vao[meshIdx]);
  479. glCheck!glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, scene.mesh.vboIndices[meshIdx]); // TODO: GL_ELEMENT_ARRAY_BUFFER should be vao state, but bugs might make this necessary
  480. glCheck!glDrawElements(GL_TRIANGLES, scene.mesh.cntIndices[meshIdx], GL_UNSIGNED_SHORT, null);
  481. }
  482. }
  483. }
  484. //======================================================================================================================
  485. //
  486. //======================================================================================================================
  487. struct SOAMesh {
  488. SoA!GLuint vao;
  489. SoA!GLuint vboVertices;
  490. SoA!GLuint vboNormals;
  491. SoA!GLuint vboTexcoords;
  492. SoA!GLuint vboColors;
  493. SoA!GLuint vboIndices;
  494. SoA!GLuint cntIndices;
  495. size_t cnt;
  496. }
  497. void loadModel(ref SOAMesh mesh, string filePath) {
  498. import std.traits;
  499. auto scene = aiImportFile(filePath.toStringz(), aiProcess_Triangulate); scope(exit) aiReleaseImport(scene);
  500. for(uint m = 0; m < scene.mNumMeshes; ++m) {
  501. const(aiMesh*) meshData = scene.mMeshes[m];
  502. assert(meshData !is null);
  503. //-----------------------------
  504. // create mesh
  505. auto meshIdx = mesh.cnt;
  506. ++mesh.cnt;
  507. mesh.vao.length = mesh.cnt;
  508. mesh.vboVertices.length = mesh.cnt;
  509. mesh.vboNormals.length = mesh.cnt;
  510. mesh.vboTexcoords.length = mesh.cnt;
  511. mesh.vboIndices.length = mesh.cnt;
  512. mesh.cntIndices.length = mesh.cnt;
  513. //-----------------------------
  514. // upload data
  515. glCheck!glGenVertexArrays(1, &mesh.vao[meshIdx]);
  516. glCheck!glBindVertexArray(mesh.vao[meshIdx]); scope(exit) glCheck!glBindVertexArray(0);
  517. alias Vertex = float[3];
  518. alias Normal = float[3];
  519. alias TexCoord = float[2];
  520. alias Color = float[4];
  521. alias Index = uint[1];
  522. size_t cntIndices = 0;
  523. foreach(f; 0..meshData.mNumFaces) {
  524. cntIndices += meshData.mFaces[f].mNumIndices;
  525. }
  526. {// upload vertex data
  527. Vertex[] vertexData;
  528. vertexData.length = meshData.mNumVertices;
  529. foreach(v; 0..meshData.mNumVertices) {
  530. vertexData[v] = [meshData.mVertices[v].x, meshData.mVertices[v].y, meshData.mVertices[v].z];
  531. }
  532. glCheck!glGenBuffers(1, &mesh.vboVertices[meshIdx]);
  533. glCheck!glBindBuffer(GL_ARRAY_BUFFER, mesh.vboVertices[meshIdx]); scope(exit) glCheck!glBindBuffer(GL_ARRAY_BUFFER, 0);
  534. GLuint attribIndex = 0;
  535. glCheck!glBufferData(GL_ARRAY_BUFFER, cast(ptrdiff_t)(Vertex.sizeof * vertexData.length) , vertexData.ptr, GL_STATIC_DRAW);
  536. glCheck!glEnableVertexAttribArray(attribIndex);
  537. glCheck!glVertexAttribPointer(attribIndex, Vertex.sizeof / ForeachType!Vertex.sizeof, GL_FLOAT, GL_FALSE, 0, cast(void*)0);
  538. }
  539. {// upload normal data
  540. Normal[] normalData;
  541. normalData.length = meshData.mNumVertices;
  542. foreach(v; 0..meshData.mNumVertices) {
  543. normalData[v] = [meshData.mNormals[v].x, meshData.mNormals[v].y, meshData.mNormals[v].z];
  544. }
  545. glCheck!glGenBuffers(1, &mesh.vboNormals[meshIdx]);
  546. glCheck!glBindBuffer(GL_ARRAY_BUFFER, mesh.vboNormals[meshIdx]); scope(exit) glCheck!glBindBuffer(GL_ARRAY_BUFFER, 0);
  547. GLuint attribIndex = 1;
  548. glCheck!glBufferData(GL_ARRAY_BUFFER, cast(ptrdiff_t)(Normal.sizeof * normalData.length) , normalData.ptr, GL_STATIC_DRAW);
  549. glCheck!glEnableVertexAttribArray(attribIndex);
  550. glCheck!glVertexAttribPointer(attribIndex, Normal.sizeof / ForeachType!Normal.sizeof, GL_FLOAT, GL_FALSE, 0, cast(void*)0);
  551. }
  552. if(meshData.mTextureCoords[0] !is null) {// upload texture data
  553. TexCoord[] textureData;
  554. textureData.length = meshData.mNumVertices;
  555. foreach(v; 0..meshData.mNumVertices) {
  556. textureData[v] = [meshData.mTextureCoords[0][v].x, meshData.mTextureCoords[0][v].y];
  557. }
  558. glCheck!glGenBuffers(1, &mesh.vboTexcoords[meshIdx]);
  559. glCheck!glBindBuffer(GL_ARRAY_BUFFER, mesh.vboTexcoords[meshIdx]); scope(exit) glCheck!glBindBuffer(GL_ARRAY_BUFFER, 0);
  560. GLuint attribIndex = 2;
  561. glBufferData(GL_ARRAY_BUFFER, cast(ptrdiff_t)(TexCoord.sizeof * textureData.length) , textureData.ptr, GL_STATIC_DRAW);
  562. glEnableVertexAttribArray(attribIndex);
  563. glVertexAttribPointer(attribIndex, TexCoord.sizeof / ForeachType!TexCoord.sizeof, GL_FLOAT, GL_FALSE, 0, cast(void*)0);
  564. }
  565. if(meshData.mColors[0] !is null) {// upload color data
  566. Color[] colorData;
  567. colorData.length = meshData.mNumVertices;
  568. foreach(v; 0..meshData.mNumVertices) {
  569. colorData[v] = [meshData.mColors[0][v].r, meshData.mColors[0][v].g, meshData.mColors[0][v].b, meshData.mColors[0][v].a];
  570. }
  571. glCheck!glGenBuffers(1, &mesh.vboTexcoords[meshIdx]);
  572. glCheck!glBindBuffer(GL_ARRAY_BUFFER, mesh.vboTexcoords[meshIdx]); scope(exit) glCheck!glBindBuffer(GL_ARRAY_BUFFER, 0);
  573. GLuint attribIndex = 2;
  574. glBufferData(GL_ARRAY_BUFFER, cast(ptrdiff_t)(Color.sizeof * colorData.length) , colorData.ptr, GL_STATIC_DRAW);
  575. glEnableVertexAttribArray(attribIndex);
  576. glVertexAttribPointer(attribIndex, Color.sizeof / ForeachType!Color.sizeof, GL_FLOAT, GL_FALSE, 0, cast(void*)0);
  577. }
  578. {// upload index data
  579. Index[] indexData;
  580. indexData.length = cntIndices;
  581. size_t curIndexDataIdx = 0;
  582. foreach(f; 0..meshData.mNumFaces) {
  583. assert(meshData.mFaces !is null);
  584. foreach(i; 0..meshData.mFaces[f].mNumIndices) {
  585. assert(meshData.mFaces[f].mIndices !is null);
  586. indexData[curIndexDataIdx++] = meshData.mFaces[f].mIndices[i];
  587. }
  588. }
  589. glCheck!glGenBuffers(1, &mesh.vboIndices[meshIdx]);
  590. glCheck!glBindBuffer(GL_ARRAY_BUFFER, mesh.vboIndices[meshIdx]); scope(exit) glCheck!glBindBuffer(GL_ARRAY_BUFFER, 0);
  591. GLuint attribIndex = 3;
  592. glCheck!glBufferData(GL_ARRAY_BUFFER, cast(ptrdiff_t)(Index.sizeof * indexData.length) , indexData.ptr, GL_STATIC_DRAW);
  593. glCheck!glEnableVertexAttribArray(attribIndex);
  594. glCheck!glVertexAttribPointer(attribIndex, Index.sizeof / ForeachType!Index.sizeof, GL_UNSIGNED_INT, GL_FALSE, 0, cast(void*)0);
  595. }
  596. }
  597. }
  598. //======================================================================================================================
  599. //
  600. //======================================================================================================================
  601. void main() {
  602. Window window;
  603. Viewport viewport;
  604. Scene scene;
  605. Camera camera;
  606. RenderTarget renderTarget;
  607. OpenGlTiledDeferredRenderer renderer;
  608. DerelictGL3.load();
  609. DerelictGLFW3.load();
  610. DerelictFI.load();
  611. // DerelictFT.load();
  612. DerelictASSIMP3.load();
  613. DerelictAntTweakBar.load();
  614. if(!glfwInit()) throw new Exception("Initialising GLFW failed"); scope(exit) glfwTerminate();
  615. window.construct("Three.d", 1600, 900); scope(exit) window.destruct();
  616. try {
  617. GLVersion glVersion = DerelictGL3.reload();
  618. import std.conv : to;
  619. writeln("Reloaded OpenGL Version: ", to!string(glVersion));
  620. } catch(Exception e) {
  621. writeln("Reloading OpenGl failed: " ~ e.msg);
  622. }
  623. // static FT_Library _s_freeTypeLibrary
  624. // if(!FT_Init_FreeType(&_s_freeTypeLibrary)) throw new Exception("Initialising FreeType failed"); scope(exit) FT_Done_FreeType(_s_freeTypeLibrary);
  625. if(TwInit(TW_OPENGL_CORE, null) == 0) throw new Exception("Initialising AntTweakBar failed"); scope(exit) TwTerminate();
  626. viewport.construct(); scope(exit) window.destruct();
  627. scene.construct(); scope(exit) window.destruct();
  628. camera.construct(); scope(exit) window.destruct();
  629. renderTarget.construct(window.width, window.height); scope(exit) renderTarget.destruct();
  630. renderer.construct(window.width, window.height); scope(exit) renderer.destruct();
  631. scene.mesh.loadModel("C:/Coding/models/Collada/duck.dae");
  632. while(true) {
  633. window.pollEvents();
  634. window.makeAktiveRenderWindow();
  635. glCheck!glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  636. glCheck!glClearDepth(1.0f);
  637. glCheck!glClearColor(0.5, 0, 0, 1);
  638. renderer.renderOneFrame(scene, camera, renderTarget, viewport);
  639. window.swapBuffers();
  640. }
  641. }
  642. /+++
  643. struct Vertex {
  644. float x, y, z;
  645. }
  646. struct Normal {
  647. float x, y, z;
  648. }
  649. struct UV {
  650. float u, v;
  651. }
  652. final class Mesh {
  653. public:
  654. Vertex[] vertexData;
  655. Normal[] normalData;
  656. UV[] textureData;
  657. RGBAf[] colorData;
  658. VertexArrayObject vao;
  659. VertexBufferObject!(VertexBufferObjectTarget.Array) vboVertexData;
  660. VertexBufferObject!(VertexBufferObjectTarget.Array) vboNormalData;
  661. VertexBufferObject!(VertexBufferObjectTarget.Array) vboTextureData;
  662. VertexBufferObject!(VertexBufferObjectTarget.Array) vboColorData;
  663. this(string filePath) {
  664. writeln("loading scene: ", filePath);
  665. auto scene = aiImportFile(filePath.toStringz(), aiProcess_Triangulate);
  666. writeln("meshes: ", scene.mNumMeshes);
  667. for(uint m = 0; m < scene.mNumMeshes; ++m) {
  668. const(aiMesh*) mesh = scene.mMeshes[m];
  669. assert(mesh !is null);
  670. writeln("mesh[", m, "] faces : ", mesh.mNumFaces);
  671. for (uint f = 0; f < mesh.mNumFaces; ++f) {
  672. const(aiFace*) face = &mesh.mFaces[f];
  673. assert(face !is null);
  674. for(uint v = 0; v < 3; ++v) {
  675. aiVector3D p, n, uv;
  676. assert(face.mNumIndices > v);
  677. uint vertex = face.mIndices[v];
  678. assert(mesh.mNumVertices > vertex);
  679. p = mesh.mVertices[vertex];
  680. n = mesh.mNormals[vertex];
  681. // check if the mesh has texture coordinates
  682. if(mesh.mTextureCoords[0] !is null) {
  683. uv = mesh.mTextureCoords[0][vertex];
  684. }
  685. vertexData ~= Vertex(p.x, p.y, p.z);
  686. normalData ~= Normal(n.x, n.y, n.z);
  687. textureData ~= UV(uv.x, uv.y);
  688. colorData ~= RGBAf(n.x, n.y, n.z, 1.0f);
  689. }
  690. }
  691. }
  692. writeln("unloading scene: ", filePath);
  693. aiReleaseImport(scene);
  694. //-----------------------------
  695. // upload
  696. writeln("uploading mesh: ", filePath);
  697. vao = new VertexArrayObject();
  698. vao.bind();
  699. writeln("vertex data");
  700. vboVertexData = new VertexBufferObject!(VertexBufferObjectTarget.Array);
  701. vboVertexData.bind();
  702. GLuint attribIndex = 0;
  703. glBufferData(GL_ARRAY_BUFFER, cast(ptrdiff_t)(Vertex.sizeof * vertexData.length) , vertexData.ptr, GL_STATIC_DRAW);
  704. glEnableVertexAttribArray(attribIndex);
  705. glVertexAttribPointer(attribIndex, 3, GL_FLOAT, GL_FALSE, 0, cast(void*)0);
  706. vboVertexData.unbind();
  707. writeln("normal data");
  708. vboNormalData = new VertexBufferObject!(VertexBufferObjectTarget.Array);
  709. vboNormalData.bind();
  710. attribIndex = 1;
  711. glBufferData(GL_ARRAY_BUFFER, cast(ptrdiff_t)(Normal.sizeof * normalData.length) , normalData.ptr, GL_STATIC_DRAW);
  712. glEnableVertexAttribArray(attribIndex);
  713. glVertexAttribPointer(attribIndex, 3, GL_FLOAT, GL_FALSE, 0, cast(void*)0);
  714. vboNormalData.unbind();
  715. writeln("uv data");
  716. vboTextureData = new VertexBufferObject!(VertexBufferObjectTarget.Array);
  717. vboTextureData.bind();
  718. attribIndex = 2;
  719. glBufferData(GL_ARRAY_BUFFER, cast(ptrdiff_t)(UV.sizeof * textureData.length) , textureData.ptr, GL_STATIC_DRAW);
  720. glEnableVertexAttribArray(attribIndex);
  721. glVertexAttribPointer(attribIndex, 2, GL_FLOAT, GL_FALSE, 0, cast(void*)0);
  722. vboTextureData.unbind();
  723. writeln("color data");
  724. vboColorData = new VertexBufferObject!(VertexBufferObjectTarget.Array);
  725. vboColorData.bind();
  726. attribIndex = 3;
  727. glBufferData(GL_ARRAY_BUFFER, cast(ptrdiff_t)(RGBAf.sizeof * colorData.length) , colorData.ptr, GL_STATIC_DRAW);
  728. glEnableVertexAttribArray(attribIndex);
  729. glVertexAttribPointer(attribIndex, 4, GL_FLOAT, GL_FALSE, 0, cast(void*)0);
  730. vboColorData.unbind();
  731. vao.unbind();
  732. writeln("done");
  733. }
  734. }
  735. void setupTweakbar() {
  736. writeln("creating TweakBar");
  737. double time = 0, dt; // Current time and enlapsed time
  738. double turn = 0; // Model turn counter
  739. double speed = 0.3; // Model rotation speed
  740. int wire = 0; // Draw model in wireframe?
  741. uint frameCount = 0;
  742. double fps = 0;
  743. float bgColor[3] = [0.1f, 0.2f, 0.4f]; // Background color
  744. ubyte cubeColor[4] = [255, 0, 0, 128]; // Model color (32bits RGBA)
  745. auto quat = Quaternionf(0,0,0,1);
  746. // auto w = this._window.getBounds()[2];
  747. // auto h = this._window.getBounds()[3];
  748. TwWindowSize(1600, 900);
  749. // // Create a tweak bar
  750. // auto bar = TwNewBar("TweakBar");
  751. // TwDefine(" GLOBAL help='This example shows how to integrate AntTweakBar with GLFW and OpenGL.' "); // Message added to the help bar.
  752. // // Add 'speed' to 'bar': it is a modifable (RW) variable of type TW_TYPE_DOUBLE. Its key shortcuts are [s] and [S].
  753. // TwAddVarRW(bar, "speed", TW_TYPE_DOUBLE, &speed, " label='Rot speed' min=0 max=2 step=0.01 keyIncr=s keyDecr=S help='Rotation speed (turns/second)' ");
  754. // // Add 'wire' to 'bar': it is a modifable variable of type TW_TYPE_BOOL32 (32 bits boolean). Its key shortcut is [w].
  755. // TwAddVarRW(bar, "wire", TW_TYPE_BOOL32, &wire, " label='Wireframe mode' key=CTRL+w help='Toggle wireframe display mode.' ");
  756. // // Add 'time' to 'bar': it is a read-only (RO) variable of type TW_TYPE_DOUBLE, with 1 precision digit
  757. // TwAddVarRO(bar, "time", TW_TYPE_DOUBLE, &time, " label='Time' precision=1 help='Time (in seconds).' ");
  758. // //
  759. // TwAddVarRO(bar, "frameCount", TW_TYPE_UINT32, &frameCount, " label='FrameCount' precision=1 help='FrameCount (in counts).' ");
  760. // TwAddVarRO(bar, "fps", TW_TYPE_DOUBLE, &fps, " label='fps' precision=1 help='fps (in fps).' ");
  761. // // Add 'bgColor' to 'bar': it is a modifable variable of type TW_TYPE_COLOR3F (3 floats color)
  762. // TwAddVarRW(bar, "bgColor", TW_TYPE_COLOR3F, &bgColor, " label='Background color' ");
  763. // // Add 'cubeColor' to 'bar': it is a modifable variable of type TW_TYPE_COLOR32 (32 bits color) with alpha
  764. // TwAddVarRW(bar, "cubeColor", TW_TYPE_COLOR32, &cubeColor, " label='Cube color' alpha help='Color and transparency of the cube.' ");
  765. // //
  766. // TwAddVarRW(bar, "quaternion", TW_TYPE_QUAT4F, &quat, " label='Cubde color' alpha help='Color anwdwd transparency of the cube.' ");
  767. }
  768. //-----------------
  769. // Create Shaders
  770. enum vertexShaderSource = "
  771. #version 420 core
  772. layout(location = 0) in vec3 in_position;
  773. layout(location = 1) in vec3 in_normal;
  774. layout(location = 2) in vec2 in_texcoord;
  775. layout(location = 3) in vec4 in_color;
  776. out vec4 v_color;
  777. out gl_PerVertex
  778. {
  779. vec4 gl_Position;
  780. };
  781. void main()
  782. {
  783. gl_Position = vec4(0.005 * in_position.x, 0.005 * in_position.y, 0.005* in_position.z, 1.0);
  784. v_color = in_color;
  785. }
  786. ";
  787. enum fragmentShaderSource = "
  788. #version 420 core
  789. in vec4 v_color;
  790. out vec4 FragColor;
  791. void main()
  792. {
  793. FragColor = v_color;
  794. }
  795. ";
  796. auto createShaderPipeline(Shader!(ShaderType.Vertex) vertexShader, Shader!(ShaderType.Fragment) fragmentShader) {
  797. assert(vertexShader.isLinked, vertexShader.infoLog());
  798. assert(fragmentShader.isLinked, fragmentShader.infoLog());
  799. writeln("a: ");
  800. auto shaderPipeline = new ShaderPipeline();
  801. shaderPipeline.bind();
  802. shaderPipeline.use(vertexShader);
  803. shaderPipeline.use(fragmentShader);
  804. writeln("b: ");
  805. assert(shaderPipeline.isValidProgramPipeline, shaderPipeline.infoLog());
  806. shaderPipeline.unbind();
  807. writeln("c: ");
  808. return shaderPipeline;
  809. }
  810. class Tester {
  811. Window _window;
  812. bool _keepRunning = true;
  813. this() {
  814. this._window = initThree();
  815. this._window.onKey.connect!"_onKey"(this);
  816. this._window.onClose.connect!"_onClose"(this);
  817. }
  818. ~this() {
  819. import core.memory;
  820. writeln("GC.collect: ");
  821. GC.collect();
  822. //Collect window _AFTER_ everything else
  823. this._window = null;
  824. GC.collect();
  825. deinitThree();
  826. }
  827. void run() {
  828. RGBAf rgg;
  829. auto mesh = new Mesh("C:/Coding/models/Collada/duck.dae");
  830. setupTweakbar();
  831. writeln("creating shaders: ");
  832. auto vertexShader = new Shader!(ShaderType.Vertex)(vertexShaderSource);
  833. auto fragmentShader = new Shader!(ShaderType.Fragment)(fragmentShaderSource);
  834. writeln("creating shader pipeline: ");
  835. auto shaderPipeline = createShaderPipeline(vertexShader, fragmentShader);
  836. writeln("connectiong window callbacks: ");
  837. this._window.onSize.connect!"onSize"(this);
  838. this._window.onPosition.connect!"onPosition"(this);
  839. this._window.onButton.connect!"onButton"(this);
  840. this._window.onCursorPos.connect!"onCursorPos"(this);
  841. writeln("begin render loop: ");
  842. //-----------------
  843. // Render Loop
  844. glfwSetTime(0);
  845. while(this._keepRunning) {
  846. this._window.clear(0, 0, 0.5, 1);
  847. shaderPipeline.bind();
  848. mesh.vao.bind();
  849. //vboVertexData.bind();
  850. glDrawArrays(GL_TRIANGLES, 0, mesh.vertexData.length);
  851. //vbo.unbind();
  852. mesh.vao.unbind();
  853. shaderPipeline.unbind();
  854. TwDraw();
  855. this._window.swapBuffers();
  856. updateWindows();
  857. // ++frameCount;
  858. // //if(frameCount % 100 == 0) {
  859. // time = glfwGetTime();
  860. // fps = cast(double)frameCount / time;
  861. // //}
  862. }
  863. }
  864. void onSize(Window window, int width, int height) {
  865. TwWindowSize(width, height);
  866. }
  867. void onPosition(Window window, int x, int y) {
  868. }
  869. void onButton(Window window , int button, ButtonAction action) {
  870. TwMouseAction twaction = action == ButtonAction.Pressed ? TW_MOUSE_PRESSED : TW_MOUSE_RELEASED;
  871. TwMouseButtonID twbutton;
  872. switch(button) {
  873. default:
  874. case GLFW_MOUSE_BUTTON_LEFT: twbutton = TW_MOUSE_LEFT; break;
  875. case GLFW_MOUSE_BUTTON_RIGHT: twbutton = TW_MOUSE_RIGHT; break;
  876. case GLFW_MOUSE_BUTTON_MIDDLE: twbutton = TW_MOUSE_MIDDLE; break;
  877. }
  878. TwMouseButton(twaction, twbutton);
  879. }
  880. void onCursorPos(Window window, double x, double y) {
  881. TwMouseMotion(cast(int)x, this._window.getBounds()[3] - cast(int)y);
  882. }
  883. void stop() {
  884. this._keepRunning = false;
  885. }
  886. void _onKey(Window window, Key key, ScanCode scanCode, KeyAction action, KeyMod keyMod) {
  887. if(window is this._window && action == KeyAction.Pressed) {
  888. if(key == Key.Escape) {
  889. this.stop();
  890. }
  891. }
  892. }
  893. void _onClose(Window window) {
  894. this.stop();
  895. }
  896. }
  897. class InputHandler {
  898. private:
  899. Window _window;
  900. OpenGlRenderer _renderer;
  901. public:
  902. this(Window window, OpenGlRenderer renderer) {
  903. _window = window;
  904. _renderer = renderer;
  905. _window.onKey.connect!"_onKey"(this);
  906. _window.onClose.connect!"_onClose"(this);
  907. _window.onSize.connect!"_onSize"(this);
  908. _window.onPosition.connect!"_onPosition"(this);
  909. _window.onButton.connect!"_onButton"(this);
  910. _window.onCursorPos.connect!"_onCursorPos"(this);
  911. }
  912. private:
  913. void _onKey(Window window, Key key, ScanCode scanCode, KeyAction action, KeyMod keyMod) {
  914. if(window is _window && action == KeyAction.Pressed) {
  915. if(key == Key.Escape) {
  916. _renderer.stop();
  917. }
  918. }
  919. }
  920. void _onClose(Window window) {
  921. _renderer.stop();
  922. }
  923. void _onSize(Window window, int width, int height) {
  924. }
  925. void _onPosition(Window window, int x, int y) {
  926. }
  927. void _onButton(Window window , int button, ButtonAction action) {
  928. }
  929. void _onCursorPos(Window window, double x, double y) {
  930. }
  931. }
  932. void main() {
  933. auto window = initThree();
  934. {
  935. OpenGlRenderer renderer = new OpenGlRenderer(window);
  936. InputHandler inputHandler = new InputHandler(window, renderer);
  937. renderer.run();
  938. }
  939. import core.memory;
  940. GC.collect();
  941. //Collect window _AFTER_ everything else
  942. this._window = null;
  943. GC.collect();
  944. deinitThree();
  945. }
  946. +++/