Browse Source

refactoring

Kajetan Johannes Hammerle 3 years ago
parent
commit
ba4769b104

+ 339 - 0
client/Engine.cpp

@@ -0,0 +1,339 @@
+#include "client/Engine.h"
+#include "client/rendering/wrapper/GLFWWrapper.h"
+
+bool Engine::useSSAO = true;
+
+float Engine::testRadius = 0.0005;
+float Engine::testBias = 0.0005;
+bool Engine::ortho = false;
+Vector Engine::testOrthoCenter;
+
+static u64 last = 0;
+static u64 sum = 0;
+static u64 tindex = 0;
+static std::array<u64, 128> values;
+
+Engine::Engine(Shaders& shaders, Framebuffers& fb, const Keys& keys, const MouseButtons& buttons, const WindowSize& size) :
+shaders(shaders), fb(fb), keys(keys), buttons(buttons), game(keys, buttons), frustum(60.0f, 0.1f, 80.0f),
+ssaoNoise(4, 4), size(size), running(!shaders.hasError() && !fb.hasError()) {
+    rectangle.add( {-1, -1, 0, 0, 0, 0, 0, 0});
+    rectangle.add( {1, 1, 0, 1, 1, 0, 0, 0});
+    rectangle.add( {-1, 1, 0, 0, 1, 0, 0, 0});
+    rectangle.add( {-1, -1, 0, 0, 0, 0, 0, 0});
+    rectangle.add( {1, -1, 0, 1, 0, 0, 0, 0});
+    rectangle.add( {1, 1, 0, 1, 1, 0, 0, 0});
+    rectangle.build();
+}
+
+bool Engine::isRunning() const {
+    return running;
+}
+
+void Engine::renderTick(float lag) {
+    u64 current = GLFWWrapper::getTimeNanos();
+    sum -= values[tindex];
+    values[tindex] = current - last;
+    sum += values[tindex];
+    last = current;
+    tindex = (tindex + 1) & (127);
+
+    cam.update(lag);
+    updateWorldProjection();
+    updateWorldView();
+
+    renderShadow(lag);
+    renderWorld(lag);
+    if(Engine::useSSAO) {
+        renderSSAO();
+    }
+    renderPostWorld();
+    renderTextOverlay(lag);
+}
+
+void Engine::tick() {
+    game.tick(cam);
+    if(keys.test5.getDownTime() == 1) {
+        ortho = !ortho;
+    }
+    if(keys.test.isDown()) {
+        //ortho = !ortho;
+        testRadius /= 0.95f;
+    }
+    if(keys.test2.isDown()) {
+        testRadius *= 0.95f;
+    }
+    if(keys.test3.isDown()) {
+        testBias /= 0.95f;
+    }
+    if(keys.test4.isDown()) {
+        testBias *= 0.95f;
+    }
+}
+
+void Engine::renderShadow(float lag) {
+    fb.shadow.bind();
+    glEnable(GL_DEPTH_TEST);
+    shaders.shadow.use();
+    worldShadowProjView = worldShadowProj;
+    worldShadowProjView.mul(worldShadowView);
+    shaders.shadow.setMatrix("projView", worldShadowProjView.getValues());
+
+    //glEnable(GL_CULL_FACE);
+    //glCullFace(GL_FRONT);
+    game.renderWorld(lag, model, shaders.shadow);
+    //glCullFace(GL_BACK);
+}
+
+void Engine::renderWorld(float lag) {
+    fb.world.bind();
+    glEnable(GL_DEPTH_TEST);
+    shaders.world.use();
+
+    Matrix rWorldShadowProjView;
+    rWorldShadowProjView.translate(0.5f, 0.5f, 0.5f);
+    rWorldShadowProjView.scale(0.5f, 0.5f, 0.5f);
+    rWorldShadowProjView.mul(worldShadowProjView);
+
+    shaders.world.setMatrix("projViewShadow", rWorldShadowProjView.getValues());
+    shaders.world.setMatrix("proj", worldProj.getValues());
+    shaders.world.setMatrix("view", worldView.getValues());
+    model.clear();
+    shaders.world.setMatrix("model", model.get().getValues());
+    fb.shadow.bindDepthTexture(1);
+    shaders.world.setFloat("radius", Engine::testRadius);
+    shaders.world.setFloat("bias", Engine::testBias);
+    game.renderWorld(lag, model, shaders.world);
+}
+
+void Engine::renderSSAO() {
+    shaders.ssao.use();
+
+    Matrix rProj;
+    rProj.translate(0.5f, 0.5f, 0.5f);
+    rProj.scale(0.5f, 0.5f, 0.5f);
+    rProj.mul(worldProj);
+
+    shaders.ssao.setMatrix("proj", rProj.getValues());
+    shaders.ssao.setInt("width", size.width);
+    shaders.ssao.setInt("height", size.height);
+    fb.world.bindPositionTexture(0);
+    fb.world.bindNormalTexture(1);
+    fb.world.bindColorTexture(2);
+    fb.world.bindDepthTexture(3);
+    ssaoNoise.bind(4);
+    fb.ssao.bind();
+    rectangle.draw();
+    // ssao blur
+    shaders.ssaoBlur.use();
+    fb.ssao.bindRedTexture(0);
+    fb.ssaoBlur.bind();
+    rectangle.draw();
+}
+
+void Engine::renderPostWorld() {
+    glBindFramebuffer(GL_FRAMEBUFFER, 0);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+    shaders.postWorld.use();
+    fb.world.bindColorTexture(0);
+    fb.ssaoBlur.bindRedTexture(1);
+    fb.world.bindRedTexture(2);
+    fb.world.bindNormalTexture(3);
+    shaders.postWorld.setInt("useSSAO", Engine::useSSAO);
+    rectangle.draw();
+}
+
+void Engine::renderTextOverlay(float lag) {
+    glDisable(GL_DEPTH_TEST);
+    shaders.text.use();
+
+    Matrix m;
+    shaders.text.setMatrix("proj", m.getValues());
+    m.translate(-1.0f, 1.0f, 0.0f);
+    m.scale(2.0f / size.width, -2.0f / size.height, 1.0f);
+    shaders.text.setMatrix("view", m.getValues());
+    model.clear();
+    model.get().scale(2.0f, 2.0f, 2.0f);
+    shaders.text.setMatrix("model", model.get().getValues());
+
+    glEnable(GL_BLEND);
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+    glBlendEquation(GL_FUNC_ADD);
+    char buffer[50];
+    snprintf(buffer, 50, "FPS: %f %f %f", 128000000000.0f / sum, Engine::testRadius, Engine::testBias);
+    fontRenderer.drawString(20, 20, buffer);
+    game.renderTextOverlay(lag, model, shaders.text, fontRenderer);
+    glDisable(GL_BLEND);
+}
+
+void Engine::updateWorldProjection() {
+    frustum.setProjection(worldProj, size.width, size.height);
+
+    // http://cgvr.informatik.uni-bremen.de/teaching/cg_literatur/lighthouse3d_view_frustum_culling/index.html
+    /*float tan = tanf((0.5f * fovY) * M_PI / 180.0f);
+    float aspect = (float) size.width / size.height;
+    
+    float closeFarClip = 4;
+    float nearHigh = tan * nearClip;
+    float nearWidth = nearHigh * aspect;
+    float farHigh = tan * closeFarClip;
+    float farWidth = farHigh * aspect;
+
+    Vector farCenter = cam.getPosition();
+    farCenter.addMul(cam.getFront(), closeFarClip);
+
+    Vector farTopLeft = farCenter;
+    farTopLeft.addMul(cam.getLeft(), farWidth);
+    farTopLeft.addMul(cam.getUp(), farHigh);
+
+    Vector farBottomLeft = farCenter;
+    farBottomLeft.addMul(cam.getLeft(), farWidth);
+    farBottomLeft.addMul(cam.getDown(), farHigh);
+
+    Vector farTopRight = farCenter;
+    farTopRight.addMul(cam.getRight(), farWidth);
+    farTopRight.addMul(cam.getUp(), farHigh);
+
+    Vector farBottomRight = farCenter;
+    farBottomRight.addMul(cam.getRight(), farWidth);
+    farBottomRight.addMul(cam.getDown(), farHigh);
+
+    Vector nearCenter = cam.getPosition();
+    nearCenter.addMul(cam.getFront(), nearClip);
+
+    Vector nearTopLeft = nearCenter;
+    nearTopLeft.addMul(cam.getLeft(), nearWidth);
+    nearTopLeft.addMul(cam.getUp(), nearHigh);
+
+    Vector nearBottomLeft = nearCenter;
+    nearBottomLeft.addMul(cam.getLeft(), nearWidth);
+    nearBottomLeft.addMul(cam.getDown(), nearHigh);
+
+    Vector nearTopRight = nearCenter;
+    nearTopRight.addMul(cam.getRight(), nearWidth);
+    nearTopRight.addMul(cam.getUp(), nearHigh);
+
+    Vector nearBottomRight = nearCenter;
+    nearBottomRight.addMul(cam.getRight(), nearWidth);
+    nearBottomRight.addMul(cam.getDown(), nearHigh);
+
+    Vector light(-0.280166, -0.573576, -0.769751);
+    Vector lightLeft = light;
+    lightLeft.cross(0.0f, 1.0f, 0.0f);
+    Vector lightUp = lightLeft;
+    lightUp.cross(light);
+
+    //std::cout << "-------------------------\n";
+    Plane plane;
+    plane.set(Vector(), light, lightUp);
+    float f[8];
+    f[0] = plane.getSignedDistance(farTopLeft);
+    f[1] = plane.getSignedDistance(farBottomLeft);
+    f[2] = plane.getSignedDistance(farTopRight);
+    f[3] = plane.getSignedDistance(farBottomRight);
+    f[4] = plane.getSignedDistance(nearTopLeft);
+    f[5] = plane.getSignedDistance(nearBottomLeft);
+    f[6] = plane.getSignedDistance(nearTopRight);
+    f[7] = plane.getSignedDistance(nearBottomRight);
+    float min = FLT_MAX;
+    float max = -FLT_MAX;
+    for(uint i = 0; i < 8; i++) {
+        if(f[i] < min) {
+            min = f[i];
+        }
+        if(f[i] > max) {
+            max = f[i];
+        }
+    }
+    float lightWidth = max - min;
+    //std::cout << lightWidth << "\n";
+
+    plane.set(Vector(), light, lightLeft);
+    f[0] = plane.getSignedDistance(farTopLeft);
+    f[1] = plane.getSignedDistance(farBottomLeft);
+    f[2] = plane.getSignedDistance(farTopRight);
+    f[3] = plane.getSignedDistance(farBottomRight);
+    f[4] = plane.getSignedDistance(nearTopLeft);
+    f[5] = plane.getSignedDistance(nearBottomLeft);
+    f[6] = plane.getSignedDistance(nearTopRight);
+    f[7] = plane.getSignedDistance(nearBottomRight);
+
+    min = FLT_MAX;
+    max = -FLT_MAX;
+    for(uint i = 0; i < 8; i++) {
+        if(f[i] < min) {
+            min = f[i];
+        }
+        if(f[i] > max) {
+            max = f[i];
+        }
+    }
+    float lightHeight = max - min;
+    //std::cout << "\n" << max << " - " << min << " " << lightHeight << "\n";
+
+    // not the real center, but good guess
+    testOrthoCenter = nearCenter;
+    testOrthoCenter.addMul(cam.getFront(), closeFarClip * 0.5f);
+
+    if(ortho) {
+        worldProj.setToIdentity();
+        worldProj.set(0, 2.0f / lightWidth);
+        worldProj.set(5, 2.0f / lightHeight);
+        worldProj.set(10, -2.0f / (farClip - nearClip));
+    }
+
+    if(once) {
+        worldShadowProj.setToIdentity();
+        worldShadowProj.set(0, 2.0f / lightWidth);
+        worldShadowProj.set(5, 2.0f / lightHeight);
+        worldShadowProj.set(10, -2.0f / (farClip - nearClip));
+    }*/
+}
+
+void Engine::updateWorldView() {
+    Vector right = cam.getRight();
+    Vector up = cam.getUp();
+    Vector back = cam.getBack();
+    Vector pos = cam.getPosition();
+
+    if(ortho) {
+        right.set(0.939693f, 0.0f, -0.34202f);
+        back.set(0.280166f, 0.573576f, 0.769751f);
+        up.set(-0.196175f, 0.819152f, -0.538986f);
+        pos = testOrthoCenter;
+    }
+
+    worldView.set(0, right.getX());
+    worldView.set(1, up.getX());
+    worldView.set(2, back.getX());
+    worldView.set(4, right.getY());
+    worldView.set(5, up.getY());
+    worldView.set(6, back.getY());
+    worldView.set(8, right.getZ());
+    worldView.set(9, up.getZ());
+    worldView.set(10, back.getZ());
+    worldView.set(12, right.dotInverse(pos));
+    worldView.set(13, up.dotInverse(pos));
+    worldView.set(14, back.dotInverse(pos));
+
+    //if(once) {
+    // lengthAngle = 20; widthAngle = 35;
+    right.set(0.939693f, 0.0f, -0.34202f);
+    back.set(0.280166f, 0.573576f, 0.769751f);
+    up.set(-0.196175f, 0.819152f, -0.538986f);
+    pos = testOrthoCenter;
+
+    //once = false;
+    worldShadowView.set(0, right.getX());
+    worldShadowView.set(1, up.getX());
+    worldShadowView.set(2, back.getX());
+    worldShadowView.set(4, right.getY());
+    worldShadowView.set(5, up.getY());
+    worldShadowView.set(6, back.getY());
+    worldShadowView.set(8, right.getZ());
+    worldShadowView.set(9, up.getZ());
+    worldShadowView.set(10, back.getZ());
+    worldShadowView.set(12, right.dotInverse(pos));
+    worldShadowView.set(13, up.dotInverse(pos));
+    worldShadowView.set(14, back.dotInverse(pos));
+    //}
+}

