Engine.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. #include "client/Engine.h"
  2. #include "client/rendering/wrapper/GLFWWrapper.h"
  3. bool Engine::useSSAO = true;
  4. float Engine::testRadius = 0.0005;
  5. float Engine::testBias = 0.0005;
  6. bool Engine::ortho = false;
  7. Vector Engine::testOrthoCenter;
  8. static u64 last = 0;
  9. static u64 sum = 0;
  10. static u64 tindex = 0;
  11. static std::array<u64, 128> values;
  12. Engine::Engine(Shaders& shaders, Framebuffers& fb, const Keys& keys, const MouseButtons& buttons, const WindowSize& size) :
  13. shaders(shaders), fb(fb), keys(keys), buttons(buttons), game(keys, buttons), frustum(60.0f, 0.1f, 80.0f),
  14. ssaoNoise(4, 4), size(size), running(!shaders.hasError() && !fb.hasError()) {
  15. rectangle.add( {-1, -1, 0, 0, 0, 0, 0, 0});
  16. rectangle.add( {1, 1, 0, 1, 1, 0, 0, 0});
  17. rectangle.add( {-1, 1, 0, 0, 1, 0, 0, 0});
  18. rectangle.add( {-1, -1, 0, 0, 0, 0, 0, 0});
  19. rectangle.add( {1, -1, 0, 1, 0, 0, 0, 0});
  20. rectangle.add( {1, 1, 0, 1, 1, 0, 0, 0});
  21. rectangle.build();
  22. }
  23. bool Engine::isRunning() const {
  24. return running;
  25. }
  26. void Engine::renderTick(float lag) {
  27. u64 current = GLFWWrapper::getTimeNanos();
  28. sum -= values[tindex];
  29. values[tindex] = current - last;
  30. sum += values[tindex];
  31. last = current;
  32. tindex = (tindex + 1) & (127);
  33. cam.update(lag);
  34. updateWorldProjection();
  35. updateWorldView();
  36. renderShadow(lag);
  37. renderWorld(lag);
  38. if(Engine::useSSAO) {
  39. renderSSAO();
  40. }
  41. renderPostWorld();
  42. renderTextOverlay(lag);
  43. }
  44. void Engine::tick() {
  45. game.tick(cam);
  46. if(keys.test5.getDownTime() == 1) {
  47. ortho = !ortho;
  48. }
  49. if(keys.test.isDown()) {
  50. //ortho = !ortho;
  51. testRadius /= 0.95f;
  52. }
  53. if(keys.test2.isDown()) {
  54. testRadius *= 0.95f;
  55. }
  56. if(keys.test3.isDown()) {
  57. testBias /= 0.95f;
  58. }
  59. if(keys.test4.isDown()) {
  60. testBias *= 0.95f;
  61. }
  62. }
  63. void Engine::renderShadow(float lag) {
  64. fb.shadow.bind();
  65. glEnable(GL_DEPTH_TEST);
  66. shaders.shadow.use();
  67. worldShadowProjView = worldShadowProj;
  68. worldShadowProjView.mul(worldShadowView);
  69. shaders.shadow.setMatrix("projView", worldShadowProjView.getValues());
  70. //glEnable(GL_CULL_FACE);
  71. //glCullFace(GL_FRONT);
  72. game.renderWorld(lag, model, shaders.shadow);
  73. //glCullFace(GL_BACK);
  74. }
  75. void Engine::renderWorld(float lag) {
  76. fb.world.bind();
  77. glEnable(GL_DEPTH_TEST);
  78. shaders.world.use();
  79. Matrix rWorldShadowProjView;
  80. rWorldShadowProjView.translate(0.5f, 0.5f, 0.5f);
  81. rWorldShadowProjView.scale(0.5f, 0.5f, 0.5f);
  82. rWorldShadowProjView.mul(worldShadowProjView);
  83. shaders.world.setMatrix("projViewShadow", rWorldShadowProjView.getValues());
  84. shaders.world.setMatrix("proj", worldProj.getValues());
  85. shaders.world.setMatrix("view", worldView.getValues());
  86. model.clear();
  87. shaders.world.setMatrix("model", model.get().getValues());
  88. fb.shadow.bindDepthTexture(1);
  89. shaders.world.setFloat("radius", Engine::testRadius);
  90. shaders.world.setFloat("bias", Engine::testBias);
  91. game.renderWorld(lag, model, shaders.world);
  92. }
  93. void Engine::renderSSAO() {
  94. shaders.ssao.use();
  95. Matrix rProj;
  96. rProj.translate(0.5f, 0.5f, 0.5f);
  97. rProj.scale(0.5f, 0.5f, 0.5f);
  98. rProj.mul(worldProj);
  99. shaders.ssao.setMatrix("proj", rProj.getValues());
  100. shaders.ssao.setInt("width", size.width);
  101. shaders.ssao.setInt("height", size.height);
  102. fb.world.bindPositionTexture(0);
  103. fb.world.bindNormalTexture(1);
  104. fb.world.bindColorTexture(2);
  105. fb.world.bindDepthTexture(3);
  106. ssaoNoise.bind(4);
  107. fb.ssao.bind();
  108. rectangle.draw();
  109. // ssao blur
  110. shaders.ssaoBlur.use();
  111. fb.ssao.bindRedTexture(0);
  112. fb.ssaoBlur.bind();
  113. rectangle.draw();
  114. }
  115. void Engine::renderPostWorld() {
  116. glBindFramebuffer(GL_FRAMEBUFFER, 0);
  117. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
  118. shaders.postWorld.use();
  119. fb.world.bindColorTexture(0);
  120. fb.ssaoBlur.bindRedTexture(1);
  121. fb.world.bindRedTexture(2);
  122. fb.world.bindNormalTexture(3);
  123. shaders.postWorld.setInt("useSSAO", Engine::useSSAO);
  124. rectangle.draw();
  125. }
  126. void Engine::renderTextOverlay(float lag) {
  127. glDisable(GL_DEPTH_TEST);
  128. shaders.text.use();
  129. Matrix m;
  130. shaders.text.setMatrix("proj", m.getValues());
  131. m.translate(-1.0f, 1.0f, 0.0f);
  132. m.scale(2.0f / size.width, -2.0f / size.height, 1.0f);
  133. shaders.text.setMatrix("view", m.getValues());
  134. model.clear();
  135. model.get().scale(2.0f, 2.0f, 2.0f);
  136. shaders.text.setMatrix("model", model.get().getValues());
  137. glEnable(GL_BLEND);
  138. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  139. glBlendEquation(GL_FUNC_ADD);
  140. char buffer[50];
  141. snprintf(buffer, 50, "FPS: %f %f %f", 128000000000.0f / sum, Engine::testRadius, Engine::testBias);
  142. fontRenderer.drawString(20, 20, buffer);
  143. game.renderTextOverlay(lag, model, shaders.text, fontRenderer);
  144. glDisable(GL_BLEND);
  145. }
  146. void Engine::updateWorldProjection() {
  147. frustum.setProjection(worldProj, size.width, size.height);
  148. // http://cgvr.informatik.uni-bremen.de/teaching/cg_literatur/lighthouse3d_view_frustum_culling/index.html
  149. /*float tan = tanf((0.5f * fovY) * M_PI / 180.0f);
  150. float aspect = (float) size.width / size.height;
  151. float closeFarClip = 4;
  152. float nearHigh = tan * nearClip;
  153. float nearWidth = nearHigh * aspect;
  154. float farHigh = tan * closeFarClip;
  155. float farWidth = farHigh * aspect;
  156. Vector farCenter = cam.getPosition();
  157. farCenter.addMul(cam.getFront(), closeFarClip);
  158. Vector farTopLeft = farCenter;
  159. farTopLeft.addMul(cam.getLeft(), farWidth);
  160. farTopLeft.addMul(cam.getUp(), farHigh);
  161. Vector farBottomLeft = farCenter;
  162. farBottomLeft.addMul(cam.getLeft(), farWidth);
  163. farBottomLeft.addMul(cam.getDown(), farHigh);
  164. Vector farTopRight = farCenter;
  165. farTopRight.addMul(cam.getRight(), farWidth);
  166. farTopRight.addMul(cam.getUp(), farHigh);
  167. Vector farBottomRight = farCenter;
  168. farBottomRight.addMul(cam.getRight(), farWidth);
  169. farBottomRight.addMul(cam.getDown(), farHigh);
  170. Vector nearCenter = cam.getPosition();
  171. nearCenter.addMul(cam.getFront(), nearClip);
  172. Vector nearTopLeft = nearCenter;
  173. nearTopLeft.addMul(cam.getLeft(), nearWidth);
  174. nearTopLeft.addMul(cam.getUp(), nearHigh);
  175. Vector nearBottomLeft = nearCenter;
  176. nearBottomLeft.addMul(cam.getLeft(), nearWidth);
  177. nearBottomLeft.addMul(cam.getDown(), nearHigh);
  178. Vector nearTopRight = nearCenter;
  179. nearTopRight.addMul(cam.getRight(), nearWidth);
  180. nearTopRight.addMul(cam.getUp(), nearHigh);
  181. Vector nearBottomRight = nearCenter;
  182. nearBottomRight.addMul(cam.getRight(), nearWidth);
  183. nearBottomRight.addMul(cam.getDown(), nearHigh);
  184. Vector light(-0.280166, -0.573576, -0.769751);
  185. Vector lightLeft = light;
  186. lightLeft.cross(0.0f, 1.0f, 0.0f);
  187. Vector lightUp = lightLeft;
  188. lightUp.cross(light);
  189. //std::cout << "-------------------------\n";
  190. Plane plane;
  191. plane.set(Vector(), light, lightUp);
  192. float f[8];
  193. f[0] = plane.getSignedDistance(farTopLeft);
  194. f[1] = plane.getSignedDistance(farBottomLeft);
  195. f[2] = plane.getSignedDistance(farTopRight);
  196. f[3] = plane.getSignedDistance(farBottomRight);
  197. f[4] = plane.getSignedDistance(nearTopLeft);
  198. f[5] = plane.getSignedDistance(nearBottomLeft);
  199. f[6] = plane.getSignedDistance(nearTopRight);
  200. f[7] = plane.getSignedDistance(nearBottomRight);
  201. float min = FLT_MAX;
  202. float max = -FLT_MAX;
  203. for(uint i = 0; i < 8; i++) {
  204. if(f[i] < min) {
  205. min = f[i];
  206. }
  207. if(f[i] > max) {
  208. max = f[i];
  209. }
  210. }
  211. float lightWidth = max - min;
  212. //std::cout << lightWidth << "\n";
  213. plane.set(Vector(), light, lightLeft);
  214. f[0] = plane.getSignedDistance(farTopLeft);
  215. f[1] = plane.getSignedDistance(farBottomLeft);
  216. f[2] = plane.getSignedDistance(farTopRight);
  217. f[3] = plane.getSignedDistance(farBottomRight);
  218. f[4] = plane.getSignedDistance(nearTopLeft);
  219. f[5] = plane.getSignedDistance(nearBottomLeft);
  220. f[6] = plane.getSignedDistance(nearTopRight);
  221. f[7] = plane.getSignedDistance(nearBottomRight);
  222. min = FLT_MAX;
  223. max = -FLT_MAX;
  224. for(uint i = 0; i < 8; i++) {
  225. if(f[i] < min) {
  226. min = f[i];
  227. }
  228. if(f[i] > max) {
  229. max = f[i];
  230. }
  231. }
  232. float lightHeight = max - min;
  233. //std::cout << "\n" << max << " - " << min << " " << lightHeight << "\n";
  234. // not the real center, but good guess
  235. testOrthoCenter = nearCenter;
  236. testOrthoCenter.addMul(cam.getFront(), closeFarClip * 0.5f);
  237. if(ortho) {
  238. worldProj.setToIdentity();
  239. worldProj.set(0, 2.0f / lightWidth);
  240. worldProj.set(5, 2.0f / lightHeight);
  241. worldProj.set(10, -2.0f / (farClip - nearClip));
  242. }
  243. if(once) {
  244. worldShadowProj.setToIdentity();
  245. worldShadowProj.set(0, 2.0f / lightWidth);
  246. worldShadowProj.set(5, 2.0f / lightHeight);
  247. worldShadowProj.set(10, -2.0f / (farClip - nearClip));
  248. }*/
  249. }
  250. void Engine::updateWorldView() {
  251. Vector right = cam.getRight();
  252. Vector up = cam.getUp();
  253. Vector back = cam.getBack();
  254. Vector pos = cam.getPosition();
  255. if(ortho) {
  256. right.set(0.939693f, 0.0f, -0.34202f);
  257. back.set(0.280166f, 0.573576f, 0.769751f);
  258. up.set(-0.196175f, 0.819152f, -0.538986f);
  259. pos = testOrthoCenter;
  260. }
  261. worldView.set(0, right.getX());
  262. worldView.set(1, up.getX());
  263. worldView.set(2, back.getX());
  264. worldView.set(4, right.getY());
  265. worldView.set(5, up.getY());
  266. worldView.set(6, back.getY());
  267. worldView.set(8, right.getZ());
  268. worldView.set(9, up.getZ());
  269. worldView.set(10, back.getZ());
  270. worldView.set(12, right.dotInverse(pos));
  271. worldView.set(13, up.dotInverse(pos));
  272. worldView.set(14, back.dotInverse(pos));
  273. //if(once) {
  274. // lengthAngle = 20; widthAngle = 35;
  275. right.set(0.939693f, 0.0f, -0.34202f);
  276. back.set(0.280166f, 0.573576f, 0.769751f);
  277. up.set(-0.196175f, 0.819152f, -0.538986f);
  278. pos = testOrthoCenter;
  279. //once = false;
  280. worldShadowView.set(0, right.getX());
  281. worldShadowView.set(1, up.getX());
  282. worldShadowView.set(2, back.getX());
  283. worldShadowView.set(4, right.getY());
  284. worldShadowView.set(5, up.getY());
  285. worldShadowView.set(6, back.getY());
  286. worldShadowView.set(8, right.getZ());
  287. worldShadowView.set(9, up.getZ());
  288. worldShadowView.set(10, back.getZ());
  289. worldShadowView.set(12, right.dotInverse(pos));
  290. worldShadowView.set(13, up.dotInverse(pos));
  291. worldShadowView.set(14, back.dotInverse(pos));
  292. //}
  293. }