]> git.localhorst.tv Git - blank.git/commitdiff
reorganize basic rendering functionality
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Mon, 27 Jul 2015 11:53:58 +0000 (13:53 +0200)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Mon, 27 Jul 2015 11:53:58 +0000 (13:53 +0200)
17 files changed:
TODO
src/app/Application.hpp
src/app/app.cpp
src/app/init.cpp
src/app/init.hpp
src/graphics/Camera.cpp [deleted file]
src/graphics/Camera.hpp
src/graphics/Canvas.hpp [new file with mode: 0644]
src/graphics/Viewport.hpp [new file with mode: 0644]
src/graphics/shader.cpp
src/graphics/viewport.cpp [new file with mode: 0644]
src/ui/HUD.hpp
src/ui/Interface.hpp
src/ui/ui.cpp
src/world/World.cpp
src/world/World.hpp
tst/test.cpp

diff --git a/TODO b/TODO
index 5fc2e9e5f32f0398479bb35030c532bf1d1d0794..8c52ca1a6bf7008bf72f8ed94f819da9d6d862a2 100644 (file)
--- a/TODO
+++ b/TODO
@@ -17,6 +17,10 @@ font colours
        set font fg and bg colour as either uniform or vertex attribute
        and lerp between them based on the texture's alpha component
 
+       it may also be feasible to get rid of SDL_ttf and use freetype
+       directly to eliminate the unneccessary surface creation
+       ftgl might also be worth looking at
+
 command line
 
        usefull for development and later on world administration
index 97cac73805b5ddad01c194e2f22d023830869d36..a8e0f2d00f3fdafda8df72d5533e4f86cbfe7c3c 100644 (file)
@@ -5,10 +5,7 @@
 #include "FrameCounter.hpp"
 #include "init.hpp"
 #include "RandomWalk.hpp"
-#include "../graphics/BlendedSprite.hpp"
-#include "../graphics/BlockLighting.hpp"
-#include "../graphics/Camera.hpp"
-#include "../graphics/DirectionalLighting.hpp"
+#include "../graphics/Viewport.hpp"
 #include "../ui/Interface.hpp"
 #include "../world/World.hpp"
 
@@ -57,21 +54,11 @@ public:
        static Entity &MakeTestEntity(World &);
 
 private:
-       InitSDL init_sdl;
-       InitIMG init_img;
-       InitTTF init_ttf;
-       InitGL init_gl;
-       Window window;
-       GLContext ctx;
-       InitGLEW init_glew;
+       Init init;
+       Viewport viewport;
        Assets assets;
        FrameCounter counter;
 
-       BlockLighting chunk_prog;
-       DirectionalLighting entity_prog;
-       BlendedSprite sprite_prog;
-
-       Camera cam;
        World world;
        Interface interface;
 