+ 69 - 0
client/Engine.h

@@ -0,0 +1,69 @@
+#ifndef ENGINE_H
+#define ENGINE_H
+
+#include <cmath>
+#include <cfloat>
+
+#include "common/utils/Types.h"
+#include "client/input/Keys.h"
+#include "client/input/MouseButtons.h"
+#include "client/rendering/FontRenderer.h"
+#include "client/rendering/Mesh.h"
+#include "client/rendering/Framebuffers.h"
+#include "client/rendering/Shaders.h"
+#include "client/math/Camera.h"
+#include "client/math/Plane.h"
+#include "client/math/MatrixStack.h"
+#include "client/math/Frustum.h"
+#include "client/Game.h"
+#include "client/rendering/NoiseTexture.h"
+
+class Engine {
+public:
+    Engine(Shaders& shaders, Framebuffers& fb, const Keys& keys, const MouseButtons& buttons, const WindowSize& size);
+    bool isRunning() const;
+    void renderTick(float lag);
+    void tick();
+
+    static bool useSSAO;
+    static float testRadius;
+    static float testBias;
+    static bool ortho;
+    static Vector testOrthoCenter;
+
+    bool once = true;
+
+    Matrix worldProj;
+    Matrix worldView;
+    Matrix worldShadowProj;
+    Matrix worldShadowView;
+    Matrix worldShadowProjView;
+
+private:
+    void renderShadow(float lag);
+    void renderWorld(float lag);
+    void renderSSAO();
+    void renderPostWorld();
+    void renderTextOverlay(float lag);
+    void updateWorldProjection();
+    void updateWorldView();
+
+    Shaders& shaders;
+    Framebuffers& fb;
+
+    const Keys& keys;
+    const MouseButtons& buttons;
+    Game game;
+    Camera cam;
+    Frustum frustum;
+    MatrixStack model;
+    FontRenderer fontRenderer;
+    NoiseTexture ssaoNoise;
+    Mesh rectangle;
+
+    const WindowSize& size;
+
+    bool running;
+};
+
+#endif

+ 3 - 4
client/Game.cpp

@@ -2,7 +2,8 @@
 
 #include "client/Game.h"
 
