Wrapper.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. #include "Wrapper.h"
  2. #include <fstream>
  3. #include <cstring>
  4. #include <iostream>
  5. using namespace std;
  6. DummyClient DummyClient::dummy;
  7. IClient* Engine::client = &DummyClient::dummy;
  8. GLFWwindow* Engine::window = nullptr;
  9. GLuint Engine::vShader = 0;
  10. GLuint Engine::fShader = 0;
  11. GLuint Engine::program = 0;
  12. GLuint Engine::postVba = 0;
  13. GLuint Engine::postVbo = 0;
  14. GLuint Engine::postVShader = 0;
  15. GLuint Engine::postFShader = 0;
  16. GLuint Engine::postProgram = 0;
  17. GLuint Engine::frameBuffer = 0;
  18. GLuint Engine::frameTexture = 0;
  19. GLuint Engine::renderBuffer = 0;
  20. int Engine::scale = 1;
  21. int Engine::width = 0;
  22. int Engine::height = 0;
  23. bool Engine::init(int width, int height, const char* name)
  24. {
  25. Engine::width = width;
  26. Engine::height = height;
  27. updateScale();
  28. if(!glfwInit())
  29. {
  30. cout << "could not initialize GLFW" << endl;
  31. return false;
  32. }
  33. glfwDefaultWindowHints();
  34. glfwWindowHint(GLFW_VISIBLE, 0);
  35. glfwWindowHint(GLFW_RESIZABLE, 1);
  36. window = glfwCreateWindow(width, height, name, nullptr, nullptr);
  37. if(!window)
  38. {
  39. cout << "could not create window" << endl;
  40. glfwTerminate();
  41. return false;
  42. }
  43. glfwMakeContextCurrent(window);
  44. glfwSwapInterval(1);
  45. glfwShowWindow(window);
  46. GLenum err = glewInit();
  47. if(GLEW_OK != err)
  48. {
  49. cout << "could not initialize GLEW: " << glewGetErrorString(err) << endl;
  50. return false;
  51. }
  52. cout << "Status: Using GLEW " << glewGetString(GLEW_VERSION) << endl;
  53. vShader = 0;
  54. fShader = 0;
  55. program = createProgram("shader/vertex.vs", "shader/fragment.fs", vShader, program);
  56. if(program == 0)
  57. {
  58. if(vShader != 0)
  59. {
  60. glDeleteShader(vShader);
  61. }
  62. if(fShader != 0)
  63. {
  64. glDeleteShader(fShader);
  65. }
  66. glfwDestroyWindow(window);
  67. glfwTerminate();
  68. return false;
  69. }
  70. postVShader = 0;
  71. postFShader = 0;
  72. postProgram = createProgram("shader/postVertex.vs", "shader/postFragment.fs", postVShader, postFShader);
  73. if(postProgram == 0)
  74. {
  75. if(postVShader != 0)
  76. {
  77. glDeleteShader(postVShader);
  78. }
  79. if(postFShader != 0)
  80. {
  81. glDeleteShader(postFShader);
  82. }
  83. glfwDestroyWindow(window);
  84. glfwTerminate();
  85. return false;
  86. }
  87. glfwSetKeyCallback(window, onKeyEvent);
  88. glfwSetMouseButtonCallback(window, onMouseClick);
  89. glfwSetFramebufferSizeCallback(window, onWindowResize);
  90. //glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
  91. //glfwSetCursorPosCallback(window, onMouseMove);
  92. return true;
  93. }
  94. void Engine::start(IClient* client)
  95. {
  96. if(client != nullptr)
  97. {
  98. Engine::client = client;
  99. }
  100. generateFramebuffer();
  101. generatePostData();
  102. glEnable(GL_CULL_FACE);
  103. glDepthFunc(GL_LEQUAL);
  104. uint64_t newTime = glfwGetTimerValue();
  105. uint64_t oldTime = newTime;
  106. uint64_t lag = 0;
  107. while(!glfwWindowShouldClose(window))
  108. {
  109. oldTime = newTime;
  110. newTime = glfwGetTimerValue();
  111. lag += newTime - oldTime;
  112. int ticksPerFrame = 0;
  113. while(lag >= NANOS_PER_TICK)
  114. {
  115. lag -= NANOS_PER_TICK;
  116. Engine::client->tick();
  117. ticksPerFrame++;
  118. if(ticksPerFrame >= MAX_TICKS_PER_FRAME)
  119. {
  120. long skip = lag / NANOS_PER_TICK;
  121. lag -= skip * NANOS_PER_TICK;
  122. if(skip > 0)
  123. {
  124. cout << "skipped " << skip << " game ticks " << lag << endl;
  125. }
  126. break;
  127. }
  128. }
  129. // draw scene in framebuffer
  130. glUseProgram(program);
  131. glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
  132. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  133. glEnable(GL_DEPTH_TEST);
  134. Engine::client->renderTick((float) lag / NANOS_PER_TICK);
  135. // draw textured framebuffer
  136. glUseProgram(postProgram);
  137. glBindFramebuffer(GL_FRAMEBUFFER, 0);
  138. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  139. glDisable(GL_DEPTH_TEST);
  140. glBindTexture(GL_TEXTURE_2D, frameTexture);
  141. glBindVertexArray(postVba);
  142. glBindBuffer(GL_ARRAY_BUFFER, postVbo);
  143. glDrawArrays(GL_TRIANGLES, 0, 6);
  144. glfwSwapBuffers(window);
  145. glfwPollEvents();
  146. }
  147. destroyPostData();
  148. glDeleteFramebuffers(1, &frameBuffer);
  149. glDeleteShader(vShader);
  150. glDeleteShader(fShader);
  151. glDeleteProgram(program);
  152. glDeleteShader(postVShader);
  153. glDeleteShader(postFShader);
  154. glDeleteProgram(postProgram);
  155. glfwDestroyWindow(window);
  156. glfwTerminate();
  157. }
  158. void Engine::stop()
  159. {
  160. glfwSetWindowShouldClose(window, 1);
  161. }
  162. GLchar* Engine::readFile(const char* name)
  163. {
  164. ifstream in;
  165. in.open(name);
  166. if(!in.fail())
  167. {
  168. int size = 128;
  169. int index = 0;
  170. GLchar* content = new GLchar[size];
  171. while(true)
  172. {
  173. GLchar c = in.get();
  174. if(in.eof())
  175. {
  176. break;
  177. }
  178. if(index >= size - 1)
  179. {
  180. GLchar* newContent = new GLchar[size * 2];
  181. memcpy(newContent, content, size);
  182. size *= 2;
  183. delete[] content;
  184. content = newContent;
  185. }
  186. content[index] = c;
  187. index++;
  188. }
  189. content[index] = '\0';
  190. index++;
  191. in.close();
  192. return content;
  193. }
  194. return nullptr;
  195. }
  196. bool Engine::checkShaderErrors(const char* name, GLuint shader)
  197. {
  198. bool returnValue = false;
  199. cout << "compiling " << name << " shader ..." << endl;
  200. GLenum error = glGetError();
  201. if(error)
  202. {
  203. cout << "error: " << glGetError() << endl;
  204. returnValue = true;
  205. }
  206. else
  207. {
  208. cout << "no error occured ..." << endl;
  209. }
  210. GLint compiled[1];
  211. glGetShaderiv(shader, GL_COMPILE_STATUS, compiled);
  212. if(compiled[0])
  213. {
  214. cout << name << " shader successfully compiled" << endl;
  215. }
  216. else
  217. {
  218. cout << name << "compiling of " << name << " failed:" << endl;
  219. GLchar buffer[512];
  220. GLsizei bufferSize = 512;
  221. GLsizei charsUsed = 0;
  222. glGetShaderInfoLog(shader, bufferSize, &charsUsed, buffer);
  223. // glGetProgramInfoLog should be null terminated ...
  224. buffer[bufferSize - 1] = '\0';
  225. cout << buffer << endl;
  226. returnValue = true;
  227. }
  228. return returnValue;
  229. }
  230. GLuint Engine::compileProgram(GLuint& vShader, GLuint& fShader, const GLchar* v, const GLchar* f)
  231. {
  232. vShader = glCreateShader(GL_VERTEX_SHADER);
  233. glShaderSource(vShader, 1, &v, nullptr);
  234. glCompileShader(vShader);
  235. if(checkShaderErrors("vertex", vShader))
  236. {
  237. return 0;
  238. }
  239. fShader = glCreateShader(GL_FRAGMENT_SHADER);
  240. glShaderSource(fShader, 1, &f, nullptr);
  241. glCompileShader(fShader);
  242. if(checkShaderErrors("fragment", fShader))
  243. {
  244. return 0;
  245. }
  246. GLuint program = glCreateProgram();
  247. glAttachShader(program, vShader);
  248. glAttachShader(program, fShader);
  249. glLinkProgram(program);
  250. cout << "linking shaders to program ..." << endl;
  251. GLenum error = glGetError();
  252. if(error)
  253. {
  254. cout << "error: " << glGetError() << endl;
  255. return 0;
  256. }
  257. else
  258. {
  259. cout << "no error occured ..." << endl;
  260. }
  261. GLint compiled[1];
  262. glGetProgramiv(program, GL_LINK_STATUS, compiled);
  263. if(compiled[0])
  264. {
  265. cout << "shaders successfully linked" << endl;
  266. }
  267. else
  268. {
  269. cout << "linking of shaders failed:" << endl;
  270. GLchar buffer[512];
  271. GLsizei bufferSize = 512;
  272. GLsizei charsUsed = 0;
  273. glGetProgramInfoLog(program, bufferSize, &charsUsed, buffer);
  274. // glGetProgramInfoLog should be null terminated ...
  275. buffer[bufferSize - 1] = '\0';
  276. cout << buffer << endl;
  277. return 0;
  278. }
  279. return program;
  280. }
  281. GLuint Engine::createProgram(const char* v, const char* f, GLuint& vShader, GLuint& fShader)
  282. {
  283. GLchar* vertex = readFile(v);
  284. if(vertex == nullptr)
  285. {
  286. cout << "cannot read " << v << endl;
  287. return 0;
  288. }
  289. GLchar* fragment = readFile(f);
  290. if(fragment == nullptr)
  291. {
  292. cout << "cannot read " << f << endl;
  293. delete[] vertex;
  294. return 0;
  295. }
  296. GLuint program = compileProgram(vShader, fShader, vertex, fragment);
  297. delete[] vertex;
  298. delete[] fragment;
  299. return program;
  300. }
  301. void Engine::onKeyEvent(GLFWwindow* w, int key, int scancode, int action, int mods)
  302. {
  303. client->onKeyEvent(key, scancode, action, mods);
  304. }
  305. void Engine::onMouseClick(GLFWwindow* w, int button, int action, int mods)
  306. {
  307. client->onMouseClick(button, action, mods);
  308. }
  309. void Engine::onWindowResize(GLFWwindow* w, int width, int height)
  310. {
  311. glViewport(0, 0, width, height);
  312. Engine::width = width;
  313. Engine::height = height;
  314. updateScale();
  315. }
  316. void Engine::updateScale()
  317. {
  318. scale = 1;
  319. while(width / (scale + 1) >= 400 && height / (scale + 1) >= 300)
  320. {
  321. scale++;
  322. }
  323. }
  324. int Engine::getScale()
  325. {
  326. return scale;
  327. }
  328. int Engine::getWidth()
  329. {
  330. return width;
  331. }
  332. int Engine::getHeight()
  333. {
  334. return height;
  335. }
  336. GLint Engine::getUniformLocation(const GLchar* name)
  337. {
  338. return glGetUniformLocation(program, name);
  339. }
  340. void Engine::setMatrix(GLint location, const GLfloat* m)
  341. {
  342. glUniformMatrix4fv(location, 1, 0, m);
  343. }
  344. void Engine::setInt(GLint location, GLint i)
  345. {
  346. glUniform1i(location, i);
  347. }
  348. void Engine::setFloat(GLint location, GLfloat f1, GLfloat f2, GLfloat f3, GLfloat f4)
  349. {
  350. glUniform4f(location, f1, f2, f3, f4);
  351. }
  352. void Engine::printError()
  353. {
  354. GLenum error = glGetError();
  355. switch(error)
  356. {
  357. case GL_NO_ERROR:
  358. //cout << "> No error has been recorded." << endl;
  359. break;
  360. case GL_INVALID_ENUM:
  361. cout << "> An unacceptable value is specified for an enumerated argument." << endl;
  362. break;
  363. case GL_INVALID_VALUE:
  364. cout << "> A numeric argument is out of range." << endl;
  365. break;
  366. case GL_INVALID_OPERATION:
  367. cout << "> The specified operation is not allowed in the current state." << endl;
  368. break;
  369. case GL_INVALID_FRAMEBUFFER_OPERATION:
  370. cout << "> The framebuffer object is not complete." << endl;
  371. break;
  372. case GL_OUT_OF_MEMORY:
  373. cout << "> There is not enough memory left to execute the command." << endl;
  374. break;
  375. case GL_STACK_UNDERFLOW:
  376. cout << "> An attempt has been made to perform an operation that would cause an internal stack to underflow." << endl;
  377. break;
  378. case GL_STACK_OVERFLOW:
  379. cout << "> An attempt has been made to perform an operation that would cause an internal stack to overflow." << endl;
  380. break;
  381. default:
  382. cout << "> Unknown OpenGL error: " << error << endl;
  383. }
  384. }
  385. void Engine::generateFramebuffer()
  386. {
  387. glGenFramebuffers(1, &frameBuffer);
  388. glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
  389. glGenTextures(1, &frameTexture);
  390. glBindTexture(GL_TEXTURE_2D, frameTexture);
  391. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
  392. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  393. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  394. glBindTexture(GL_TEXTURE_2D, 0);
  395. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, frameTexture, 0);
  396. glGenRenderbuffers(1, &renderBuffer);
  397. glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer);
  398. glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
  399. glBindRenderbuffer(GL_RENDERBUFFER, 0);
  400. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderBuffer);
  401. if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
  402. {
  403. cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" << endl;
  404. }
  405. else
  406. {
  407. cout << "WORKS" << endl;
  408. }
  409. glBindFramebuffer(GL_FRAMEBUFFER, 0);
  410. }
  411. void Engine::generatePostData()
  412. {
  413. glGenVertexArrays(1, &postVba);
  414. glBindVertexArray(postVba);
  415. glGenBuffers(1, &postVbo);
  416. glBindBuffer(GL_ARRAY_BUFFER, postVbo);
  417. glVertexAttribPointer(0, 2, GL_FLOAT, 0, sizeof(float) * 4, (GLvoid*) 0);
  418. glEnableVertexAttribArray(0);
  419. glVertexAttribPointer(1, 2, GL_FLOAT, 0, sizeof(float) * 4, (GLvoid*) (sizeof(float) * 2));
  420. glEnableVertexAttribArray(1);
  421. float data[] =
  422. {
  423. -1.0f, 1.0f, 0.0f, 1.0f,
  424. -1.0f, -1.0f, 0.0f, 0.0f,
  425. 1.0f, -1.0f, 1.0f, 0.0f,
  426. -1.0f, 1.0f, 0.0f, 1.0f,
  427. 1.0f, -1.0f, 1.0f, 0.0f,
  428. 1.0f, 1.0f, 1.0f, 1.0f
  429. };
  430. glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 24, data, GL_STATIC_DRAW);
  431. }
  432. void Engine::destroyPostData()
  433. {
  434. glDeleteVertexArrays(1, &postVba);
  435. glDeleteBuffers(1, &postVbo);
  436. }