]> git.localhorst.tv Git - blank.git/blob - src/graphics/viewport.cpp
some skybox experiments
[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 , model() {
80         model.LoadUnitBox();
81 }
82
83 void SkyBox::Render(Viewport &viewport) noexcept {
84         SkyBoxShader &prog = viewport.SkyBoxProgram();
85         prog.SetTexture(texture);
86         model.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         chunk_prog.SetProjection(Perspective());
152         if (active_prog == HUD) {
153                 entity_prog.SetProjection(Ortho());
154         } else {
155                 entity_prog.SetProjection(Perspective());
156         }
157         sky_prog.SetProjection(Perspective());
158         sprite_prog.SetProjection(Ortho());
159 }
160
161 void Viewport::Clear() noexcept {
162         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
163 }
164
165 void Viewport::ClearDepth() noexcept {
166         glClear(GL_DEPTH_BUFFER_BIT);
167 }
168
169
170 void Viewport::SetCursor(const glm::vec3 &pos) {
171         cursor[3].x = pos.x;
172         cursor[3].y = pos.y;
173         cursor[3].z = pos.z;
174 }
175
176 void Viewport::SetCursor(const glm::vec3 &pos, Gravity grav) {
177         glm::vec2 p(align(grav, canv.Size(), glm::vec2(pos) + canv.Offset()));
178         cursor[3].x = p.x;
179         cursor[3].y = p.y;
180         cursor[3].z = pos.z;
181 }
182
183 void Viewport::MoveCursor(const glm::vec3 &d) {
184         cursor[3].x += d.x;
185         cursor[3].y += d.y;
186         cursor[3].z += d.z;
187 }
188
189
190 BlockLighting &Viewport::ChunkProgram() noexcept {
191         if (active_prog != CHUNK) {
192                 chunk_prog.Activate();
193                 EnableDepthTest();
194                 EnableBackfaceCulling();
195                 DisableBlending();
196                 active_prog = CHUNK;
197         }
198         return chunk_prog;
199 }
200
201 DirectionalLighting &Viewport::EntityProgram() noexcept {
202         if (active_prog != ENTITY) {
203                 entity_prog.Activate();
204                 EnableDepthTest();
205                 EnableBackfaceCulling();
206                 DisableBlending();
207                 entity_prog.SetVP(cam.View(), cam.Projection());
208                 active_prog = ENTITY;
209         }
210         return entity_prog;
211 }
212
213 DirectionalLighting &Viewport::HUDProgram() noexcept {
214         if (active_prog != HUD) {
215                 entity_prog.Activate();
216                 EnableDepthTest();
217                 EnableBackfaceCulling();
218                 entity_prog.SetVP(canv.View(), canv.Projection());
219                 active_prog = HUD;
220         }
221         return entity_prog;
222 }
223
224 PlainColor &Viewport::WorldOutlineProgram() noexcept {
225         if (active_prog != OUTLINE_WORLD) {
226                 outline_prog.Activate();
227                 outline_prog.SetVP(cam.View(), cam.Projection());
228                 active_prog = OUTLINE_WORLD;
229         }
230         return outline_prog;
231 }
232
233 PlainColor &Viewport::HUDOutlineProgram() noexcept {
234         if (active_prog != OUTLINE_HUD) {
235                 outline_prog.Activate();
236                 outline_prog.SetVP(canv.View(), canv.Projection());
237                 active_prog = OUTLINE_HUD;
238         }
239         return outline_prog;
240 }
241
242 SkyBoxShader &Viewport::SkyBoxProgram() noexcept {
243         if (active_prog != SKY_BOX) {
244                 sky_prog.Activate();
245                 DisableBlending();
246                 DisableBackfaceCulling();
247                 EqualDepthTest();
248                 active_prog = SKY_BOX;
249         }
250         return sky_prog;
251 }
252
253 BlendedSprite &Viewport::SpriteProgram() noexcept {
254         if (active_prog != SPRITE) {
255                 sprite_prog.Activate();
256                 EnableAlphaBlending();
257                 active_prog = SPRITE;
258         }
259         return sprite_prog;
260 }
261
262
263 void Viewport::WorldPosition(const glm::mat4 &t) noexcept {
264         cam.View(glm::inverse(t));
265         chunk_prog.SetView(cam.View());
266         sky_prog.SetView(cam.View());
267 }
268
269 }