-Game::Game() : lengthAngle(20.0f), widthAngle(35.0f), texture("resources/textures.png") {
+Game::Game(const Keys& keys, const MouseButtons& buttons) : keys(keys), buttons(buttons), lengthAngle(20.0f), 
+        widthAngle(35.0f), texture("resources/textures.png") {
     for(int x = -6; x <= 6; x++) {
         for(int y = -6; y <= 6; y++) {
             for(int z = -6; z <= 6; z++) {
@@ -81,9 +82,7 @@ void Game::addCube(float x, float y, float z, bool bottom, bool top, bool left,
     }
 }
 
-void Game::tick(const Keys& keys, const MouseButtons& mButtons, Camera& cam) {
-    (void) mButtons;
-
+void Game::tick(Camera& cam) {
     const float speed = 0.25f;
     if(keys.down.isDown()) {
         pos.addMul(cam.getFlatBack(), speed);

+ 6 - 3
client/Game.h

@@ -3,7 +3,7 @@
 
 #include "client/input/Keys.h"
 #include "client/input/MouseButtons.h"
-#include "client/rendering/Shader.h"
+#include "client/rendering/wrapper/Shader.h"
 #include "client/math/MatrixStack.h"
 #include "client/math/Camera.h"
 #include "client/rendering/Mesh.h"
@@ -12,15 +12,18 @@
 
 class Game {
 public:
-    Game();
+    Game(const Keys& keys, const MouseButtons& buttons);
 
-    void tick(const Keys& keys, const MouseButtons& mButtons, Camera& cam);
+    void tick(Camera& cam);
     void renderWorld(float lag, MatrixStack& stack, Shader& sh);
     void renderTextOverlay(float lag, MatrixStack& stack, Shader& sh, FontRenderer& fr);
 
 private:
     void addCube(float x, float y, float z, bool bottom, bool top, bool left, bool right, bool front, bool back);
 
+    const Keys& keys;
+    const MouseButtons& buttons;
+    
     float lengthAngle;
     float widthAngle;
     Vector pos;

+ 0 - 582
client/GameClient.cpp

@@ -1,582 +0,0 @@
-#include <iostream>
-#include <GL/glew.h>
-#include <GLFW/glfw3.h>
-#include <unordered_map>
-#include <cmath>
-#include <cstring>
-#include <array>
-#include <cfloat>
-
-#include "common/utils/Types.h"
-#include "client/GameClient.h"
-#include "client/input/Keys.h"
-#include "client/input/MouseButtons.h"
-#include "client/rendering/Shader.h"
-#include "client/rendering/FontRenderer.h"
-#include "client/rendering/Mesh.h"
-#include "client/rendering/Framebuffer.h"
-#include "client/Utils.h"
-#include "client/math/Camera.h"
-#include "client/math/Matrix.h"
-#include "client/math/Plane.h"
-#include "client/math/MatrixStack.h"
-#include "client/Game.h"
-#include "rendering/NoiseTexture.h"
-
-struct InternGameClient {
-
-    ~InternGameClient() {
-        if(window != nullptr) {
-            glfwDestroyWindow(window);
-        }
-        if(glfwInitDone) {
-            glfwTerminate();
-        }
-    }
-
-    bool glfwInitDone = false;
-    GLFWwindow* window = nullptr;
-};
-
-static const u64 NANOS_PER_TICK = 50000000;
-static const float lagFactor = 1.0f / NANOS_PER_TICK;
-static u64 timeFactor = 1;
-static int width = 0;
-static int height = 0;
-static bool resize = false;
-static float fovY = 60.0f;
-static float nearClip = 0.1f;
-static float farClip = 80.0f;
-static InternGameClient client;
-static Keys keys;
-static MouseButtons mButtons;
-static bool useSSAO = false;
-
-static float testRadius = 0.0005;
-static float testBias = 0.000025;
-static bool ortho = false;
-static Vector testOrthoCenter;
-
-struct Shaders {
-
-    Shaders() :
-    world("resources/shader/worldVertex.vs", "resources/shader/worldFragment.fs"),
-    ssao("resources/shader/ssaoVertex.vs", "resources/shader/ssaoFragment.fs"),
-    ssaoBlur("resources/shader/ssaoBlurVertex.vs", "resources/shader/ssaoBlurFragment.fs"),
-    shadow("resources/shader/worldShadowVertex.vs", "resources/shader/worldShadowFragment.fs"),
-    postWorld("resources/shader/worldPostVertex.vs", "resources/shader/worldPostFragment.fs"),
-    text("resources/shader/textVertex.vs", "resources/shader/textFragment.fs") {
-        worldProj.set(11, -1.0f);
-        worldProj.set(15, 0.0f);
-    }
-
-    Shader world;
-    Shader ssao;
-    Shader ssaoBlur;
-    Shader shadow;
-    Shader postWorld;
-    Shader text;
-    bool once = true;
-
-    Matrix worldProj;
-    Matrix worldView;
-
-    Matrix worldShadowProj;
-    Matrix worldShadowView;
-    Matrix worldShadowProjView;
-
-    bool isValid() const {
-        return world.isValid() && ssao.isValid() && ssaoBlur.isValid() &&
-                shadow.isValid() && postWorld.isValid() && text.isValid();
-    }
-
-    void updateWorldProjection(const Camera& cam) {
-        float tan = tanf((0.5f * fovY) * M_PI / 180.0f);
-        float q = 1.0f / tan;
-        float aspect = (float) width / height;
-
-        worldProj.setToIdentity();
-        worldProj.set(11, -1.0f);
-        worldProj.set(15, 0.0f);
-        worldProj.set(0, q / aspect);
-        worldProj.set(5, q);
-        worldProj.set(10, (nearClip + farClip) / (nearClip - farClip));
-        worldProj.set(14, (2.0f * nearClip * farClip) / (nearClip - farClip));
-
-        // http://cgvr.informatik.uni-bremen.de/teaching/cg_literatur/lighthouse3d_view_frustum_culling/index.html
-        float closeFarClip = 4;
-        float nearHigh = tan * nearClip;
-        float nearWidth = nearHigh * aspect;
-        float farHigh = tan * closeFarClip;
-        float farWidth = farHigh * aspect;
-
-        Vector farCenter = cam.getPosition();
-        farCenter.addMul(cam.getFront(), closeFarClip);
-
-        Vector farTopLeft = farCenter;
-        farTopLeft.addMul(cam.getLeft(), farWidth);
-        farTopLeft.addMul(cam.getUp(), farHigh);
-
-        Vector farBottomLeft = farCenter;
-        farBottomLeft.addMul(cam.getLeft(), farWidth);
-        farBottomLeft.addMul(cam.getDown(), farHigh);
-
-        Vector farTopRight = farCenter;
-        farTopRight.addMul(cam.getRight(), farWidth);
-        farTopRight.addMul(cam.getUp(), farHigh);
-
-        Vector farBottomRight = farCenter;
-        farBottomRight.addMul(cam.getRight(), farWidth);
-        farBottomRight.addMul(cam.getDown(), farHigh);
-
-        Vector nearCenter = cam.getPosition();
-        nearCenter.addMul(cam.getFront(), nearClip);
-
-        Vector nearTopLeft = nearCenter;
-        nearTopLeft.addMul(cam.getLeft(), nearWidth);
-        nearTopLeft.addMul(cam.getUp(), nearHigh);
-
-        Vector nearBottomLeft = nearCenter;
-        nearBottomLeft.addMul(cam.getLeft(), nearWidth);
-        nearBottomLeft.addMul(cam.getDown(), nearHigh);
-
-        Vector nearTopRight = nearCenter;
-        nearTopRight.addMul(cam.getRight(), nearWidth);
-        nearTopRight.addMul(cam.getUp(), nearHigh);
-
-        Vector nearBottomRight = nearCenter;
-        nearBottomRight.addMul(cam.getRight(), nearWidth);
-        nearBottomRight.addMul(cam.getDown(), nearHigh);
-
-        Vector light(-0.280166, -0.573576, -0.769751);
-        Vector lightLeft = light;
-        lightLeft.cross(0.0f, 1.0f, 0.0f);
-        Vector lightUp = lightLeft;
-        lightUp.cross(light);
-        
-        //std::cout << "-------------------------\n";
-        Plane plane;
-        plane.set(Vector(), light, lightUp);
-        float f[8];
-        f[0] = plane.getSignedDistance(farTopLeft);
-        f[1] = plane.getSignedDistance(farBottomLeft);
-        f[2] = plane.getSignedDistance(farTopRight);
-        f[3] = plane.getSignedDistance(farBottomRight);
-        f[4] = plane.getSignedDistance(nearTopLeft);
-        f[5] = plane.getSignedDistance(nearBottomLeft);
-        f[6] = plane.getSignedDistance(nearTopRight);
-        f[7] = plane.getSignedDistance(nearBottomRight);
-        float min = FLT_MAX;
-        float max = -FLT_MAX;
-        for(uint i = 0; i < 8; i++) {
-            if(f[i] < min) {
-                min = f[i];
-            }
-            if(f[i] > max) {
-                max = f[i];
-            }
-        }
-        float lightWidth = max - min;
-        //std::cout << lightWidth << "\n";
-        
-        plane.set(Vector(), light, lightLeft);
-        f[0] = plane.getSignedDistance(farTopLeft);
-        f[1] = plane.getSignedDistance(farBottomLeft);
-        f[2] = plane.getSignedDistance(farTopRight);
-        f[3] = plane.getSignedDistance(farBottomRight);
-        f[4] = plane.getSignedDistance(nearTopLeft);
-        f[5] = plane.getSignedDistance(nearBottomLeft);
-        f[6] = plane.getSignedDistance(nearTopRight);
-        f[7] = plane.getSignedDistance(nearBottomRight);
-        
-        min = FLT_MAX;
-        max = -FLT_MAX;
-        for(uint i = 0; i < 8; i++) {
-            if(f[i] < min) {
-                min = f[i];
-            }
-            if(f[i] > max) {
-                max = f[i];
-            }
-        }
-        float lightHeight = max - min;
-        //std::cout << "\n" << max << " - " << min << " " << lightHeight << "\n";
-        
-        // not the real center, but good guess
-        testOrthoCenter = nearCenter;
-        testOrthoCenter.addMul(cam.getFront(), closeFarClip * 0.5f);
-
-        if(ortho) {
-            worldProj.setToIdentity();
-            worldProj.set(0, 2.0f / lightWidth);
-            worldProj.set(5, 2.0f / lightHeight);
-            worldProj.set(10, -2.0f / (farClip - nearClip));
-        }
-
-        if(once) {
-            worldShadowProj.setToIdentity();
-            worldShadowProj.set(0, 2.0f / lightWidth);
-            worldShadowProj.set(5, 2.0f / lightHeight);
-            worldShadowProj.set(10, -2.0f / (farClip - nearClip));
-        }
-    }
-
-    void updateWorldView(Camera& cam) {
-        Vector right = cam.getRight();
-        Vector up = cam.getUp();
-        Vector back = cam.getBack();
-        Vector pos = cam.getPosition();
-
-        if(ortho) {
-            right.set(0.939693f, 0.0f, -0.34202f);
-            back.set(0.280166f, 0.573576f, 0.769751f);
-            up.set(-0.196175f, 0.819152f, -0.538986f);
-            pos = testOrthoCenter;
-        }
-
-        worldView.set(0, right.getX());
-        worldView.set(1, up.getX());
-        worldView.set(2, back.getX());
-        worldView.set(4, right.getY());
-        worldView.set(5, up.getY());
-        worldView.set(6, back.getY());
-        worldView.set(8, right.getZ());
-        worldView.set(9, up.getZ());
-        worldView.set(10, back.getZ());
-        worldView.set(12, right.dotInverse(pos));
-        worldView.set(13, up.dotInverse(pos));
-        worldView.set(14, back.dotInverse(pos));
-
-        //if(once) {
-        // lengthAngle = 20; widthAngle = 35;
-        right.set(0.939693f, 0.0f, -0.34202f);
-        back.set(0.280166f, 0.573576f, 0.769751f);
-        up.set(-0.196175f, 0.819152f, -0.538986f);
-        pos = testOrthoCenter;
-
-        //once = false;
-        worldShadowView.set(0, right.getX());
-        worldShadowView.set(1, up.getX());
-        worldShadowView.set(2, back.getX());
-        worldShadowView.set(4, right.getY());
-        worldShadowView.set(5, up.getY());
-        worldShadowView.set(6, back.getY());
-        worldShadowView.set(8, right.getZ());
-        worldShadowView.set(9, up.getZ());
-        worldShadowView.set(10, back.getZ());
-        worldShadowView.set(12, right.dotInverse(pos));
-        worldShadowView.set(13, up.dotInverse(pos));
-        worldShadowView.set(14, back.dotInverse(pos));
-        //}
-    }
-};
-
-struct Framebuffers {
-
-    Framebuffers(u32 w, u32 h) :
-    world(w, h, Framebuffer::POSITION | Framebuffer::NORMAL | Framebuffer::COLOR | Framebuffer::RED | Framebuffer::DEPTH24_STENCIL8, 0),
-    ssao(w, h, Framebuffer::RED, 0),
-    ssaoBlur(w, h, Framebuffer::RED, 0),
-    shadow(w, h, Framebuffer::DEPTH24_STENCIL8, 0 /*GL_LEQUAL*/) {
-    }
-
-    void resize(u32 w, u32 h) const {
-        world.resize(w, h);
-        ssao.resize(w, h);
-        ssaoBlur.resize(w, h);
-        shadow.resize(w, h);
-    }
-
-    bool isValid() const {
-        return world.isValid() && ssao.isValid() && ssaoBlur.isValid();
-    }
-
-    Framebuffer world;
-    Framebuffer ssao;
-    Framebuffer ssaoBlur;
-    Framebuffer shadow;
-};
-
-struct InternGame {
-
-    InternGame() : ssaoNoise(4, 4) {
-        rectangle.add( {-1, -1, 0, 0, 0, 0, 0, 0});
-        rectangle.add( {1, 1, 0, 1, 1, 0, 0, 0});
-        rectangle.add( {-1, 1, 0, 0, 1, 0, 0, 0});
-        rectangle.add( {-1, -1, 0, 0, 0, 0, 0, 0});
-        rectangle.add( {1, -1, 0, 1, 0, 0, 0, 0});
-        rectangle.add( {1, 1, 0, 1, 1, 0, 0, 0});
-        rectangle.build();
-    }
-
-    Game game;
-    Camera cam;
-    MatrixStack model;
-    FontRenderer fontRenderer;
-    NoiseTexture ssaoNoise;
-    Mesh rectangle;
-};
-
-static u64 getTimeNanos() {
-    return glfwGetTimerValue() * timeFactor;
-}
-
-static bool initGLFW() {
-    client.glfwInitDone = glfwInit();
-    if(!client.glfwInitDone) {
-        std::cout << "could not initialize GLFW\n";
-        return true;
-    }
-    timeFactor = 1000000000 / glfwGetTimerFrequency();
-    return false;
-}
-
-static bool initWindow(int w, int h, const char* windowName) {
-    width = w;
-    height = h;
-
-    glfwDefaultWindowHints();
-    glfwWindowHint(GLFW_VISIBLE, 0);
-    glfwWindowHint(GLFW_RESIZABLE, 1);
-
-    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
-    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
-    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
-
-    client.window = glfwCreateWindow(width, height, windowName, nullptr, nullptr);
-    if(client.window == nullptr) {
-        std::cout << "could not create window\n";
-        return true;
-    }
-    glfwMakeContextCurrent(client.window);
-    glfwSwapInterval(1);
-    return false;
-}
-
-static bool initGLEW() {
-    GLenum err = glewInit();
-    if(err != GLEW_OK) {
-        std::cout << "could not initialize GLEW: " << glewGetErrorString(err) << "\n";
-        return true;
-    }
-    std::cout << "using GLEW " << glewGetString(GLEW_VERSION) << "\n";
-    return false;
-}
-
-static void initCallbacks() {
-    // GLFWwindow* w, int key, int scancode, int action, int mod
-    glfwSetKeyCallback(client.window, [](GLFWwindow*, int key, int, int action, int) {
-        if(action == GLFW_PRESS) {
-            keys.press(key);
-        } else if(action == GLFW_RELEASE) {
-            keys.release(key);
-        }
-    });
-    // GLFWwindow* w, int button, int action, int mods
-    glfwSetMouseButtonCallback(client.window, [](GLFWwindow*, int button, int action, int) {
-        if(action == GLFW_PRESS) {
-            mButtons.press(button);
-        } else if(action == GLFW_RELEASE) {
-            mButtons.release(button);
-        }
-    });
-    // GLFWwindow* w, double xpos, double ypos
-    glfwSetCursorPosCallback(client.window, [](GLFWwindow*, double x, double y) {
-        mButtons.move(x, y);
-    });
-    // GLFWwindow* w, int width, int height
-    glfwSetFramebufferSizeCallback(client.window, [](GLFWwindow*, int w, int h) {
-        glViewport(0, 0, w, h);
-        width = w;
-        height = h;
-        resize = true;
-    });
-}
-
-static void tick(InternGame& game) {
-    keys.tick();
-    mButtons.tick();
-    game.game.tick(keys, mButtons, game.cam);
-    if(keys.test5.getDownTime() == 1) {
-        ortho = !ortho;
-    }
-    if(keys.test.isDown()) {
-        //ortho = !ortho;
-        testRadius /= 0.95f;
-    }
-    if(keys.test2.isDown()) {
-        testRadius *= 0.95f;
-    }
-    if(keys.test3.isDown()) {
-        testBias /= 0.95f;
-    }
-    if(keys.test4.isDown()) {
-        testBias *= 0.95f;
-    }
-    mButtons.postTick();
-}
-
-static void renderShadow(float lag, Shaders& shaders, InternGame& game, Framebuffers& fb) {
-    fb.shadow.bind();
-    glEnable(GL_DEPTH_TEST);
-    shaders.shadow.use();
-    shaders.worldShadowProjView = shaders.worldShadowProj;
-    shaders.worldShadowProjView.mul(shaders.worldShadowView);
-    shaders.shadow.setMatrix("projView", shaders.worldShadowProjView.getValues());
-
-    //glEnable(GL_CULL_FACE);
-    //glCullFace(GL_FRONT);
-    game.game.renderWorld(lag, game.model, shaders.shadow);
-    //glCullFace(GL_BACK);
-}
-
-static void renderWorld(float lag, Shaders& shaders, InternGame& game, Framebuffers& fb) {
-    fb.world.bind();
-    glEnable(GL_DEPTH_TEST);
-    shaders.world.use();
-
-    Matrix rWorldShadowProjView;
-    rWorldShadowProjView.translate(0.5f, 0.5f, 0.5f);
-    rWorldShadowProjView.scale(0.5f, 0.5f, 0.5f);
-    rWorldShadowProjView.mul(shaders.worldShadowProjView);
-
-    shaders.world.setMatrix("projViewShadow", rWorldShadowProjView.getValues());
-    shaders.world.setMatrix("proj", shaders.worldProj.getValues());
-    shaders.world.setMatrix("view", shaders.worldView.getValues());
-    game.model.clear();
-    shaders.world.setMatrix("model", game.model.get().getValues());
-    fb.shadow.bindDepthTexture(1);
-    shaders.world.setFloat("radius", testRadius);
-    shaders.world.setFloat("bias", testBias);
-    game.game.renderWorld(lag, game.model, shaders.world);
-}
-
-static void renderSSAO(Shaders& shaders, InternGame& game, Framebuffers& fb) {
-    // ssao
-    shaders.ssao.use();
-
-    Matrix rProj;
-    rProj.translate(0.5f, 0.5f, 0.5f);
-    rProj.scale(0.5f, 0.5f, 0.5f);
-    rProj.mul(shaders.worldProj);
-
-    shaders.ssao.setMatrix("proj", rProj.getValues());
-    shaders.ssao.setInt("width", width);
-    shaders.ssao.setInt("height", height);
-    fb.world.bindPositionTexture(0);
-    fb.world.bindNormalTexture(1);
-    fb.world.bindColorTexture(2);
-    fb.world.bindDepthTexture(3);
-    game.ssaoNoise.bind(4);
-    fb.ssao.bind();
-    game.rectangle.draw();
-    // ssao blur
-    shaders.ssaoBlur.use();
-    fb.ssao.bindRedTexture(0);
-    fb.ssaoBlur.bind();
-    game.rectangle.draw();
-}
-
-static void renderPostWorld(Shaders& shaders, InternGame& game, Framebuffers& fb) {
-    glBindFramebuffer(GL_FRAMEBUFFER, 0);
-    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-    shaders.postWorld.use();
-    fb.world.bindColorTexture(0);
-    fb.ssaoBlur.bindRedTexture(1);
-    fb.world.bindRedTexture(2);
-    fb.world.bindNormalTexture(3);
-    shaders.postWorld.setInt("useSSAO", useSSAO);
-    game.rectangle.draw();
-}
-
-static u64 last = 0;
-static u64 sum = 0;
-static u64 tindex = 0;
-static std::array<u64, 128> values;
-
-static void renderTextOverlay(float lag, Shaders& shaders, InternGame& game) {
-    glDisable(GL_DEPTH_TEST);
-    shaders.text.use();
-
-    Matrix m;
-    shaders.text.setMatrix("proj", m.getValues());
-    m.translate(-1.0f, 1.0f, 0.0f);
-    m.scale(2.0f / width, -2.0f / height, 1.0f);
-    shaders.text.setMatrix("view", m.getValues());
-    game.model.clear();
-    game.model.get().scale(2.0f, 2.0f, 2.0f);
-    shaders.text.setMatrix("model", game.model.get().getValues());
-
-    glEnable(GL_BLEND);
-    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-    glBlendEquation(GL_FUNC_ADD);
-    char buffer[50];
-    snprintf(buffer, 50, "FPS: %f %f %f", 128000000000.0f / sum, testRadius, testBias);
-    game.fontRenderer.drawString(20, 20, buffer);
-    game.game.renderTextOverlay(lag, game.model, shaders.text, game.fontRenderer);
-    glDisable(GL_BLEND);
-}
-
-static void renderTick(float lag, Shaders& shaders, InternGame& game, Framebuffers& fb) {
-    u64 current = getTimeNanos();
-    sum -= values[tindex];
-    values[tindex] = current - last;
-    sum += values[tindex];
-    last = current;
-    tindex = (tindex + 1) & (127);
-
-    if(resize) {
-        fb.resize(width, height);
-        resize = false;
-    }
-    game.cam.update(lag);
-    shaders.updateWorldProjection(game.cam);
-    shaders.updateWorldView(game.cam);
-
-    renderShadow(lag, shaders, game, fb);
-    renderWorld(lag, shaders, game, fb);
-    if(useSSAO) {
-        renderSSAO(shaders, game, fb);
-    }
-    renderPostWorld(shaders, game, fb);
-    renderTextOverlay(lag, shaders, game);
-}
-
-static void loop() {
-    Shaders shaders;
-    if(!shaders.isValid()) {
-        return;
-    }
-    Framebuffers fb(width, height);
-    if(!fb.isValid()) {
-        return;
-    }
-    InternGame game;
-
-    last = getTimeNanos();
-    u64 lastTime = getTimeNanos();
-    u64 lag = 0;
-    while(!glfwWindowShouldClose(client.window)) {
-        renderTick(lag * lagFactor, shaders, game, fb);
-        glfwSwapBuffers(client.window);
-
-        u64 newTime = getTimeNanos();
-        lag += newTime - lastTime;
-        lastTime = newTime;
-
-        while(lag >= NANOS_PER_TICK) {
-            lag -= NANOS_PER_TICK;
-            tick(game);
-        }
-        glfwPollEvents();
-    }
-}
-
-void GameClient::start(int w, int h, const char* windowName) {
-    if(initGLFW() || initWindow(w, h, windowName) || initGLEW()) {
-        return;
-    }
-    initCallbacks();
-    glfwShowWindow(client.window);
-    loop();
-}

+ 0 - 10
client/GameClient.h

@@ -1,10 +0,0 @@
-#ifndef CLIENT_H
-#define CLIENT_H
-
-#include "common/utils/Types.h"
-
-namespace GameClient {
-    void start(int width, int height, const char* windowName);
-}
-
-#endif

+ 100 - 3
client/Main.cpp

@@ -1,6 +1,103 @@
-#include "client/GameClient.h"
+#include <iostream>
+
+#include "client/rendering/wrapper/GLFWWrapper.h"
+#include "client/rendering/WindowSize.h"
+#include "client/rendering/wrapper/Window.h"
+#include "client/rendering/Shaders.h"
+#include "client/rendering/Framebuffers.h"
+#include "client/input/Keys.h"
+#include "client/input/MouseButtons.h"
+#include "client/Engine.h"
+
+bool initGLEW() {
+    GLenum err = glewInit();
+    if(err != GLEW_OK) {
+        std::cout << "could not initialize GLEW: " << glewGetErrorString(err) << "\n";
+        return true;
+    }
+    std::cout << "using GLEW " << glewGetString(GLEW_VERSION) << "\n";
+    return false;
+}
+
+void initCallbacks(Window& w, WindowSize& size, Framebuffers& framebuffers, Keys& keys, MouseButtons& buttons) {
+    static WindowSize& cSize = size;
+    static Framebuffers& cFramebuffers = framebuffers;
+    static Keys& cKeys = keys;
+    static MouseButtons& cButtons = buttons;
+    w.setFramebufferSizeCallback([](GLFWwindow*, int newWidth, int newHeight) {
+        glViewport(0, 0, newWidth, newHeight);
+        cSize.width = newWidth;
+        cSize.height = newHeight;
+        cFramebuffers.resize(newWidth, newHeight);
+    });
+    w.setKeyCallback([](GLFWwindow*, int key, int, int action, int) {
+        if(action == GLFW_PRESS) {
+            cKeys.press(key);
+        } else if(action == GLFW_RELEASE) {
+            cKeys.release(key);
+        }
+    });
+    w.setMouseButtonCallback([](GLFWwindow*, int button, int action, int) {
+        if(action == GLFW_PRESS) {
+            cButtons.press(button);
+        } else if(action == GLFW_RELEASE) {
+            cButtons.release(button);
+        }
+    });
+    w.setCursorPosCallback([](GLFWwindow*, double x, double y) {
+        cButtons.move(x, y);
+    });
+}
+
+int main() {
+    if(GLFWWrapper::hasError()) {
+        return 0;
+    }
+    
+    WindowSize size(1024, 620);
+    Window window(size, "Test");
+    if(window.hasError() || initGLEW()) {
+        return 0;
+    }
+    
+    Shaders shaders;
+    if(shaders.hasError()) {
+        return 0;
+    }
+    
+    Framebuffers framebuffers(size);
+    if(framebuffers.hasError()) {
+        return 0;
+    }
+    
+    Keys keys;
+    MouseButtons mButtons;
+    initCallbacks(window, size, framebuffers, keys, mButtons);
+    
+    Engine engine(shaders, framebuffers, keys, mButtons, size);
+    window.show();
+
+    const u64 nanosPerTick = 50000000;
+    u64 lastTime = GLFWWrapper::getTimeNanos();
+    u64 lag = 0;
+    while(!window.shouldClose() && engine.isRunning()) {
+        engine.renderTick((float) lag / nanosPerTick);
+        window.swapBuffers();
+
+        u64 newTime = GLFWWrapper::getTimeNanos();
+        lag += newTime - lastTime;
+        lastTime = newTime;
+
+        while(lag >= nanosPerTick) {
+            lag -= nanosPerTick;
+            keys.tick();
+            mButtons.tick();
+            engine.tick();
+            mButtons.postTick();
+        }
+
+        glfwPollEvents();
+    }
 
-int main(int /*argc*/, char** /*argv*/) {
-    GameClient::start(1024, 620, "Test");
     return 0;
 }

+ 3 - 0
client/input/Keys.cpp

@@ -2,6 +2,9 @@
 
 #include "client/input/Keys.h"
 
+Keys::Key::Key() : down(false), shouldRelease(false), downTime(0) {
+}
+
 bool Keys::Key::isDown() const {
     return down;
 }

+ 1 - 1
client/input/Keys.h

@@ -18,7 +18,7 @@ public:
         u32 getDownTime() const;
 
     private:
-        Key() = default;
+        Key();
         Key(const Key&) = delete;
         Key(Key&&) = delete;
         Key& operator=(const Key&) = delete;

+ 3 - 0
client/input/MouseButtons.cpp

@@ -2,6 +2,9 @@
 
 #include "client/input/MouseButtons.h"
 
+MouseButtons::MouseButton::MouseButton() : down(false), shouldRelease(false), downTime(0) {
+}
+
 bool MouseButtons::MouseButton::isDown() const {
     return down;
 }

+ 1 - 1
client/input/MouseButtons.h

@@ -18,7 +18,7 @@ public:
         u32 getDownTime() const;
 
     private:
-        MouseButton() = default;
+        MouseButton();
         MouseButton(const MouseButton&) = delete;
         MouseButton(MouseButton&&) = delete;
         MouseButton& operator=(const MouseButton&) = delete;

+ 29 - 0
client/math/Frustum.cpp

@@ -0,0 +1,29 @@
+#include <cmath>
+
+#include "client/math/Frustum.h"
+
+Frustum::Frustum(float fovY, float nearClip, float farClip) : fovY(fovY), nearClip(nearClip), farClip(farClip) {
+}
+
+void Frustum::setProjection(Matrix& m, int width, int height) {
+    float tan = tanf((0.5f * fovY) * M_PI / 180.0f);
+    float q = 1.0f / tan;
+    float aspect = (float) width / height;
+
+    m.set(0, q / aspect);
+    m.set(1, 0.0f);
+    m.set(2, 0.0f);
+    m.set(3, 0.0f);
+    m.set(4, 0.0f);
+    m.set(5, q);
+    m.set(6, 0.0f);
+    m.set(7, 0.0f);
+    m.set(8, 0.0f);
+    m.set(9, 0.0f);
+    m.set(10, (nearClip + farClip) / (nearClip - farClip));
+    m.set(11, -1.0f);
+    m.set(12, 0.0f);
+    m.set(13, 0.0f);
+    m.set(14, (2.0f * nearClip * farClip) / (nearClip - farClip));
+    m.set(15, 0.0f);
+}

+ 17 - 0
client/math/Frustum.h

@@ -0,0 +1,17 @@
+#ifndef FRUSTUM_H
+#define FRUSTUM_H
+
+#include "client/math/Matrix.h"
+
+class Frustum {
+public:
+    Frustum(float fovY, float nearClip, float farClip);
+    void setProjection(Matrix& m, int width, int height);
+
+private:
+    float fovY;
+    float nearClip;
+    float farClip;
+};
+
+#endif

+ 0 - 151
client/rendering/Framebuffer.cpp

@@ -1,151 +0,0 @@
-#include <iostream>
-
-#include "Framebuffer.h"
-#include "client/Utils.h"
-
-Framebuffer::Framebuffer(u32 width, u32 height, u32 mode, int textureCompareFunc) : mode(mode), buffer(0), valid(false) {
-    glGenFramebuffers(1, &buffer);
-    glBindFramebuffer(GL_FRAMEBUFFER, buffer);
-
-    GLuint attachments[4];
-    u32 counter = 0;
-
-    if(mode & POSITION) {
-        glGenTextures(1, &(textures[0]));
-        glBindTexture(GL_TEXTURE_2D, textures[0]);
-        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_FLOAT, nullptr);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + counter, GL_TEXTURE_2D, textures[0], 0);
-        attachments[counter] = GL_COLOR_ATTACHMENT0 + counter;
-        counter++;
-    }
-
-    if(mode & NORMAL) {
-        glGenTextures(1, &(textures[1]));
-        glBindTexture(GL_TEXTURE_2D, textures[1]);
-        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_FLOAT, nullptr);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + counter, GL_TEXTURE_2D, textures[1], 0);
-        attachments[counter] = GL_COLOR_ATTACHMENT0 + counter;
-        counter++;
-    }
-
-    if(mode & COLOR) {
-        glGenTextures(1, &(textures[2]));
-        glBindTexture(GL_TEXTURE_2D, textures[2]);
-        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + counter, GL_TEXTURE_2D, textures[2], 0);
-        attachments[counter] = GL_COLOR_ATTACHMENT0 + counter;
-        counter++;
-    }
-
-    if(mode & RED) {
-        glGenTextures(1, &textures[3]);
-        glBindTexture(GL_TEXTURE_2D, textures[3]);
-        glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, width, height, 0, GL_RGB, GL_FLOAT, nullptr);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + counter, GL_TEXTURE_2D, textures[3], 0);
-        attachments[counter] = GL_COLOR_ATTACHMENT0 + counter;
-        counter++;
-    }
-
-    if(mode & DEPTH24_STENCIL8) {
-        glGenTextures(1, &textures[4]);
-        glBindTexture(GL_TEXTURE_2D, textures[4]);
-        glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_STENCIL, width, height, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, nullptr);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-        if(textureCompareFunc != 0) {
-            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
-            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, textureCompareFunc);
-        }
-        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, textures[4], 0);
-    }
-
-    glDrawBuffers(counter, attachments);
-
-    if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
-        std::cout << "frame buffer is not complete\n";
-        return;
-    }
-    valid = true;
-}
-
-Framebuffer::~Framebuffer() {
-    glDeleteFramebuffers(1, &buffer);
-    for(GLuint& texture : textures) {
-        glDeleteTextures(1, &texture);
-    }
-}
-
-bool Framebuffer::isValid() const {
-    return valid;
-}
-
-void Framebuffer::bind() const {
-    glBindFramebuffer(GL_FRAMEBUFFER, buffer);
-    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-}
-
-void Framebuffer::resize(u32 width, u32 height) const {
-    if(mode & POSITION) {
-        glBindTexture(GL_TEXTURE_2D, textures[0]);
-        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, width, height, 0, GL_RGB, GL_FLOAT, nullptr);
-    }
-    if(mode & NORMAL) {
-        glBindTexture(GL_TEXTURE_2D, textures[1]);
-        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGB, GL_FLOAT, nullptr);
-    }
-    if(mode & COLOR) {
-        glBindTexture(GL_TEXTURE_2D, textures[2]);
-        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
-    }
-    if(mode & RED) {
-        glBindTexture(GL_TEXTURE_2D, textures[3]);
-        glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width, height, 0, GL_RGB, GL_FLOAT, nullptr);
-    }
-    if(mode & DEPTH24_STENCIL8) {
-        glBindTexture(GL_TEXTURE_2D, textures[4]);
-        glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_STENCIL, width, height, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, nullptr);
-    }
-}
-
-void Framebuffer::bindPositionTexture(u32 textureUnit) const {
-    glActiveTexture(GL_TEXTURE0 + textureUnit);
-    glBindTexture(GL_TEXTURE_2D, textures[0]);
-}
-
-void Framebuffer::bindNormalTexture(u32 textureUnit) const {
-    glActiveTexture(GL_TEXTURE0 + textureUnit);
-    glBindTexture(GL_TEXTURE_2D, textures[1]);
-}
-
-void Framebuffer::bindColorTexture(u32 textureUnit) const {
-    glActiveTexture(GL_TEXTURE0 + textureUnit);
-    glBindTexture(GL_TEXTURE_2D, textures[2]);
-}
-
-void Framebuffer::bindRedTexture(u32 textureUnit) const {
-    glActiveTexture(GL_TEXTURE0 + textureUnit);
-    glBindTexture(GL_TEXTURE_2D, textures[3]);
-}
-
-void Framebuffer::bindDepthTexture(u32 textureUnit) const {
-    glActiveTexture(GL_TEXTURE0 + textureUnit);
-    glBindTexture(GL_TEXTURE_2D, textures[4]);
-}

