Wrapper.cpp 12 KB

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