Engine.cpp 10 KB

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