+ 0 - 43
client/rendering/Framebuffer.h

@@ -1,43 +0,0 @@
-#ifndef FRAMEBUFFER_H
-#define FRAMEBUFFER_H
-
-#include <GL/glew.h>
-#include <array>
-
-#include "common/utils/Types.h"
-
-class Framebuffer final {
-public:
-    static const u32 POSITION = 1;
-    static const u32 NORMAL = 2;
-    static const u32 COLOR = 4;
-    static const u32 RED = 8;
-    static const u32 DEPTH24_STENCIL8 = 16;
-
-    Framebuffer(u32 width, u32 height, u32 mode, int textureCompareFunc);
-    ~Framebuffer();
-
-    bool isValid() const;
-    void bind() const;
-
-    void resize(u32 width, u32 height) const;
-
-    void bindPositionTexture(u32 textureUnit) const;
-    void bindNormalTexture(u32 textureUnit) const;
-    void bindColorTexture(u32 textureUnit) const;
-    void bindRedTexture(u32 textureUnit) const;
-    void bindDepthTexture(u32 textureUnit) const;
-
-private:
-    Framebuffer(const Framebuffer& other) = delete;
-    Framebuffer(Framebuffer&& other) = delete;
-    Framebuffer& operator=(const Framebuffer& other) = delete;
-    Framebuffer& operator=(Framebuffer&& other) = delete;
-
-    u32 mode;
-    std::array<GLuint, 5> textures;
-    GLuint buffer;
-    bool valid;
-};
-
-#endif

