Wrapper.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. #include "Wrapper.h"
  2. #include <random>
  3. DummyClient DummyClient::dummy;
  4. IClient* Engine::client = &DummyClient::dummy;
  5. GLFWwindow* Engine::window = nullptr;
  6. // active program
  7. GLuint Engine::activeProgram = 0;
  8. // world data
  9. ShaderProgram Engine::worldShader;
  10. GLuint Engine::worldFrameBuffer = 0;
  11. GLuint Engine::worldPositionTexture = 0;
  12. GLuint Engine::worldNormalTexture = 0;
  13. GLuint Engine::worldColorTexture = 0;
  14. GLuint Engine::worldDepthTexture = 0;
  15. // ssao shader
  16. ShaderProgram Engine::ssaoShader;
  17. GLuint Engine::ssaoFrameBuffer = 0;
  18. GLuint Engine::ssaoTexture = 0;
  19. // post shader
  20. GLuint Engine::postVba = 0;
  21. GLuint Engine::postVbo = 0;
  22. ShaderProgram Engine::postShader;
  23. int Engine::scale = 1;
  24. int Engine::width = 0;
  25. int Engine::height = 0;
  26. bool Engine::lineMode = false;
  27. float Engine::testX = 0;
  28. float Engine::testY = 0;
  29. float Engine::testZ = 0;
  30. // ssao kernel data
  31. Vector3D Engine::ssaoKernel[ssaoKernelAmount];
  32. GLuint Engine::noiseTexture = 0;
  33. Matrix3D Engine::testMat;
  34. bool Engine::init(int width, int height, const char* name)
  35. {
  36. Engine::width = width;
  37. Engine::height = height;
  38. updateScale();
  39. if(!glfwInit())
  40. {
  41. cout << "could not initialize GLFW" << endl;
  42. return false;
  43. }
  44. glfwDefaultWindowHints();
  45. glfwWindowHint(GLFW_VISIBLE, 0);
  46. glfwWindowHint(GLFW_RESIZABLE, 1);
  47. window = glfwCreateWindow(width, height, name, nullptr, nullptr);
  48. if(!window)
  49. {
  50. cout << "could not create window" << endl;
  51. glfwTerminate();
  52. return false;
  53. }
  54. glfwMakeContextCurrent(window);
  55. glfwSwapInterval(1);
  56. glfwShowWindow(window);
  57. GLenum err = glewInit();
  58. if(GLEW_OK != err)
  59. {
  60. cout << "could not initialize GLEW: " << glewGetErrorString(err) << endl;
  61. return false;
  62. }
  63. cout << "Status: Using GLEW " << glewGetString(GLEW_VERSION) << endl;
  64. worldShader.compile("shader/worldVertex.vs", "shader/worldFragment.fs");
  65. if(!worldShader.isValid())
  66. {
  67. glfwDestroyWindow(window);
  68. glfwTerminate();
  69. return false;
  70. }
  71. activeProgram = worldShader.getProgram();
  72. ssaoShader.compile("shader/ssaoVertex.vs", "shader/ssaoFragment.fs");
  73. if(!ssaoShader.isValid())
  74. {
  75. glfwDestroyWindow(window);
  76. glfwTerminate();
  77. return false;
  78. }
  79. postShader.compile("shader/postVertex.vs", "shader/postFragment.fs");
  80. if(!postShader.isValid())
  81. {
  82. glfwDestroyWindow(window);
  83. glfwTerminate();
  84. return false;
  85. }
  86. glfwSetKeyCallback(window, onKeyEvent);
  87. glfwSetMouseButtonCallback(window, onMouseClick);
  88. glfwSetFramebufferSizeCallback(window, onWindowResize);
  89. //glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
  90. //glfwSetCursorPosCallback(window, onMouseMove);
  91. return true;
  92. }
  93. void Engine::start(IClient* client)
  94. {
  95. if(client != nullptr)
  96. {
  97. Engine::client = client;
  98. }
  99. onInit();
  100. glEnable(GL_CULL_FACE);
  101. glDepthFunc(GL_LEQUAL);
  102. uint64_t newTime = glfwGetTimerValue();
  103. uint64_t oldTime = newTime;
  104. uint64_t lag = 0;
  105. while(!glfwWindowShouldClose(window))
  106. {
  107. oldTime = newTime;
  108. newTime = glfwGetTimerValue();
  109. lag += newTime - oldTime;
  110. int ticksPerFrame = 0;
  111. while(lag >= NANOS_PER_TICK)
  112. {
  113. lag -= NANOS_PER_TICK;
  114. Engine::client->tick();
  115. ticksPerFrame++;
  116. if(ticksPerFrame >= MAX_TICKS_PER_FRAME)
  117. {
  118. long skip = lag / NANOS_PER_TICK;
  119. lag -= skip * NANOS_PER_TICK;
  120. if(skip > 0)
  121. {
  122. cout << "skipped " << skip << " game ticks " << lag << endl;
  123. }
  124. break;
  125. }
  126. }
  127. onRenderTick((float) lag / NANOS_PER_TICK);
  128. glfwSwapBuffers(window);
  129. glfwPollEvents();
  130. }
  131. onTerm();
  132. glfwDestroyWindow(window);
  133. glfwTerminate();
  134. }
  135. void Engine::stop()
  136. {
  137. glfwSetWindowShouldClose(window, 1);
  138. }
  139. void Engine::onKeyEvent(GLFWwindow* w, int key, int scancode, int action, int mods)
  140. {
  141. client->onKeyEvent(key, scancode, action, mods);
  142. }
  143. void Engine::onMouseClick(GLFWwindow* w, int button, int action, int mods)
  144. {
  145. client->onMouseClick(button, action, mods);
  146. }
  147. void Engine::onWindowResize(GLFWwindow* w, int width, int height)
  148. {
  149. glViewport(0, 0, width, height);
  150. Engine::width = width;
  151. Engine::height = height;
  152. updateScale();
  153. /*glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
  154. glBindTexture(GL_TEXTURE_2D, frameTexture);
  155. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
  156. glBindTexture(GL_TEXTURE_2D, 0);
  157. glBindRenderbuffer(GL_RENDERBUFFER, depthTexture);
  158. glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
  159. glBindRenderbuffer(GL_RENDERBUFFER, 0);
  160. glBindFramebuffer(GL_FRAMEBUFFER, 0);*/
  161. }
  162. void Engine::updateScale()
  163. {
  164. scale = 1;
  165. while(width / (scale + 1) >= 400 && height / (scale + 1) >= 300)
  166. {
  167. scale++;
  168. }
  169. }
  170. int Engine::getScale()
  171. {
  172. return scale;
  173. }
  174. int Engine::getWidth()
  175. {
  176. return width;
  177. }
  178. int Engine::getHeight()
  179. {
  180. return height;
  181. }
  182. GLint Engine::getUniformLocation(const GLchar* name)
  183. {
  184. return glGetUniformLocation(activeProgram, name);
  185. }
  186. void Engine::setMatrix(GLint location, const GLfloat* m)
  187. {
  188. glUniformMatrix4fv(location, 1, 0, m);
  189. }
  190. void Engine::setInt(GLint location, GLint i)
  191. {
  192. glUniform1i(location, i);
  193. }
  194. void Engine::setFloat(GLint location, GLfloat f1, GLfloat f2, GLfloat f3, GLfloat f4)
  195. {
  196. glUniform4f(location, f1, f2, f3, f4);
  197. }
  198. void Engine::printError()
  199. {
  200. GLenum error = glGetError();
  201. switch(error)
  202. {
  203. case GL_NO_ERROR:
  204. cout << "> No error has been recorded." << endl;
  205. break;
  206. case GL_INVALID_ENUM:
  207. cout << "> An unacceptable value is specified for an enumerated argument." << endl;
  208. break;
  209. case GL_INVALID_VALUE:
  210. cout << "> A numeric argument is out of range." << endl;
  211. break;
  212. case GL_INVALID_OPERATION:
  213. cout << "> The specified operation is not allowed in the current state." << endl;
  214. break;
  215. case GL_INVALID_FRAMEBUFFER_OPERATION:
  216. cout << "> The framebuffer object is not complete." << endl;
  217. break;
  218. case GL_OUT_OF_MEMORY:
  219. cout << "> There is not enough memory left to execute the command." << endl;
  220. break;
  221. case GL_STACK_UNDERFLOW:
  222. cout << "> An attempt has been made to perform an operation that would cause an internal stack to underflow." << endl;
  223. break;
  224. case GL_STACK_OVERFLOW:
  225. cout << "> An attempt has been made to perform an operation that would cause an internal stack to overflow." << endl;
  226. break;
  227. default:
  228. cout << "> Unknown OpenGL error: " << error << endl;
  229. }
  230. }
  231. void Engine::onInit()
  232. {
  233. // generate framebuffer and textures for world buffer
  234. glGenFramebuffers(1, &worldFrameBuffer);
  235. glBindFramebuffer(GL_FRAMEBUFFER, worldFrameBuffer);
  236. // world position texture
  237. glGenTextures(1, &worldPositionTexture);
  238. glBindTexture(GL_TEXTURE_2D, worldPositionTexture);
  239. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGB, GL_FLOAT, NULL);
  240. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  241. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  242. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  243. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  244. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, worldPositionTexture, 0);
  245. // world normal texture
  246. glGenTextures(1, &worldNormalTexture);
  247. glBindTexture(GL_TEXTURE_2D, worldNormalTexture);
  248. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGB, GL_FLOAT, NULL);
  249. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  250. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  251. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, worldNormalTexture, 0);
  252. // world color texture
  253. glGenTextures(1, &worldColorTexture);
  254. glBindTexture(GL_TEXTURE_2D, worldColorTexture);
  255. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
  256. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  257. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  258. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, worldColorTexture, 0);
  259. // set color attachements for the worldFrameBuffer
  260. GLuint attachments[3] =
  261. {
  262. GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2
  263. };
  264. glDrawBuffers(3, attachments);
  265. // world depth texture
  266. glGenTextures(1, &worldDepthTexture);
  267. glBindTexture(GL_TEXTURE_2D, worldDepthTexture);
  268. glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, width, height, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL);
  269. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  270. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  271. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, worldDepthTexture, 0);
  272. // check if world framebuffer is okay
  273. if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
  274. {
  275. cout << "world frame buffer is not complete!" << endl;
  276. }
  277. glBindFramebuffer(GL_FRAMEBUFFER, 0);
  278. // generate data for drawing previously generated framebuffer as rectangle
  279. glGenVertexArrays(1, &postVba);
  280. glBindVertexArray(postVba);
  281. glGenBuffers(1, &postVbo);
  282. glBindBuffer(GL_ARRAY_BUFFER, postVbo);
  283. glVertexAttribPointer(0, 2, GL_FLOAT, 0, sizeof(float) * 4, (GLvoid*) 0);
  284. glEnableVertexAttribArray(0);
  285. glVertexAttribPointer(1, 2, GL_FLOAT, 0, sizeof(float) * 4, (GLvoid*) (sizeof(float) * 2));
  286. glEnableVertexAttribArray(1);
  287. float data[] =
  288. {
  289. -1.0f, 1.0f, 0.0f, 1.0f,
  290. -1.0f, -1.0f, 0.0f, 0.0f,
  291. 1.0f, -1.0f, 1.0f, 0.0f,
  292. -1.0f, 1.0f, 0.0f, 1.0f,
  293. 1.0f, -1.0f, 1.0f, 0.0f,
  294. 1.0f, 1.0f, 1.0f, 1.0f
  295. };
  296. glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 24, data, GL_STATIC_DRAW);
  297. // generate ssao kernel data
  298. glGenFramebuffers(1, &ssaoFrameBuffer);
  299. glBindFramebuffer(GL_FRAMEBUFFER, ssaoFrameBuffer);
  300. // ssao color texture
  301. glGenTextures(1, &ssaoTexture);
  302. glBindTexture(GL_TEXTURE_2D, ssaoTexture);
  303. glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width, height, 0, GL_RGB, GL_FLOAT, NULL);
  304. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  305. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  306. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ssaoTexture, 0);
  307. // check if world framebuffer is okay
  308. if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
  309. {
  310. cout << "ssao frame buffer is not complete!" << endl;
  311. }
  312. glBindFramebuffer(GL_FRAMEBUFFER, 0);
  313. std::uniform_real_distribution<float> randomF(0.0, 1.0); // random floats between 0.0 - 1.0
  314. std::default_random_engine gen;
  315. for(int i = 0; i < ssaoKernelAmount; i++)
  316. {
  317. ssaoKernel[i].set(randomF(gen) * 2.0 - 1.0, randomF(gen) * 2.0 - 1.0, randomF(gen));
  318. ssaoKernel[i].normalize();
  319. ssaoKernel[i].mul(randomF(gen));
  320. float scale = (float) i / ssaoKernelAmount;
  321. scale = 0.1f + (scale * scale) * 0.9f;
  322. ssaoKernel[i].mul(scale);
  323. //cout << ssaoKernel[i] << endl;
  324. }
  325. float noise[48];
  326. for(int i = 0; i < 16; i++)
  327. {
  328. noise[i * 3] = randomF(gen) * 2.0 - 1.0;
  329. noise[i * 3 + 1] = randomF(gen) * 2.0 - 1.0;
  330. noise[i * 3 + 2] = 0.0f;
  331. }
  332. glGenTextures(1, &noiseTexture);
  333. glBindTexture(GL_TEXTURE_2D, noiseTexture);
  334. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, 4, 4, 0, GL_RGB, GL_FLOAT, noise);
  335. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  336. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  337. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  338. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  339. }
  340. void Engine::onRenderTick(float lag)
  341. {
  342. //--------------------------------------------------------------------------
  343. // Stage 1: draw scene in world framebuffer
  344. //--------------------------------------------------------------------------
  345. glActiveTexture(GL_TEXTURE0);
  346. activeProgram = worldShader.getProgram();
  347. glUseProgram(activeProgram);
  348. glBindFramebuffer(GL_FRAMEBUFFER, worldFrameBuffer);
  349. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
  350. glEnable(GL_DEPTH_TEST);
  351. if(lineMode)
  352. {
  353. glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  354. Engine::client->renderTick(lag);
  355. glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  356. }
  357. else
  358. {
  359. Engine::client->renderTick(lag);
  360. }
  361. //--------------------------------------------------------------------------
  362. // Stage 2: draw textured framebuffer
  363. //--------------------------------------------------------------------------
  364. glActiveTexture(GL_TEXTURE1);
  365. glBindTexture(GL_TEXTURE_2D, worldPositionTexture);
  366. glActiveTexture(GL_TEXTURE2);
  367. glBindTexture(GL_TEXTURE_2D, worldNormalTexture);
  368. glActiveTexture(GL_TEXTURE3);
  369. glBindTexture(GL_TEXTURE_2D, worldColorTexture);
  370. glActiveTexture(GL_TEXTURE4);
  371. glBindTexture(GL_TEXTURE_2D, worldDepthTexture);
  372. glActiveTexture(GL_TEXTURE5);
  373. glBindTexture(GL_TEXTURE_2D, noiseTexture);
  374. activeProgram = ssaoShader.getProgram();
  375. glUseProgram(activeProgram);
  376. for(int i = 0; i < ssaoKernelAmount; i++)
  377. {
  378. glUniform3f(glGetUniformLocation(activeProgram, (string("ssaoKernel[") + std::to_string(i) + "]").c_str()),
  379. ssaoKernel[i].getX(), ssaoKernel[i].getY(), ssaoKernel[i].getZ());
  380. }
  381. Engine::setMatrix(glGetUniformLocation(activeProgram, "projMatrix"), testMat.getValues());
  382. glBindFramebuffer(GL_FRAMEBUFFER, ssaoFrameBuffer);
  383. glClear(GL_COLOR_BUFFER_BIT);
  384. glDisable(GL_DEPTH_TEST);
  385. glBindVertexArray(postVba);
  386. glBindBuffer(GL_ARRAY_BUFFER, postVbo);
  387. glDrawArrays(GL_TRIANGLES, 0, 6);
  388. glActiveTexture(GL_TEXTURE6);
  389. glBindTexture(GL_TEXTURE_2D, ssaoTexture);
  390. glBindFramebuffer(GL_FRAMEBUFFER, 0);
  391. glClear(GL_COLOR_BUFFER_BIT);
  392. activeProgram = postShader.getProgram();
  393. glUseProgram(activeProgram);
  394. glDrawArrays(GL_TRIANGLES, 0, 6);
  395. }
  396. void Engine::onTerm()
  397. {
  398. glDeleteVertexArrays(1, &postVba);
  399. glDeleteBuffers(1, &postVbo);
  400. glDeleteFramebuffers(1, &worldFrameBuffer);
  401. glDeleteTextures(1, &worldPositionTexture);
  402. glDeleteTextures(1, &worldNormalTexture);
  403. glDeleteTextures(1, &worldColorTexture);
  404. glDeleteTextures(1, &worldDepthTexture);
  405. }
  406. void Engine::setLineMode(bool mode)
  407. {
  408. lineMode = mode;
  409. }