1 | #include "ZydecoCommon.hpp" |
2 | #include "Renderer.hpp" |
3 | #include "IEventHandler.hpp" |
4 | #include "IWindow.hpp" |
5 | #include "ITimer.hpp" |
6 | #include "GLShader.hpp" |
7 | #include "GLProgram.hpp" |
8 | #include "GLRenderObject.hpp" |
9 | #include "GLRenderObjectBackground.hpp" |
10 | #include "GLRenderObjectRainbowTriangle.hpp" |
11 |
|
12 |
|
13 | static Logger LOGGER("Renderer"); |
14 | static uint64_t frame_start; |
15 |
|
16 |
|
17 | // Set up OpenGL error handling |
18 | void MessageCallback(GLenum source, |
19 | GLenum type, |
20 | GLuint id, |
21 | GLenum severity, |
22 | GLsizei length, |
23 | const GLchar* message, |
24 | const void* userParam) |
25 | { |
26 | if (type == GL_DEBUG_TYPE_ERROR) |
27 | { |
28 | ZydecoFault("OpenGL Error: type = {}, severity = {}, message = {}", type, severity, message); |
29 | } |
30 | } |
31 |
|
32 |
|
33 | Renderer::Renderer(IEventHandler& r_event_handler, IWindow& r_window, ITimer& r_timer): |
34 | m_rWindow(r_window), |
35 | m_rTimer(r_timer), |
36 | m_windowWidth(800), |
37 | m_windowHeight(600), |
38 | m_glString(std::string((char*)glGetString(GL_VERSION))), |
39 | m_rendererString(std::string((char*)glGetString(GL_RENDERER))), |
40 | m_frameTimeSum(0), |
41 | m_frameCount(0), |
42 | m_doRender(true) |
43 | { |
44 | LOGGER.Log(Logger::TRACE, "Renderer()"); |
45 |
|
46 | r_event_handler.RegisterWindowEventSubscriber(this); |
47 |
|
48 | glEnable(GL_DEBUG_OUTPUT); |
49 | glDebugMessageCallback(MessageCallback, nullptr); |
50 |
|
51 |
|
52 | GLShader vert_shader {GL_VERTEX_SHADER, |
53 | #include "triangle.vs.glsl" |
54 | }; |
55 | GLShader frag_shader {GL_FRAGMENT_SHADER, |
56 | #include "triangle.fs.glsl" |
57 | }; |
58 | new GLProgram { "RainbowTriangle", {&vert_shader, &frag_shader} }; |
59 |
|
60 | GLShader sky_vert_shader {GL_VERTEX_SHADER, |
61 | #include "background.vs.glsl" |
62 | }; |
63 | GLShader sky_frag_shader {GL_FRAGMENT_SHADER, |
64 | #include "background.fs.glsl" |
65 | }; |
66 | new GLProgram { "Background", {&sky_vert_shader, &sky_frag_shader} }; |
67 | }; |
68 |
|
69 | bool Renderer::Update() |
70 | { |
71 | // Render loop |
72 | frame_start = *m_rTimer.GetGlobalTimePointer(); |
73 |
|
74 | if (m_doRender) |
75 | { |
76 | m_rWindow.MakeContextCurrent(); |
77 |
|
78 | glClearColor(0.18f, 0.18f, 0.18f, 0.0f); |
79 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
80 | glEnable(GL_BLEND); |
81 |
|
82 | glViewport(0, 0, m_windowWidth, m_windowHeight); |
83 |
|
84 | glBindFramebuffer(GL_FRAMEBUFFER, 0); |
85 |
|
86 | // Render objects are mapped with {int: order, list<GLRenderObject*>: objects} |
87 | // TODO: preliminary testing shows this iterator automatically sorts order keys, determine if actually true |
88 | std::map<uint64_t, std::list<GLRenderObject*>> objects = GLRenderObject::GetRenderObjects(); |
89 | for (std::pair<uint64_t, std::list<GLRenderObject*>> order_list : objects) |
90 | { |
91 | for (GLRenderObject *render_object : order_list.second) |
92 | { |
93 | LOGGER.Log(Logger::TRACE, |
94 | "Update(): Rendering {}", |
95 | (void*)render_object); |
96 | render_object->Render(); |
97 | } |
98 | } |
99 | } |
100 |
|
101 | m_rWindow.Update(); |
102 |
|
103 | m_frameTimeSum += (*m_rTimer.GetGlobalTimePointer() - frame_start); |
104 | m_frameCount++; |
105 |
|
106 | return false; |
107 | } |
108 |
|
109 | void Renderer::OnWindowMinimizedEvent() |
110 | { |
111 | m_doRender = false; |
112 | } |
113 |
|
114 | void Renderer::OnWindowMaximizedEvent() |
115 | { |
116 | m_doRender = true; |
117 | } |
118 |
|
119 | void Renderer::OnWindowRestoredEvent() |
120 | { |
121 | m_doRender = true; |
122 | } |
123 |
|
124 | void Renderer::OnWindowExposedEvent() |
125 | { |
126 | m_doRender = true; |
127 | } |
128 |
|
129 | void Renderer::OnWindowResizedEvent(uint64_t new_width, uint64_t new_height) |
130 | { |
131 | LOGGER.Log(Logger::VERBOSE, "Window resized: {}x{}", new_width, new_height); |
132 | m_windowWidth = new_width; |
133 | m_windowHeight = new_height; |
134 | } |
135 |
|
136 | void Renderer::OnWindowRequestedCloseEvent() |
137 | { |
138 |
|
139 | } |
140 |
|
141 | // Called periodically from Engine::Execute (main thread) |
142 | void Renderer::UpdateDebug() |
143 | { |
144 | m_framerate = static_cast<float>(m_frameCount) / (static_cast<float>(m_frameTimeSum) / 1000.); |
145 | m_rWindow.SetTitle(fmt::format("Zydeco ({:.1f} FPS, OpenGL {})", m_framerate, m_glString)); |
146 | m_frameTimeSum = 0; |
147 | m_frameCount = 0; |
148 | } |
149 |
|