+ 19 - 0
client/rendering/Framebuffers.cpp

@@ -0,0 +1,19 @@
+#include "client/rendering/Framebuffers.h"
+
+Framebuffers::Framebuffers(const WindowSize& size) :
+world(size, Framebuffer::POSITION | Framebuffer::NORMAL | Framebuffer::COLOR | Framebuffer::RED | Framebuffer::DEPTH24_STENCIL8),
+ssao(size, Framebuffer::RED),
+ssaoBlur(size, Framebuffer::RED),
+shadow(size, Framebuffer::DEPTH24_STENCIL8) {
+}
+
+void Framebuffers::resize(uint width, uint height) {
+    world.resize(width, height);
+    ssao.resize(width, height);
+    ssaoBlur.resize(width, height);
+    shadow.resize(width, height);
+}
+
+bool Framebuffers::hasError() const {
+    return world.hasError() || ssao.hasError() || ssaoBlur.hasError() || shadow.hasError();
+}

+ 18 - 0
client/rendering/Framebuffers.h

@@ -0,0 +1,18 @@
+#ifndef FRAMEBUFFERS_H
+#define FRAMEBUFFERS_H
+
+#include "client/rendering/WindowSize.h"
+#include "client/rendering/wrapper/Framebuffer.h"
+
+struct Framebuffers {
+    Framebuffers(const WindowSize& size);
+    void resize(uint width, uint height);
+    bool hasError() const;
+
+    Framebuffer world;
+    Framebuffer ssao;
+    Framebuffer ssaoBlur;
+    Framebuffer shadow;
+};
+
+#endif

