]> git.localhorst.tv Git - blank.git/blob - src/graphics/viewport.cpp
model -> mesh
[blank.git] / src / graphics / viewport.cpp
1 #include "Camera.hpp"
2 #include "Canvas.hpp"
3 #include "SkyBox.hpp"
4 #include "Viewport.hpp"
5
6 #include "../app/init.hpp"
7 #include "../model/geometry.hpp"
8
9 #include <GL/glew.h>
10 #include <glm/gtc/matrix_transform.hpp>
11 #include <glm/gtx/transform.hpp>
12 #include <SDL.h>
13
14
15 namespace blank {
16
17 Camera::Camera() noexcept
18 : fov(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
49 void Camera::UpdateProjection() noexcept {
50         projection = glm::perspective(fov, aspect, near, far);
51 }
52
53
54 Canvas::Canvas() noexcept
55 : offset(0.0f, 0.0f)
56 , size(1.0f, 1.0f)
57 , near(100.0f)
58 , far(-100.0f)
59 , projection(glm::ortho(offset.x, size.x, size.y, offset.y, near, far))
60 , view(1.0f) {
61
62 }
63
64
65 void Canvas::Resize(float w, float h) noexcept {
66         size.x = w;
67         size.y = h;
68         UpdateProjection();
69 }
70
71
72 void Canvas::UpdateProjection() noexcept {
73         projection = glm::ortho(offset.x, size.x, size.y, offset.y, near, far);
74 }
75
76
77 SkyBox::SkyBox(CubeMap &&tex)
78 : texture(std::move(tex))
79 , mesh() {
80         mesh.LoadUnitBox();
81 }
82
83 void SkyBox::Render(Viewport &viewport) noexcept {
84         SkyBoxShader &prog = viewport.SkyBoxProgram();
85         prog.SetTexture(texture);
86         mesh.Draw();
87 }
88
89
90 Viewport::Viewport()
91 : cam()
92 , canv()
93 , cursor(1.0f)
94 , chunk_prog()
95 , entity_prog()
96 , sky_prog()
97 , sprite_prog()
98 , active_prog(NONE) {
99         glClearColor(0.0, 0.0, 0.0, 1.0);
100 }
101
102 void Viewport::VSync(bool b) noexcept {
103         if (SDL_GL_SetSwapInterval(b) != 0) {
104                 throw SDLError("SDL_GL_SetSwapInterval");
105         }
106 }
107
108 void Viewport::EnableDepthTest() noexcept {
109         glEnable(GL_DEPTH_TEST);
110         glDepthFunc(GL_LESS);
111 }
112
113 void Viewport::EqualDepthTest() noexcept {
114         glEnable(GL_DEPTH_TEST);
115         glDepthFunc(GL_LEQUAL);
116 }
117
118 void Viewport::DisableDepthTest() noexcept {
119         glDisable(GL_DEPTH_TEST);
120 }
121
122 void Viewport::EnableBackfaceCulling() noexcept {
123         glEnable(GL_CULL_FACE);
124 }
125
126 void Viewport::DisableBackfaceCulling() noexcept {
127         glDisable(GL_CULL_FACE);
128 }
129
130 void Viewport::EnableAlphaBlending() noexcept {
131         glEnable(GL_BLEND);
132         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
133 }
134
135 void Viewport::EnableInvertBlending() noexcept {
136         glEnable(GL_BLEND);
137         glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO);
138 }
139
140 void Viewport::DisableBlending() noexcept {
141         glDisable(GL_BLEND);
142 }
143
144 void Viewport::Resize(int w, int h) noexcept {
145         glViewport(0, 0, w, h);
146         float fw = w;
147         float fh = h;
148         cam.Aspect(fw, fh);
149         canv.Resize(fw, fh);
150
151         ChunkProgram().SetProjection(Perspective());
152         SkyBoxProgram().SetProjection(Perspective());
153         SpriteProgram().SetProjection(Ortho());
154 }
155
156 void Viewport::Clear() noexcept {
157         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
158 }
159
160 void Viewport::ClearDepth() noexcept {
161         glClear(GL_DEPTH_BUFFER_BIT);
162 }
163
164
165 void Viewport::SetCursor(const glm::vec3 &pos) {
166         cursor[3].x = pos.x;
167         cursor[3].y = pos.y;
168         cursor[3].z = pos.z;
169 }
170
171 void Viewport::SetCursor(const glm::vec3 &pos, Gravity grav) {
172         glm::vec2 p(align(grav, canv.Size(), glm::vec2(pos) + canv.Offset()));
173         cursor[3].x = p.x;
174         cursor[3].y = p.y;
175         cursor[3].z = pos.z;
176 }
177
178 void Viewport::MoveCursor(const glm::vec3 &d) {
179         cursor[3].x += d.x;
180         cursor[3].y += d.y;
181         cursor[3].z += d.z;
182 }
183
184
185 BlockLighting &Viewport::ChunkProgram() noexcept {
186         if (active_prog != CHUNK) {
187                 chunk_prog.Activate();
188                 EnableDepthTest();
189                 EnableBackfaceCulling();
190                 DisableBlending();
191                 active_prog = CHUNK;
192         }
193         return chunk_prog;
194 }
195
196 DirectionalLighting &Viewport::EntityProgram() noexcept {
197         if (active_prog != ENTITY) {
198                 entity_prog.Activate();
199                 EnableDepthTest();
200                 EnableBackfaceCulling();
201                 DisableBlending();
202                 entity_prog.SetVP(cam.View(), cam.Projection());
203                 active_prog = ENTITY;
204         }
205         return entity_prog;
206 }
207
208 DirectionalLighting &Viewport::HUDProgram() noexcept {
209         if (active_prog != HUD) {
210                 entity_prog.Activate();
211                 EnableDepthTest();
212                 EnableBackfaceCulling();
213                 entity_prog.SetVP(canv.View(), canv.Projection());
214                 active_prog = HUD;
215         }
216         return entity_prog;
217 }
218
219 PlainColor &Viewport::WorldOutlineProgram() noexcept {
220         if (active_prog != OUTLINE_WORLD) {
221                 outline_prog.Activate();
222                 outline_prog.SetVP(cam.View(), cam.Projection());
223                 active_prog = OUTLINE_WORLD;
224         }
225         return outline_prog;
226 }
227
228 PlainColor &Viewport::HUDOutlineProgram() noexcept {
229         if (active_prog != OUTLINE_HUD) {
230                 outline_prog.Activate();
231                 outline_prog.SetVP(canv.View(), canv.Projection());
232                 active_prog = OUTLINE_HUD;
233         }
234         return outline_prog;
235 }
236
237 SkyBoxShader &Viewport::SkyBoxProgram() noexcept {
238         if (active_prog != SKY_BOX) {
239                 sky_prog.Activate();
240                 DisableBlending();
241                 DisableBackfaceCulling();
242                 EqualDepthTest();
243                 active_prog = SKY_BOX;
244         }
245         return sky_prog;
246 }
247
248 BlendedSprite &Viewport::SpriteProgram() noexcept {
249         if (active_prog != SPRITE) {
250                 sprite_prog.Activate();
251                 EnableAlphaBlending();
252                 active_prog = SPRITE;
253         }
254         return sprite_prog;
255 }
256
257
258 void Viewport::WorldPosition(const glm::mat4 &t) noexcept {
259         cam.View(glm::inverse(t));
260         ChunkProgram().SetView(cam.View());
261         sky_prog.Activate();
262         SkyBoxProgram().SetView(cam.View());
263 }
264
265 }