index 52a5905bd19b065828edc708212c0021587cada0..8577e45b48383ded5ef5d793b27a152cf424af42 100644 (file)
@@ -27,28 +27,15 @@ string get_asset_path() {
 namespace blank {
 
 Application::Application(const Config &config)
-: init_sdl()
-, init_img()
-, init_ttf()
-, init_gl(config.doublebuf, config.multisampling)
-, window()
-, ctx(window.CreateContext())
-, init_glew()
+: init(config.doublebuf, config.multisampling)
+, viewport()
 , assets(get_asset_path())
 , counter()
-, chunk_prog()
-, entity_prog()
-, sprite_prog()
-, cam()
 , world(config.world)
 , interface(config.interface, assets, counter, world)
 , test_controller(MakeTestEntity(world))
 , running(false) {
-       if (config.vsync) {
-               GLContext::EnableVSync();
-       }
-
-       glClearColor(0.0, 0.0, 0.0, 1.0);
+       viewport.VSync(config.vsync);
 }
 
 Entity &Application::MakeTestEntity(World &world) {
@@ -94,7 +81,7 @@ void Application::RunS(size_t n, size_t t) {
 void Application::Run() {
        running = true;
        Uint32 last = SDL_GetTicks();
-       window.GrabMouse();
+       init.window.GrabMouse();
        while (running) {
                Uint32 now = SDL_GetTicks();
                int delta = now - last;
@@ -151,17 +138,16 @@ void Application::HandleEvents() {
 void Application::Handle(const SDL_WindowEvent &event) {
        switch (event.event) {
                case SDL_WINDOWEVENT_FOCUS_GAINED:
-                       window.GrabMouse();
+                       init.window.GrabMouse();
                        break;
                case SDL_WINDOWEVENT_FOCUS_LOST:
-                       window.ReleaseMouse();
+                       init.window.ReleaseMouse();
                        break;
                case SDL_WINDOWEVENT_RESIZED:
-                       cam.Viewport(event.data1, event.data2);
-                       interface.Handle(event);
+                       viewport.Resize(event.data1, event.data2);
+                       interface.Resize(viewport);
                        break;
                default:
-                       interface.Handle(event);
                        break;
        }
 }
@@ -177,18 +163,14 @@ void Application::Update(int dt) {
 void Application::Render() {
        // gl implementation may (and will probably) delay vsync blocking until
        // the first write after flipping, which is this clear call
-       GLContext::Clear();
+       viewport.Clear();
        counter.EnterRender();
 
-       chunk_prog.SetProjection(cam.Projection());
-       entity_prog.SetProjection(cam.Projection());
-
-       world.Render(chunk_prog, entity_prog);
-
-       interface.Render(entity_prog, sprite_prog);
+       world.Render(viewport);
+       interface.Render(viewport);
 
        counter.ExitRender();
-       window.Flip();
+       init.window.Flip();
 }
 
 
index 9c97c9f4b31432b212149efc1e2d30338eb317d0..1cc0c2485b50db7e79a5fdd5baf242ef4201a72d 100644 (file)
@@ -4,30 +4,39 @@
 #include <SDL.h>
 #include <SDL_image.h>
 #include <SDL_ttf.h>
-#include <stdexcept>
-#include <string>
 #include <GL/glew.h>
 
 
 namespace {
 
-void sdl_error(std::string msg) {
+std::string sdl_error_append(std::string msg) {
        const char *error = SDL_GetError();
        if (*error != '\0') {
                msg += ": ";
                msg += error;
                SDL_ClearError();
        }
-       throw std::runtime_error(msg);
+       return msg;
 }
 
 }
 
 namespace blank {
 
+SDLError::SDLError()
+: std::runtime_error(SDL_GetError()) {
+
+}
+
+SDLError::SDLError(const std::string &msg)
+: std::runtime_error(sdl_error_append(msg)) {
+
+}
+
+
 InitSDL::InitSDL() {
        if (SDL_Init(SDL_INIT_VIDEO) != 0) {
-               sdl_error("SDL_Init(SDL_INIT_VIDEO)");
+               throw SDLError("SDL_Init(SDL_INIT_VIDEO)");
        }
 }
 
@@ -38,7 +47,7 @@ InitSDL::~InitSDL() {
 
 InitIMG::InitIMG() {
        if (IMG_Init(IMG_INIT_PNG) == 0) {
-               sdl_error("IMG_Init(IMG_INIT_PNG)");
+               throw SDLError("IMG_Init(IMG_INIT_PNG)");
        }
 }
 
@@ -49,7 +58,7 @@ InitIMG::~InitIMG() {
 
 InitTTF::InitTTF() {
        if (TTF_Init() != 0) {
-               sdl_error("TTF_Init()");
+               throw SDLError("TTF_Init()");
        }
 }
 
@@ -60,27 +69,27 @@ InitTTF::~InitTTF() {
 
 InitGL::InitGL(bool double_buffer, int sample_size) {
        if (SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3) != 0) {
-               sdl_error("SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3)");
+               throw SDLError("SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3)");
        }
        if (SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3) != 0) {
-               sdl_error("SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3)");
+               throw SDLError("SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3)");
        }
        if (SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE) != 0) {
-               sdl_error("SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE)");
+               throw SDLError("SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE)");
        }
 
        if (double_buffer) {
                if (SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1) != 0) {
-                       sdl_error("SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1)");
+                       throw SDLError("SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1)");
                }
        }
 
        if (sample_size > 1) {
                if (SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1) != 0) {
-                       sdl_error("SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS)");
+                       throw SDLError("SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS)");
                }
                if (SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, sample_size) != 0) {
-                       sdl_error("SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES)");
+                       throw SDLError("SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES)");
                }
        }
 }
@@ -94,7 +103,7 @@ Window::Window()
        SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE
 )) {
        if (!handle) {
-               sdl_error("SDL_CreateWindow");
+               throw SDLError("SDL_CreateWindow");
        }
 }
 
@@ -112,84 +121,30 @@ void Window::ReleaseInput() {
 
 void Window::GrabMouse() {
        if (SDL_SetRelativeMouseMode(SDL_TRUE) != 0) {
-               sdl_error("SDL_SetRelativeMouseMode");
+               throw SDLError("SDL_SetRelativeMouseMode");
        }
 }
 
 void Window::ReleaseMouse() {
        if (SDL_SetRelativeMouseMode(SDL_FALSE) != 0) {
-               sdl_error("SDL_SetRelativeMouseMode");
+               throw SDLError("SDL_SetRelativeMouseMode");
        }
 }
 
-GLContext Window::CreateContext() {
-       return GLContext(handle);
-}
-
 void Window::Flip() {
        SDL_GL_SwapWindow(handle);
 }
 
 
 GLContext::GLContext(SDL_Window *win)
-: handle(SDL_GL_CreateContext(win)) {
-       if (!handle) {
-               sdl_error("SDL_GL_CreateContext");
+: ctx(SDL_GL_CreateContext(win)) {
+       if (!ctx) {
+               throw SDLError("SDL_GL_CreateContext");
        }
 }
 
 GLContext::~GLContext() {
-       if (handle) {
-               SDL_GL_DeleteContext(handle);
-       }
-}
-
-
-GLContext::GLContext(GLContext &&other)
-: handle(other.handle) {
-       other.handle = nullptr;
-}
-
-GLContext &GLContext::operator =(GLContext &&other) {
-       std::swap(handle, other.handle);
-       return *this;
-}
-
-void GLContext::EnableVSync() {
-       if (SDL_GL_SetSwapInterval(1) != 0) {
-               sdl_error("SDL_GL_SetSwapInterval");
-       }
-}
-
-void GLContext::EnableDepthTest() noexcept {
-       glEnable(GL_DEPTH_TEST);
-       glDepthFunc(GL_LESS);
-}
-
-void GLContext::EnableBackfaceCulling() noexcept {
-       glEnable(GL_CULL_FACE);
-}
-
-void GLContext::EnableAlphaBlending() noexcept {
-       glEnable(GL_BLEND);
-       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-}
-
-void GLContext::EnableInvertBlending() noexcept {
-       glEnable(GL_BLEND);
-       glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO);
-}
-
-void GLContext::DisableBlending() noexcept {
-       glDisable(GL_BLEND);
-}
-
-void GLContext::Clear() noexcept {
-       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-}
-
-void GLContext::ClearDepthBuffer() noexcept {
-       glClear(GL_DEPTH_BUFFER_BIT);
+       SDL_GL_DeleteContext(ctx);
 }
 
 
@@ -208,4 +163,16 @@ InitGLEW::InitGLEW() {
        }
 }
 
+
+Init::Init(bool double_buffer, int sample_size)
+: init_sdl()
+, init_img()
+, init_ttf()
+, init_gl(double_buffer, sample_size)
+, window()
+, ctx(window.Handle())
+, init_glew() {
+
+}
+
 }
index f0777c85d5e4161b5f4926f37798f70a598a7a12..122210d1e96bc426a33de8b8a6fb938eda02976e 100644 (file)
@@ -2,11 +2,20 @@
 #define BLANK_APP_INIT_HPP_
 
 #include <SDL.h>
+#include <stdexcept>
+#include <string>
 
 
 namespace blank {
 
-class GLContext;
+class SDLError
+: public std::runtime_error {
+
+public:
+       SDLError();
+       explicit SDLError(const std::string &);
+
+};
 
 
 class InitSDL {
@@ -71,7 +80,7 @@ public:
        void GrabMouse();
        void ReleaseMouse();
 
-       GLContext CreateContext();
+       SDL_Window *Handle() { return handle; }
 
        void Flip();
 
@@ -87,24 +96,11 @@ public:
        explicit GLContext(SDL_Window *);
        ~GLContext();
 
-       GLContext(GLContext &&);
-       GLContext &operator =(GLContext &&);
-
        GLContext(const GLContext &) = delete;
        GLContext &operator =(const GLContext &) = delete;
 
-       static void EnableVSync();
-       static void EnableDepthTest() noexcept;
-       static void EnableBackfaceCulling() noexcept;
-       static void EnableAlphaBlending() noexcept;
-       static void EnableInvertBlending() noexcept;
-       static void DisableBlending() noexcept;
-
-       static void Clear() noexcept;
-       static void ClearDepthBuffer() noexcept;
-
 private:
-       SDL_GLContext handle;
+       SDL_GLContext ctx;
 
 };
 
@@ -119,6 +115,21 @@ public:
 
 };
 
+
+struct Init {
+
+       Init(bool double_buffer = true, int sample_size = 1);
+
+       InitSDL init_sdl;
+       InitIMG init_img;
+       InitTTF init_ttf;
+       InitGL init_gl;
+       Window window;
+       GLContext ctx;
+       InitGLEW init_glew;
+
+};
+
 }
 
 #endif
diff --git a/src/graphics/Camera.cpp b/src/graphics/Camera.cpp
deleted file mode 100644 (file)
index 5f61d26..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-#include "Camera.hpp"
-
-#include "../model/geometry.hpp"
-
-#include <GL/glew.h>
-#include <glm/gtc/matrix_transform.hpp>
-
-
-namespace blank {
-
-Camera::Camera() noexcept
-: fov(PI_0p25)
-, aspect(1.0f)
-, near_clip(0.1f)
-, far_clip(256.0f)
-, projection(glm::perspective(fov, aspect, near_clip, far_clip)) {
-
-}
-
-
-void Camera::Viewport(int width, int height) noexcept {
-       Viewport(0, 0, width, height);
-}
-
-void Camera::Viewport(int x, int y, int width, int height) noexcept {
-       glViewport(x, y, width, height);
-       Aspect(width, height);
-}
-
-void Camera::FOV(float f) noexcept {
-       fov = f;
-       UpdateProjection();
-}
-
-void Camera::Aspect(float r) noexcept {
-       aspect = r;
-       UpdateProjection();
-}
-
-void Camera::Aspect(float w, float h) noexcept {
-       Aspect(w / h);
-}
-
-void Camera::Clip(float near, float far) noexcept {
-       near_clip = near;
-       far_clip = far;
-       UpdateProjection();
-}
-
-
-void Camera::UpdateProjection() noexcept {
-       projection = glm::perspective(fov, aspect, near_clip, far_clip);
-}
-
-}
index 2fabfc6a66a9e77dd1d8c9458d277ef8f811aeb0..924b5b4bd320396ab28dbdb2dd3c710c28cdf91c 100644 (file)
@@ -11,16 +11,15 @@ class Camera {
 public:
        Camera() noexcept;
 
-       void Viewport(int width, int height) noexcept;
-       void Viewport(int x, int y, int width, int height) noexcept;
-
        /// FOV in radians
        void FOV(float f) noexcept;
        void Aspect(float r) noexcept;
        void Aspect(float w, float h) noexcept;
        void Clip(float near, float far) noexcept;
 
-       const glm::mat4 &Projection() noexcept { return projection; }
+       const glm::mat4 &Projection() const noexcept { return projection; }
+       const glm::mat4 &View() const noexcept { return view; }
+       void View(const glm::mat4 &v) noexcept { view = v; }
 
 private:
        void UpdateProjection() noexcept;
@@ -28,10 +27,11 @@ private:
 private:
        float fov;
        float aspect;
-       float near_clip;
-       float far_clip;
+       float near;
+       float far;
 
        glm::mat4 projection;
+       glm::mat4 view;
 
 };
 
diff --git a/src/graphics/Canvas.hpp b/src/graphics/Canvas.hpp
new file mode 100644 (file)
index 0000000..a9ce7f5
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef BLANK_GRAPHICS_CANVAS_HPP_
+#define BLANK_GRAPHICS_CANVAS_HPP_
+
+#include <glm/glm.hpp>
+
+
+namespace blank {
+
+class Canvas {
+
+public:
+       Canvas() noexcept;
+
+       void Resize(float w, float h) noexcept;
+
+       const glm::vec2 &Offset() const noexcept { return offset; }
+       const glm::vec2 &Size() const noexcept { return size; }
+
+       const glm::mat4 &Projection() const noexcept { return projection; }
+       const glm::mat4 &View() const noexcept { return view; }
+
+private:
+       void UpdateProjection() noexcept;
+
+private:
+       glm::vec2 offset;
+       glm::vec2 size;
+       float near;
+       float far;
+
+       glm::mat4 projection;
+       glm::mat4 view;
+
+};
+
+}
+
+#endif
diff --git a/src/graphics/Viewport.hpp b/src/graphics/Viewport.hpp
new file mode 100644 (file)
index 0000000..d64e580
--- /dev/null
@@ -0,0 +1,78 @@
+#ifndef BLANK_GRAPHICS_VIEWPORT_HPP_
+#define BLANK_GRAPHICS_VIEWPORT_HPP_
+
+#include "BlendedSprite.hpp"
+#include "BlockLighting.hpp"
+#include "Camera.hpp"
+#include "Canvas.hpp"
+#include "DirectionalLighting.hpp"
+
+#include <glm/glm.hpp>
+#include <SDL.h>
+
+
+namespace blank {
+
+class Viewport {
+
+public:
+       Viewport();
+
+       Viewport(const Viewport &) = delete;
+       Viewport &operator =(const Viewport &) = delete;
+
+       void VSync(bool b) noexcept;
+
+       void EnableDepthTest() noexcept;
+       void DisableDepthTest() noexcept;
+
+       void EnableBackfaceCulling() noexcept;
+       void DisableBackfaceCulling() noexcept;
+
+       void EnableAlphaBlending() noexcept;
+       void EnableInvertBlending() noexcept;
+       void DisableBlending() noexcept;
+
+       void Resize(int w, int h) noexcept;
+
+       float Width() const noexcept { return canv.Size().x; }
+       float Height() const noexcept { return canv.Size().y; }
+
+       void Clear() noexcept;
+       void ClearDepth() noexcept;
+
+       BlockLighting &ChunkProgram() noexcept;
+       DirectionalLighting &EntityProgram() noexcept;
+       DirectionalLighting &HUDProgram() noexcept;
+       BlendedSprite &SpriteProgram() noexcept;
+
+       void WorldPosition(const glm::mat4 &) noexcept;
+
+       const glm::mat4 &Perspective() const noexcept { return cam.Projection(); }
+       const glm::mat4 &Ortho() const noexcept { return canv.Projection(); }
+       const glm::mat4 &CenterTransform() const noexcept { return center; }
+
+private:
+       SDL_GLContext ctx;
+       Camera cam;
+       Canvas canv;
+
+       glm::mat4 center;
+
+       BlockLighting chunk_prog;
+       DirectionalLighting entity_prog;
+       BlendedSprite sprite_prog;
+
+       enum {
+               NONE,
+               CHUNK,
+               ENTITY,
+               HUD,
+               SPRITE,
+       } active_prog;
+
+};
+
+}
+
+#endif
index c38f9af2d15177ab65e514044eb736faad9f0f14..de994ce2a170437e07b9a37d647f8da571c85ae4 100644 (file)
@@ -215,8 +215,6 @@ DirectionalLighting::DirectionalLighting()
 
 
 void DirectionalLighting::Activate() noexcept {
-       GLContext::EnableDepthTest();
-       GLContext::EnableBackfaceCulling();
        program.Use();
 
        glUniform3f(light_direction_handle, light_direction.x, light_direction.y, light_direction.z);
@@ -319,9 +317,6 @@ BlockLighting::BlockLighting()
 
 
 void BlockLighting::Activate() noexcept {
-       GLContext::EnableDepthTest();
-       GLContext::EnableBackfaceCulling();
-       GLContext::DisableBlending();
        program.Use();
 }
 
@@ -398,7 +393,6 @@ BlendedSprite::BlendedSprite()
 
 
 void BlendedSprite::Activate() noexcept {
-       GLContext::EnableAlphaBlending();
        program.Use();
 }
 
diff --git a/src/graphics/viewport.cpp b/src/graphics/viewport.cpp
new file mode 100644 (file)
index 0000000..0607380
--- /dev/null
@@ -0,0 +1,200 @@
+#include "Camera.hpp"
+#include "Canvas.hpp"
+#include "Viewport.hpp"
+
+#include "../app/init.hpp"
+#include "../model/geometry.hpp"
+
+#include <GL/glew.h>
+#include <glm/gtc/matrix_transform.hpp>
+#include <glm/gtx/transform.hpp>
+#include <SDL.h>
+
+
+namespace blank {
+
+Camera::Camera() noexcept
+: fov(PI_0p25)
+, aspect(1.0f)
+, near(0.1f)
+, far(256.0f)
+, projection(glm::perspective(fov, aspect, near, far))
+, view(1.0f) {
+
+}
+
+
+void Camera::FOV(float f) noexcept {
+       fov = f;
+       UpdateProjection();
+}
+
+void Camera::Aspect(float r) noexcept {
+       aspect = r;
+       UpdateProjection();
+}
+
+void Camera::Aspect(float w, float h) noexcept {
+       Aspect(w / h);
+}
+
+void Camera::Clip(float n, float f) noexcept {
+       near = n;
+       far = f;
+       UpdateProjection();
+}
+
+
+void Camera::UpdateProjection() noexcept {
+       projection = glm::perspective(fov, aspect, near, far);
+}
+
+
+Canvas::Canvas() noexcept
+: offset(0.0f, 0.0f)
+, size(1.0f, 1.0f)
+, near(100.0f)
+, far(-100.0f)
+, projection(glm::ortho(offset.x, size.x, size.y, offset.y, near, far))
+, view(1.0f) {
+
+}
+
+
+void Canvas::Resize(float w, float h) noexcept {
+       size.x = w;
+       size.y = h;
+       UpdateProjection();
+}
+
+
+void Canvas::UpdateProjection() noexcept {
+       projection = glm::ortho(offset.x, size.x, size.y, offset.y, near, far);
+}
+
+
+Viewport::Viewport()
+: cam()
+, canv()
+, center(1.0f)
+, chunk_prog()
+, entity_prog()
+, sprite_prog()
+, active_prog(NONE) {
+       glClearColor(0.0, 0.0, 0.0, 1.0);
+}
+
+void Viewport::VSync(bool b) noexcept {
+       if (SDL_GL_SetSwapInterval(b) != 0) {
+               throw SDLError("SDL_GL_SetSwapInterval");
+       }
+}
+
+void Viewport::EnableDepthTest() noexcept {
+       glEnable(GL_DEPTH_TEST);
+       glDepthFunc(GL_LESS);
+}
+
+void Viewport::DisableDepthTest() noexcept {
+       glDisable(GL_DEPTH_TEST);
+}
+
+void Viewport::EnableBackfaceCulling() noexcept {
+       glEnable(GL_CULL_FACE);
+}
+
+void Viewport::DisableBackfaceCulling() noexcept {
+       glDisable(GL_CULL_FACE);
+}
+
+void Viewport::EnableAlphaBlending() noexcept {
+       glEnable(GL_BLEND);
+       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+}
+
+void Viewport::EnableInvertBlending() noexcept {
+       glEnable(GL_BLEND);
+       glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO);
+}
+
+void Viewport::DisableBlending() noexcept {
+       glDisable(GL_BLEND);
+}
+
+void Viewport::Resize(int w, int h) noexcept {
+       glViewport(0, 0, w, h);
+       float fw = w;
+       float fh = h;
+       cam.Aspect(fw, fh);
+       canv.Resize(fw, fh);
+
+       center = glm::translate(glm::vec3(fw * 0.5f, fh * 0.5f, 0.0f));
+
+       chunk_prog.SetProjection(Perspective());
+       if (active_prog == HUD) {
+               entity_prog.SetProjection(Ortho());
+       } else {
+               entity_prog.SetProjection(Perspective());
+       }
+       sprite_prog.SetProjection(Ortho());
+}
+
+void Viewport::Clear() noexcept {
+       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+}
+
+void Viewport::ClearDepth() noexcept {
+       glClear(GL_DEPTH_BUFFER_BIT);
+}
+
+
+BlockLighting &Viewport::ChunkProgram() noexcept {
+       if (active_prog != CHUNK) {
+               chunk_prog.Activate();
+               EnableDepthTest();
+               EnableBackfaceCulling();
+               DisableBlending();
+               active_prog = CHUNK;
+       }
+       return chunk_prog;
+}
+
+DirectionalLighting &Viewport::EntityProgram() noexcept {
+       if (active_prog != ENTITY) {
+               entity_prog.Activate();
+               EnableDepthTest();
+               EnableBackfaceCulling();
+               DisableBlending();
+               entity_prog.SetVP(cam.View(), cam.Projection());
+               active_prog = ENTITY;
+       }
+       return entity_prog;
+}
+
+DirectionalLighting &Viewport::HUDProgram() noexcept {
+       if (active_prog != HUD) {
+               entity_prog.Activate();
+               EnableDepthTest();
+               EnableBackfaceCulling();
+               entity_prog.SetVP(canv.View(), canv.Projection());
+               active_prog = HUD;
+       }
+       return entity_prog;
+}
+
+BlendedSprite &Viewport::SpriteProgram() noexcept {
+       if (active_prog != SPRITE) {
+               sprite_prog.Activate();
+               EnableAlphaBlending();
+               active_prog = SPRITE;
+       }
+       return sprite_prog;
+}
+
+
+void Viewport::WorldPosition(const glm::mat4 &t) noexcept {
+       cam.View(glm::inverse(t));
+       chunk_prog.SetView(cam.View());
+}
+
+}
index 245d886e795ffaccf35b658e7fde710457d46d9d..4b60127e685d7eb45462a9b3453b4c43a3251a44 100644 (file)
 
 namespace blank {
 
-class BlendedSprite;
 class Block;
 class BlockTypeRegistry;
-class DirectionalLighting;
 class Font;
+class Viewport;
 
 class HUD {
 
@@ -25,12 +24,9 @@ public:
        HUD(const HUD &) = delete;
        HUD &operator =(const HUD &) = delete;
 
-       void Viewport(float width, float height) noexcept;
-       void Viewport(float x, float y, float width, float height) noexcept;
-
        void Display(const Block &);
 
-       void Render(DirectionalLighting &, BlendedSprite &) noexcept;
+       void Render(Viewport &) noexcept;
 
 private:
        const BlockTypeRegistry &types;
@@ -48,11 +44,6 @@ private:
        bool block_visible;
 
        OutlineModel crosshair;
-       glm::mat4 crosshair_transform;
-
-       float near, far;
-       glm::mat4 projection;
-       glm::mat4 view;
 
 };
 
index d01fe254a665ed0011c214a97fae7af4b9dbb030..f3b1252643c93f02c8065c347a90ce7229bc3dcb 100644 (file)
@@ -17,9 +17,8 @@ namespace blank {
 
 class Assets;
 class Chunk;
-class BlendedSprite;
-class DirectionalLighting;
 class FrameCounter;
+class Viewport;
 class World;
 
 class Interface {
@@ -43,7 +42,8 @@ public:
        void HandlePress(const SDL_MouseButtonEvent &);
        void HandleRelease(const SDL_MouseButtonEvent &);
        void Handle(const SDL_MouseWheelEvent &);
-       void Handle(const SDL_WindowEvent &) noexcept;
+
+       void Resize(const Viewport &);
 
        void FaceBlock();
        void TurnBlock();
@@ -68,7 +68,7 @@ public:
 
        void Update(int dt);
 
-       void Render(DirectionalLighting &, BlendedSprite &) noexcept;
+       void Render(Viewport &) noexcept;
 
 private:
        void CheckAim();
@@ -92,6 +92,7 @@ private:
        Texture counter_tex;
        SpriteModel counter_sprite;
        glm::mat4 counter_transform;
+       float counter_x;
        SDL_Color counter_color;
 
        Config config;
index 88190e643d57b05f6bf9dba6e9db9b617ea8bfdd..80fbbcdb5a63e265ff678eef1861e58a23104abf 100644 (file)
@@ -4,9 +4,8 @@
 #include "../app/Assets.hpp"
 #include "../app/FrameCounter.hpp"
 #include "../app/init.hpp"
-#include "../graphics/BlendedSprite.hpp"
-#include "../graphics/DirectionalLighting.hpp"
 #include "../graphics/Font.hpp"
+#include "../graphics/Viewport.hpp"
 #include "../model/shapes.hpp"
 #include "../world/World.hpp"
 
@@ -31,12 +30,7 @@ HUD::HUD(const BlockTypeRegistry &types, const Font &font)
 , label_transform(1.0f)
 , label_color{0xFF, 0xFF, 0xFF, 0xFF}
 , block_visible(false)
-, crosshair()
-, crosshair_transform(1.0f)
-, near(100.0f)
-, far(-100.0f)
-, projection(glm::ortho(0.0f, 1.0f, 1.0f, 0.0f, near, far))
-, view(1.0f) {
+, crosshair() {
        block_transform = glm::translate(block_transform, glm::vec3(50.0f, 50.0f, 0.0f));
        block_transform = glm::scale(block_transform, glm::vec3(50.0f));
        block_transform = glm::rotate(block_transform, 3.5f, glm::vec3(1.0f, 0.0f, 0.0f));
@@ -54,16 +48,6 @@ HUD::HUD(const BlockTypeRegistry &types, const Font &font)
 }
 
 
-void HUD::Viewport(float width, float height) noexcept {
-       Viewport(0, 0, width, height);
-}
-
-void HUD::Viewport(float x, float y, float width, float height) noexcept {
-       projection = glm::ortho(x, width, height, y, near, far);
-       crosshair_transform = glm::translate(glm::vec3(width * 0.5f, height * 0.5f, 0.0f));
-}
-
-
 void HUD::Display(const Block &b) {
        const BlockType &type = types.Get(b.type);
 
@@ -84,24 +68,25 @@ void HUD::Display(const Block &b) {
 }
 
 
-void HUD::Render(DirectionalLighting &world_prog, BlendedSprite &sprite_prog) noexcept {
-       world_prog.Activate();
+void HUD::Render(Viewport &viewport) noexcept {
+       viewport.ClearDepth();
+
+       DirectionalLighting &world_prog = viewport.HUDProgram();
        world_prog.SetLightDirection({ 1.0f, 3.0f, 5.0f });
        // disable distance fog
        world_prog.SetFogDensity(0.0f);
-       GLContext::ClearDepthBuffer();
 
-       GLContext::EnableInvertBlending();
-       world_prog.SetMVP(crosshair_transform, view, projection);
+       viewport.EnableInvertBlending();
+       world_prog.SetM(viewport.CenterTransform());
        crosshair.Draw();
 
        if (block_visible) {
-               GLContext::DisableBlending();
+               viewport.DisableBlending();
                world_prog.SetM(block_transform);
                block.Draw();
 
-               sprite_prog.Activate();
-               sprite_prog.SetMVP(label_transform, view, projection);
+               BlendedSprite &sprite_prog = viewport.SpriteProgram();
+               sprite_prog.SetM(label_transform);
                sprite_prog.SetTexture(block_label);
                label_sprite.Draw();
        }
@@ -128,6 +113,7 @@ Interface::Interface(
 , counter_tex()
 , counter_sprite()
 , counter_transform(1.0f)
+, counter_x(935.0f)
 , counter_color{0xFF, 0xFF, 0xFF, 0xFF}
 , config(config)
 , place_timer(256)
@@ -136,7 +122,6 @@ Interface::Interface(
 , selection(1)
 , fwd(0)
 , rev(0) {
-       hud.Viewport(960, 600);
        hud.Display(selection);
 }
 
@@ -314,7 +299,7 @@ void Interface::UpdateCounter() {
        glm::vec2 size(font.TextSize(text.c_str()));
        counter_sprite.LoadRect(size.x, size.y);
        counter_transform = glm::translate(glm::vec3(
-               400.0f - size.x,
+               counter_x - size.x,
                25.0f,
                0.75f
        ));
@@ -402,10 +387,9 @@ void Interface::SelectPrevious() {
        hud.Display(selection);
 }
 
-void Interface::Handle(const SDL_WindowEvent &event) noexcept {
-       if (event.event == SDL_WINDOWEVENT_RESIZED) {
-               hud.Viewport(event.data1, event.data2);
-       }
+
+void Interface::Resize(const Viewport &viewport) {
+       counter_x = viewport.Width() - 25.0f;
 }
 
 
@@ -448,23 +432,23 @@ void Interface::CheckAim() {
 }
 
 
-void Interface::Render(DirectionalLighting &world_prog, BlendedSprite &sprite_prog) noexcept {
+void Interface::Render(Viewport &viewport) noexcept {
        if (config.visual_disabled) return;
 
        if (aim_chunk) {
-               world_prog.Activate();
+               DirectionalLighting &world_prog = viewport.EntityProgram();
                world_prog.SetM(outline_transform);
                outline.Draw();
        }
 
        if (show_counter) {
-               sprite_prog.Activate();
+               BlendedSprite &sprite_prog = viewport.SpriteProgram();
                sprite_prog.SetM(counter_transform);
                sprite_prog.SetTexture(counter_tex);
                counter_sprite.Draw();
        }
 
-       hud.Render(world_prog, sprite_prog);
+       hud.Render(viewport);
 }
 
 }
index 94cd092f88c03a7fd40562342231e06c6bb00dfc..97dcc0848a40a7936179ee7e4171aac8c29f1fd1 100644 (file)
@@ -1,8 +1,7 @@
 #include "World.hpp"
 
 #include "WorldCollision.hpp"
-#include "../graphics/BlockLighting.hpp"
-#include "../graphics/DirectionalLighting.hpp"
+#include "../graphics/Viewport.hpp"
 
 #include <iostream>
 #include <limits>
@@ -295,10 +294,11 @@ void World::Resolve(Entity &e, std::vector<WorldCollision> &col) {
 }
 
 
-void World::Render(BlockLighting &chunk_prog, DirectionalLighting &entity_prog) {
-       chunk_prog.Activate();
+void World::Render(Viewport &viewport) {
+       viewport.WorldPosition(player->Transform(player->ChunkCoords()));
+
+       BlockLighting &chunk_prog = viewport.ChunkProgram();
        chunk_prog.SetFogDensity(fog_density);
-       chunk_prog.SetView(glm::inverse(player->Transform(player->ChunkCoords())));
 
        for (Chunk &chunk : chunks.Loaded()) {
                glm::mat4 m(chunk.Transform(player->ChunkCoords()));
@@ -309,10 +309,9 @@ void World::Render(BlockLighting &chunk_prog, DirectionalLighting &entity_prog)
                }
        }
 
-       entity_prog.Activate();
+       DirectionalLighting &entity_prog = viewport.EntityProgram();
        entity_prog.SetLightDirection(light_direction);
        entity_prog.SetFogDensity(fog_density);
-       entity_prog.SetView(glm::inverse(player->Transform(player->ChunkCoords())));
 
        for (Entity &entity : entities) {
                if (entity.HasShape()) {
index 9ec4cb2faf7fae204c53672e0b1f6e800a09e9dc..10710fbd6667a2dc8ac957d8068dae4564a392ab 100644 (file)
@@ -14,8 +14,7 @@
 
 namespace blank {
 
-class BlockLighting;
-class DirectionalLighting;
+class Viewport;
 class WorldCollision;
 
 class World {
@@ -59,7 +58,7 @@ public:
 
        void Update(int dt);
 
-       void Render(BlockLighting &, DirectionalLighting &);
+       void Render(Viewport &);
 
 private:
        BlockTypeRegistry blockType;
index 180b0edca640286a520c767d37a74f2a4547eea0..b12d04bc178e945b16ec0d9257b2823311713e5a 100644 (file)
@@ -8,11 +8,7 @@ using CppUnit::TextUi::TestRunner;
 
 
 int main(int, char **) {
-       blank::InitSDL sdl;
-       blank::InitGL gl;
-       blank::Window win;
-       blank::GLContext ctx(win.CreateContext());
-       blank::InitGLEW glew;
+       blank::Init init;
 
        TestRunner runner;
        TestFactoryRegistry &registry = TestFactoryRegistry::getRegistry();