+ 15 - 0
client/rendering/Shaders.cpp

@@ -0,0 +1,15 @@
+#include "Shaders.h"
+
+Shaders::Shaders() :
+world("resources/shader/worldVertex.vs", "resources/shader/worldFragment.fs"),
+ssao("resources/shader/ssaoVertex.vs", "resources/shader/ssaoFragment.fs"),
+ssaoBlur("resources/shader/ssaoBlurVertex.vs", "resources/shader/ssaoBlurFragment.fs"),
+shadow("resources/shader/worldShadowVertex.vs", "resources/shader/worldShadowFragment.fs"),
+postWorld("resources/shader/worldPostVertex.vs", "resources/shader/worldPostFragment.fs"),
+text("resources/shader/textVertex.vs", "resources/shader/textFragment.fs") {
+}
+
+bool Shaders::hasError() const {
+    return world.hasError() || ssao.hasError() || ssaoBlur.hasError() || shadow.hasError() || postWorld.hasError() ||
+            text.hasError();
+}

+ 18 - 0
client/rendering/Shaders.h

@@ -0,0 +1,18 @@
+#ifndef SHADERS_H
+#define SHADERS_H
+
+#include "client/rendering/wrapper/Shader.h"
+
+struct Shaders {
+    Shaders();
+    bool hasError() const;
+
+    Shader world;
+    Shader ssao;
+    Shader ssaoBlur;
+    Shader shadow;
+    Shader postWorld;
+    Shader text;
+};
+
+#endif

+ 4 - 0
client/rendering/WindowSize.cpp

@@ -0,0 +1,4 @@
+#include "WindowSize.h"
+
+WindowSize::WindowSize(int width, int height) : width(width), height(height) {
+}

+ 11 - 0
client/rendering/WindowSize.h

@@ -0,0 +1,11 @@
+#ifndef WINDOWSIZE_H
+#define WINDOWSIZE_H
+
+struct WindowSize {
+    WindowSize(int width, int height);
+    
+    int width;
+    int height;
+};
+
+#endif

