app.d 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525
  1. import std.stdio;
  2. import std.typecons;
  3. import three;
  4. import std.experimental.logger;
  5. //======================================================================================================================
  6. //
  7. //======================================================================================================================
  8. struct SOAVector3 {
  9. SoA!float x;
  10. SoA!float y;
  11. SoA!float z;
  12. }
  13. struct SOAQuaternion {
  14. SoA!float x;
  15. SoA!float y;
  16. SoA!float z;
  17. SoA!float w;
  18. }
  19. //======================================================================================================================
  20. //
  21. //======================================================================================================================
  22. void main() {
  23. Window window;
  24. Viewport viewport;
  25. Scene scene;
  26. Camera camera;
  27. RenderTarget renderTarget;
  28. OpenGlTiledDeferredRenderer renderer;
  29. bool keepRunning = true;
  30. DerelictGL3.load();
  31. DerelictGLFW3.load();
  32. DerelictFI.load();
  33. // DerelictFT.load();
  34. DerelictASSIMP3.load();
  35. DerelictAntTweakBar.load();
  36. if(!glfwInit()) throw new Exception("Initialising GLFW failed"); scope(exit) glfwTerminate();
  37. window.construct("Three.d", 1600, 900); scope(exit) window.destruct();
  38. try {
  39. GLVersion glVersion = DerelictGL3.reload();
  40. import std.conv : to;
  41. writeln("Reloaded OpenGL Version: ", to!string(glVersion));
  42. } catch(Exception e) {
  43. writeln("Reloading OpenGl failed: " ~ e.msg);
  44. }
  45. // static FT_Library _s_freeTypeLibrary
  46. // if(!FT_Init_FreeType(&_s_freeTypeLibrary)) throw new Exception("Initialising FreeType failed"); scope(exit) FT_Done_FreeType(_s_freeTypeLibrary);
  47. if(TwInit(TW_OPENGL_CORE, null) == 0) throw new Exception("Initialising AntTweakBar failed"); scope(exit) TwTerminate();
  48. viewport.construct(); scope(exit) window.destruct();
  49. scene.construct(); scope(exit) window.destruct();
  50. camera.construct(); scope(exit) window.destruct();
  51. renderTarget.construct(window.width, window.height); scope(exit) renderTarget.destruct();
  52. renderer.construct(window.width, window.height); scope(exit) renderer.destruct();
  53. scene.mesh.loadModel("C:/Coding/models/Collada/duck.dae");
  54. TwWindowSize(window.width, window.height);
  55. auto tweakBar = TwNewBar("TweakBar");
  56. window.onKey = (Window* pWindow, Key key, ScanCode scanCode, KeyAction action, KeyMod keyMod) {
  57. if(window is window && action == KeyAction.Pressed) {
  58. if(key == Key.Escape) {
  59. keepRunning = false;
  60. }
  61. }
  62. };
  63. window.onClose = (Window* pWindow) {
  64. keepRunning = false;
  65. };
  66. window.onSize = (Window* pWindow, int width, int height) {
  67. TwWindowSize(width, height);
  68. };
  69. window.onPosition = (Window* pWindow, int x, int y) {
  70. };
  71. window.onButton = (Window* pWindow , int button, ButtonAction action) {
  72. TwMouseAction twaction = action == ButtonAction.Pressed ? TW_MOUSE_PRESSED : TW_MOUSE_RELEASED;
  73. TwMouseButtonID twbutton;
  74. switch(button) {
  75. default:
  76. case GLFW_MOUSE_BUTTON_LEFT: twbutton = TW_MOUSE_LEFT; break;
  77. case GLFW_MOUSE_BUTTON_RIGHT: twbutton = TW_MOUSE_RIGHT; break;
  78. case GLFW_MOUSE_BUTTON_MIDDLE: twbutton = TW_MOUSE_MIDDLE; break;
  79. }
  80. TwMouseButton(twaction, twbutton);
  81. };
  82. window.onCursorPos = (Window* pWindow, double x, double y) {
  83. TwMouseMotion(cast(int)x, window.height - cast(int)y);
  84. };
  85. while(keepRunning) {
  86. window.pollEvents();
  87. window.makeAktiveRenderWindow();
  88. glCheck!glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  89. glCheck!glClearDepth(1.0f);
  90. glCheck!glClearColor(0.5, 0, 0, 1);
  91. renderer.renderOneFrame(scene, camera, renderTarget, viewport);
  92. TwDraw();
  93. window.swapBuffers();
  94. }
  95. }
  96. /+++
  97. struct Vertex {
  98. float x, y, z;
  99. }
  100. struct Normal {
  101. float x, y, z;
  102. }
  103. struct UV {
  104. float u, v;
  105. }
  106. final class Mesh {
  107. public:
  108. Vertex[] vertexData;
  109. Normal[] normalData;
  110. UV[] textureData;
  111. RGBAf[] colorData;
  112. VertexArrayObject vao;
  113. VertexBufferObject!(VertexBufferObjectTarget.Array) vboVertexData;
  114. VertexBufferObject!(VertexBufferObjectTarget.Array) vboNormalData;
  115. VertexBufferObject!(VertexBufferObjectTarget.Array) vboTextureData;
  116. VertexBufferObject!(VertexBufferObjectTarget.Array) vboColorData;
  117. this(string filePath) {
  118. writeln("loading scene: ", filePath);
  119. auto scene = aiImportFile(filePath.toStringz(), aiProcess_Triangulate);
  120. writeln("meshes: ", scene.mNumMeshes);
  121. for(uint m = 0; m < scene.mNumMeshes; ++m) {
  122. const(aiMesh*) mesh = scene.mMeshes[m];
  123. assert(mesh !is null);
  124. writeln("mesh[", m, "] faces : ", mesh.mNumFaces);
  125. for (uint f = 0; f < mesh.mNumFaces; ++f) {
  126. const(aiFace*) face = &mesh.mFaces[f];
  127. assert(face !is null);
  128. for(uint v = 0; v < 3; ++v) {
  129. aiVector3D p, n, uv;
  130. assert(face.mNumIndices > v);
  131. uint vertex = face.mIndices[v];
  132. assert(mesh.mNumVertices > vertex);
  133. p = mesh.mVertices[vertex];
  134. n = mesh.mNormals[vertex];
  135. // check if the mesh has texture coordinates
  136. if(mesh.mTextureCoords[0] !is null) {
  137. uv = mesh.mTextureCoords[0][vertex];
  138. }
  139. vertexData ~= Vertex(p.x, p.y, p.z);
  140. normalData ~= Normal(n.x, n.y, n.z);
  141. textureData ~= UV(uv.x, uv.y);
  142. colorData ~= RGBAf(n.x, n.y, n.z, 1.0f);
  143. }
  144. }
  145. }
  146. writeln("unloading scene: ", filePath);
  147. aiReleaseImport(scene);
  148. //-----------------------------
  149. // upload
  150. writeln("uploading mesh: ", filePath);
  151. vao = new VertexArrayObject();
  152. vao.bind();
  153. writeln("vertex data");
  154. vboVertexData = new VertexBufferObject!(VertexBufferObjectTarget.Array);
  155. vboVertexData.bind();
  156. GLuint attribIndex = 0;
  157. glBufferData(GL_ARRAY_BUFFER, cast(ptrdiff_t)(Vertex.sizeof * vertexData.length) , vertexData.ptr, GL_STATIC_DRAW);
  158. glEnableVertexAttribArray(attribIndex);
  159. glVertexAttribPointer(attribIndex, 3, GL_FLOAT, GL_FALSE, 0, cast(void*)0);
  160. vboVertexData.unbind();
  161. writeln("normal data");
  162. vboNormalData = new VertexBufferObject!(VertexBufferObjectTarget.Array);
  163. vboNormalData.bind();
  164. attribIndex = 1;
  165. glBufferData(GL_ARRAY_BUFFER, cast(ptrdiff_t)(Normal.sizeof * normalData.length) , normalData.ptr, GL_STATIC_DRAW);
  166. glEnableVertexAttribArray(attribIndex);
  167. glVertexAttribPointer(attribIndex, 3, GL_FLOAT, GL_FALSE, 0, cast(void*)0);
  168. vboNormalData.unbind();
  169. writeln("uv data");
  170. vboTextureData = new VertexBufferObject!(VertexBufferObjectTarget.Array);
  171. vboTextureData.bind();
  172. attribIndex = 2;
  173. glBufferData(GL_ARRAY_BUFFER, cast(ptrdiff_t)(UV.sizeof * textureData.length) , textureData.ptr, GL_STATIC_DRAW);
  174. glEnableVertexAttribArray(attribIndex);
  175. glVertexAttribPointer(attribIndex, 2, GL_FLOAT, GL_FALSE, 0, cast(void*)0);
  176. vboTextureData.unbind();
  177. writeln("color data");
  178. vboColorData = new VertexBufferObject!(VertexBufferObjectTarget.Array);
  179. vboColorData.bind();
  180. attribIndex = 3;
  181. glBufferData(GL_ARRAY_BUFFER, cast(ptrdiff_t)(RGBAf.sizeof * colorData.length) , colorData.ptr, GL_STATIC_DRAW);
  182. glEnableVertexAttribArray(attribIndex);
  183. glVertexAttribPointer(attribIndex, 4, GL_FLOAT, GL_FALSE, 0, cast(void*)0);
  184. vboColorData.unbind();
  185. vao.unbind();
  186. writeln("done");
  187. }
  188. }
  189. void setupTweakbar() {
  190. writeln("creating TweakBar");
  191. double time = 0, dt; // Current time and enlapsed time
  192. double turn = 0; // Model turn counter
  193. double speed = 0.3; // Model rotation speed
  194. int wire = 0; // Draw model in wireframe?
  195. uint frameCount = 0;
  196. double fps = 0;
  197. float bgColor[3] = [0.1f, 0.2f, 0.4f]; // Background color
  198. ubyte cubeColor[4] = [255, 0, 0, 128]; // Model color (32bits RGBA)
  199. auto quat = Quaternionf(0,0,0,1);
  200. // auto w = this._window.getBounds()[2];
  201. // auto h = this._window.getBounds()[3];
  202. TwWindowSize(1600, 900);
  203. // // Create a tweak bar
  204. // auto bar = TwNewBar("TweakBar");
  205. // TwDefine(" GLOBAL help='This example shows how to integrate AntTweakBar with GLFW and OpenGL.' "); // Message added to the help bar.
  206. // // Add 'speed' to 'bar': it is a modifable (RW) variable of type TW_TYPE_DOUBLE. Its key shortcuts are [s] and [S].
  207. // 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)' ");
  208. // // Add 'wire' to 'bar': it is a modifable variable of type TW_TYPE_BOOL32 (32 bits boolean). Its key shortcut is [w].
  209. // TwAddVarRW(bar, "wire", TW_TYPE_BOOL32, &wire, " label='Wireframe mode' key=CTRL+w help='Toggle wireframe display mode.' ");
  210. // // Add 'time' to 'bar': it is a read-only (RO) variable of type TW_TYPE_DOUBLE, with 1 precision digit
  211. // TwAddVarRO(bar, "time", TW_TYPE_DOUBLE, &time, " label='Time' precision=1 help='Time (in seconds).' ");
  212. // //
  213. // TwAddVarRO(bar, "frameCount", TW_TYPE_UINT32, &frameCount, " label='FrameCount' precision=1 help='FrameCount (in counts).' ");
  214. // TwAddVarRO(bar, "fps", TW_TYPE_DOUBLE, &fps, " label='fps' precision=1 help='fps (in fps).' ");
  215. // // Add 'bgColor' to 'bar': it is a modifable variable of type TW_TYPE_COLOR3F (3 floats color)
  216. // TwAddVarRW(bar, "bgColor", TW_TYPE_COLOR3F, &bgColor, " label='Background color' ");
  217. // // Add 'cubeColor' to 'bar': it is a modifable variable of type TW_TYPE_COLOR32 (32 bits color) with alpha
  218. // TwAddVarRW(bar, "cubeColor", TW_TYPE_COLOR32, &cubeColor, " label='Cube color' alpha help='Color and transparency of the cube.' ");
  219. // //
  220. // TwAddVarRW(bar, "quaternion", TW_TYPE_QUAT4F, &quat, " label='Cubde color' alpha help='Color anwdwd transparency of the cube.' ");
  221. }
  222. //-----------------
  223. // Create Shaders
  224. enum vertexShaderSource = "
  225. #version 420 core
  226. layout(location = 0) in vec3 in_position;
  227. layout(location = 1) in vec3 in_normal;
  228. layout(location = 2) in vec2 in_texcoord;
  229. layout(location = 3) in vec4 in_color;
  230. out vec4 v_color;
  231. out gl_PerVertex
  232. {
  233. vec4 gl_Position;
  234. };
  235. void main()
  236. {
  237. gl_Position = vec4(0.005 * in_position.x, 0.005 * in_position.y, 0.005* in_position.z, 1.0);
  238. v_color = in_color;
  239. }
  240. ";
  241. enum fragmentShaderSource = "
  242. #version 420 core
  243. in vec4 v_color;
  244. out vec4 FragColor;
  245. void main()
  246. {
  247. FragColor = v_color;
  248. }
  249. ";
  250. auto createShaderPipeline(Shader!(ShaderType.Vertex) vertexShader, Shader!(ShaderType.Fragment) fragmentShader) {
  251. assert(vertexShader.isLinked, vertexShader.infoLog());
  252. assert(fragmentShader.isLinked, fragmentShader.infoLog());
  253. writeln("a: ");
  254. auto shaderPipeline = new ShaderPipeline();
  255. shaderPipeline.bind();
  256. shaderPipeline.use(vertexShader);
  257. shaderPipeline.use(fragmentShader);
  258. writeln("b: ");
  259. assert(shaderPipeline.isValidProgramPipeline, shaderPipeline.infoLog());
  260. shaderPipeline.unbind();
  261. writeln("c: ");
  262. return shaderPipeline;
  263. }
  264. class Tester {
  265. Window _window;
  266. bool _keepRunning = true;
  267. this() {
  268. this._window = initThree();
  269. this._window.onKey.connect!"_onKey"(this);
  270. this._window.onClose.connect!"_onClose"(this);
  271. }
  272. ~this() {
  273. import core.memory;
  274. writeln("GC.collect: ");
  275. GC.collect();
  276. //Collect window _AFTER_ everything else
  277. this._window = null;
  278. GC.collect();
  279. deinitThree();
  280. }
  281. void run() {
  282. RGBAf rgg;
  283. auto mesh = new Mesh("C:/Coding/models/Collada/duck.dae");
  284. setupTweakbar();
  285. writeln("creating shaders: ");
  286. auto vertexShader = new Shader!(ShaderType.Vertex)(vertexShaderSource);
  287. auto fragmentShader = new Shader!(ShaderType.Fragment)(fragmentShaderSource);
  288. writeln("creating shader pipeline: ");
  289. auto shaderPipeline = createShaderPipeline(vertexShader, fragmentShader);
  290. writeln("connectiong window callbacks: ");
  291. this._window.onSize.connect!"onSize"(this);
  292. this._window.onPosition.connect!"onPosition"(this);
  293. this._window.onButton.connect!"onButton"(this);
  294. this._window.onCursorPos.connect!"onCursorPos"(this);
  295. writeln("begin render loop: ");
  296. //-----------------
  297. // Render Loop
  298. glfwSetTime(0);
  299. while(this._keepRunning) {
  300. this._window.clear(0, 0, 0.5, 1);
  301. shaderPipeline.bind();
  302. mesh.vao.bind();
  303. //vboVertexData.bind();
  304. glDrawArrays(GL_TRIANGLES, 0, mesh.vertexData.length);
  305. //vbo.unbind();
  306. mesh.vao.unbind();
  307. shaderPipeline.unbind();
  308. TwDraw();
  309. this._window.swapBuffers();
  310. updateWindows();
  311. // ++frameCount;
  312. // //if(frameCount % 100 == 0) {
  313. // time = glfwGetTime();
  314. // fps = cast(double)frameCount / time;
  315. // //}
  316. }
  317. }
  318. void onSize(Window window, int width, int height) {
  319. TwWindowSize(width, height);
  320. }
  321. void onPosition(Window window, int x, int y) {
  322. }
  323. void onButton(Window window , int button, ButtonAction action) {
  324. TwMouseAction twaction = action == ButtonAction.Pressed ? TW_MOUSE_PRESSED : TW_MOUSE_RELEASED;
  325. TwMouseButtonID twbutton;
  326. switch(button) {
  327. default:
  328. case GLFW_MOUSE_BUTTON_LEFT: twbutton = TW_MOUSE_LEFT; break;
  329. case GLFW_MOUSE_BUTTON_RIGHT: twbutton = TW_MOUSE_RIGHT; break;
  330. case GLFW_MOUSE_BUTTON_MIDDLE: twbutton = TW_MOUSE_MIDDLE; break;
  331. }
  332. TwMouseButton(twaction, twbutton);
  333. }
  334. void onCursorPos(Window window, double x, double y) {
  335. TwMouseMotion(cast(int)x, this._window.getBounds()[3] - cast(int)y);
  336. }
  337. void stop() {
  338. this._keepRunning = false;
  339. }
  340. void _onKey(Window window, Key key, ScanCode scanCode, KeyAction action, KeyMod keyMod) {
  341. if(window is this._window && action == KeyAction.Pressed) {
  342. if(key == Key.Escape) {
  343. this.stop();
  344. }
  345. }
  346. }
  347. void _onClose(Window window) {
  348. this.stop();
  349. }
  350. }
  351. class InputHandler {
  352. private:
  353. Window _window;
  354. OpenGlRenderer _renderer;
  355. public:
  356. this(Window window, OpenGlRenderer renderer) {
  357. _window = window;
  358. _renderer = renderer;
  359. _window.onKey.connect!"_onKey"(this);
  360. _window.onClose.connect!"_onClose"(this);
  361. _window.onSize.connect!"_onSize"(this);
  362. _window.onPosition.connect!"_onPosition"(this);
  363. _window.onButton.connect!"_onButton"(this);
  364. _window.onCursorPos.connect!"_onCursorPos"(this);
  365. }
  366. private:
  367. void _onKey(Window window, Key key, ScanCode scanCode, KeyAction action, KeyMod keyMod) {
  368. if(window is _window && action == KeyAction.Pressed) {
  369. if(key == Key.Escape) {
  370. _renderer.stop();
  371. }
  372. }
  373. }
  374. void _onClose(Window window) {
  375. _renderer.stop();
  376. }
  377. void _onSize(Window window, int width, int height) {
  378. }
  379. void _onPosition(Window window, int x, int y) {
  380. }
  381. void _onButton(Window window , int button, ButtonAction action) {
  382. }
  383. void _onCursorPos(Window window, double x, double y) {
  384. }
  385. }
  386. void main() {
  387. auto window = initThree();
  388. {
  389. OpenGlRenderer renderer = new OpenGlRenderer(window);
  390. InputHandler inputHandler = new InputHandler(window, renderer);
  391. renderer.run();
  392. }
  393. import core.memory;
  394. GC.collect();
  395. //Collect window _AFTER_ everything else
  396. this._window = null;
  397. GC.collect();
  398. deinitThree();
  399. }
  400. +++/