You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

opengl.cpp 25KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  1. #include "opengl.h"
  2. #include "../../../../app/browser/Browser.h"
  3. #include <iostream>
  4. #include <cmath>
  5. #include <cstring> // for memset
  6. // for creating new windows
  7. extern std::unique_ptr<Browser> browser;
  8. inline void checkGLState(std::string whereWhat) {
  9. GLenum glErr=glGetError();
  10. if(glErr != GL_NO_ERROR) {
  11. std::cout << whereWhat << " - not ok: " << glErr << std::endl;
  12. }
  13. }
  14. // maybe change to return std::pair<GLuint, GLuint>
  15. // with the renderer and version?
  16. bool initGL() {
  17. const GLubyte *brenderer = glGetString(GL_RENDERER);
  18. const GLubyte *version = glGetString(GL_VERSION);
  19. std::cout << "Renderer: " << brenderer << std::endl;
  20. std::cout << "Version: " << version << std::endl;
  21. checkGLState("opengl::initGL - start");
  22. glEnable(GL_BLEND); checkGLState("opengl::initGL - glEnable blend");
  23. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); checkGLState("opengl::initGL - glBlendFunc");
  24. unsigned int clearColor = 0xCCCCCCCC;
  25. float r = (static_cast<float>((clearColor >> 24) & 0xFF)) / 255;
  26. float g = (static_cast<float>((clearColor >> 16) & 0xFF)) / 255;
  27. float b = (static_cast<float>((clearColor >> 8) & 0xFF)) / 255;
  28. float a = (static_cast<float>((clearColor >> 0) & 0xFF)) / 255;
  29. //glClearColor(0.8f, 0.8f, 0.8f, 0.8f);
  30. glClearColor(r, g, b, a); checkGLState("opengl::initGL - glClearColor");
  31. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); checkGLState("opengl::initGL - glTexParameteri min");
  32. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); checkGLState("opengl::initGL - glTexParameteri mag");
  33. //std::cout << "OpenGL is set up" << std::endl;
  34. return true;
  35. }
  36. bool initGLEW() {
  37. glewExperimental = GL_TRUE;
  38. const GLenum err = glewInit();
  39. if (err != GLEW_OK) {
  40. std::cout << "Could not initialize GLEW: " << glewGetErrorString(err) << std::endl;
  41. return false;
  42. }
  43. return true;
  44. }
  45. // only called once
  46. bool OpenGL::initialize() {
  47. if (!glfwInit()) {
  48. std::cout << "Could not initialize GLFW" << std::endl;
  49. return false;
  50. }
  51. cursorHand = glfwCreateStandardCursor(GLFW_HAND_CURSOR);
  52. cursorArrow = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
  53. cursorIbeam = glfwCreateStandardCursor(GLFW_IBEAM_CURSOR);
  54. glfwSetErrorCallback([](int error, const char* description) {
  55. std::cout << "glfw error [" << error << "]:" << description << std::endl;
  56. });
  57. // I don't think you can init GLEW without a window
  58. return true;
  59. }
  60. OpenGLWindowHandle * OpenGL::createWindow(std::string title, Rect *position, unsigned int flags) {
  61. glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
  62. glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
  63. glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
  64. glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
  65. int windowWidth = position->w;
  66. int windowHeight = position->h;
  67. OpenGLWindowHandle *twin = new OpenGLWindowHandle();
  68. twin->width = position->w;
  69. twin->height = position->h;
  70. GLFWwindow *window = glfwCreateWindow(windowWidth, windowHeight, title.c_str(), nullptr, nullptr);
  71. twin->window = window;
  72. // replace first parameter of all these callbacks with our window object instead of a GLFWwindow
  73. glfwSetWindowUserPointer(window, this);
  74. // probably should set up all the hooks here
  75. glfwMakeContextCurrent(window);
  76. // init GLEW
  77. if (!initGLEW()) {
  78. // FIXME: un do glfw create window
  79. // can't delete without a non-virtual deconstrcutor
  80. //delete win;
  81. return nullptr;
  82. }
  83. // init shaders?
  84. // we only want the box (texture shader)
  85. // I don't think you can init GLEW without a window
  86. initGL();
  87. // load the shaders
  88. twin->textureShader = twin->shaderLoader.getShader(VertexShader("TextureShader.vert"),
  89. FragmentShader("TextureShader.frag"));
  90. twin->fontShader = twin->shaderLoader.getShader(VertexShader("FontShader.vert"),
  91. FragmentShader("FontShader.frag"));
  92. // configure opengl coordinates
  93. //std::cout << "position: " << position->w << "x" << position->h << std::endl;
  94. glViewport(0, 0, static_cast<GLsizei>(position->w), static_cast<GLsizei>(position->h)); checkGLState("OpenGL::createWindow - glViewport");
  95. // replace first parameter of all these callbacks with our window object instead of a GLFWwindow
  96. glfwSetWindowUserPointer(twin->window, twin);
  97. // set up event callbacks
  98. // window events
  99. glfwSetFramebufferSizeCallback(window, [](GLFWwindow *glfwwin, int width, int height) {
  100. glViewport(0, 0, width, height);
  101. });
  102. glfwSetWindowSizeCallback(window, [](GLFWwindow *glfwwin, int width, int height) {
  103. OpenGLWindowHandle *thiz = reinterpret_cast<OpenGLWindowHandle*>(glfwGetWindowUserPointer(glfwwin));
  104. if (thiz->onResize) {
  105. thiz->onResize(width, height);
  106. }
  107. });
  108. // mouse events
  109. glfwSetCursorPosCallback(window, [](GLFWwindow *glfwwin, double xPos, double yPos) {
  110. OpenGLWindowHandle *thiz = reinterpret_cast<OpenGLWindowHandle*>(glfwGetWindowUserPointer(glfwwin));
  111. //std::cout << "Window::Window:onMousemove - at " << static_cast<int>(xPos) << "," << static_cast<int>(yPos) << std::endl;
  112. thiz->cursorX = xPos;
  113. thiz->cursorY = yPos;
  114. if (xPos < 0 || yPos < 0) return;
  115. if (xPos > thiz->width || yPos > thiz->height) return;
  116. // p. much worthless on double
  117. /*
  118. static double lx = 0;
  119. static double ly = 0;
  120. if (lx == xPos && ly == yPos) {
  121. return;
  122. }
  123. lx = xPos;
  124. ly = yPos;
  125. std::cout << "Window::Window:onMousemove - noCache" << std::endl;
  126. */
  127. //std::cout << "Window::Window:onMousemove - onWheel" << std::endl;
  128. if (thiz->onMouseMove) {
  129. thiz->onMouseMove(xPos, yPos);
  130. }
  131. });
  132. glfwSetScrollCallback(window, [](GLFWwindow *glfwwin, double xOffset, double yOffset) {
  133. OpenGLWindowHandle *thiz = reinterpret_cast<OpenGLWindowHandle*>(glfwGetWindowUserPointer(glfwwin));
  134. //std::cout << "glfwSetScrollCallback " << yOffset << " int" << (int)(yOffset * 10) << std::endl;
  135. if (thiz->onWheel) {
  136. thiz->onWheel(xOffset * 10, yOffset * 10);
  137. }
  138. });
  139. glfwSetMouseButtonCallback(window, [](GLFWwindow *glfwwin, int button, int action, int mods) {
  140. OpenGLWindowHandle *thiz = reinterpret_cast<OpenGLWindowHandle*>(glfwGetWindowUserPointer(glfwwin));
  141. if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) {
  142. //std::cout << "left press" << std::endl;
  143. if (thiz->onMouseUp) {
  144. thiz->onMouseDown(thiz->cursorX, thiz->cursorY);
  145. }
  146. }
  147. if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_RELEASE) {
  148. //std::cout << "left release" << std::endl;
  149. if (thiz->onMouseUp) {
  150. thiz->onMouseUp(thiz->cursorX, thiz->cursorY);
  151. }
  152. }
  153. });
  154. // keyboard events
  155. // works with utf-32 and os keyboard layout but we'll lkeep the low level for now
  156. glfwSetCharCallback(window, [](GLFWwindow* glfwwin, unsigned int codepoint) {
  157. OpenGLWindowHandle *thiz = reinterpret_cast<OpenGLWindowHandle*>(glfwGetWindowUserPointer(glfwwin));
  158. //std::cout << "OpenGL::glfwSetCharCallback - codepoint: " << codepoint << std::endl;
  159. // should be used for inputComponent
  160. if (thiz->onKeyPress) {
  161. thiz->onKeyPress(codepoint);
  162. }
  163. });
  164. glfwSetKeyCallback(window, [](GLFWwindow *glfwwin, int key, int scancode, int action, int mods) {
  165. OpenGLWindowHandle *thiz = reinterpret_cast<OpenGLWindowHandle*>(glfwGetWindowUserPointer(glfwwin));
  166. std::cout << "opengl::glfwSetKeyCallback - Key " << key << " action: " << action << " mods: " << mods << std::endl;
  167. switch(action) {
  168. case GLFW_RELEASE:
  169. if (thiz->onKeyUp) {
  170. std::cout << "hasKeyUp" << std::endl;
  171. thiz->onKeyUp(key, scancode, mods);
  172. }
  173. break;
  174. case GLFW_PRESS:
  175. //thiz->ui->onKeyDown(key, scancode, mods);
  176. //thiz->ui->onKeyPress(key, scancode, action, mods);
  177. if (thiz->onKeyDown) {
  178. std::cout << "hasKeyDown" << std::endl;
  179. thiz->onKeyDown(key, scancode, mods);
  180. }
  181. break;
  182. case GLFW_REPEAT:
  183. //thiz->ui->onKeyRepeat(key, scancode, mods);
  184. //thiz->ui->onKeyPress(key, scancode, action, mods);
  185. if (thiz->onKeyRepeat) {
  186. std::cout << "hasKeyRepeat" << std::endl;
  187. thiz->onKeyRepeat(key, scancode, mods);
  188. }
  189. break;
  190. }
  191. });
  192. /*
  193. // Change to the projection matrix, reset the matrix and set up orthagonal projection (i.e. 2D)
  194. glMatrixMode(GL_PROJECTION);
  195. glErr=glGetError();
  196. if(glErr != GL_NO_ERROR) {
  197. std::cout << "OpenGL::createWindow - glMatrixMode - not ok: " << gluErrorString(glErr) << std::endl;
  198. }
  199. glLoadIdentity();
  200. glErr=glGetError();
  201. if(glErr != GL_NO_ERROR) {
  202. std::cout << "OpenGL::createWindow - glLoadIdentity - not ok: " << gluErrorString(glErr) << std::endl;
  203. }
  204. glOrtho(0, position->w, position->h, 0, 0, 1); // Paramters: left, right, bottom, top, near, far
  205. glErr=glGetError();
  206. if(glErr != GL_NO_ERROR) {
  207. std::cout << "OpenGL::createWindow - glOrtho - not ok: " << gluErrorString(glErr) << std::endl;
  208. }
  209. */
  210. // set up box shader
  211. GLuint elementBufferObject = 0;
  212. glGenVertexArrays(1, &twin->vertexArrayObjectBox); checkGLState("OpenGL::createWindow - genVAOBox");
  213. glBindVertexArray(twin->vertexArrayObjectBox); checkGLState("OpenGL::createWindow - bindVAOBox");
  214. glGenBuffers(1, &elementBufferObject); checkGLState("OpenGL::createWindow - genEBO");
  215. // we may need the VBO here...
  216. glGenBuffers(1, &twin->vertexBufferObjectBox); checkGLState("OpenGL::createWindow - genVBOBox");
  217. float vertices[20] = {
  218. 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
  219. 0.0f, 0.0f, 0.0f, 1.0f, 1.0f,
  220. 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
  221. 0.0f, 0.0f, 0.0f, 0.0f, 0.0f
  222. };
  223. // select buffer
  224. glBindBuffer(GL_ARRAY_BUFFER, twin->vertexBufferObjectBox); checkGLState("OpenGL::createWindow - bindVBO");
  225. // write buffer
  226. glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); checkGLState("OpenGL::createWindow - bufVBO");
  227. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBufferObject); checkGLState("OpenGL::createWindow - bindEBO");
  228. glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(this->indices), this->indices, GL_STATIC_DRAW); checkGLState("OpenGL::createWindow - buffEBO");
  229. // attribute 0 = 3 floats
  230. glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), nullptr); checkGLState("OpenGL::createWindow - glVertexAttribPointer0");
  231. glEnableVertexAttribArray(0); checkGLState("OpenGL::createWindow - glEnableVertexAttribArray0");
  232. // attribute 1 = 2 floats, at 3
  233. glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), reinterpret_cast<void*>(3 * sizeof(float))); checkGLState("OpenGL::createWindow - glVertexAttribPointer1");
  234. glEnableVertexAttribArray(1); checkGLState("OpenGL::createWindow - glEnableVertexAttribArray1");
  235. //glBindVertexArray(0);
  236. // set up text shader
  237. glGenVertexArrays(1, &twin->vertexArrayObjectText); checkGLState("OpenGL::createWindow - genVAOText");
  238. glBindVertexArray(twin->vertexArrayObjectText); checkGLState("OpenGL::createWindow - bindVBOText");
  239. // vBO
  240. glGenBuffers(1, &twin->vertexBufferObjectText); checkGLState("OpenGL::createWindow - genVBOText");
  241. glBindBuffer(GL_ARRAY_BUFFER, twin->vertexBufferObjectText); checkGLState("OpenGL::createWindow - bindVBOText");
  242. std::unique_ptr<float[]> vertices2 = std::make_unique<float[]>(36); // upload garbage for now
  243. glBufferData(GL_ARRAY_BUFFER, ((3 + 4 + 2) * 4) * sizeof(float), vertices2.get(), GL_STATIC_DRAW); checkGLState("OpenGL::createWindow - buffVBOText");
  244. // eBO
  245. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBufferObject); checkGLState("OpenGL::createWindow - bindVBOText");
  246. //glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
  247. glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, (3 + 4 + 2) * sizeof(float), nullptr); checkGLState("OpenGL::createWindow - glVertexAttribPointerText0");
  248. glEnableVertexAttribArray(0); checkGLState("OpenGL::createWindow - glEnableVertexAttribArrayText0");
  249. glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, (3 + 4 + 2) * sizeof(float), reinterpret_cast<void*>(3 * sizeof(float))); checkGLState("opengl::createWindow - glVertexAttribPointerText1");
  250. glEnableVertexAttribArray(1); checkGLState("OpenGL::createWindow - glEnableVertexAttribArrayText1");
  251. glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, (3 + 4 + 2) * sizeof(float), reinterpret_cast<void*>(7 * sizeof(float))); checkGLState("opengl::createWindow - glVertexAttribPointerText2");
  252. glEnableVertexAttribArray(2); checkGLState("OpenGL::createWindow - glEnableVertexAttribArrayText2");
  253. glBindVertexArray(0);
  254. return twin;
  255. }
  256. void OpenGLWindowHandle::clear() {
  257. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); checkGLState("OpenGLWindowHandle::clear");
  258. }
  259. void OpenGLWindowHandle::swapBuffers() {
  260. glfwSwapBuffers(this->window); checkGLState("OpenGLWindowHandle::swapBuffers");
  261. }
  262. OpenGLTexture* OpenGLWindowHandle::createSprite(unsigned char* texture, GLsizei w, GLsizei h) {
  263. OpenGLTexture *handle = new OpenGLTexture;
  264. glGenTextures(1, &handle->number);
  265. // make sure texture size is a power of two
  266. size_t potw = pow(2, ceil(log(w) / log(2)));
  267. size_t poth = pow(2, ceil(log(h) / log(2)));
  268. // FIXME: need to dynamically allocate for c++
  269. //unsigned char data[16384][16384][4];
  270. //unsigned char ***image = allocate_dynamic_bitmap(poth, potw, 4);
  271. unsigned char *data = reinterpret_cast<unsigned char *>(tlsf_malloc(sizeof(unsigned char) * poth * potw * 4));
  272. //memset(data, 0, poth * potw * 4);
  273. //memset(image, 0, poth * potw * 4);
  274. // unflip texture
  275. unsigned int loadWidth = static_cast<unsigned int>(w);
  276. unsigned int loadHeight = static_cast<unsigned int>(h);
  277. for (unsigned int py = 0; py < loadHeight; py++) {
  278. for (unsigned int px = 0; px < loadWidth; px++) {
  279. for (unsigned int i = 0; i < 4; i++) {
  280. //data[1023 - py][px][i] = anime.pixel_data[((px * 4) + (py * 4 * 1024)) + i];
  281. size_t read = ((px * 4) + (py * 4 * loadWidth)) + i;
  282. unsigned char val = texture[read];
  283. size_t ypos = potw - 1 - py; // flip y
  284. size_t write = ((px * 4) + (ypos * 4 * potw)) + i;
  285. data[write] = val;
  286. //data[ypos][px][i] = val;
  287. }
  288. }
  289. }
  290. // upload to video card
  291. // select
  292. glBindTexture(GL_TEXTURE_2D, handle->number); checkGLState("OpenGLWindowHandle::createSprite - bind");
  293. // upload
  294. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, static_cast<int>(potw), static_cast<int>(poth), 0, GL_RGBA, GL_UNSIGNED_BYTE, data); checkGLState("OpenGLWindowHandle::createSprite - upload");
  295. // process
  296. glGenerateMipmap(GL_TEXTURE_2D); checkGLState("OpenGLWindowHandle::createSprite - process");
  297. // unselect
  298. glBindTexture(GL_TEXTURE_2D, 0); checkGLState("OpenGLWindowHandle::createSprite - unselect");
  299. return handle;
  300. }
  301. OpenGLTexture* OpenGLWindowHandle::createTextSprite(unsigned char *texture, GLsizei w, GLsizei h, textureMap &textureMap) {
  302. OpenGLTexture *handle = new OpenGLTexture;
  303. glGenTextures(1, &handle->number); checkGLState("OpenGLWindowHandle::createTextureFromColor - glGenTextures");
  304. // upload
  305. glBindTexture(GL_TEXTURE_2D, handle->number); checkGLState("OpenGLWindowHandle::createTextureFromColor - bindTexture");
  306. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, texture); checkGLState("OpenGLWindowHandle::createTextureFromColor - glTexImage2D");
  307. glGenerateMipmap(GL_TEXTURE_2D); checkGLState("OpenGLWindowHandle::createTextureFromColor - glGenerateMipmap");
  308. glBindTexture(GL_TEXTURE_2D, 0); checkGLState("OpenGLWindowHandle::createTextureFromColor - unBindTex");
  309. // I flipped this maybe due to coords...
  310. handle->s0 = textureMap.map[0];
  311. handle->t0 = textureMap.map[1];
  312. handle->s1 = textureMap.map[2];
  313. handle->t1 = textureMap.map[3];
  314. return handle;
  315. }
  316. OpenGLTexture* OpenGLWindowHandle::createSpriteFromColor(const unsigned int hexColor) {
  317. //std::cout << "createTextureFromColor: " << hexColor << std::endl;
  318. unsigned char texture[1][1][4];
  319. texture[0][0][0]=(hexColor >> 24) & 0xFF;
  320. texture[0][0][1]=(hexColor >> 16) & 0xFF;
  321. texture[0][0][2]=(hexColor >> 8) & 0xFF;
  322. texture[0][0][3]=(hexColor >> 0) & 0xFF;
  323. //std::cout << "opengl::createTextureFromColor R: " << (int)texture[0][0][0] << " G: " << (int)texture[0][0][1] << " B: " << (int)texture[0][0][2] << " A: " << (int)texture[0][0][3] << std::endl;
  324. // I can't figure out how to pass data to opengl::createTexture
  325. // so we'll just do this for now
  326. OpenGLTexture *handle=new OpenGLTexture;
  327. glGenTextures(1, &handle->number); checkGLState("OpenGLWindowHandle::createTextureFromColor - glGenTextures");
  328. glBindTexture(GL_TEXTURE_2D, handle->number); checkGLState("OpenGLWindowHandle::createTextureFromColor - glBindTexture");
  329. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture); checkGLState("OpenGLWindowHandle::createTextureFromColor - glTexImage2D");
  330. glGenerateMipmap(GL_TEXTURE_2D); checkGLState("OpenGLWindowHandle::createTextureFromColor - glGenerateMipmap");
  331. glBindTexture(GL_TEXTURE_2D, 0); checkGLState("OpenGLWindowHandle::createTextureFromColor - unselect");
  332. return handle;
  333. }
  334. #include <cmath>
  335. // converts 0-1 to screen
  336. // but centered
  337. void pointToViewport(float &rawX, float &rawY, size_t windowWidth, size_t windowHeight) {
  338. //std::cout << "Component::pointToViewport - notBoundToPage converting from " << static_cast<int>(rawX) << "," << static_cast<int>(rawY) << std::endl;
  339. //std::cout << "BoundToPage using " << screenWidth << "x" << screenHeight << std::endl;
  340. rawX = ((rawX / windowWidth) * 2) - 1;
  341. rawY = ((rawY / windowHeight) * 2) - 1;
  342. //std::cout << "Component::pointToViewport - BoundToPage using " << static_cast<int>(rawX) << "x" << static_cast<int>(rawY) << std::endl;
  343. //std::cout << "Component::pointToViewport - BoundToPage converted to " << rawX << "," << rawY << std::endl;
  344. }
  345. void pointToViewportText(float &rawX, float &rawY, size_t windowWidth, size_t windowHeight);
  346. void pointToViewportText(float &rawX, float &rawY, size_t windowWidth, size_t windowHeight) {
  347. //std::cout << "notBoundToPage using " << screenWidth << "x" << screenHeight << std::endl;
  348. //std::cout << "Component::pointToViewport - notBoundToPage converting from " << static_cast<int>(rawX) << "," << static_cast<int>(rawY) << std::endl;
  349. if (rawX < 0) {
  350. rawX += windowWidth;
  351. }
  352. if (rawY < 0) {
  353. rawY += windowHeight;
  354. }
  355. if (rawX > 1) {
  356. rawX /= windowWidth;
  357. }
  358. if (rawY > 1) {
  359. rawY /= windowHeight;
  360. }
  361. rawX = (rawX * 2) - 1;
  362. rawY = (rawY * 2) - 1;
  363. //std::cout << "Component::pointToViewport - notBoundToPage converted to " << rawX << "," << rawY << std::endl;
  364. }
  365. // keeps 0-1 (and *2 to convert to screen)
  366. // but also takes pixels (and converts to screen)
  367. // anchors to upperleft
  368. void distanceToViewport(float &rawX, float &rawY, size_t windowWidth, size_t windowHeight) {
  369. if (std::abs(rawX) > 1) {
  370. rawX /= windowWidth;
  371. }
  372. if (std::abs(rawY) > 1) {
  373. rawY /= windowHeight;
  374. }
  375. rawX *= 2;
  376. rawY *= 2;
  377. }
  378. void OpenGLWindowHandle::drawSpriteBox(OpenGLTexture *texture, Rect *position) {
  379. std::cout << "Window size: " << this->width << "," << this->height << std::endl;
  380. // figure out new vertices
  381. float vx = position->x;
  382. // 320, 320 is mid to top
  383. // 0, 320 to bottom to top
  384. //float vy = (int)position->h - (int)position->y - (int)this->height;
  385. float vy = static_cast<int>(position->h) - position->y;
  386. float vWidth = position->w;
  387. float vHeight = position->h;
  388. //std::cout << "placing box at " << (int)vx << "x" << (int)vy << " size: " << (int)vWidth << "x" << (int)vHeight << std::endl;
  389. pointToViewport(vx, vy, this->width, this->height);
  390. //std::cout << "vWidth before: " << (int)vWidth << std::endl;
  391. distanceToViewport(vWidth, vHeight, this->width, this->height);
  392. //std::cout << "vWidth after: " << (int)vWidth << std::endl;
  393. //std::cout << "placing box at GL " << (int)vx << "x" << (int)vy << " size: " << (int)(vWidth*10000) << "x" << (int)(vHeight*10000) << std::endl;
  394. float vertices[20] = {
  395. 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
  396. 0.0f, 0.0f, 0.0f, 1.0f, 1.0f,
  397. 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
  398. 0.0f, 0.0f, 0.0f, 0.0f, 0.0f
  399. };
  400. vertices[(0 * 5) + 0] = vx;
  401. vertices[(0 * 5) + 1] = vy + vHeight;
  402. vertices[(1 * 5) + 0] = vx + vWidth;
  403. vertices[(1 * 5) + 1] = vy + vHeight;
  404. vertices[(2 * 5) + 0] = vx + vWidth;
  405. vertices[(2 * 5) + 1] = vy;
  406. vertices[(3 * 5) + 0] = vx;
  407. vertices[(3 * 5) + 1] = vy;
  408. glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObjectBox); checkGLState("OpenGLWindowHandle::drawSpriteBox - unselect");
  409. glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); checkGLState("OpenGLWindowHandle::drawSpriteBox - glBufferData");
  410. float textureTransformMatrix[16] = {
  411. 1, 0, 0, 0,
  412. 0, 1, 0, 0,
  413. 0, 0, 1, 0,
  414. 0, 0, 0, 1
  415. };
  416. textureShader->bind();
  417. GLint transformLocation = textureShader->uniform("transform");
  418. glUniformMatrix4fv(transformLocation, 1, GL_FALSE, textureTransformMatrix); checkGLState("OpenGLWindowHandle::drawSpriteBox - glUniformMatrix4fv");
  419. glBindVertexArray(vertexArrayObjectBox); checkGLState("OpenGLWindowHandle::drawSpriteBox - glBindVertexArray");
  420. glBindTexture(GL_TEXTURE_2D, texture->number); checkGLState("OpenGLWindowHandle::drawSpriteBox - glBindTexture");
  421. glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr); checkGLState("OpenGLWindowHandle::drawSpriteBox - glDrawElements");
  422. }
  423. inline void setVerticesColor(std::unique_ptr<float[]> &vertices, int p, unsigned int color);
  424. #define posMac(p) (p * (3 + 4 + 2)) // 3 positions + 4 color channels + 2 S&T (texture mapping)
  425. inline void setVerticesColor(std::unique_ptr<float[]> &vertices, int p, unsigned int color) {
  426. vertices[static_cast<size_t>(posMac(p) + 2)] = 0.0f;
  427. vertices[static_cast<size_t>(posMac(p) + 3)] = (static_cast<float>((color >> 24) & 0xFF)) / 255;
  428. vertices[static_cast<size_t>(posMac(p) + 4)] = (static_cast<float>((color >> 16) & 0xFF)) / 255;
  429. vertices[static_cast<size_t>(posMac(p) + 5)] = (static_cast<float>((color >> 8) & 0xFF)) / 255;
  430. vertices[static_cast<size_t>(posMac(p) + 6)] = (static_cast<float>((color >> 0) & 0xFF)) / 255;
  431. }
  432. void OpenGLWindowHandle::drawSpriteText(OpenGLTexture *texture, unsigned int hexColor, Rect *position) {
  433. float vx0 = position->x;
  434. float vy0 = static_cast<int>(this->height) - position->y + position->h;
  435. float vx1 = position->x + position->w;
  436. float vy1 = static_cast<int>(this->height) - position->y;
  437. pointToViewportText(vx0, vy0, this->width, this->height);
  438. pointToViewportText(vx1, vy1, this->width, this->height);
  439. std::unique_ptr<float[]> vertices = std::make_unique<float[]>(36);
  440. vertices[posMac(0) + 0] = vx0;
  441. vertices[posMac(0) + 1] = vy0;
  442. setVerticesColor(vertices, 0, hexColor);
  443. vertices[posMac(0) + 7] = texture->s0;
  444. vertices[posMac(0) + 8] = texture->t0;
  445. vertices[posMac(1) + 0] = vx0;
  446. vertices[posMac(1) + 1] = vy1;
  447. setVerticesColor(vertices, 1, hexColor);
  448. vertices[posMac(1) + 7] = texture->s0;
  449. vertices[posMac(1) + 8] = texture->t1;
  450. vertices[posMac(2) + 0] = vx1;
  451. vertices[posMac(2) + 1] = vy1;
  452. setVerticesColor(vertices, 2, hexColor);
  453. vertices[posMac(2) + 7] = texture->s1;
  454. vertices[posMac(2) + 8] = texture->t1;
  455. vertices[posMac(3) + 0] = vx1;
  456. vertices[posMac(3) + 1] = vy0;
  457. setVerticesColor(vertices, 3, hexColor);
  458. vertices[posMac(3) + 7] = texture->s1;
  459. vertices[posMac(3) + 8] = texture->t0;
  460. glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObjectText); checkGLState("OpenGLWindowHandle::drawSpriteText - glBindBuffer");
  461. glBufferData(GL_ARRAY_BUFFER, ((3 + 4 + 2) * 4) * sizeof(float), vertices.get(), GL_STATIC_DRAW); checkGLState("OpenGLWindowHandle::drawSpriteText - glBufferData");
  462. float transformMatrix[16] = {
  463. 1, 0, 0, 0,
  464. 0, 1, 0, 0,
  465. 0, 0, 1, 0,
  466. 0, 0, 0, 1
  467. };
  468. fontShader->bind();
  469. GLint transformLocation = fontShader->uniform("transform");
  470. glUniformMatrix4fv(transformLocation, 1, GL_FALSE, transformMatrix); checkGLState("OpenGLWindowHandle::drawSpriteText - glUniformMatrix4fv");
  471. // load vertices
  472. glBindVertexArray(vertexArrayObjectText); checkGLState("OpenGLWindowHandle::drawSpriteText - glBindVertexArray");
  473. // load texture
  474. glBindTexture(GL_TEXTURE_2D, texture->number); checkGLState("OpenGLWindowHandle::drawSpriteText - glBindTexture");
  475. // draw primitives using vertices and texture
  476. glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr); checkGLState("OpenGLWindowHandle::drawSpriteText - glDrawElements");
  477. }