+ 119 - 0
client/rendering/wrapper/Framebuffer.cpp

@@ -0,0 +1,119 @@
+#include <iostream>
+
+#include "client/rendering/wrapper/Framebuffer.h"
+
+Framebuffer::Framebuffer(const WindowSize& size, uint mode, bool texCompare) : mode(mode), textures(0),
+buffer(0), error(false) {
+    glGenFramebuffers(1, &buffer);
+    glBindFramebuffer(GL_FRAMEBUFFER, buffer);
+
+    data[0] = {POSITION, GL_RGB16F, GL_RGB, GL_FLOAT};
+    data[1] = {NORMAL, GL_RGB16F, GL_RGB, GL_FLOAT};
+    data[2] = {COLOR, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE};
+    data[3] = {RED, GL_R32F, GL_RGB, GL_FLOAT};
+    data[4] = {DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8};
+
+    GLuint attachments[4];
+    uint counter = 0;
+    for(uint i = 0; i < 4; i++) {
+        if(mode & data[i].mask) {
+            setupTexture(i, size.width, size.height, attachments, counter);
+        }
+    }
+    if(mode & DEPTH24_STENCIL8) {
+        genTexture(4, size.width, size.height);
+        if(texCompare) {
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
+        }
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, textures[4], 0);
+    }
+    glDrawBuffers(counter, attachments);
+
+    GLenum error = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+    if(error != GL_FRAMEBUFFER_COMPLETE) {
+        std::cout << "frame buffer error: " << getErrorString(error) << "\n";
+        error = true;
+    }
+}
+
+Framebuffer::~Framebuffer() {
+    glDeleteFramebuffers(1, &buffer);
+    for(GLuint& texture : textures) {
+        glDeleteTextures(1, &texture);
+    }
+}
+
+bool Framebuffer::hasError() const {
+    return error;
+}
+
+void Framebuffer::bind() const {
+    glBindFramebuffer(GL_FRAMEBUFFER, buffer);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+}
+
+void Framebuffer::resize(uint width, uint height) const {
+    for(uint i = 0; i < 5; i++) {
+        if(mode & data[i].mask) {
+            glBindTexture(GL_TEXTURE_2D, textures[i]);
+            glTexImage2D(GL_TEXTURE_2D, 0, data[i].internalFormat, width, height, 0, data[i].format, data[i].type, nullptr);
+        }
+    }
+}
+
+void Framebuffer::bindTexture(uint textureUnit, GLuint texture) const {
+    glActiveTexture(GL_TEXTURE0 + textureUnit);
+    glBindTexture(GL_TEXTURE_2D, texture);
+}
+
+void Framebuffer::bindPositionTexture(uint textureUnit) const {
+    bindTexture(textureUnit, textures[0]);
+}
+
+void Framebuffer::bindNormalTexture(uint textureUnit) const {
+    bindTexture(textureUnit, textures[1]);
+}
+
+void Framebuffer::bindColorTexture(uint textureUnit) const {
+    bindTexture(textureUnit, textures[2]);
+}
+
+void Framebuffer::bindRedTexture(uint textureUnit) const {
+    bindTexture(textureUnit, textures[3]);
+}
+
+void Framebuffer::bindDepthTexture(uint textureUnit) const {
+    bindTexture(textureUnit, textures[4]);
+}
+
+void Framebuffer::genTexture(uint index, uint width, uint height) {
+    glGenTextures(1, textures + index);
+    glBindTexture(GL_TEXTURE_2D, textures[index]);
+    glTexImage2D(GL_TEXTURE_2D, 0, data[index].internalFormat, width, height, 0, data[index].format, data[index].type, nullptr);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+}
+
+void Framebuffer::setupTexture(uint index, uint width, uint height, GLuint* attachments, uint& counter) {
+    genTexture(index, width, height);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + counter, GL_TEXTURE_2D, textures[index], 0);
+    attachments[counter] = GL_COLOR_ATTACHMENT0 + counter;
+    counter++;
+}
+
+const char* Framebuffer::getErrorString(GLenum error) const {
+    switch(error) {
+        case GL_FRAMEBUFFER_UNDEFINED: return "GL_FRAMEBUFFER_UNDEFINED";
+        case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: return "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT";
+        case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: return "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
+        case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: return "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER";
+        case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: return "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER";
+        case GL_FRAMEBUFFER_UNSUPPORTED: return "GL_FRAMEBUFFER_UNSUPPORTED";
+        case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: return "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE";
+        case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS: return "GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS";
+    }
+    return "unknown error";
+}

+ 56 - 0
client/rendering/wrapper/Framebuffer.h

@@ -0,0 +1,56 @@
+#ifndef FRAMEBUFFER_H
+#define FRAMEBUFFER_H
+
+#include <GL/glew.h>
+
+#include "client/rendering/WindowSize.h"
+#include "common/utils/Array.h"
+#include "common/utils/Types.h"
+
+class Framebuffer final {
+public:
+    static const uint POSITION = 1;
+    static const uint NORMAL = 2;
+    static const uint COLOR = 4;
+    static const uint RED = 8;
+    static const uint DEPTH24_STENCIL8 = 16;
+
+    Framebuffer(const WindowSize& size, uint mode, bool texCompare = false);
+    ~Framebuffer();
+    Framebuffer(const Framebuffer& other) = delete;
+    Framebuffer(Framebuffer&& other) = delete;
+    Framebuffer& operator=(const Framebuffer& other) = delete;
+    Framebuffer& operator=(Framebuffer&& other) = delete;
+
+    bool hasError() const;
+    void bind() const;
+
+    void resize(uint width, uint height) const;
+
+    void bindPositionTexture(uint textureUnit) const;
+    void bindNormalTexture(uint textureUnit) const;
+    void bindColorTexture(uint textureUnit) const;
+    void bindRedTexture(uint textureUnit) const;
+    void bindDepthTexture(uint textureUnit) const;
+
+private:
+    void genTexture(uint index, uint width, uint height);
+    void setupTexture(uint index, uint width, uint height, GLuint* attachments, uint& counter);
+    void bindTexture(uint textureUnit, GLuint texture) const;
+    const char* getErrorString(GLenum error) const;
+
+    uint mode;
+    Array<GLuint, 5> textures;
+    GLuint buffer;
+    bool error;
+
+    struct Data {
+        uint mask;
+        GLint internalFormat;
+        GLenum format;
+        GLenum type;
+    };
+    Data data[5];
+};
+
+#endif

+ 29 - 0
client/rendering/wrapper/GLFWWrapper.cpp

@@ -0,0 +1,29 @@
+#include <iostream>
+#include <GL/glew.h>
+#include <GLFW/glfw3.h>
+
+#include "client/rendering/wrapper/GLFWWrapper.h"
+
+struct GLFWInit final {
+    bool error;
+
+    GLFWInit() : error(glfwInit() == GLFW_FALSE) {
+        if(error) {
+            std::cout << "could not initialize GLFW\n";
+        }
+    }
+
+    ~GLFWInit() {
+        glfwTerminate();
+    }
+};
+
+static GLFWInit init;
+
+bool GLFWWrapper::hasError() {
+    return init.error;
+}
+
+u64 GLFWWrapper::getTimeNanos() {
+    return glfwGetTimerValue() * (1000000000 / glfwGetTimerFrequency());
+}

+ 11 - 0
client/rendering/wrapper/GLFWWrapper.h

@@ -0,0 +1,11 @@
+#ifndef GLFWWRAPPER_H
+#define GLFWWRAPPER_H
+
+#include "common/utils/Types.h"
+
+namespace GLFWWrapper {
+    bool hasError();
+    u64 getTimeNanos();
+}
+
+#endif

+ 17 - 33
client/rendering/Shader.cpp → client/rendering/wrapper/Shader.cpp

@@ -1,34 +1,20 @@
 #include <fstream>
-#include <cstring>
+#include <iostream>
 
-#include "client/rendering/Shader.h"
+#include "client/rendering/wrapper/Shader.h"
 #include "client/Utils.h"
 
