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