source: opengl-game/opengl-game.cpp

feature/imgui-sdl
Last change on this file was d8cf709, checked in by Dmitry Portnoy <dportnoy@…>, 3 years ago

Change UIEvent to also include the original event from the UI library the game gui is currently using, such as SDL or GLFW.

  • Property mode set to 100644
File size: 10.4 KB
Line 
1#include "opengl-game.hpp"
2
3#include <iostream>
4
5#include "consts.hpp"
6#include "logger.hpp"
7
8#include "utils.hpp"
9
10using namespace std;
11
12OpenGLGame::OpenGLGame() {
13 gui = nullptr;
14 window = nullptr;
15}
16
17OpenGLGame::~OpenGLGame() {
18}
19
20void OpenGLGame::run(int width, int height, unsigned char guiFlags) {
21#ifdef NDEBUG
22 cout << "DEBUGGING IS OFF" << endl;
23#else
24 cout << "DEBUGGING IS ON" << endl;
25#endif
26
27 cout << "OpenGL Game" << endl;
28
29 // TODO: Refactor the logger api to be more flexible,
30 // esp. since gl_log() and gl_log_err() have issues printing anything besides stirngs
31 restart_gl_log();
32 gl_log("starting GLFW\n%s", glfwGetVersionString());
33
34 open_log();
35 get_log() << "starting GLFW" << endl;
36 get_log() << glfwGetVersionString() << endl;
37
38 if (initWindow(width, height, guiFlags) == RTWO_ERROR) {
39 return;
40 }
41
42 initOpenGL();
43 mainLoop();
44 cleanup();
45
46 close_log();
47}
48
49// TODO: Make some more initi functions, or call this initUI if the
50// amount of things initialized here keeps growing
51bool OpenGLGame::initWindow(int width, int height, unsigned char guiFlags) {
52 // TODO: Put all fonts, textures, and images in the assets folder
53 gui = new GameGui_GLFW();
54
55 if (gui->init() == RTWO_ERROR) {
56 // TODO: Also print these sorts of errors to the log
57 cout << "UI library could not be initialized!" << endl;
58 cout << gui->getError() << endl;
59 return RTWO_ERROR;
60 }
61 cout << "GUI init succeeded" << endl;
62
63 window = (GLFWwindow*) gui->createWindow("OpenGL Game", width, height, guiFlags & GUI_FLAGS_WINDOW_FULLSCREEN);
64 if (window == nullptr) {
65 cout << "Window could not be created!" << endl;
66 cout << gui->getError() << endl;
67 return RTWO_ERROR;
68 }
69
70 viewport = { 0, 0, gui->getWindowWidth(), gui->getWindowHeight() };
71
72 cout << "Target window size: (" << width << ", " << height << ")" << endl;
73 cout << "Actual window size: (" << viewport.width << ", " << viewport.height << ")" << endl;
74
75 return RTWO_SUCCESS;
76}
77
78void OpenGLGame::initOpenGL() {
79 glfwMakeContextCurrent(window);
80 glViewport(0, 0, gui->getWindowWidth(), gui->getWindowHeight());
81
82 glewExperimental = GL_TRUE;
83 glewInit();
84
85 if (GLEW_KHR_debug) {
86 cout << "FOUND GLEW debug extension" << endl;
87 glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
88 glDebugMessageCallback((GLDEBUGPROC)opengl_debug_callback, nullptr);
89 cout << "Bound debug callback" << endl;
90 } else {
91 cout << "OpenGL debug message callback is not supported" << endl;
92 }
93
94 // Setup Dear ImGui binding
95 IMGUI_CHECKVERSION();
96 ImGui::CreateContext();
97 ImGuiIO& io = ImGui::GetIO(); (void)io;
98 //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
99 //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
100 ImGui_ImplGlfwGL3_Init(window, true);
101
102 // Setup style
103 ImGui::StyleColorsDark();
104 //ImGui::StyleColorsClassic();
105
106 // The glfw event handlers have to be bound after ImGui is initialized.
107 // Otherwise, it seems they get overridden by ImGui
108 ((GameGui_GLFW*)gui)->bindEventHandlers();
109
110 graphicsPipelines.push_back(GraphicsPipeline_OpenGL(viewport));
111
112 graphicsPipelines.back().addVaryingAttribute(ATTRIB_POINT_VARYING, 3, GL_FLOAT,
113 offset_of(&SceneObject::points));
114 graphicsPipelines.back().addVaryingAttribute(ATTRIB_POINT_VARYING, 3, GL_FLOAT,
115 offset_of(&SceneObject::colors));
116 graphicsPipelines.back().addVaryingAttribute(ATTRIB_POINT_VARYING, 3, GL_FLOAT,
117 offset_of(&SceneObject::normals));
118 graphicsPipelines.back().addVaryingAttribute(ATTRIB_OBJECT_VARYING, 1, GL_UNSIGNED_INT,
119 offset_of(&SceneObject::ubo_offset));
120
121 graphicsPipelines.back().createPipeline("gl-shaders/ship.vert", "gl-shaders/ship.frag");
122
123 graphicsPipelines.push_back(GraphicsPipeline_OpenGL(viewport));
124
125 graphicsPipelines.back().addVaryingAttribute(ATTRIB_POINT_VARYING, 3, GL_FLOAT,
126 offset_of(&SceneObject::points));
127 graphicsPipelines.back().addVaryingAttribute(ATTRIB_POINT_VARYING, 3, GL_FLOAT,
128 offset_of(&SceneObject::colors));
129 graphicsPipelines.back().addVaryingAttribute(ATTRIB_POINT_VARYING, 3, GL_FLOAT,
130 offset_of(&SceneObject::normals));
131 graphicsPipelines.back().addVaryingAttribute(ATTRIB_OBJECT_VARYING, 1, GL_UNSIGNED_INT,
132 offset_of(&SceneObject::ubo_offset));
133
134 graphicsPipelines.back().createPipeline("gl-shaders/asteroid.vert", "gl-shaders/asteroid.frag");
135
136 graphicsPipelines.push_back(GraphicsPipeline_OpenGL(viewport));
137
138 graphicsPipelines.back().addVaryingAttribute(ATTRIB_POINT_VARYING, 3, GL_FLOAT,
139 offset_of(&SceneObject::points));
140 graphicsPipelines.back().addVaryingAttribute(ATTRIB_POINT_VARYING, 2, GL_FLOAT,
141 offset_of(&SceneObject::texcoords));
142 graphicsPipelines.back().addVaryingAttribute(ATTRIB_OBJECT_VARYING, 1, GL_UNSIGNED_INT,
143 offset_of(&SceneObject::ubo_offset));
144
145 graphicsPipelines.back().createPipeline("gl-shaders/laser.vert", "gl-shaders/laser.frag");
146
147 graphicsPipelines.push_back(GraphicsPipeline_OpenGL(viewport));
148
149 graphicsPipelines.back().addVaryingAttribute(ATTRIB_POINT_VARYING, 3, GL_FLOAT,
150 offset_of(&ParticleEffect::particleVelocities));
151 graphicsPipelines.back().addVaryingAttribute(ATTRIB_POINT_VARYING, 1, GL_FLOAT,
152 offset_of(&ParticleEffect::particleTimes));
153 graphicsPipelines.back().addVaryingAttribute(ATTRIB_OBJECT_VARYING, 1, GL_UNSIGNED_INT,
154 offset_of(&ParticleEffect::ubo_offset));
155
156 graphicsPipelines.back().createPipeline("gl-shaders/explosion.vert", "gl-shaders/explosion.frag");
157
158 cout << "Created " << graphicsPipelines.size() << " graphics pipelines" << endl;
159}
160
161void OpenGLGame::mainLoop() {
162 UIEvent uiEvent;
163 bool quit = false;
164
165 while (!quit) {
166 gui->processEvents();
167
168 while (gui->pollEvent(&uiEvent)) {
169 GameEvent& e = uiEvent.event;
170
171 switch (e.type) {
172 case UI_EVENT_QUIT:
173 cout << "Quit event detected" << endl;
174 quit = true;
175 break;
176 case UI_EVENT_KEYDOWN:
177 if (e.key.keycode == GLFW_KEY_ESCAPE) {
178 quit = true;
179 } else {
180 cout << "Key event detected" << endl;
181 }
182 break;
183 case UI_EVENT_WINDOWRESIZE:
184 cout << "Window resize event detected" << endl;
185 viewport.width = e.windowResize.width;
186 viewport.height = e.windowResize.height;
187 break;
188 default:
189 cout << "Unhandled UI event: " << e.type << endl;
190 }
191 }
192
193 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
194
195 // Anton's book suggests placing this here, after glClear(). Check it's impact on framerate
196 // TODO: This doesn't seem to work correctly when in the loop. DO some research
197 // max viewport dims are clamped to glGet(GL_MAX_VIEWPORT_DIMS)
198 //glViewport(0, 0, gui->getWindowWidth(), gui->getWindowHeight());
199
200 renderScene();
201 renderUI();
202
203 glfwSwapBuffers(window);
204 }
205}
206
207void OpenGLGame::renderScene() {
208
209}
210
211void OpenGLGame::renderUI() {
212 ImGui_ImplGlfwGL3_NewFrame();
213
214 {
215 int padding = 4;
216 ImGui::SetNextWindowPos(ImVec2(-padding, -padding), ImGuiCond_Once);
217 ImGui::SetNextWindowSize(ImVec2(gui->getWindowWidth() + 2 * padding, gui->getWindowHeight() + 2 * padding), ImGuiCond_Always);
218 ImGui::Begin("WndMain", NULL,
219 ImGuiWindowFlags_NoTitleBar |
220 ImGuiWindowFlags_NoResize |
221 ImGuiWindowFlags_NoMove);
222
223 ImGui::InvisibleButton("", ImVec2(10, 80));
224 ImGui::InvisibleButton("", ImVec2(285, 18));
225 ImGui::SameLine();
226 ImGui::Button("New Game");
227
228 ImGui::InvisibleButton("", ImVec2(10, 15));
229 ImGui::InvisibleButton("", ImVec2(300, 18));
230 ImGui::SameLine();
231 ImGui::Button("Quit");
232
233 ImGui::End();
234 }
235
236 ImGui::Render();
237 ImGui_ImplGlfwGL3_RenderDrawData(ImGui::GetDrawData());
238}
239
240void OpenGLGame::cleanup() {
241 ImGui_ImplGlfwGL3_Shutdown();
242 ImGui::DestroyContext();
243
244 gui->destroyWindow();
245 gui->shutdown();
246 delete gui;
247}
248
249void APIENTRY opengl_debug_callback(
250 GLenum source,
251 GLenum type,
252 GLuint id,
253 GLenum severity,
254 GLsizei length,
255 const GLchar* message,
256 const void* userParam
257) {
258 string strMessage(message);
259
260 // TODO: Use C++ strings directly and see if there are other ways to clean
261 // this function up
262 char source_str[2048];
263 char type_str[2048];
264 char severity_str[2048];
265
266 switch (source) {
267 case 0x8246:
268 strcpy(source_str, "API");
269 break;
270 case 0x8247:
271 strcpy(source_str, "WINDOW_SYSTEM");
272 break;
273 case 0x8248:
274 strcpy(source_str, "SHADER_COMPILER");
275 break;
276 case 0x8249:
277 strcpy(source_str, "THIRD_PARTY");
278 break;
279 case 0x824A:
280 strcpy(source_str, "APPLICATION");
281 break;
282 case 0x824B:
283 strcpy(source_str, "OTHER");
284 break;
285 default:
286 strcpy(source_str, "undefined");
287 break;
288 }
289
290 switch (type) {
291 case 0x824C:
292 strcpy(type_str, "ERROR");
293 break;
294 case 0x824D:
295 strcpy(type_str, "DEPRECATED_BEHAVIOR");
296 break;
297 case 0x824E:
298 strcpy(type_str, "UNDEFINED_BEHAVIOR");
299 break;
300 case 0x824F:
301 strcpy(type_str, "PORTABILITY");
302 break;
303 case 0x8250:
304 strcpy(type_str, "PERFORMANCE");
305 break;
306 case 0x8251:
307 strcpy(type_str, "OTHER");
308 break;
309 case 0x8268:
310 strcpy(type_str, "MARKER");
311 break;
312 case 0x8269:
313 strcpy(type_str, "PUSH_GROUP");
314 break;
315 case 0x826A:
316 strcpy(type_str, "POP_GROUP");
317 break;
318 default:
319 strcpy(type_str, "undefined");
320 break;
321 }
322 switch (severity) {
323 case 0x9146:
324 strcpy(severity_str, "HIGH");
325 break;
326 case 0x9147:
327 strcpy(severity_str, "MEDIUM");
328 break;
329 case 0x9148:
330 strcpy(severity_str, "LOW");
331 break;
332 case 0x826B:
333 strcpy(severity_str, "NOTIFICATION");
334 break;
335 default:
336 strcpy(severity_str, "undefined");
337 break;
338 }
339
340 if (string(severity_str) != "NOTIFICATION") {
341 cout << "OpenGL Error!!!" << endl;
342 cout << "Source: " << string(source_str) << endl;
343 cout << "Type: " << string(type_str) << endl;
344 cout << "Severity: " << string(severity_str) << endl;
345 cout << strMessage << endl;
346 }
347}
Note: See TracBrowser for help on using the repository browser.