]> git.localhorst.tv Git - gong.git/blob - src/graphics/viewport.cpp
code, assets, and other stuff stolen from blank
[gong.git] / src / graphics / viewport.cpp
1 #include "Camera.hpp"
2 #include "Canvas.hpp"
3 #include "Viewport.hpp"
4
5 #include "../app/error.hpp"
6 #include "../geometry/const.hpp"
7
8 #include <GL/glew.h>
9 #include <glm/gtc/matrix_transform.hpp>
10 #include <glm/gtx/transform.hpp>
11 #include <SDL.h>
12
13
14 namespace gong {
15 namespace graphics {
16
17 Camera::Camera() noexcept
18 : fov(geometry::PI_0p25)
19 , aspect(1.0f)
20 , near(0.1f)
21 , far(256.0f)
22 , projection(glm::perspective(fov, aspect, near, far))
23 , view(1.0f) {
24
25 }
26
27
28 void Camera::FOV(float f) noexcept {
29         fov = f;
30         UpdateProjection();
31 }
32
33 void Camera::Aspect(float r) noexcept {
34         aspect = r;
35         UpdateProjection();
36 }
37
38 void Camera::Aspect(float w, float h) noexcept {
39         Aspect(w / h);
40 }
41
42 void Camera::Clip(float n, float f) noexcept {
43         near = n;
44         far = f;
45         UpdateProjection();
46 }
47
48 void Camera::View(const glm::mat4 &v) noexcept {
49         view = v;
50 }
51
52 void Camera::UpdateProjection() noexcept {
53         projection = glm::perspective(fov, aspect, near, far);
54 }
55
56
57 Canvas::Canvas() noexcept
58 : offset(0.0f, 0.0f)
59 , size(1.0f, 1.0f)
60 , near(100.0f)
61 , far(-100.0f)
62 , projection(glm::ortho(offset.x, size.x, size.y, offset.y, near, far))
63 , view(1.0f) {
64
65 }
66
67
68 void Canvas::Resize(float w, float h) noexcept {
69         size.x = w;
70         size.y = h;
71         UpdateProjection();
72 }
73
74
75 void Canvas::UpdateProjection() noexcept {
76         projection = glm::ortho(offset.x, size.x, size.y, offset.y, near, far);
77 }
78
79
80 Viewport::Viewport()
81 : cam()
82 , canv()
83 , cursor(1.0f)
84 , cam_offset(0.0f)
85 , color_prog()
86 , sky_prog()
87 , sprite_prog()
88 , active_prog(NONE) {
89         glClearColor(0.0, 0.0, 0.0, 1.0);
90 }
91
92 void Viewport::VSync(bool b) {
93         if (SDL_GL_SetSwapInterval(b) != 0) {
94                 if (b) {
95                         throw app::SDLError("SDL_GL_SetSwapInterval(1)");
96                 } else {
97                         // allow failure, because this usually means there's no vsync
98                         // support at all, i.e. "it's off"
99                 }
100         }
101 }
102
103 void Viewport::EnableDepthTest() noexcept {
104         glEnable(GL_DEPTH_TEST);
105         glDepthFunc(GL_LESS);
106 }
107
108 void Viewport::EqualDepthTest() noexcept {
109         glEnable(GL_DEPTH_TEST);
110         glDepthFunc(GL_LEQUAL);
111 }
112
113 void Viewport::DisableDepthTest() noexcept {
114         glDisable(GL_DEPTH_TEST);
115 }
116
117 void Viewport::EnableBackfaceCulling() noexcept {
118         glEnable(GL_CULL_FACE);
119 }
120
121 void Viewport::DisableBackfaceCulling() noexcept {
122         glDisable(GL_CULL_FACE);
123 }
124
125 void Viewport::EnableAlphaBlending() noexcept {
126         glEnable(GL_BLEND);
127         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
128 }
129
130 void Viewport::EnableInvertBlending() noexcept {
131         glEnable(GL_BLEND);
132         glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO);
133 }
134
135 void Viewport::DisableBlending() noexcept {
136         glDisable(GL_BLEND);
137 }
138
139 void Viewport::Resize(int w, int h) noexcept {
140         glViewport(0, 0, w, h);
141         float fw = w;
142         float fh = h;
143         cam.Aspect(fw, fh);
144         canv.Resize(fw, fh);
145
146         SkyBoxProgram().SetProjection(Perspective());
147         SpriteProgram().SetProjection(Ortho());
148 }
149
150 void Viewport::Clear() noexcept {
151         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
152 }
153
154 void Viewport::ClearDepth() noexcept {
155         glClear(GL_DEPTH_BUFFER_BIT);
156 }
157
158
159 glm::vec2 Viewport::GetPosition(const glm::vec2 &off, Gravity grav) const noexcept {
160         return align(grav, canv.Size(), off + canv.Offset());
161 }
162
163 void Viewport::SetCursor(const glm::vec3 &pos) noexcept {
164         cursor[3].x = pos.x;
165         cursor[3].y = pos.y;
166         cursor[3].z = pos.z;
167 }
168
169 void Viewport::SetCursor(const glm::vec3 &pos, Gravity grav) noexcept {
170         glm::vec2 p(GetPosition(glm::vec2(pos), grav));
171         cursor[3].x = p.x;
172         cursor[3].y = p.y;
173         cursor[3].z = pos.z;
174 }
175
176 void Viewport::MoveCursor(const glm::vec3 &d) noexcept {
177         cursor[3].x += d.x;
178         cursor[3].y += d.y;
179         cursor[3].z += d.z;
180 }
181
182
183 PlainColor &Viewport::HUDColorProgram() noexcept {
184         if (active_prog != COLOR_HUD) {
185                 color_prog.Activate();
186                 color_prog.SetVP(canv.View(), canv.Projection());
187                 active_prog = COLOR_HUD;
188         }
189         return color_prog;
190 }
191
192 SkyBoxShader &Viewport::SkyBoxProgram() noexcept {
193         if (active_prog != SKY_BOX) {
194                 sky_prog.Activate();
195                 DisableBlending();
196                 DisableBackfaceCulling();
197                 EqualDepthTest();
198                 active_prog = SKY_BOX;
199         }
200         return sky_prog;
201 }
202
203 BlendedSprite &Viewport::SpriteProgram() noexcept {
204         if (active_prog != SPRITE) {
205                 sprite_prog.Activate();
206                 EnableAlphaBlending();
207                 active_prog = SPRITE;
208         }
209         return sprite_prog;
210 }
211
212
213 void Viewport::WorldPosition(const glm::mat4 &t) noexcept {
214         cam.View(glm::translate(glm::inverse(t), glm::vec3(t * glm::vec4(cam_offset, 0.0f))));
215 }
216
217 }
218 }