summary refs log tree commit diff stats
path: root/src/renderer
diff options
context:
space:
mode:
Diffstat (limited to 'src/renderer')
-rw-r--r--src/renderer/gl.h7
-rw-r--r--src/renderer/mesh.cpp109
-rw-r--r--src/renderer/mesh.h62
-rw-r--r--src/renderer/renderer.cpp635
-rw-r--r--src/renderer/renderer.h114
-rw-r--r--src/renderer/shader.cpp84
-rw-r--r--src/renderer/shader.h58
-rw-r--r--src/renderer/texture.cpp124
-rw-r--r--src/renderer/texture.h52
-rw-r--r--src/renderer/wrappers.h273
10 files changed, 1518 insertions, 0 deletions
diff --git a/src/renderer/gl.h b/src/renderer/gl.h new file mode 100644 index 0000000..4e98c42 --- /dev/null +++ b/src/renderer/gl.h
@@ -0,0 +1,7 @@
1#ifndef GL_H_3EE4A268
2#define GL_H_3EE4A268
3
4#include <GL/glew.h>
5#include <GLFW/glfw3.h>
6
7#endif /* end of include guard: GL_H_3EE4A268 */
diff --git a/src/renderer/mesh.cpp b/src/renderer/mesh.cpp new file mode 100644 index 0000000..b06b723 --- /dev/null +++ b/src/renderer/mesh.cpp
@@ -0,0 +1,109 @@
1#include "mesh.h"
2#include <fstream>
3#include <vector>
4#include <map>
5#include <glm/glm.hpp>
6#include "util.h"
7
8Mesh::Mesh(std::string filename)
9{
10 std::ifstream meshfile(filename);
11 if (!meshfile.is_open())
12 {
13 throw std::invalid_argument("Could not open mesh file");
14 }
15
16 std::vector<glm::vec3> tempVertices;
17 std::vector<glm::vec2> tempUvs;
18 std::vector<glm::vec3> tempNormals;
19
20 std::vector<glm::vec3> outVertices;
21 std::vector<glm::vec2> outUvs;
22 std::vector<glm::vec3> outNormals;
23 std::map<element, unsigned short> elementIds;
24 std::vector<unsigned short> indices;
25
26 while (meshfile)
27 {
28 std::string linetype;
29 meshfile >> linetype;
30
31 if (linetype == "v")
32 {
33 glm::vec3 vertex;
34 meshfile >> vertex.x >> vertex.y >> vertex.z;
35
36 tempVertices.push_back(std::move(vertex));
37 } else if (linetype == "vt")
38 {
39 glm::vec2 uv;
40 meshfile >> uv.x >> uv.y;
41
42 tempUvs.push_back(std::move(uv));
43 } else if (linetype == "vn")
44 {
45 glm::vec3 normal;
46 meshfile >> normal.x >> normal.y >> normal.z;
47
48 tempNormals.push_back(std::move(normal));
49 } else if (linetype == "f")
50 {
51 element elements[3];
52
53 meshfile
54 >> elements[0].vertexId >> chlit('/')
55 >> elements[0].uvId >> chlit('/')
56 >> elements[0].normalId
57 >> elements[1].vertexId >> chlit('/')
58 >> elements[1].uvId >> chlit('/')
59 >> elements[1].normalId
60 >> elements[2].vertexId >> chlit('/')
61 >> elements[2].uvId >> chlit('/')
62 >> elements[2].normalId;
63
64 for (size_t i = 0; i < 3; i++)
65 {
66 if (!elementIds.count(elements[i]))
67 {
68 elementIds[elements[i]] = outVertices.size();
69
70 outVertices.push_back(tempVertices[elements[i].vertexId - 1]);
71 outUvs.push_back(tempUvs[elements[i].uvId - 1]);
72 outNormals.push_back(tempNormals[elements[i].normalId - 1]);
73 }
74
75 indices.push_back(elementIds[elements[i]]);
76 }
77 }
78 }
79
80 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer_.getId());
81 glBufferData(
82 GL_ARRAY_BUFFER,
83 outVertices.size() * sizeof(glm::vec3),
84 outVertices.data(),
85 GL_STATIC_DRAW);
86
87 glBindBuffer(GL_ARRAY_BUFFER, uvBuffer_.getId());
88 glBufferData(
89 GL_ARRAY_BUFFER,
90 outUvs.size() * sizeof(glm::vec2),
91 outUvs.data(),
92 GL_STATIC_DRAW);
93
94 glBindBuffer(GL_ARRAY_BUFFER, normalBuffer_.getId());
95 glBufferData(
96 GL_ARRAY_BUFFER,
97 outNormals.size() * sizeof(glm::vec3),
98 outNormals.data(),
99 GL_STATIC_DRAW);
100
101 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer_.getId());
102 glBufferData(
103 GL_ELEMENT_ARRAY_BUFFER,
104 indices.size() * sizeof(unsigned short),
105 indices.data(),
106 GL_STATIC_DRAW);
107
108 indexCount_ = indices.size();
109}
diff --git a/src/renderer/mesh.h b/src/renderer/mesh.h new file mode 100644 index 0000000..06bf65d --- /dev/null +++ b/src/renderer/mesh.h
@@ -0,0 +1,62 @@
1#ifndef MESH_H_76B72E12
2#define MESH_H_76B72E12
3
4#include <string>
5#include "gl.h"
6#include "wrappers.h"
7
8class Mesh {
9public:
10
11 Mesh(std::string filename);
12
13 Mesh(const Mesh& other) = delete;
14 Mesh& operator=(const Mesh& other) = delete;
15
16 inline GLuint getVertexBufferId() const
17 {
18 return vertexBuffer_.getId();
19 }
20
21 inline GLuint getUvBufferId() const
22 {
23 return uvBuffer_.getId();
24 }
25
26 inline GLuint getNormalBufferId() const
27 {
28 return normalBuffer_.getId();
29 }
30
31 inline GLuint getIndexBufferId() const
32 {
33 return indexBuffer_.getId();
34 }
35
36 inline size_t getIndexCount() const
37 {
38 return indexCount_;
39 }
40
41private:
42
43 struct element {
44 size_t vertexId;
45 size_t uvId;
46 size_t normalId;
47
48 bool operator<(const element& other) const
49 {
50 return std::tie(vertexId, uvId, normalId) <
51 std::tie(other.vertexId, other.uvId, other.normalId);
52 }
53 };
54
55 GLBuffer vertexBuffer_;
56 GLBuffer uvBuffer_;
57 GLBuffer normalBuffer_;
58 GLBuffer indexBuffer_;
59 size_t indexCount_;
60};
61
62#endif /* end of include guard: MESH_H_76B72E12 */
diff --git a/src/renderer/renderer.cpp b/src/renderer/renderer.cpp new file mode 100644 index 0000000..6eef2f3 --- /dev/null +++ b/src/renderer/renderer.cpp
@@ -0,0 +1,635 @@
1#include "renderer.h"
2#include "consts.h"
3#include "game.h"
4#include <glm/gtc/matrix_transform.hpp>
5#include "texture.h"
6
7// include stb_image
8#define STB_IMAGE_IMPLEMENTATION
9#define STBI_ONLY_PNG
10#define STBI_ONLY_BMP
11#include "stb_image.h"
12
13void setFramebufferSize(GLFWwindow* w, int width, int height)
14{
15 Game& game = *static_cast<Game*>(glfwGetWindowUserPointer(w));
16 Renderer& renderer = game.getRenderer();
17
18 renderer.width_ = width;
19 renderer.height_ = height;
20
21 renderer.bloomFb_ = {};
22 renderer.bloomDepth_ = {};
23 renderer.preBloomTex_ = {};
24 renderer.bloomPassTex1_ = {};
25 renderer.bloomPassTex2_ = {};
26
27 renderer.initializeFramebuffers();
28}
29
30bool Renderer::singletonInitialized_ = false;
31
32Renderer::Window::Window()
33{
34 // Initialize GLFW
35 if (!glfwInit())
36 {
37 throw std::runtime_error("Failed to initialize GLFW");
38 }
39
40 glfwWindowHint(GLFW_SAMPLES, 4); // 4x antialiasing
41 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // We want version 3.3
42 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
43 glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Mac requires this
44 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
45
46 // Create a window
47 window_ = glfwCreateWindow(1024, 768, "Aromatherapy", nullptr, nullptr);
48 if (window_ == nullptr)
49 {
50 throw std::runtime_error("Failed to open GLFW window");
51 }
52
53 glfwMakeContextCurrent(window_);
54
55 glewExperimental = true; // Needed in core profile
56 if (glewInit() != GLEW_OK)
57 {
58 throw std::runtime_error("Failed to initialize GLEW");
59 }
60
61 glfwSetFramebufferSizeCallback(window_, &setFramebufferSize);
62}
63
64Renderer::Window::~Window()
65{
66 glfwTerminate();
67}
68
69Renderer::Renderer() :
70 monitor_("res/monitor-old.obj"),
71 ntscShader_("ntsc"),
72 finalShader_("final"),
73 blitShader_("blit"),
74 fillShader_("fill"),
75 bloom1Shader_("bloom1"),
76 bloom2Shader_("bloom2")
77{
78 if (singletonInitialized_)
79 {
80 throw std::logic_error("Singleton renderer already initialized");
81 }
82
83 singletonInitialized_ = true;
84
85 // Set up vertex array object
86 glBindVertexArray(vao_.getId());
87
88 // Enable depth testing
89 glEnable(GL_DEPTH_TEST);
90 glDepthFunc(GL_LESS);
91
92 // Enable blending
93 glEnable(GL_BLEND);
94 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
95
96 // Set up the rendering buffers and textures
97 glfwGetFramebufferSize(window_.getHandle(), &width_, &height_);
98
99 initializeFramebuffers();
100
101 // Load the vertices of a flat surface
102 GLfloat g_quad_vertex_buffer_data[] = {
103 -1.0f, -1.0f, 0.0f,
104 1.0f, -1.0f, 0.0f,
105 -1.0f, 1.0f, 0.0f,
106 -1.0f, 1.0f, 0.0f,
107 1.0f, -1.0f, 0.0f,
108 1.0f, 1.0f, 0.0f,
109 };
110
111 glBindBuffer(GL_ARRAY_BUFFER, quadBuffer_.getId());
112 glBufferData(
113 GL_ARRAY_BUFFER,
114 sizeof(GLfloat) * 18,
115 g_quad_vertex_buffer_data,
116 GL_STATIC_DRAW);
117
118 // Load NTSC artifacts
119 int atdw, atdh;
120 unsigned char* artifactsData =
121 stbi_load("res/artifacts.bmp", &atdw, &atdh, 0, 3);
122
123 flipImageData(artifactsData, atdw, atdh, 3);
124
125 glBindTexture(GL_TEXTURE_2D, artifactsTex_.getId());
126 glTexImage2D(
127 GL_TEXTURE_2D,
128 0,
129 GL_RGB,
130 atdw,
131 atdh,
132 0,
133 GL_RGB,
134 GL_UNSIGNED_BYTE,
135 artifactsData);
136
137 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
138 glTexParameteri(
139 GL_TEXTURE_2D,
140 GL_TEXTURE_MIN_FILTER,
141 GL_NEAREST_MIPMAP_NEAREST);
142
143 glGenerateMipmap(GL_TEXTURE_2D);
144 stbi_image_free(artifactsData);
145
146 // Load NTSC scanlines
147 unsigned char* scanlinesData =
148 stbi_load("res/scanlines_333.bmp", &atdw, &atdh, 0, 3);
149
150 flipImageData(scanlinesData, atdw, atdh, 3);
151
152 glBindTexture(GL_TEXTURE_2D, scanlinesTex_.getId());
153 glTexImage2D(
154 GL_TEXTURE_2D,
155 0,
156 GL_RGB,
157 atdw,
158 atdh,
159 0,
160 GL_RGB,
161 GL_UNSIGNED_BYTE,
162 scanlinesData);
163
164 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
165 glTexParameteri(
166 GL_TEXTURE_2D,
167 GL_TEXTURE_MIN_FILTER,
168 GL_NEAREST_MIPMAP_NEAREST);
169
170 glGenerateMipmap(GL_TEXTURE_2D);
171 stbi_image_free(scanlinesData);
172}
173
174void Renderer::initializeFramebuffers()
175{
176 // Set up the framebuffer
177 glBindFramebuffer(GL_FRAMEBUFFER, genericFb_.getId());
178 GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0};
179 glDrawBuffers(1, DrawBuffers);
180
181 // Set up the bloom framebuffer and depthbuffer
182 glBindFramebuffer(GL_FRAMEBUFFER, bloomFb_.getId());
183 GLenum DrawBuffers2[1] = {GL_COLOR_ATTACHMENT1};
184 glDrawBuffers(1, DrawBuffers2);
185
186 glBindRenderbuffer(GL_RENDERBUFFER, bloomDepth_.getId());
187 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width_, height_);
188 glFramebufferRenderbuffer(
189 GL_FRAMEBUFFER,
190 GL_DEPTH_ATTACHMENT,
191 GL_RENDERBUFFER,
192 bloomDepth_.getId());
193
194 // Set up the NTSC rendering buffers
195 glBindTexture(GL_TEXTURE_2D, renderPages_[0].getId());
196 glTexImage2D(
197 GL_TEXTURE_2D,
198 0,
199 GL_RGB,
200 GAME_WIDTH,
201 GAME_HEIGHT,
202 0,
203 GL_RGB,
204 GL_UNSIGNED_BYTE,
205 0);
206
207 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
208 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
209 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
210 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
211
212 glBindTexture(GL_TEXTURE_2D, renderPages_[1].getId());
213 glTexImage2D(
214 GL_TEXTURE_2D,
215 0,
216 GL_RGB,
217 GAME_WIDTH,
218 GAME_HEIGHT,
219 0,
220 GL_RGB,
221 GL_UNSIGNED_BYTE,
222 0);
223
224 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
225 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
226 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
227 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
228
229 // Set up bloom rendering buffers
230 glBindTexture(GL_TEXTURE_2D, preBloomTex_.getId());
231 glTexImage2D(
232 GL_TEXTURE_2D,
233 0,
234 GL_RGB,
235 width_,
236 height_,
237 0,
238 GL_RGB,
239 GL_UNSIGNED_BYTE,
240 0);
241
242 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
243 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
244 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
245 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
246
247 glBindTexture(GL_TEXTURE_2D, bloomPassTex1_.getId());
248 glTexImage2D(
249 GL_TEXTURE_2D,
250 0,
251 GL_RGB,
252 width_ / 4,
253 height_ / 4,
254 0,
255 GL_RGB,
256 GL_UNSIGNED_BYTE,
257 0);
258
259 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
260 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
261 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
262 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
263
264 glBindTexture(GL_TEXTURE_2D, bloomPassTex2_.getId());
265 glTexImage2D(
266 GL_TEXTURE_2D,
267 0,
268 GL_RGB,
269 width_ / 4,
270 height_ / 4,
271 0,
272 GL_RGB,
273 GL_UNSIGNED_BYTE,
274 0);
275
276 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
277 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
278 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
279 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
280}
281
282Renderer::~Renderer()
283{
284 singletonInitialized_ = false;
285}
286
287void Renderer::fill(Texture& tex, Rectangle dstrect, int r, int g, int b)
288{
289 // Target the framebuffer
290 glBindFramebuffer(GL_FRAMEBUFFER, genericFb_.getId());
291 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex.getId(), 0);
292
293 // Set up the vertex attributes
294 int width = tex.getWidth();
295 int height = tex.getHeight();
296
297 GLfloat minx = (GLfloat) dstrect.x / width * 2.0 - 1.0;
298 GLfloat miny = -((GLfloat) dstrect.y / height * 2.0 - 1.0);
299 GLfloat maxx = (GLfloat) (dstrect.x + dstrect.w) / width * 2.0 - 1.0;
300 GLfloat maxy = -((GLfloat) (dstrect.y + dstrect.h) / height * 2.0 - 1.0);
301
302 GLfloat vertexData[] = {
303 minx, miny,
304 maxx, miny,
305 maxx, maxy,
306 minx, miny,
307 minx, maxy,
308 maxx, maxy
309 };
310
311 GLBuffer vertexBuffer;
312 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer.getId());
313 glBufferData(
314 GL_ARRAY_BUFFER,
315 sizeof(GLfloat) * 12,
316 vertexData, GL_STATIC_DRAW);
317
318 glEnableVertexAttribArray(0);
319 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
320
321 glViewport(0, 0, tex.getWidth(), tex.getHeight());
322 glClear(GL_DEPTH_BUFFER_BIT);
323
324 fillShader_.use();
325 glUniform3f(
326 fillShader_.getUniformLocation("vecColor"),
327 r / 255.0,
328 g / 255.0,
329 b / 255.0);
330
331 glDrawArrays(GL_TRIANGLES, 0, 6);
332
333 glDisableVertexAttribArray(0);
334}
335
336void Renderer::blit(
337 const Texture& src,
338 Texture& dst,
339 Rectangle srcrect,
340 Rectangle dstrect,
341 double alpha)
342{
343 alpha = glm::clamp(alpha, 0.0, 1.0);
344
345 // Target the framebuffer
346 glBindFramebuffer(GL_FRAMEBUFFER, genericFb_.getId());
347 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, dst.getId(), 0);
348
349 // Set up the vertex attributes
350 int width = dst.getWidth();
351 int height = dst.getHeight();
352
353 GLfloat minx = (GLfloat) dstrect.x / width * 2.0 - 1.0;
354 GLfloat miny = -((GLfloat) dstrect.y / height * 2.0 - 1.0);
355 GLfloat maxx = (GLfloat) (dstrect.x + dstrect.w) / width * 2.0 - 1.0;
356 GLfloat maxy = -((GLfloat) (dstrect.y + dstrect.h) / height * 2.0 - 1.0);
357
358 GLfloat vertexData[] = {
359 minx, miny,
360 maxx, miny,
361 minx, maxy,
362 maxx, maxy
363 };
364
365 GLBuffer vertexBuffer;
366 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer.getId());
367 glBufferData(
368 GL_ARRAY_BUFFER,
369 sizeof(GLfloat) * 8,
370 vertexData,
371 GL_STATIC_DRAW);
372
373 glEnableVertexAttribArray(0);
374 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
375
376 GLfloat minu = (GLfloat) srcrect.x / src.getWidth();
377 GLfloat minv = 1 - ((GLfloat) srcrect.y / src.getHeight());
378 GLfloat maxu = (GLfloat) (srcrect.x + srcrect.w) / src.getWidth();
379 GLfloat maxv = 1 - ((GLfloat) (srcrect.y + srcrect.h) / src.getHeight());
380
381 GLfloat uvData[] = {
382 minu, minv,
383 maxu, minv,
384 minu, maxv,
385 maxu, maxv
386 };
387
388 GLBuffer uvBuffer;
389 glBindBuffer(GL_ARRAY_BUFFER, uvBuffer.getId());
390 glBufferData(
391 GL_ARRAY_BUFFER,
392 sizeof(GLfloat) * 8,
393 uvData,
394 GL_STATIC_DRAW);
395
396 glEnableVertexAttribArray(1);
397 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
398
399 // Set up the shader
400 blitShader_.use();
401 glClear(GL_DEPTH_BUFFER_BIT);
402 glViewport(0, 0, dst.getWidth(), dst.getHeight());
403
404 glActiveTexture(GL_TEXTURE0);
405 glBindTexture(GL_TEXTURE_2D, src.getId());
406 glUniform1i(blitShader_.getUniformLocation("srctex"), 0);
407 glUniform1f(blitShader_.getUniformLocation("alpha"), alpha);
408
409 // Blit!
410 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
411
412 // Unload everything
413 glDisableVertexAttribArray(1);
414 glDisableVertexAttribArray(0);
415}
416
417void Renderer::bloomPass1(
418 const GLTexture& src,
419 GLTexture& dst,
420 bool horizontal,
421 glm::vec2 srcRes,
422 glm::vec2 dstRes)
423{
424 glBindFramebuffer(GL_FRAMEBUFFER, genericFb_.getId());
425 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, dst.getId(), 0);
426 glViewport(0,0,dstRes.x,dstRes.y);
427 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
428 bloom1Shader_.use();
429
430 glActiveTexture(GL_TEXTURE0);
431 glBindTexture(GL_TEXTURE_2D, src.getId());
432 glUniform1i(bloom1Shader_.getUniformLocation("inTex"), 0);
433
434 glm::vec2 offset = glm::vec2(0.0);
435 if (horizontal)
436 {
437 offset.x = 1.2/srcRes.x;
438 } else {
439 offset.y = 1.2/srcRes.y;
440 }
441
442 glUniform2f(bloom1Shader_.getUniformLocation("offset"), offset.x, offset.y);
443
444 glEnableVertexAttribArray(0);
445 glBindBuffer(GL_ARRAY_BUFFER, quadBuffer_.getId());
446 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
447 glDrawArrays(GL_TRIANGLES, 0, 6);
448 glDisableVertexAttribArray(0);
449}
450
451void Renderer::renderScreen(const Texture& tex)
452{
453 // First we're going to composite our frame with the previous frame
454 // We start by setting up the framebuffer
455 glBindFramebuffer(GL_FRAMEBUFFER, genericFb_.getId());
456 glFramebufferTexture(
457 GL_FRAMEBUFFER,
458 GL_COLOR_ATTACHMENT0,
459 renderPages_[curBuf_].getId(),
460 0);
461
462 // Set up the shader
463 glViewport(0,0,GAME_WIDTH,GAME_HEIGHT);
464 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
465 ntscShader_.use();
466
467 // Use the current frame texture, nearest neighbor and clamped to edge
468 glActiveTexture(GL_TEXTURE0);
469 glBindTexture(GL_TEXTURE_2D, tex.getId());
470 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
471 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
472 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
473 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
474 glUniform1i(ntscShader_.getUniformLocation("curFrameSampler"), 0);
475
476 // Use the previous frame composite texture, nearest neighbor and clamped to
477 // edge
478 glActiveTexture(GL_TEXTURE1);
479 glBindTexture(GL_TEXTURE_2D, renderPages_[(curBuf_ + 1) % 2].getId());
480 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
481 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
482 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
483 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
484 glUniform1i(ntscShader_.getUniformLocation("prevFrameSampler"), 1);
485
486 // Load the NTSC artifact texture
487 glActiveTexture(GL_TEXTURE2);
488 glBindTexture(GL_TEXTURE_2D, artifactsTex_.getId());
489 glUniform1i(ntscShader_.getUniformLocation("NTSCArtifactSampler"), 2);
490 glUniform1f(ntscShader_.getUniformLocation("NTSCLerp"), curBuf_ * 1.0);
491
492 // Change the 0.0 to a 1.0 or a 10.0 for a glitchy effect!
493 glUniform1f(ntscShader_.getUniformLocation("Tuning_NTSC"), 0.0);
494
495 // Render our composition
496 glEnableVertexAttribArray(0);
497 glBindBuffer(GL_ARRAY_BUFFER, quadBuffer_.getId());
498 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
499 glDrawArrays(GL_TRIANGLES, 0, 6);
500 glDisableVertexAttribArray(0);
501
502 // We're going to render the screen now
503 glBindFramebuffer(GL_FRAMEBUFFER, bloomFb_.getId());
504 glFramebufferTexture(
505 GL_FRAMEBUFFER,
506 GL_COLOR_ATTACHMENT1,
507 preBloomTex_.getId(),
508 0);
509
510 glViewport(0,0,width_,height_);
511 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
512 finalShader_.use();
513
514 // Use the composited frame texture, linearly filtered and filling in black
515 // for the border
516 glActiveTexture(GL_TEXTURE0);
517 glBindTexture(GL_TEXTURE_2D, renderPages_[curBuf_].getId());
518 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
519 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
520 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
521 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
522
523 float borderColor[] = {0.0f, 0.0f, 0.0f, 1.0f};
524 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
525
526 glGenerateMipmap(GL_TEXTURE_2D);
527 glUniform1i(finalShader_.getUniformLocation("rendertex"), 0);
528
529 // Use the scanlines texture
530 glActiveTexture(GL_TEXTURE1);
531 glBindTexture(GL_TEXTURE_2D, scanlinesTex_.getId());
532 glUniform1i(finalShader_.getUniformLocation("scanlinestex"), 1);
533
534 // Initialize the MVP matrices
535 glm::mat4 p_matrix = glm::perspective(
536 glm::radians(25.0f),
537 static_cast<float>(width_) / static_cast<float>(height_),
538 0.1f,
539 100.0f);
540
541 glm::mat4 v_matrix = glm::lookAt(
542 glm::vec3(3.75,0,0), // Camera
543 glm::vec3(0,0,0), // Center
544 glm::vec3(0,1,0)); // Up
545
546 glm::mat4 m_matrix = glm::mat4(1.0);
547 glm::mat4 mvp_matrix = p_matrix * v_matrix * m_matrix;
548
549 glUniformMatrix4fv(
550 finalShader_.getUniformLocation("MVP"),
551 1,
552 GL_FALSE,
553 &mvp_matrix[0][0]);
554
555 glUniformMatrix4fv(
556 finalShader_.getUniformLocation("worldMat"),
557 1,
558 GL_FALSE,
559 &m_matrix[0][0]);
560
561 glUniform2f(finalShader_.getUniformLocation("resolution"), width_, height_);
562 glUniform1f(finalShader_.getUniformLocation("iGlobalTime"), glfwGetTime());
563
564 glUniform3f(
565 finalShader_.getUniformLocation("frameColor"),
566 0.76f,
567 0.78f,
568 0.81f);
569
570 glEnableVertexAttribArray(0);
571 glBindBuffer(GL_ARRAY_BUFFER, monitor_.getVertexBufferId());
572 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
573
574 glEnableVertexAttribArray(1);
575 glBindBuffer(GL_ARRAY_BUFFER, monitor_.getNormalBufferId());
576 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
577
578 glEnableVertexAttribArray(2);
579 glBindBuffer(GL_ARRAY_BUFFER, monitor_.getUvBufferId());
580 glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
581
582 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, monitor_.getIndexBufferId());
583 glDrawElements(
584 GL_TRIANGLES,
585 monitor_.getIndexCount(),
586 GL_UNSIGNED_SHORT,
587 nullptr);
588
589 glDisableVertexAttribArray(2);
590 glDisableVertexAttribArray(1);
591 glDisableVertexAttribArray(0);
592
593 // First pass of bloom!
594 glm::vec2 bufferSize = glm::vec2(width_, height_);
595
596 bloomPass1(
597 preBloomTex_,
598 bloomPassTex1_,
599 true,
600 bufferSize,
601 bufferSize / 4.0f);
602
603 bloomPass1(
604 bloomPassTex1_,
605 bloomPassTex2_,
606 false,
607 bufferSize / 4.0f,
608 bufferSize / 4.0f);
609
610 // Do the second pass of bloom and render to screen
611 glBindFramebuffer(GL_FRAMEBUFFER, 0);
612 glViewport(0, 0, width_, height_);
613 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
614 bloom2Shader_.use();
615
616 glActiveTexture(GL_TEXTURE0);
617 glBindTexture(GL_TEXTURE_2D, preBloomTex_.getId());
618 glUniform1i(bloom2Shader_.getUniformLocation("clearTex"), 0);
619
620 glActiveTexture(GL_TEXTURE1);
621 glBindTexture(GL_TEXTURE_2D, bloomPassTex2_.getId());
622 glUniform1i(bloom2Shader_.getUniformLocation("blurTex"), 1);
623
624 glUniform1f(bloom2Shader_.getUniformLocation("iGlobalTime"), glfwGetTime());
625
626 glEnableVertexAttribArray(0);
627 glBindBuffer(GL_ARRAY_BUFFER, quadBuffer_.getId());
628 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
629 glDrawArrays(GL_TRIANGLES, 0, 6);
630 glDisableVertexAttribArray(0);
631
632 glfwSwapBuffers(window_.getHandle());
633
634 curBuf_ = (curBuf_ + 1) % 2;
635}
diff --git a/src/renderer/renderer.h b/src/renderer/renderer.h new file mode 100644 index 0000000..0b10af5 --- /dev/null +++ b/src/renderer/renderer.h
@@ -0,0 +1,114 @@
1#ifndef RENDERER_H
2#define RENDERER_H
3
4#include "gl.h"
5#include "wrappers.h"
6#include "mesh.h"
7#include "shader.h"
8#include <glm/glm.hpp>
9
10class Texture;
11struct Rectangle;
12
13class Renderer {
14public:
15
16 class Window {
17 public:
18
19 Window();
20
21 Window(const Window& other) = delete;
22 Window& operator=(const Window& other) = delete;
23
24 ~Window();
25
26 inline GLFWwindow* getHandle()
27 {
28 return window_;
29 }
30
31 private:
32
33 GLFWwindow* window_;
34 };
35
36 static inline bool isSingletonInitialized()
37 {
38 return singletonInitialized_;
39 }
40
41 Renderer();
42
43 Renderer(const Renderer& other) = delete;
44 Renderer& operator=(const Renderer& other) = delete;
45
46 ~Renderer();
47
48 inline Window& getWindow()
49 {
50 return window_;
51 }
52
53 void fill(
54 Texture& tex,
55 Rectangle loc,
56 int r,
57 int g,
58 int b);
59
60 void blit(
61 const Texture& src,
62 Texture& dst,
63 Rectangle srcrect,
64 Rectangle dstrect,
65 double alpha = 1.0);
66
67 void renderScreen(const Texture& tex);
68
69private:
70
71 friend void setFramebufferSize(GLFWwindow* w, int width, int height);
72
73 void initializeFramebuffers();
74
75 void bloomPass1(
76 const GLTexture& src,
77 GLTexture& dst,
78 bool horizontal,
79 glm::vec2 srcRes,
80 glm::vec2 dstRes);
81
82 static bool singletonInitialized_;
83
84 Window window_;
85 GLVertexArray vao_;
86
87 GLFramebuffer genericFb_;
88 GLFramebuffer bloomFb_;
89 GLRenderbuffer bloomDepth_;
90
91 GLTexture renderPages_[2];
92 GLTexture preBloomTex_;
93 GLTexture bloomPassTex1_;
94 GLTexture bloomPassTex2_;
95
96 Mesh monitor_;
97 GLBuffer quadBuffer_;
98
99 GLTexture artifactsTex_;
100 GLTexture scanlinesTex_;
101
102 Shader ntscShader_;
103 Shader finalShader_;
104 Shader blitShader_;
105 Shader fillShader_;
106 Shader bloom1Shader_;
107 Shader bloom2Shader_;
108
109 size_t curBuf_ = 0;
110 int width_;
111 int height_;
112};
113
114#endif
diff --git a/src/renderer/shader.cpp b/src/renderer/shader.cpp new file mode 100644 index 0000000..735fc22 --- /dev/null +++ b/src/renderer/shader.cpp
@@ -0,0 +1,84 @@
1#include "shader.h"
2#include <fstream>
3#include <vector>
4#include "util.h"
5
6Shader::Shader(std::string name)
7{
8 GLShader vertexShader(GL_VERTEX_SHADER);
9 GLShader fragmentShader(GL_FRAGMENT_SHADER);
10
11 std::ifstream vertexFile("shaders/" + name + ".vertex");
12 std::ifstream fragmentFile("shaders/" + name + ".fragment");
13
14 std::string vertexCode(slurp(vertexFile));
15 std::string fragmentCode(slurp(fragmentFile));
16
17 const char* vertexCodePtr = vertexCode.c_str();
18 const char* fragmentCodePtr = fragmentCode.c_str();
19
20 glShaderSource(vertexShader.getId(), 1, &vertexCodePtr, nullptr);
21 glShaderSource(fragmentShader.getId(), 1, &fragmentCodePtr, nullptr);
22
23 glCompileShader(vertexShader.getId());
24 glCompileShader(fragmentShader.getId());
25
26#ifdef DEBUG
27 GLint result = GL_FALSE;
28 int infoLogLength;
29
30 glGetShaderiv(vertexShader.getId(), GL_COMPILE_STATUS, &result);
31
32 if (result == GL_FALSE)
33 {
34 glGetShaderiv(vertexShader.getId(), GL_INFO_LOG_LENGTH, &infoLogLength);
35
36 std::vector<char> errMsg(infoLogLength);
37 glGetShaderInfoLog(
38 vertexShader.getId(),
39 infoLogLength,
40 nullptr,
41 errMsg.data());
42
43 throw std::gl_error("Could not compile shader", errMsg.data());
44 }
45
46 glGetShaderiv(fragmentShader.getId(), GL_COMPILE_STATUS, &result);
47
48 if (result == GL_FALSE)
49 {
50 glGetShaderiv(fragmentShader.getId(), GL_INFO_LOG_LENGTH, &infoLogLength);
51
52 std::vector<char> errMsg(infoLogLength);
53 glGetShaderInfoLog(
54 fragmentShader.getId(),
55 infoLogLength,
56 nullptr,
57 errMsg.data());
58
59 throw std::gl_error("Could not compile shader", errMsg.data());
60 }
61#endif
62
63 glAttachShader(program_.getId(), vertexShader.getId());
64 glAttachShader(program_.getId(), fragmentShader.getId());
65 glLinkProgram(program_.getId());
66
67#ifdef DEBUG
68 glGetProgramiv(program_.getId(), GL_LINK_STATUS, &result);
69
70 if (result == GL_FALSE)
71 {
72 glGetProgramiv(program_.getId(), GL_INFO_LOG_LENGTH, &infoLogLength);
73
74 std::vector<char> errMsg(infoLogLength);
75 glGetProgramInfoLog(
76 program_.getId(),
77 infoLogLength,
78 nullptr,
79 errMsg.data());
80
81 throw std::gl_error("Could not link shader program", errMsg.data());
82 }
83#endif
84}
diff --git a/src/renderer/shader.h b/src/renderer/shader.h new file mode 100644 index 0000000..d2c673c --- /dev/null +++ b/src/renderer/shader.h
@@ -0,0 +1,58 @@
1#ifndef SHADER_H_25115B63
2#define SHADER_H_25115B63
3
4#include <string>
5#include <stdexcept>
6#include "gl.h"
7#include "wrappers.h"
8
9class gl_error : public std::logic_error {
10public:
11
12 gl_error(
13 const char* msg,
14 std::string info) :
15 std::logic_error(msg),
16 info_(std::move(info))
17 {
18 }
19
20 gl_error(
21 std::string& msg,
22 std::string info) :
23 std::logic_error(msg),
24 info_(std::move(info))
25 {
26 }
27
28 inline const std::string& getInfo() const
29 {
30 return info_;
31 }
32
33private:
34
35 std::string info_;
36};
37
38class Shader {
39public:
40
41 Shader(std::string name);
42
43 inline void use()
44 {
45 glUseProgram(program_.getId());
46 }
47
48 inline GLint getUniformLocation(const GLchar* name)
49 {
50 return glGetUniformLocation(program_.getId(), name);
51 }
52
53private:
54
55 GLProgram program_;
56};
57
58#endif /* end of include guard: SHADER_H_25115B63 */
diff --git a/src/renderer/texture.cpp b/src/renderer/texture.cpp new file mode 100644 index 0000000..2728665 --- /dev/null +++ b/src/renderer/texture.cpp
@@ -0,0 +1,124 @@
1#include "texture.h"
2#include <stdexcept>
3#include "renderer.h"
4#include "util.h"
5
6// include stb_image
7#define STBI_ONLY_PNG
8#define STBI_ONLY_BMP
9#include "stb_image.h"
10
11Texture::Texture(
12 int width,
13 int height) :
14 width_(width),
15 height_(height)
16{
17 if (!Renderer::isSingletonInitialized())
18 {
19 throw std::logic_error("Renderer needs to be initialized");
20 }
21
22 glBindTexture(GL_TEXTURE_2D, texture_.getId());
23 glTexImage2D(
24 GL_TEXTURE_2D,
25 0,
26 GL_RGBA,
27 width_,
28 height_,
29 0,
30 GL_RGBA,
31 GL_UNSIGNED_BYTE,
32 0);
33
34 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
35 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
36 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
37 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
38}
39
40Texture::Texture(const char* filename)
41{
42 if (!Renderer::isSingletonInitialized())
43 {
44 throw std::logic_error("Renderer needs to be initialized");
45 }
46
47 glBindTexture(GL_TEXTURE_2D, texture_.getId());
48 unsigned char* data = stbi_load(filename, &width_, &height_, 0, 4);
49 flipImageData(data, width_, height_, 4);
50 glTexImage2D(
51 GL_TEXTURE_2D,
52 0,
53 GL_RGBA,
54 width_,
55 height_,
56 0,
57 GL_RGBA,
58 GL_UNSIGNED_BYTE,
59 data);
60
61 stbi_image_free(data);
62 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
63 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
64 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
65 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
66}
67
68Texture::Texture(
69 const Texture& tex) :
70 width_(tex.width_),
71 height_(tex.height_)
72{
73 if (!Renderer::isSingletonInitialized())
74 {
75 throw std::logic_error("Renderer needs to be initialized");
76 }
77
78 unsigned char* data = new unsigned char[4 * width_ * height_];
79 glBindTexture(GL_TEXTURE_2D, tex.getId());
80 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
81
82 glBindTexture(GL_TEXTURE_2D, texture_.getId());
83 glTexImage2D(
84 GL_TEXTURE_2D,
85 0,
86 GL_RGBA,
87 width_,
88 height_,
89 0,
90 GL_RGBA,
91 GL_UNSIGNED_BYTE,
92 data);
93
94 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
95 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
96 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
97 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
98
99 delete[] data;
100}
101
102Texture::Texture(Texture&& tex) : Texture(0, 0)
103{
104 swap(*this, tex);
105}
106
107Texture& Texture::operator= (Texture tex)
108{
109 swap(*this, tex);
110
111 return *this;
112}
113
114void swap(Texture& tex1, Texture& tex2)
115{
116 std::swap(tex1.width_, tex2.width_);
117 std::swap(tex1.height_, tex2.height_);
118 std::swap(tex1.texture_, tex2.texture_);
119}
120
121Rectangle Texture::entirety() const
122{
123 return {0, 0, width_, height_};
124}
diff --git a/src/renderer/texture.h b/src/renderer/texture.h new file mode 100644 index 0000000..3aa8773 --- /dev/null +++ b/src/renderer/texture.h
@@ -0,0 +1,52 @@
1#ifndef TEXTURE_H_84EC6DF6
2#define TEXTURE_H_84EC6DF6
3
4#include "wrappers.h"
5
6struct Rectangle {
7 int x;
8 int y;
9 int w;
10 int h;
11};
12
13class Texture {
14public:
15
16 Texture(int width, int height);
17
18 Texture(const char* file);
19
20 Texture(const Texture& tex);
21
22 Texture(Texture&& tex);
23
24 Texture& operator= (Texture tex);
25
26 friend void swap(Texture& tex1, Texture& tex2);
27
28 Rectangle entirety() const;
29
30 inline GLuint getId() const
31 {
32 return texture_.getId();
33 }
34
35 inline int getWidth() const
36 {
37 return width_;
38 }
39
40 inline int getHeight() const
41 {
42 return height_;
43 }
44
45private:
46
47 GLTexture texture_;
48 int width_;
49 int height_;
50};
51
52#endif /* end of include guard: TEXTURE_H_84EC6DF6 */
diff --git a/src/renderer/wrappers.h b/src/renderer/wrappers.h new file mode 100644 index 0000000..c6edc11 --- /dev/null +++ b/src/renderer/wrappers.h
@@ -0,0 +1,273 @@
1#ifndef WRAPPERS_H_1EE0965B
2#define WRAPPERS_H_1EE0965B
3
4#include "gl.h"
5#include <utility>
6
7class GLVertexArray {
8public:
9
10 GLVertexArray()
11 {
12 glGenVertexArrays(1, &id_);
13 }
14
15 GLVertexArray(const GLVertexArray& other) = delete;
16 GLVertexArray& operator=(const GLVertexArray& other) = delete;
17
18 GLVertexArray(GLVertexArray&& other) : GLVertexArray()
19 {
20 std::swap(id_, other.id_);
21 }
22
23 GLVertexArray& operator=(GLVertexArray&& other)
24 {
25 std::swap(id_, other.id_);
26
27 return *this;
28 }
29
30 ~GLVertexArray()
31 {
32 glDeleteVertexArrays(1, &id_);
33 }
34
35 inline GLuint getId() const
36 {
37 return id_;
38 }
39
40private:
41
42 GLuint id_;
43};
44
45class GLFramebuffer {
46public:
47
48 GLFramebuffer()
49 {
50 glGenFramebuffers(1, &id_);
51 }
52
53 GLFramebuffer(const GLFramebuffer& other) = delete;
54 GLFramebuffer& operator=(const GLFramebuffer& other) = delete;
55
56 GLFramebuffer(GLFramebuffer&& other) : GLFramebuffer()
57 {
58 std::swap(id_, other.id_);
59 }
60
61 GLFramebuffer& operator=(GLFramebuffer&& other)
62 {
63 std::swap(id_, other.id_);
64
65 return *this;
66 }
67
68 ~GLFramebuffer()
69 {
70 glDeleteFramebuffers(1, &id_);
71 }
72
73 inline GLuint getId() const
74 {
75 return id_;
76 }
77
78private:
79
80 GLuint id_;
81};
82
83class GLRenderbuffer {
84public:
85
86 GLRenderbuffer()
87 {
88 glGenRenderbuffers(1, &id_);
89 }
90
91 GLRenderbuffer(const GLRenderbuffer& other) = delete;
92 GLRenderbuffer& operator=(const GLRenderbuffer& other) = delete;
93
94 GLRenderbuffer(GLRenderbuffer&& other) : GLRenderbuffer()
95 {
96 std::swap(id_, other.id_);
97 }
98
99 GLRenderbuffer& operator=(GLRenderbuffer&& other)
100 {
101 std::swap(id_, other.id_);
102
103 return *this;
104 }
105
106 ~GLRenderbuffer()
107 {
108 glDeleteRenderbuffers(1, &id_);
109 }
110
111 inline GLuint getId() const
112 {
113 return id_;
114 }
115
116private:
117
118 GLuint id_;
119};
120
121class GLBuffer {
122public:
123
124 GLBuffer()
125 {
126 glGenBuffers(1, &id_);
127 }
128
129 GLBuffer(const GLBuffer& other) = delete;
130 GLBuffer& operator=(const GLBuffer& other) = delete;
131
132 GLBuffer(GLBuffer&& other) : GLBuffer()
133 {
134 std::swap(id_, other.id_);
135 }
136
137 GLBuffer& operator=(GLBuffer&& other)
138 {
139 std::swap(id_, other.id_);
140
141 return *this;
142 }
143
144 ~GLBuffer()
145 {
146 glDeleteBuffers(1, &id_);
147 }
148
149 inline GLuint getId() const
150 {
151 return id_;
152 }
153
154private:
155
156 GLuint id_;
157};
158
159class GLTexture {
160public:
161
162 GLTexture()
163 {
164 glGenTextures(1, &id_);
165 }
166
167 GLTexture(const GLTexture& other) = delete;
168 GLTexture& operator=(const GLTexture& other) = delete;
169
170 GLTexture(GLTexture&& other) : GLTexture()
171 {
172 std::swap(id_, other.id_);
173 }
174
175 GLTexture& operator=(GLTexture&& other)
176 {
177 std::swap(id_, other.id_);
178
179 return *this;
180 }
181
182 ~GLTexture()
183 {
184 glDeleteTextures(1, &id_);
185 }
186
187 inline GLuint getId() const
188 {
189 return id_;
190 }
191
192private:
193
194 GLuint id_;
195};
196
197class GLShader {
198public:
199
200 GLShader(GLenum type)
201 {
202 id_ = glCreateShader(type);
203 }
204
205 GLShader(const GLShader& other) = delete;
206 GLShader& operator=(const GLShader& other) = delete;
207
208 GLShader(GLShader&& other) : GLShader(GL_VERTEX_SHADER)
209 {
210 std::swap(id_, other.id_);
211 }
212
213 GLShader& operator=(GLShader&& other)
214 {
215 std::swap(id_, other.id_);
216
217 return *this;
218 }
219
220 ~GLShader()
221 {
222 glDeleteShader(id_);
223 }
224
225 inline GLuint getId() const
226 {
227 return id_;
228 }
229
230private:
231
232 GLuint id_;
233};
234
235class GLProgram {
236public:
237
238 GLProgram()
239 {
240 id_ = glCreateProgram();
241 }
242
243 GLProgram(const GLProgram& other) = delete;
244 GLProgram& operator=(const GLProgram& other) = delete;
245
246 GLProgram(GLProgram&& other) : GLProgram()
247 {
248 std::swap(id_, other.id_);
249 }
250
251 GLProgram& operator=(GLProgram&& other)
252 {
253 std::swap(id_, other.id_);
254
255 return *this;
256 }
257
258 ~GLProgram()
259 {
260 glDeleteProgram(id_);
261 }
262
263 inline GLuint getId() const
264 {
265 return id_;
266 }
267
268private:
269
270 GLuint id_;
271};
272
273#endif /* end of include guard: WRAPPERS_H_1EE0965B */