-Shader::Shader(const GLchar* vPath, const GLchar* fPath) : valid(false),
-vShader(0), fShader(0), program(0) {
-    std::vector<GLchar> vCode;
-    std::vector<GLchar> fCode;
-    bool vCheck = readFile(vCode, vPath);
-    bool fCheck = readFile(fCode, fPath);
-    if(vCheck || fCheck) {
+Shader::Shader(const GLchar* vPath, const GLchar* fPath) : vShader(0), fShader(0), program(0) {
+    if(readFileAndCompile(vPath, vShader, GL_VERTEX_SHADER) || readFileAndCompile(fPath, fShader, GL_FRAGMENT_SHADER)) {
         return;
     }
-
-    vCheck = compileShader(vShader, vCode.data(), GL_VERTEX_SHADER);
-    fCheck = compileShader(fShader, fCode.data(), GL_FRAGMENT_SHADER);
-    if(vCheck || fCheck) {
-        return;
-    }
-
     program = glCreateProgram();
     glAttachShader(program, vShader);
     glAttachShader(program, fShader);
     glLinkProgram(program);
-
     if(checkAndPrintError("shader linking error")) {
         return;
     }
-
     GLint linked;
     glGetProgramiv(program, GL_LINK_STATUS, &linked);
     if(linked == GL_FALSE) {
@@ -37,7 +23,6 @@ vShader(0), fShader(0), program(0) {
         std::cout << "programm linking info log: " << buffer << "\n";
         return;
     }
-    valid = true;
 }
 
 Shader::~Shader() {
@@ -46,37 +31,36 @@ Shader::~Shader() {
     glDeleteShader(fShader);
 }
 
-bool Shader::isValid() const {
-    return valid;
+bool Shader::hasError() const {
+    return vShader == 0 || fShader == 0 || program == 0;
 }
 
-bool Shader::readFile(std::vector<GLchar>& buffer, const GLchar* path) const {
+bool Shader::readFileAndCompile(const GLchar* path, GLuint& shader, GLenum shaderType) {
+    GLchar buffer[8192];
+    if(readFile(buffer, 8192, path)) {
+        return true;
+    }
+    return compile(shader, buffer, shaderType);
+}
+
+bool Shader::readFile(GLchar* buffer, size_t bufferSize, const GLchar* path) const {
     std::ifstream in;
     in.open(path);
     if(in.fail()) {
         std::cout << "cannot read shader file: '" << path << "'\n";
         return true;
     }
-    while(true) {
-        GLchar c = in.get();
-        if(in.eof()) {
-            break;
-        }
-        buffer.push_back(c);
-    }
-    buffer.push_back('\0');
+    in.get(buffer, bufferSize, EOF);
     return false;
 }
 
-bool Shader::compileShader(GLuint& shader, const GLchar* code, GLenum shaderType) const {
+bool Shader::compile(GLuint& shader, const GLchar* code, GLenum shaderType) {
     shader = glCreateShader(shaderType);
     glShaderSource(shader, 1, &code, nullptr);
     glCompileShader(shader);
-
     if(checkAndPrintError("shader error")) {
         return true;
     }
-
     GLint compiled;
     glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
     if(compiled == GL_FALSE) {

+ 8 - 12
client/rendering/Shader.h → client/rendering/wrapper/Shader.h

@@ -2,31 +2,27 @@
 #define SHADER_H
 
 #include <GL/glew.h>
-#include <GLFW/glfw3.h>
-#include <iostream>
-#include <vector>
 
 class Shader final {
 public:
     Shader(const GLchar* vPath, const GLchar* fPath);
     ~Shader();
+    Shader(const Shader& other) = delete;
+    Shader(Shader&& other) = delete;
+    Shader& operator=(const Shader& other) = delete;
+    Shader& operator=(Shader&& other) = delete;
 
-    bool isValid() const;
+    bool hasError() const;
     void use() const;
     void setMatrix(const GLchar* name, const GLfloat* data) const;
     void setInt(const GLchar* name, GLint data) const;
     void setFloat(const GLchar* name, GLfloat data) const;
 
 private:
-    Shader(const Shader& other) = delete;
-    Shader(Shader&& other) = delete;
-    Shader& operator=(const Shader& other) = delete;
-    Shader& operator=(Shader&& other) = delete;
-
-    bool readFile(std::vector<GLchar>& buffer, const GLchar* path) const;
-    bool compileShader(GLuint& shader, const GLchar* code, GLenum shaderType) const;
+    bool readFileAndCompile(const GLchar* path, GLuint& shader, GLenum shaderType);
+    bool readFile(GLchar* buffer, size_t bufferSize, const GLchar* path) const;
+    bool compile(GLuint& shader, const GLchar* code, GLenum shaderType);
 
-    bool valid;
     GLuint vShader;
     GLuint fShader;
     GLuint program;

+ 61 - 0
client/rendering/wrapper/Window.cpp

@@ -0,0 +1,61 @@
+#include <iostream>
+
+#include "client/rendering/wrapper/Window.h"
+
+Window::Window(const WindowSize& size, const char* windowName) : window(nullptr) {
+    glfwDefaultWindowHints();
+    glfwWindowHint(GLFW_VISIBLE, 0);
+    glfwWindowHint(GLFW_RESIZABLE, 1);
+
+    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
+    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
+    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
+
+    window = glfwCreateWindow(size.width, size.height, windowName, nullptr, nullptr);
+    if(window == nullptr) {
+        std::cout << "could not create window\n";
+        return;
+    }
+    glfwMakeContextCurrent(window);
+    glfwSwapInterval(1);
+
+    glfwSetWindowUserPointer(window, this);
+}
+
+Window::~Window() {
+    if(window != nullptr) {
+        glfwDestroyWindow(window);
+    }
+}
+
+bool Window::hasError() const {
+    return window == nullptr;
+}
+
+void Window::show() {
+    glfwShowWindow(window);
+}
+
+bool Window::shouldClose() const {
+    return glfwWindowShouldClose(window);
+}
+
+void Window::swapBuffers() {
+    glfwSwapBuffers(window);
+}
+
+void Window::setFramebufferSizeCallback(GLFWframebuffersizefun f) {
+    glfwSetFramebufferSizeCallback(window, f);
+}
+
+void Window::setKeyCallback(GLFWkeyfun f) {
+    glfwSetKeyCallback(window, f);
+}
+
+void Window::setMouseButtonCallback(GLFWmousebuttonfun f) {
+    glfwSetMouseButtonCallback(window, f);
+}
+
+void Window::setCursorPosCallback(GLFWcursorposfun f) {
+    glfwSetCursorPosCallback(window, f);
+}

+ 33 - 0
client/rendering/wrapper/Window.h

@@ -0,0 +1,33 @@
+#ifndef WINDOW_H
+#define WINDOW_H
+
+#include <GL/glew.h>
+#include <GLFW/glfw3.h>
+
+#include "client/rendering/WindowSize.h"
+
+class Window final {
+public:
+    Window(const WindowSize& size, const char* windowName);
+    ~Window();
+
+    Window(const Window&) = delete;
+    Window& operator=(const Window&) = delete;
+    Window(Window&&) = delete;
+    Window& operator=(Window&&) = delete;
+
+    bool hasError() const;
+    void show();
+    bool shouldClose() const;
+    void swapBuffers();
+
+    void setFramebufferSizeCallback(GLFWframebuffersizefun f);
+    void setKeyCallback(GLFWkeyfun f);
+    void setMouseButtonCallback(GLFWmousebuttonfun f);
+    void setCursorPosCallback(GLFWcursorposfun f);
+
+private:
+    GLFWwindow* window;
+};
+
+#endif

+ 52 - 0
common/utils/Array.h

@@ -0,0 +1,52 @@
+#ifndef ARRAY_H
+#define ARRAY_H
+
+#include "common/utils/Types.h"
+
+template<typename T, size_t N>
+class Array final {
+public:
+
+    Array(const T& t) {
+        for(uint i = 0; i < N; i++) {
+            data[i] = t;
+        }
+    }
+
+    const T& operator[](size_t index) const {
+        return data[index];
+    }
+
+    T& operator[](size_t index) {
+        return data[index];
+    }
+
+    const T* operator+(size_t index) const {
+        return data + index;
+    }
+
+    T* operator+(size_t index) {
+        return data + index;
+    }
+
+    T* begin() {
+        return data;
+    }
+
+    const T* begin() const {
+        return data;
+    }
+
+    T* end() {
+        return data + N;
+    }
+
+    const T* end() const {
+        return data + N;
+    }
+
+private:
+    T data[N];
+};
+
+#endif

+ 1 - 1
meson.build

@@ -4,7 +4,7 @@ sourcesCommon = ['common/block/BlockRegistry.cpp', 'common/block/Block.cpp', 'co
 
 sourcesServer = ['server/GameServer.cpp', 'server/commands/CommandUtils.cpp', 'server/commands/ServerCommands.cpp', 'server/commands/CommandManager.cpp', 'server/network/Server.cpp', 'server/Main.cpp']
 
-sourcesClient = ['client/Main.cpp', 'client/GameClient.cpp', 'client/input/Keys.cpp', 'client/rendering/Shader.cpp', 'client/Utils.cpp', 'client/rendering/Mesh.cpp', 'client/math/Matrix.cpp', 'client/math/MatrixStack.cpp', 'client/math/Vector.cpp', 'client/math/Camera.cpp', 'client/math/Plane.cpp', 'client/Game.cpp', 'client/input/MouseButtons.cpp', 'client/rendering/Texture.cpp', 'client/rendering/FontRenderer.cpp', 'client/rendering/Framebuffer.cpp', 'client/rendering/NoiseTexture.cpp']
+sourcesClient = ['client/Main.cpp', 'client/rendering/WindowSize.cpp', 'client/math/Frustum.cpp', 'client/rendering/Framebuffers.cpp', 'client/rendering/wrapper/GLFWWrapper.cpp', 'client/rendering/wrapper/Window.cpp', 'client/Engine.cpp', 'client/input/Keys.cpp', 'client/rendering/wrapper/Shader.cpp', 'client/rendering/Shaders.cpp', 'client/Utils.cpp', 'client/rendering/Mesh.cpp', 'client/math/Matrix.cpp', 'client/math/MatrixStack.cpp', 'client/math/Vector.cpp', 'client/math/Camera.cpp', 'client/math/Plane.cpp', 'client/Game.cpp', 'client/input/MouseButtons.cpp', 'client/rendering/Texture.cpp', 'client/rendering/FontRenderer.cpp', 'client/rendering/wrapper/Framebuffer.cpp', 'client/rendering/NoiseTexture.cpp']
 
 sourcesTest = ['tests/Main.cpp', 'server/commands/CommandUtils.cpp']
 

+ 1 - 2
resources/shader/worldFragment.fs

@@ -66,8 +66,7 @@ void main(void) {
         shadow = 1 - exp(-40 * shadow - 0.693147180559945 + 20);
     }*/
     //shadow = 1 - exp(-40 * shadow - 0.693147180559945 + 20);
-    //shadow = 1 - exp(-shadow);
-    shadow = float(shadow > 0.05);
+    //shadow = float(shadow > 0.05);
 
     worldShadow = shadow;