Browse Source

improved shader stages(class for each, ...), refactoring, improved ssao

Kajetan Johannes Hammerle 5 years ago
parent
commit
7b1d7cb4c4
45 changed files with 1454 additions and 894 deletions
  1. BIN
      LineCounter.jar
  2. 27 4
      Makefile
  3. 25 32
      client/Client.cpp
  4. 4 1
      client/Client.h
  5. 5 4
      client/rendering/ChunkRenderer.cpp
  6. 4 3
      client/rendering/ChunkRenderer.h
  7. 2 2
      client/rendering/ClientChunkProvider.h
  8. 4 287
      engine/Shader.cpp
  9. 2 63
      engine/Shader.h
  10. 1 7
      engine/Texture.cpp
  11. 0 1
      engine/Texture.h
  12. 98 259
      engine/Wrapper.cpp
  13. 42 52
      engine/Wrapper.h
  14. 51 0
      engine/shader/FramebufferRectangle.cpp
  15. 21 0
      engine/shader/FramebufferRectangle.h
  16. 91 0
      engine/shader/OverlayShader.cpp
  17. 34 0
      engine/shader/OverlayShader.h
  18. 73 0
      engine/shader/SSAOBlurShader.cpp
  19. 29 0
      engine/shader/SSAOBlurShader.h
  20. 135 0
      engine/shader/SSAOShader.cpp
  21. 45 0
      engine/shader/SSAOShader.h
  22. 21 28
      engine/shader/ShaderProgram.cpp
  23. 2 2
      engine/shader/ShaderProgram.h
  24. 72 0
      engine/shader/WorldPostShader.cpp
  25. 31 0
      engine/shader/WorldPostShader.h
  26. 159 0
      engine/shader/WorldShader.cpp
  27. 42 0
      engine/shader/WorldShader.h
  28. 226 0
      math/Camera3D.cpp
  29. 56 0
      math/Camera3D.h
  30. 0 15
      math/Matrix3D.cpp
  31. 0 3
      math/Matrix3D.h
  32. 0 8
      math/Matrix3DStack.cpp
  33. 0 2
      math/Matrix3DStack.h
  34. 27 0
      shader/overlayFragment.fs
  35. 19 0
      shader/overlayVertex.vs
  36. 0 12
      shader/postVertex.vs
  37. 5 2
      shader/ssaoBlurFragment.fs
  38. 14 0
      shader/ssaoBlurVertex.vs
  39. 37 17
      shader/ssaoFragment.fs
  40. 6 4
      shader/ssaoVertex.vs
  41. 0 41
      shader/vertex.vs
  42. 4 27
      shader/worldFragment.fs
  43. 18 0
      shader/worldPostFragment.fs
  44. 14 0
      shader/worldPostVertex.vs
  45. 8 18
      shader/worldVertex.vs

BIN
LineCounter.jar


+ 27 - 4
Makefile

@@ -8,8 +8,10 @@ run_client: game_client
 	vblank_mode=0 optirun ./game_client
 	
 game_client: MainClient.cpp\
-	Clock.o DirectRenderer.o KeyManager.o Mesh.o MouseManager.o Shader.o Texture.o Utils.o Wrapper.o ShaderProgram.o\
-	Matrix3D.o Matrix3DStack.o StackOverflow.o StackUnderflow.o Vector3D.o Plane3D.o\
+	Clock.o DirectRenderer.o KeyManager.o Mesh.o MouseManager.o Shader.o\
+	Texture.o Utils.o Wrapper.o ShaderProgram.o WorldShader.o FramebufferRectangle.o\
+	SSAOShader.o SSAOBlurShader.o WorldPostShader.o OverlayShader.o\
+	Matrix3D.o Matrix3DStack.o StackOverflow.o StackUnderflow.o Vector3D.o Plane3D.o Camera3D.o\
 	Client.o\
 	Chunk.o World.o ChunkRenderer.o ClientChunkProvider.o
 	g++ $(VERSION) -o $@ MainClient.cpp *.o $(LDFLAGS)
@@ -45,8 +47,26 @@ Utils.o: engine/Utils.cpp engine/Utils.h
 Wrapper.o: engine/Wrapper.cpp engine/Wrapper.h
 	g++ $(VERSION) -c engine/Wrapper.cpp -o $@
 	
-ShaderProgram.o: engine/ShaderProgram.cpp engine/ShaderProgram.h
-	g++ $(VERSION) -c engine/ShaderProgram.cpp -o $@
+ShaderProgram.o: engine/shader/ShaderProgram.cpp engine/shader/ShaderProgram.h
+	g++ $(VERSION) -c engine/shader/ShaderProgram.cpp -o $@
+	
+WorldShader.o: engine/shader/WorldShader.cpp engine/shader/WorldShader.h
+	g++ $(VERSION) -c engine/shader/WorldShader.cpp -o $@
+	
+FramebufferRectangle.o: engine/shader/FramebufferRectangle.cpp engine/shader/FramebufferRectangle.h
+	g++ $(VERSION) -c engine/shader/FramebufferRectangle.cpp -o $@
+	
+SSAOShader.o: engine/shader/SSAOShader.cpp engine/shader/SSAOShader.h
+	g++ $(VERSION) -c engine/shader/SSAOShader.cpp -o $@
+	
+SSAOBlurShader.o: engine/shader/SSAOBlurShader.cpp engine/shader/SSAOBlurShader.h
+	g++ $(VERSION) -c engine/shader/SSAOBlurShader.cpp -o $@
+	
+WorldPostShader.o: engine/shader/WorldPostShader.cpp engine/shader/WorldPostShader.h
+	g++ $(VERSION) -c engine/shader/WorldPostShader.cpp -o $@
+	
+OverlayShader.o: engine/shader/OverlayShader.cpp engine/shader/OverlayShader.h
+	g++ $(VERSION) -c engine/shader/OverlayShader.cpp -o $@
 	
 # ------------------------------------------------------------------------------	
 # Client
@@ -93,6 +113,9 @@ Vector3D.o: math/Vector3D.h math/Vector3D.cpp
 Plane3D.o: math/Plane3D.h math/Plane3D.cpp
 	g++ $(VERSION) -c math/Plane3D.cpp -o $@
 	
+Camera3D.o: math/Camera3D.h math/Camera3D.cpp
+	g++ $(VERSION) -c math/Camera3D.cpp -o $@
+	
 # ------------------------------------------------------------------------------	
 # server
 # ------------------------------------------------------------------------------

+ 25 - 32
client/Client.cpp

@@ -5,9 +5,12 @@ using namespace std;
 
 Client::Client() : world(&chunkProvider)
 {    
-    position.set(0, 0, -2);
-    shader.setCamera(position.getX(), position.getY(), position.getZ(), 0, 0);
-    shader.storeCamera();
+    position.set(16, 50, -5);
+    lengthAngle = -15;
+    widthAngle = -20;
+    
+    camera.setPosition(position.getX(), position.getY(), position.getZ(), 0, 0);
+    camera.storePosition();
     
     keyManager.map(KEY_LEFT, GLFW_KEY_A);
     keyManager.map(KEY_RIGHT, GLFW_KEY_D);
@@ -36,41 +39,32 @@ void Client::tick()
 {
     tps.update();
     
-    if(keyManager.isDown(KEY_CAM_TEST))
-    {
-        Engine::setLineMode(true);
-    }
-    else
-    {
-        Engine::setLineMode(false);
-    }
-    
-    shader.storeCamera();
+    camera.storePosition();
     
     float factor = 0.5f;
     if(keyManager.isDown(KEY_LEFT))
     {
-        position.addMul(shader.getLeft(), factor);
+        position.addMul(camera.getFlatLeft(), factor);
     }
     if(keyManager.isDown(KEY_RIGHT))
     {
-        position.addMul(shader.getRight(), factor);
+        position.addMul(camera.getFlatRight(), factor);
     }
     if(keyManager.isDown(KEY_UP))
     {
-        position.addMul(shader.getFront(), factor);
+        position.addMul(camera.getFlatFront(), factor);
     }
     if(keyManager.isDown(KEY_DOWN))
     {
-        position.addMul(shader.getBack(), factor);
+        position.addMul(camera.getFlatBack(), factor);
     }
     if(keyManager.isDown(KEY_JUMP))
     {
-        position.addMul(shader.getUp(), factor);
+        position.addMul(camera.getFlatUp(), factor);
     }
     if(keyManager.isDown(KEY_SNEAK))
     {
-        position.addMul(shader.getDown(), factor);
+        position.addMul(camera.getFlatDown(), factor);
     }
     
     if(keyManager.isDown(KEY_CAM_LEFT))
@@ -90,29 +84,28 @@ void Client::tick()
         widthAngle -= 2;
     }
     
-    shader.setCamera(position.getX(), position.getY(), position.getZ(), lengthAngle, widthAngle);
+    camera.setPosition(position.getX(), position.getY(), position.getZ(), lengthAngle, widthAngle);
     
     mouseManager.tick();
     keyManager.tick();
 }
 
-void Client::renderTick(float lag)
+void Client::render3DTick(float lag)
 {
     fps.update();
     
-    shader.set3DMode(lag);
-    shader.setToIdentity();
-    shader.updateModelMatrix();
-    shader.setColorEnabled(true);
-    shader.setTextureEnabled(false);
-    shader.setUseBlending(false);
-    shader.setNormalsEnabled(true);
-    chunkRenderer.renderTick(shader, directRenderer, lag);
+    camera.update(lag);
+    Engine::setWorldViewMatrix(camera.getViewMatrix());
     
-    shader.set2DMode();
     shader.setToIdentity();
-    shader.updateModelMatrix();
-    shader.setTextMode();
+    Engine::setWorldModelMatrix(shader.getModelMatrix());
+    chunkRenderer.renderTick(shader, camera, directRenderer, lag);
+}
+
+void Client::render2DTick(float lag)
+{
+    shader.setToIdentity();
+    Engine::setOverlayModelMatrix(shader.getModelMatrix());
     
     string wusi;
     wusi = "FPS: " + to_string(fps.getUpdatesPerSecond());

+ 4 - 1
client/Client.h

@@ -7,6 +7,7 @@
 #include "../engine/Clock.h"
 #include "../engine/Shader.h"
 #include "../engine/DirectRenderer.h"
+#include "../math/Camera3D.h"
 #include "../world/World.h"
 #include "../world/IChunkProvider.h"
 #include "rendering/ClientChunkProvider.h"
@@ -21,7 +22,8 @@ public:
     virtual ~Client();
     
     void tick() override;
-    void renderTick(float lag) override;
+    void render3DTick(float lag) override;
+    void render2DTick(float lag) override;
     void onKeyEvent(int key, int scancode, int action, int mods) override;
     void onMouseClick(int button, int action, int mods) override;
 private:
@@ -51,6 +53,7 @@ private:
     ClientChunkProvider chunkProvider;
     World world;
     
+    Camera3D camera;
     Shader shader;
     DirectRenderer directRenderer;
 

+ 5 - 4
client/rendering/ChunkRenderer.cpp

@@ -1,4 +1,5 @@
 #include "ChunkRenderer.h"
+#include "../../engine/Wrapper.h"
 
 ChunkRenderer::ChunkRenderer()
 {
@@ -10,7 +11,7 @@ ChunkRenderer::~ChunkRenderer()
     delete[] mesh;
 }
 
-void ChunkRenderer::renderTick(Shader& shader, DirectRenderer& dr, float lag)
+void ChunkRenderer::renderTick(Shader& shader, Camera3D camera, DirectRenderer& dr, float lag)
 {
     //int frustumCull1 = 0;
     //int frustumCull2 = 0;
@@ -23,14 +24,14 @@ void ChunkRenderer::renderTick(Shader& shader, DirectRenderer& dr, float lag)
             int ex = sx + Chunk::WIDTH;
             int ez = sz + Chunk::DEPTH;
             
-            if(shader.isInFrustum(sx, 0, sz, ex, Chunk::HEIGHT, ez))
+            if(camera.isInFrustum(sx, 0, sz, ex, Chunk::HEIGHT, ez))
             {
                 shader.translateTo(x * Chunk::WIDTH, 0, z * Chunk::DEPTH);
-                shader.updateModelMatrix();
+                Engine::setWorldModelMatrix(shader.getModelMatrix());
 
                 for(int l = 0; l < Chunk::HEIGHT_PARTIONS; l++)
                 {
-                    if(shader.isInFrustum(sx, l * Chunk::PARTION_HEIGHT, sz, ex, (l + 1) * Chunk::PARTION_HEIGHT, ez))
+                    if(camera.isInFrustum(sx, l * Chunk::PARTION_HEIGHT, sz, ex, (l + 1) * Chunk::PARTION_HEIGHT, ez))
                     {
                         mesh[l + z * Chunk::HEIGHT_PARTIONS + x * chunkZ * Chunk::HEIGHT_PARTIONS].draw();
                     }

+ 4 - 3
client/rendering/ChunkRenderer.h

@@ -5,6 +5,7 @@
 #include "../../engine/Shader.h"
 #include "../../engine/DirectRenderer.h"
 #include "../../world/IChunkListener.h"
+#include "../../math/Camera3D.h"
 
 class ChunkRenderer : public IChunkListener
 {
@@ -12,13 +13,13 @@ public:
     ChunkRenderer();
     virtual ~ChunkRenderer();
     
-    void renderTick(Shader& shader, DirectRenderer& dr, float lag);
+    void renderTick(Shader& shader, Camera3D camera, DirectRenderer& dr, float lag);
     void updateChunk(Chunk& c, Chunk* north, Chunk* east, Chunk* south, Chunk* west) override;
 private:
     void buildChunk(int partionY, Chunk& c, Chunk* north, Chunk* east, Chunk* south, Chunk* west);
     
-    const int chunkX = 2;
-    const int chunkZ = 2;
+    const int chunkX = 16;
+    const int chunkZ = 16;
     ChunkMesh* mesh;
 };
 

+ 2 - 2
client/rendering/ClientChunkProvider.h

@@ -14,8 +14,8 @@ public:
     void forEachLoadedChunk(void* data, void (*fun) (Chunk&, void*)) const override;
     
 private:
-    const int chunkX = 2;
-    const int chunkZ = 2;
+    const int chunkX = 16;
+    const int chunkZ = 16;
     Chunk** chunks;
 };
 

+ 4 - 287
engine/Shader.cpp

@@ -5,287 +5,9 @@
 
 Shader::Shader()
 {
-    unifProjMatrix = Engine::getUniformLocation("projMatrix");
-    unifViewMatrix = Engine::getUniformLocation("viewMatrix");
-    unifModelMatrix = Engine::getUniformLocation("modelMatrix");
-    
-    unifUseTexture = Engine::getUniformLocation("useTexture");
-    unifUseColor = Engine::getUniformLocation("useColor");
-    unifUseMixColor = Engine::getUniformLocation("useMixColor");
-    unifMixColorLoc = Engine::getUniformLocation("mixColor");
-    unifUseNormals = Engine::getUniformLocation("useNormals");
-}
-
-Shader::Shader(const Shader& orig)
-{
-}
-
-Shader::~Shader()
-{
-}
-
-void Shader::set3DMode(float lag)
-{
-    float tan = tanf((0.5f * fovY) * M_PI / 180.0f);
-    float q = 1.0f / tan;
-    float aspect = (float) Engine::getWidth() / Engine::getHeight();
-
-    proj.set(0, 0, q / aspect);
-    proj.set(1, 1, q);
-    proj.set(2, 2, (nearClip + farClip) / (nearClip - farClip));
-    proj.set(3, 2, -1.0f);
-    proj.set(2, 3, (2.0f * nearClip * farClip) / (nearClip - farClip));
-    proj.set(3, 3, 0);   
-    
-    Engine::setMatrix(unifProjMatrix, proj.getValues());
-    Engine::testMat.set(proj);
-    
-    // -------------------------------------------------------------------------
-    // calculate vectors for the view matrix
-    // -------------------------------------------------------------------------
-    
-    // front
-    front.setAngles(interpolate(lag, oldLengthAngle, lengthAngle), interpolate(lag, oldWidthAngle, widthAngle));
-
-    // back
-    back.setInverse(front);
-
-    // right
-    right.set(front);
-    right.cross(0.0f, 1.0f, 0.0f);
-    right.normalize();
-    
-    // left
-    left.setInverse(right);
-    
-    // up
-    up.set(front);
-    up.cross(left);
-    up.normalize();
-    
-    // down
-    down.setInverse(up);
-    
-    Vector3D interCamera = oldCamera;
-    interCamera.addMul(camera, lag);
-    interCamera.addMul(oldCamera, -lag);
-    
-    Engine::testX = interCamera.getX();
-    Engine::testY = interCamera.getY();
-    Engine::testZ = interCamera.getZ();
-    
-    view.set(0, 0, right.getX());
-    view.set(0, 1, right.getY());
-    view.set(0, 2, right.getZ());
-    view.set(0, 3, right.dotInverse(interCamera));
-    
-    view.set(1, 0, up.getX());
-    view.set(1, 1, up.getY());
-    view.set(1, 2, up.getZ());
-    view.set(1, 3, up.dotInverse(interCamera));
-    
-    view.set(2, 0, back.getX());
-    view.set(2, 1, back.getY());
-    view.set(2, 2, back.getZ());
-    view.set(2, 3, back.dotInverse(interCamera));
-    
-    view.set(3, 0, 0.0f);
-    view.set(3, 1, 0.0f);
-    view.set(3, 0, 0.0f);
-    view.set(3, 3, 1.0f);
-    
-    Engine::setMatrix(unifViewMatrix, view.getValues());
-    
-    // -------------------------------------------------------------------------
-    // update frustum planes
-    // -------------------------------------------------------------------------
-    
-    // http://cgvr.informatik.uni-bremen.de/teaching/cg_literatur/lighthouse3d_view_frustum_culling/index.html
-    float nearHigh = tan * nearClip;
-    float nearWidth = nearHigh * aspect;
-
-    float farHigh = tan * farClip;
-    float farWidth = farHigh * aspect;
-
-    Vector3D fc = interCamera;
-    fc.addMul(front, farClip);
-
-    Vector3D ftl = fc;
-    ftl.addMul(left, farWidth);
-    ftl.addMul(up, farHigh);
-
-    Vector3D fbl = fc;
-    fbl.addMul(left, farWidth);
-    fbl.addMul(down, farHigh);
-
-    Vector3D fbr = fc;
-    fbr.addMul(right, farWidth);
-    fbr.addMul(down, farHigh);
-
-    Vector3D nc = interCamera;
-    nc.addMul(front, nearClip);
-
-    Vector3D ntl = nc;
-    ntl.addMul(left, nearWidth);
-    ntl.addMul(down, nearHigh);
-
-    Vector3D ntr = nc;
-    ntr.addMul(right, nearWidth);
-    ntr.addMul(up, nearHigh);
-
-    Vector3D nbr = nc;
-    nbr.addMul(right, nearWidth);
-    nbr.addMul(down, nearHigh);
-
-    // generating planes with counter clockwise vector order
-    frustumPlanes[0].set(fbl, ftl, fbr); // far
-    frustumPlanes[1].set(ntl, ftl, fbl); // left
-    frustumPlanes[2].set(fbr, ntr, nbr); // right
-    frustumPlanes[3].set(fbl, fbr, nbr); // bottom
-    frustumPlanes[4].set(ntr, ftl, ntl); // top
-    frustumPlanes[5].set(nbr, ntr, ntl); // near
-   
-    // -------------------------------------------------------------------------
-    // calculate vectors for movement
-    // -------------------------------------------------------------------------
-    
-    // front
-    front.setY(0.0f);
-    front.normalize();
-
-    // back
-    back.setInverse(front);
-
-    // right
-    right.set(front);
-    right.cross(0.0f, 1.0f, 0.0f);
-    right.normalize();
-    
-    // left
-    left.setInverse(right);
-
-    // up
-    up.set(0.0f, 1.0f, 0.0f);
-    
-    // down
-    down.setInverse(up);
-}
-
-void Shader::set2DMode()
-{
-    proj.setToIdentity();
-    Engine::setMatrix(unifProjMatrix, proj.getValues());
-    
-    int scale = Engine::getScale();
-    view.set(0, 0, (2.0f * scale) / Engine::getWidth());
-    view.set(0, 1, 0.0f);
-    view.set(0, 2, 0.0f);
-    view.set(0, 3, -1.0f);
-    
-    view.set(1, 0, 0.0f);
-    view.set(1, 1, (-2.0f * scale) / Engine::getHeight());
-    view.set(1, 2, 0.0f);
-    view.set(1, 3, 1.0f);
-    
-    view.set(2, 0, 0.0f);
-    view.set(2, 1, 0.0f);
-    view.set(2, 2, (-1.0f * scale) / Engine::getHeight());
-    view.set(2, 3, 0.5f);
-    
-    view.set(3, 0, 0.0f);
-    view.set(3, 1, 0.0f);
-    view.set(3, 0, 0.0f);
-    view.set(3, 3, 1.0f);
-    
-    Engine::setMatrix(unifViewMatrix, view.getValues());
-}
-
-void Shader::storeCamera()
-{
-    oldCamera.set(camera);
-    oldLengthAngle = lengthAngle;
-    oldWidthAngle = widthAngle;
-}
-
-void Shader::setCamera(float x, float y, float z, float length, float width)
-{
-    camera.set(x, y, z);
-    lengthAngle = length;
-    widthAngle = width;
-}
-
-float Shader::distanceFromCamera(float x, float y, float z, float lag) const
-{
-    Vector3D cam = oldCamera;
-    cam.addMul(camera, lag);
-    cam.addMul(oldCamera, -lag);
-    return sqrtf((x - cam.getX()) * (x - cam.getX()) + (y - cam.getY()) * (y - cam.getY()) + (z - cam.getZ()) * (z - cam.getZ()));
-}
-
-bool Shader::isInFrustum(float x, float y, float z, float x2, float y2, float z2) const
-{
-    //return true;
-    // http://cgvr.informatik.uni-bremen.de/teaching/cg_literatur/lighthouse3d_view_frustum_culling/index.html
-    // for each plane do ...
-    for(int fp = 0; fp < 6; fp++) 
-    {
-        // reset counters for corners in and out
-        int out = 0;
-        int in = 0;
-        // for each corner of the box do ...
-        // get out of the cycle as soon as a box as corners
-        // both inside and out of the frustum
-        for(int i = 0; i < 8 && (in == 0 || out == 0); i++) 
-        {
-            // is the corner outside or inside
-            if(frustumPlanes[fp].getSignedDistance(((i >> 2) & 1) ? x : x2, ((i >> 1) & 1) ? y : y2, (i & 1) ? z : z2) > 0)
-            {
-                out++;
-            }
-            else
-            {
-                in++;
-            }
-        }
-        //if all corners are out
-        if(in == 0)
-        {
-            return false;
-        }
-    }
-    return true;
-}
-
-const Vector3D& Shader::getFront() const
-{
-    return front;
-}
-
-const Vector3D& Shader::getBack() const
-{
-    return back;
-}
-
-const Vector3D& Shader::getRight() const
-{
-    return right;
-}
-
-const Vector3D& Shader::getLeft() const
-{
-    return left;
-}
-
-const Vector3D& Shader::getUp() const
-{
-    return up;
-}
-
-const Vector3D& Shader::getDown() const
-{
-    return down;
 }
 
+/*
 void Shader::setTextureEnabled(bool use)
 {
     Engine::setInt(unifUseTexture, use);
@@ -332,7 +54,7 @@ void Shader::setUseBlending(bool use)
     {
         glDisable(GL_BLEND);
     }
-}
+}*/
 
 void Shader::pop()
 {
@@ -379,11 +101,6 @@ void Shader::translateTo(float tx, float ty, float tz)
     model.get().translateTo(tx, ty, tz);
 }
 
-void Shader::rotate(float xDegrees, float yDegrees, float zDegrees)
-{
-    model.get().rotate(xDegrees, yDegrees, zDegrees);
-}
-
 void Shader::rotateX(float degrees)
 {
     model.get().rotateX(degrees);
@@ -399,7 +116,7 @@ void Shader::rotateZ(float degrees)
     model.get().rotateZ(degrees);
 }
 
-void Shader::updateModelMatrix()
+const float* Shader::getModelMatrix()
 {
-    Engine::setMatrix(unifModelMatrix, model.get().getValues());
+    return model.get().getValues();
 }

+ 2 - 63
engine/Shader.h

@@ -10,36 +10,6 @@ class Shader
 {
 public:
     Shader();
-    Shader(const Shader& orig);
-    virtual ~Shader();
-    
-    void set3DMode(float lag);
-    void set2DMode();
-    
-    void storeCamera();
-    void setCamera(float x, float y, float z, float length, float width);
-    
-    float distanceFromCamera(float x, float y, float z, float lag) const;
-    
-    bool isInFrustum(float x, float y, float z, float x2, float y2, float z2) const;
-
-    const Vector3D& getFront() const;
-    const Vector3D& getBack() const;
-    const Vector3D& getRight() const;
-    const Vector3D& getLeft() const;
-    const Vector3D& getUp() const;
-    const Vector3D& getDown() const;
-    
-    void setTextureEnabled(bool use);
-    void setColorEnabled(bool use);
-    void setMixColorEnabled(bool use);
-    void setMixColor(float r, float g, float b, float a);
-    void setTextMode();
-    void setNormalsEnabled(bool use);
-    
-    void setUseBlending(bool use);
-    
-    // model matrix operations
     
     void pop();
     void push();
@@ -50,45 +20,14 @@ public:
     void translateY(float ty);
     void translateZ(float tz);
     void translateTo(float tx, float ty, float tz);
-    void rotate(float xDegrees, float yDegrees, float zDegrees);
     void rotateX(float degrees);
     void rotateY(float degrees);
     void rotateZ(float degrees);
-    void updateModelMatrix();
+    
+    const float* getModelMatrix();
 
 private:
-    Matrix3D proj;
-    int unifProjMatrix = 0;
-    Matrix3D view;
-    int unifViewMatrix = 0;
     Matrix3DStack model;
-    int unifModelMatrix = 0;
-    
-    Vector3D oldCamera;
-    Vector3D camera;
-    float oldLengthAngle;
-    float lengthAngle;
-    float oldWidthAngle;
-    float widthAngle;
-    
-    Vector3D front;
-    Vector3D back;
-    Vector3D right;
-    Vector3D left;
-    Vector3D up;
-    Vector3D down;   
-    
-    Plane3D frustumPlanes[6];
-    
-    float fovY = 60;
-    float nearClip = 0.1f;
-    float farClip = 1000.0f;
-    
-    int unifUseTexture = 0;
-    int unifUseColor = 0;
-    int unifUseMixColor = 0;
-    int unifMixColorLoc = 0;
-    int unifUseNormals = 0;
 };
 
 #endif

+ 1 - 7
engine/Texture.cpp

@@ -3,8 +3,6 @@
 
 using namespace std;
 
-GLuint Texture::boundTexture = 0; 
-
 Texture::Texture(const char* path)
 {
     if(!load(path))
@@ -153,11 +151,7 @@ void Texture::initGL()
 
 void Texture::bind()
 {
-    if(boundTexture != texture)
-    {
-        boundTexture = texture;
-        glBindTexture(GL_TEXTURE_2D, texture);
-    }
+    glBindTexture(GL_TEXTURE_2D, texture);
 }
 
 bool Texture::isLoaded()

+ 0 - 1
engine/Texture.h

@@ -24,7 +24,6 @@ private:
     unsigned int height = 0;
     unsigned int* data = nullptr;
     
-    static GLuint boundTexture; 
     GLuint texture = 0;
 };
 

+ 98 - 259
engine/Wrapper.cpp

@@ -1,46 +1,35 @@
 #include "Wrapper.h"
-#include <random>
+#include <cmath>
 
 DummyClient DummyClient::dummy;
 
 IClient* Engine::client = &DummyClient::dummy;
-GLFWwindow* Engine::window = nullptr;
-
-// active program
-GLuint Engine::activeProgram = 0;
-
-// world data
-ShaderProgram Engine::worldShader;
-GLuint Engine::worldFrameBuffer = 0;
-GLuint Engine::worldPositionTexture = 0;
-GLuint Engine::worldNormalTexture = 0;
-GLuint Engine::worldColorTexture = 0;
-GLuint Engine::worldDepthTexture = 0;
-
-// ssao shader
-ShaderProgram Engine::ssaoShader;
-GLuint Engine::ssaoFrameBuffer = 0;
-GLuint Engine::ssaoTexture = 0;
-
-// post shader
-GLuint Engine::postVba = 0;
-GLuint Engine::postVbo = 0;
-ShaderProgram Engine::postShader;
 
+// window data
+GLFWwindow* Engine::window = nullptr;
 int Engine::scale = 1;
 int Engine::width = 0;
 int Engine::height = 0;
 
-bool Engine::lineMode = false;
-
-float Engine::testX = 0;
-float Engine::testY = 0;
-float Engine::testZ = 0;
-
-// ssao kernel data
-Vector3D Engine::ssaoKernel[ssaoKernelAmount];
-GLuint Engine::noiseTexture = 0;
-Matrix3D Engine::testMat;
+// projection data
+float Engine::fovY = 60;
+float Engine::nearClip = 0.1f;
+float Engine::farClip = 1000.0f;
+Matrix3D Engine::projMatrix;
+
+// rectangle for framebuffer drawing
+FramebufferRectangle Engine::rectangle;
+
+// shader stage 1 - world
+WorldShader Engine::worldShader;
+// shader stage 2 - world ssao
+SSAOShader Engine::ssaoShader;
+// shader stage 3 - world ssao blur
+SSAOBlurShader Engine::ssaoBlurShader;
+// shader stage 4 - world post
+WorldPostShader Engine::worldPostShader;
+// shader stage 5 - 2D overlay
+OverlayShader Engine::overlayShader;
 
 bool Engine::init(int width, int height, const char* name)
 {
@@ -78,25 +67,7 @@ bool Engine::init(int width, int height, const char* name)
     }
     cout << "Status: Using GLEW " << glewGetString(GLEW_VERSION) << endl;
 
-    worldShader.compile("shader/worldVertex.vs", "shader/worldFragment.fs");
-    if(!worldShader.isValid())
-    {
-        glfwDestroyWindow(window);
-        glfwTerminate();
-        return false;
-    }
-    activeProgram = worldShader.getProgram();
-
-    ssaoShader.compile("shader/ssaoVertex.vs", "shader/ssaoFragment.fs");
-    if(!ssaoShader.isValid())
-    {
-        glfwDestroyWindow(window);
-        glfwTerminate();
-        return false;
-    }
-    
-    postShader.compile("shader/postVertex.vs", "shader/postFragment.fs");
-    if(!postShader.isValid())
+    if(!worldShader.init() || !ssaoShader.init() || !ssaoBlurShader.init() || !worldPostShader.init() || !overlayShader.init() || !rectangle.init())
     {
         glfwDestroyWindow(window);
         glfwTerminate();
@@ -118,8 +89,6 @@ void Engine::start(IClient* client)
         Engine::client = client;
     }
     
-    onInit();
-
     glEnable(GL_CULL_FACE);
     glDepthFunc(GL_LEQUAL);
     
@@ -158,7 +127,6 @@ void Engine::start(IClient* client)
         glfwPollEvents();
     }
     
-    onTerm();
     glfwDestroyWindow(window);
     glfwTerminate();
 }
@@ -184,15 +152,10 @@ void Engine::onWindowResize(GLFWwindow* w, int width, int height)
     Engine::width = width;
     Engine::height = height;
     updateScale();
-    
-    /*glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer); 
-    glBindTexture(GL_TEXTURE_2D, frameTexture);
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
-    glBindTexture(GL_TEXTURE_2D, 0);
-    glBindRenderbuffer(GL_RENDERBUFFER, depthTexture); 
-    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);  
-    glBindRenderbuffer(GL_RENDERBUFFER, 0);
-    glBindFramebuffer(GL_FRAMEBUFFER, 0);*/
+    worldShader.resize();
+    ssaoShader.resize();
+    ssaoBlurShader.resize();
+    worldPostShader.resize();
 }
 
 void Engine::updateScale()
@@ -219,24 +182,19 @@ int Engine::getHeight()
     return height;
 }
 
-GLint Engine::getUniformLocation(const GLchar* name)
-{
-    return glGetUniformLocation(activeProgram, name);
-}
-
-void Engine::setMatrix(GLint location, const GLfloat* m)
+float Engine::getFieldOfView()
 {
-    glUniformMatrix4fv(location, 1, 0, m);
+    return fovY;
 }
 
-void Engine::setInt(GLint location, GLint i)
+float Engine::getNearClip()
 {
-    glUniform1i(location, i);
+    return nearClip;
 }
 
-void Engine::setFloat(GLint location, GLfloat f1, GLfloat f2, GLfloat f3, GLfloat f4)
+float Engine::getFarClip()
 {
-    glUniform4f(location, f1, f2, f3, f4);
+    return farClip;
 }
 
 void Engine::printError()
@@ -273,205 +231,86 @@ void Engine::printError()
     }
 }
 
-void Engine::onInit()
+void Engine::onRenderTick(float lag)
 {
-    // generate framebuffer and textures for world buffer
-    glGenFramebuffers(1, &worldFrameBuffer);
-    glBindFramebuffer(GL_FRAMEBUFFER, worldFrameBuffer);
-    // world position texture
-    glGenTextures(1, &worldPositionTexture);
-    glBindTexture(GL_TEXTURE_2D, worldPositionTexture);
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGB, GL_FLOAT, NULL);
-    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, GL_TEXTURE_2D, worldPositionTexture, 0);   
-    // world normal texture
-    glGenTextures(1, &worldNormalTexture);
-    glBindTexture(GL_TEXTURE_2D, worldNormalTexture);
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGB, GL_FLOAT, NULL);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, worldNormalTexture, 0);   
-    // world color texture
-    glGenTextures(1, &worldColorTexture);
-    glBindTexture(GL_TEXTURE_2D, worldColorTexture);
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, worldColorTexture, 0);  
-    // set color attachements for the worldFrameBuffer
-    GLuint attachments[3] = 
-    {
-        GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 
-    };
-    glDrawBuffers(3, attachments);
-    // world depth texture
-    glGenTextures(1, &worldDepthTexture);
-    glBindTexture(GL_TEXTURE_2D, worldDepthTexture);
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, width, height, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, worldDepthTexture, 0); 
-    // check if world framebuffer is okay
-    if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
-    {
-	cout << "world frame buffer is not complete!" << endl;
-    }
-    glBindFramebuffer(GL_FRAMEBUFFER, 0);
+    // update projection matrix
+    float tan = tanf((0.5f * fovY) * M_PI / 180.0f);
+    float q = 1.0f / tan;
+    float aspect = (float) width / height;
+
+    projMatrix.set(0, 0, q / aspect);
+    projMatrix.set(1, 1, q);
+    projMatrix.set(2, 2, (nearClip + farClip) / (nearClip - farClip));
+    projMatrix.set(3, 2, -1.0f);
+    projMatrix.set(2, 3, (2.0f * nearClip * farClip) / (nearClip - farClip));
+    projMatrix.set(3, 3, 0); 
     
-    // generate data for drawing previously generated framebuffer as rectangle
-    glGenVertexArrays(1, &postVba);
-    glBindVertexArray(postVba);
+    // -------------------------------------------------------------------------
+    // shader stage 1 - world
+    // -------------------------------------------------------------------------
+    worldShader.preRender(projMatrix.getValues());
+    // call render tick for further drawing
+    client->render3DTick(lag);
     
-    glGenBuffers(1, &postVbo);
-    glBindBuffer(GL_ARRAY_BUFFER, postVbo);
-
-    glVertexAttribPointer(0, 2, GL_FLOAT, 0, sizeof(float) * 4, (GLvoid*) 0);
-    glEnableVertexAttribArray(0);
-
-    glVertexAttribPointer(1, 2, GL_FLOAT, 0, sizeof(float) * 4, (GLvoid*) (sizeof(float) * 2));
-    glEnableVertexAttribArray(1);
+    // -------------------------------------------------------------------------
+    // shader stage 2 - world ssao
+    // -------------------------------------------------------------------------
+    ssaoShader.preRender(projMatrix.getValues());
+ 
+    // bind previously generated texture data buffers
+    worldShader.bindPositionTexture(1);
+    worldShader.bindNormalTexture(2);
+    worldShader.bindColorTexture(3);
+    worldShader.bindDepthTexture(4);
+    ssaoShader.bindNoiseTexture(5);
     
-    float data[] = 
-    {
-        -1.0f, 1.0f, 0.0f, 1.0f, 
-        -1.0f, -1.0f, 0.0f, 0.0f,
-        1.0f, -1.0f, 1.0f, 0.0f,
-        -1.0f, 1.0f, 0.0f, 1.0f,
-        1.0f, -1.0f, 1.0f, 0.0f,
-        1.0f, 1.0f, 1.0f, 1.0f
-    };
+    rectangle.draw();
     
-    glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 24, data, GL_STATIC_DRAW);
+    // -------------------------------------------------------------------------
+    // shader stage 3 - world ssao blur
+    // -------------------------------------------------------------------------
+    ssaoBlurShader.preRender();
+    ssaoShader.bindTexture(6);
+    rectangle.draw();
     
-    // generate ssao kernel data
-    glGenFramebuffers(1, &ssaoFrameBuffer);
-    glBindFramebuffer(GL_FRAMEBUFFER, ssaoFrameBuffer);
-    // ssao color texture
-    glGenTextures(1, &ssaoTexture);
-    glBindTexture(GL_TEXTURE_2D, ssaoTexture);
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width, height, 0, GL_RGB, GL_FLOAT, NULL);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ssaoTexture, 0);  
-    // check if world framebuffer is okay
-    if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
-    {
-	cout << "ssao frame buffer is not complete!" << endl;
-    }
-    glBindFramebuffer(GL_FRAMEBUFFER, 0);
+    // -------------------------------------------------------------------------
+    // shader stage 4 - world post
+    // -------------------------------------------------------------------------
+    worldPostShader.preRender();
+    ssaoBlurShader.bindTexture(7);
+    rectangle.draw();
     
-    std::uniform_real_distribution<float> randomF(0.0, 1.0); // random floats between 0.0 - 1.0
-    std::default_random_engine gen;
-    for(int i = 0; i < ssaoKernelAmount; i++)
-    {
-        ssaoKernel[i].set(randomF(gen) * 2.0 - 1.0, randomF(gen) * 2.0 - 1.0, randomF(gen));
-        ssaoKernel[i].normalize();
-        ssaoKernel[i].mul(randomF(gen));
-        
-        float scale = (float) i / ssaoKernelAmount; 
-        scale  = 0.1f + (scale * scale) * 0.9f;
-        ssaoKernel[i].mul(scale);
-        //cout << ssaoKernel[i] << endl;
-    }
+    // -------------------------------------------------------------------------
+    // shader stage 5 - 2D overlay
+    // -------------------------------------------------------------------------
     
-    float noise[48];
-    for(int i = 0; i < 16; i++)
-    {
-        noise[i * 3] = randomF(gen) * 2.0 - 1.0;
-        noise[i * 3 + 1] = randomF(gen) * 2.0 - 1.0;
-        noise[i * 3 + 2] = 0.0f;
-    }  
+    overlayShader.preRender();
+    worldPostShader.bindTexture(0);
+    rectangle.draw();
+    overlayShader.setViewMatrix();
     
-    glGenTextures(1, &noiseTexture);
-    glBindTexture(GL_TEXTURE_2D, noiseTexture);
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, 4, 4, 0, GL_RGB, GL_FLOAT, noise);
-    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_REPEAT);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 
+    overlayShader.setUseColor(true);
+    overlayShader.setUseTexture(true);
+    
+    glEnable(GL_BLEND);
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+    glBlendEquation(GL_FUNC_ADD);
+    client->render2DTick(lag);
+    glDisable(GL_BLEND);
 }
 
-void Engine::onRenderTick(float lag)
+void Engine::setWorldViewMatrix(const float* data)
 {
-    //--------------------------------------------------------------------------
-    // Stage 1: draw scene in world framebuffer
-    //--------------------------------------------------------------------------
-    glActiveTexture(GL_TEXTURE0);
-    
-    activeProgram = worldShader.getProgram();
-    glUseProgram(activeProgram);
-    
-    glBindFramebuffer(GL_FRAMEBUFFER, worldFrameBuffer);
-    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-    glEnable(GL_DEPTH_TEST);
-    if(lineMode)
-    {
-        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
-        Engine::client->renderTick(lag);
-        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
-    }
-    else
-    {
-        Engine::client->renderTick(lag);
-    }
-
-    //--------------------------------------------------------------------------
-    // Stage 2: draw textured framebuffer
-    //--------------------------------------------------------------------------
-    glActiveTexture(GL_TEXTURE1);
-    glBindTexture(GL_TEXTURE_2D, worldPositionTexture);
-    glActiveTexture(GL_TEXTURE2);
-    glBindTexture(GL_TEXTURE_2D, worldNormalTexture);
-    glActiveTexture(GL_TEXTURE3);
-    glBindTexture(GL_TEXTURE_2D, worldColorTexture);
-    glActiveTexture(GL_TEXTURE4);
-    glBindTexture(GL_TEXTURE_2D, worldDepthTexture);
-    glActiveTexture(GL_TEXTURE5);
-    glBindTexture(GL_TEXTURE_2D, noiseTexture);
-
-    activeProgram = ssaoShader.getProgram();
-    glUseProgram(activeProgram);
-    
-    for(int i = 0; i < ssaoKernelAmount; i++)
-    {
-        glUniform3f(glGetUniformLocation(activeProgram, (string("ssaoKernel[") + std::to_string(i) + "]").c_str()), 
-                ssaoKernel[i].getX(), ssaoKernel[i].getY(), ssaoKernel[i].getZ());
-    }
-    
-    Engine::setMatrix(glGetUniformLocation(activeProgram, "projMatrix"), testMat.getValues());
-
-    glBindFramebuffer(GL_FRAMEBUFFER, ssaoFrameBuffer);
-    glClear(GL_COLOR_BUFFER_BIT);
-    glDisable(GL_DEPTH_TEST);
-    glBindVertexArray(postVba);
-    glBindBuffer(GL_ARRAY_BUFFER, postVbo);
-    glDrawArrays(GL_TRIANGLES, 0, 6);
-    
-    glActiveTexture(GL_TEXTURE6);
-    glBindTexture(GL_TEXTURE_2D, ssaoTexture);
-    glBindFramebuffer(GL_FRAMEBUFFER, 0);
-    glClear(GL_COLOR_BUFFER_BIT);
-    activeProgram = postShader.getProgram();
-    glUseProgram(activeProgram);
-    glDrawArrays(GL_TRIANGLES, 0, 6);
+    worldShader.setViewMatrix(data);
 }
 
-void Engine::onTerm()
+void Engine::setWorldModelMatrix(const float* data)
 {
-    glDeleteVertexArrays(1, &postVba);
-    glDeleteBuffers(1, &postVbo);
-    
-    glDeleteFramebuffers(1, &worldFrameBuffer);
-    glDeleteTextures(1, &worldPositionTexture);
-    glDeleteTextures(1, &worldNormalTexture);
-    glDeleteTextures(1, &worldColorTexture);
-    glDeleteTextures(1, &worldDepthTexture);
+    worldShader.setModelMatrix(data);
 }
 
-void Engine::setLineMode(bool mode)
+void Engine::setOverlayModelMatrix(const float* data)
 {
-    lineMode = mode;
-}
+    overlayShader.setModelMatrix(data);
+}
+// 562

+ 42 - 52
engine/Wrapper.h

@@ -3,10 +3,16 @@
 
 #include <GL/glew.h>
 #include <GLFW/glfw3.h>
-#include "ShaderProgram.h"
+#include "shader/ShaderProgram.h"
 #include "../math/Vector3D.h"
 #include "../math/Matrix3D.h"
-
+#include "shader/WorldShader.h"
+#include "shader/SSAOShader.h"
+#include "shader/SSAOBlurShader.h"
+#include "shader/FramebufferRectangle.h"
+#include "shader/WorldPostShader.h"
+#include "shader/OverlayShader.h"
+#include "Mesh.h"
 #include <iostream>
 
 using namespace std;
@@ -15,7 +21,8 @@ class IClient
 {
 public:
     virtual void tick() = 0;
-    virtual void renderTick(float lag) = 0;
+    virtual void render3DTick(float lag) = 0;
+    virtual void render2DTick(float lag) = 0;
     virtual void onKeyEvent(int key, int scancode, int action, int mods) = 0;
     virtual void onMouseClick(int button, int action, int mods) = 0;
 };
@@ -26,7 +33,8 @@ public:
     static DummyClient dummy;
     
     void tick() override { cout << "Dummy tick" << endl; };
-    void renderTick(float lag) override { cout << "Dummy renderTick" << endl; };
+    void render3DTick(float lag) override { cout << "Dummy render3DTick" << endl; };
+    void render2DTick(float lag) override { cout << "Dummy render3DTick" << endl; };
     void onKeyEvent(int key, int scancode, int action, int mods) override { cout << "Dummy onKeyEvent" << endl; };
     void onMouseClick(int button, int action, int mods) override { cout << "Dummy onMouseClick" << endl; };
 private:
@@ -46,31 +54,21 @@ public:
     static int getWidth();
     static int getHeight();
     
-    static GLint getUniformLocation(const GLchar* name);
-    static void setMatrix(GLint location, const GLfloat* m);
-    static void setInt(GLint location, GLint i);
-    static void setFloat(GLint location, GLfloat f1, GLfloat f2, GLfloat f3, GLfloat f4);
-    
-    static void setLineMode(bool mode);
+    static float getFieldOfView();
+    static float getNearClip();
+    static float getFarClip();
     
-    static float testX;
-    static float testY;
-    static float testZ;
-    static Matrix3D testMat;
+    static void setWorldViewMatrix(const float* data);
+    static void setWorldModelMatrix(const float* data);
+    static void setOverlayModelMatrix(const float* data);
+
 private:
     static const uint64_t NANOS_PER_TICK = 50000000;
     static const int MAX_TICKS_PER_FRAME = 5;
     
-    static bool onProgramInit();
+    static bool initOverlayShader();   
     
-    static void onInit();
     static void onRenderTick(float lag);
-    static void onTerm();
-    
-    static GLchar* readFile(const char* name);
-    static bool checkShaderErrors(const char* name, GLuint shader);
-    static GLuint compileProgram(GLuint& vShader, GLuint& fShader, const GLchar* v, const GLchar* f);
-    static GLuint createProgram(const char* v, const char* f, GLuint& vShader, GLuint& fShader);
     
     static void onKeyEvent(GLFWwindow* w, int key, int scancode, int action, int mods);
     static void onMouseClick(GLFWwindow* w, int button, int action, int mods);
@@ -79,40 +77,32 @@ private:
     static void updateScale();
     
     static IClient* client;    
-    static GLFWwindow* window;   
-    
-    // active program
-    static GLuint activeProgram;
     
-    // world data
-    static ShaderProgram worldShader;
-    static GLuint worldFrameBuffer;
-    static GLuint worldPositionTexture;
-    static GLuint worldNormalTexture;
-    static GLuint worldColorTexture;
-    static GLuint worldDepthTexture;
-    
-    // ssao shader
-    static ShaderProgram ssaoShader;
-    static GLuint ssaoFrameBuffer;
-    static GLuint ssaoTexture;
-    
-    // post shader
-    static GLuint postVba;
-    static GLuint postVbo;
-    static ShaderProgram postShader;
-
+    // window data
+    static GLFWwindow* window;  
     static int scale;
     static int width;
     static int height;
     
-    static bool lineMode;
-    
-    // ssao kernel data
-    static constexpr int ssaoKernelAmount = 64;
-    static Vector3D ssaoKernel[ssaoKernelAmount];
-    static GLuint noiseTexture;
+    // projection data
+    static float fovY;
+    static float nearClip;
+    static float farClip;
+    static Matrix3D projMatrix;
+    
+    // rectangle for framebuffer drawing
+    static FramebufferRectangle rectangle;
+    
+    // shader stage 1 - world
+    static WorldShader worldShader;
+    // shader stage 2 - world ssao
+    static SSAOShader ssaoShader;
+    // shader stage 3 - world ssao blur
+    static SSAOBlurShader ssaoBlurShader;
+    // shader stage 4 - world post
+    static WorldPostShader worldPostShader;
+    // shader stage 5 - 2D overlay
+    static OverlayShader overlayShader;
 };
 
-#endif
-
+#endif

+ 51 - 0
engine/shader/FramebufferRectangle.cpp

@@ -0,0 +1,51 @@
+#include "FramebufferRectangle.h"
+#include "../Wrapper.h"
+
+FramebufferRectangle::FramebufferRectangle()
+{
+}
+
+FramebufferRectangle::~FramebufferRectangle()
+{
+    glDeleteVertexArrays(1, &vba);
+    glDeleteBuffers(1, &vbo);
+}
+
+bool FramebufferRectangle::init()
+{
+    glGenVertexArrays(1, &vba);
+    glBindVertexArray(vba);
+    
+    glGenBuffers(1, &vbo);
+    glBindBuffer(GL_ARRAY_BUFFER, vbo);
+
+    glVertexAttribPointer(0, 2, GL_FLOAT, 0, sizeof(float) * 4, (GLvoid*) 0);
+    glEnableVertexAttribArray(0);
+
+    glVertexAttribPointer(2, 2, GL_FLOAT, 0, sizeof(float) * 4, (GLvoid*) (sizeof(float) * 2));
+    glEnableVertexAttribArray(2);
+    
+    Engine::printError();
+    
+    float data[] = 
+    {
+        -1.0f, 1.0f, 0.0f, 1.0f, 
+        -1.0f, -1.0f, 0.0f, 0.0f,
+        1.0f, -1.0f, 1.0f, 0.0f,
+        -1.0f, 1.0f, 0.0f, 1.0f,
+        1.0f, -1.0f, 1.0f, 0.0f,
+        1.0f, 1.0f, 1.0f, 1.0f
+    };
+    
+    glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 24, data, GL_STATIC_DRAW);
+    
+    return true;
+}
+
+void FramebufferRectangle::draw()
+{
+    glBindVertexArray(vba);
+    glBindBuffer(GL_ARRAY_BUFFER, vbo);
+    glDrawArrays(GL_TRIANGLES, 0, 6);
+}
+

+ 21 - 0
engine/shader/FramebufferRectangle.h

@@ -0,0 +1,21 @@
+#ifndef FRAMEBUFFERRECTANGLE_H
+#define FRAMEBUFFERRECTANGLE_H
+
+#include <GL/glew.h>
+#include <GLFW/glfw3.h>
+
+class FramebufferRectangle
+{
+public:
+    FramebufferRectangle();
+    virtual ~FramebufferRectangle();
+    
+    bool init();
+    void draw();
+private:
+    GLuint vba;
+    GLuint vbo;
+};
+
+#endif
+

+ 91 - 0
engine/shader/OverlayShader.cpp

@@ -0,0 +1,91 @@
+#include "OverlayShader.h"
+#include "../Wrapper.h"
+
+OverlayShader::OverlayShader()
+{
+}
+
+OverlayShader::~OverlayShader()
+{
+}
+
+bool OverlayShader::init()
+{
+    program.compile("shader/overlayVertex.vs", "shader/overlayFragment.fs");
+    if(!program.isValid())
+    {
+        return false;
+    } 
+    
+    // get uniform locations
+    unifUseTexture = glGetUniformLocation(program.getProgram(), "useTexture");
+    unifUseColor = glGetUniformLocation(program.getProgram(), "useColor");
+    unifViewMatrix = glGetUniformLocation(program.getProgram(), "viewMatrix");
+    unifModelMatrix = glGetUniformLocation(program.getProgram(), "modelMatrix");
+
+    return true;
+}
+
+void OverlayShader::preRender()
+{
+    // bind overlay shader program
+    glUseProgram(program.getProgram());
+    
+    // reset view and model matrix
+    view.setToIdentity();
+    glUniformMatrix4fv(unifViewMatrix, 1, 0, view.getValues());
+    glUniformMatrix4fv(unifModelMatrix, 1, 0, view.getValues());
+    
+    // set defaults
+    setUseTexture(true);
+    setUseColor(false);
+    
+    // reset to default framebuffer
+    glBindFramebuffer(GL_FRAMEBUFFER, 0);
+    
+    // clear color buffer
+    glClear(GL_COLOR_BUFFER_BIT);
+    
+    // depth testing is not needed
+    glDisable(GL_DEPTH_TEST);
+}
+
+void OverlayShader::setViewMatrix()
+{
+    view.set(0, 0, (2.0f * Engine::getScale()) / Engine::getWidth());
+    view.set(0, 1, 0.0f);
+    view.set(0, 2, 0.0f);
+    view.set(0, 3, -1.0f);
+    
+    view.set(1, 0, 0.0f);
+    view.set(1, 1, (-2.0f * Engine::getScale()) / Engine::getHeight());
+    view.set(1, 2, 0.0f);
+    view.set(1, 3, 1.0f);
+    
+    view.set(2, 0, 0.0f);
+    view.set(2, 1, 0.0f);
+    view.set(2, 2, (-1.0f * Engine::getScale()) / Engine::getHeight());
+    view.set(2, 3, 0.5f);
+    
+    view.set(3, 0, 0.0f);
+    view.set(3, 1, 0.0f);
+    view.set(3, 0, 0.0f);
+    view.set(3, 3, 1.0f);
+    
+    glUniformMatrix4fv(unifViewMatrix, 1, 0, view.getValues());
+}
+
+void OverlayShader::setModelMatrix(const float* data)
+{
+    glUniformMatrix4fv(unifModelMatrix, 1, 0, data);
+}
+
+void OverlayShader::setUseTexture(bool use)
+{
+    glUniform1i(unifUseTexture, use);
+}
+
+void OverlayShader::setUseColor(bool use)
+{
+    glUniform1i(unifUseColor, use);
+}

+ 34 - 0
engine/shader/OverlayShader.h

@@ -0,0 +1,34 @@
+#ifndef OVERLAYSHADER_H
+#define OVERLAYSHADER_H
+
+#include "ShaderProgram.h"
+#include "../../math/Matrix3D.h"
+
+class OverlayShader
+{
+public:
+    OverlayShader();
+    virtual ~OverlayShader();
+    
+    bool init();
+    
+    void preRender();
+
+    void setViewMatrix();
+    void setModelMatrix(const float* data);
+    void setUseTexture(bool use);
+    void setUseColor(bool use);
+    
+private:
+    // shader
+    ShaderProgram program;
+    // uniform data
+    Matrix3D view;
+    // uniforms locations
+    GLint unifUseTexture = 0;
+    GLint unifUseColor = 0;
+    GLint unifViewMatrix = 0;
+    GLint unifModelMatrix = 0;
+};
+
+#endif

+ 73 - 0
engine/shader/SSAOBlurShader.cpp

@@ -0,0 +1,73 @@
+#include "SSAOBlurShader.h"
+#include "../Wrapper.h"
+
+SSAOBlurShader::SSAOBlurShader()
+{
+}
+
+SSAOBlurShader::~SSAOBlurShader()
+{
+    glDeleteFramebuffers(1, &framebuffer);
+    glDeleteTextures(1, &texture);
+}
+
+bool SSAOBlurShader::init()
+{
+    program.compile("shader/ssaoBlurVertex.vs", "shader/ssaoBlurFragment.fs");
+    if(!program.isValid())
+    {
+        return false;
+    }
+    
+    // generate framebuffer
+    glGenFramebuffers(1, &framebuffer);
+    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
+    
+    // color texture
+    glGenTextures(1, &texture);
+    glBindTexture(GL_TEXTURE_2D, texture);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, Engine::getWidth(), Engine::getHeight(), 0, GL_RGB, GL_FLOAT, NULL);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    // attache color texture to framebuffer
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);  
+    
+    // check if framebuffer is okay
+    if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+    {
+	cout << "ssao blur frame buffer is not complete!" << endl;
+        return false;
+    }
+    // unbind framebuffer
+    glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+    return true;
+}
+
+void SSAOBlurShader::resize()
+{
+    glBindTexture(GL_TEXTURE_2D, texture);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, Engine::getWidth(), Engine::getHeight(), 0, GL_RGB, GL_FLOAT, NULL);
+}
+
+void SSAOBlurShader::preRender()
+{
+    // bind ssao blur shader program
+    glUseProgram(program.getProgram());
+    
+    // bind ssao blur framebuffer
+    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
+    //glBindFramebuffer(GL_FRAMEBUFFER, 0);
+    
+    // clear color buffer
+    glClear(GL_COLOR_BUFFER_BIT);
+    
+    // depth testing is not needed
+    glDisable(GL_DEPTH_TEST);
+}
+
+void SSAOBlurShader::bindTexture(unsigned int textureUnit)
+{
+    glActiveTexture(GL_TEXTURE0 + textureUnit);
+    glBindTexture(GL_TEXTURE_2D, texture);
+}

+ 29 - 0
engine/shader/SSAOBlurShader.h

@@ -0,0 +1,29 @@
+#ifndef SSAOBLURSHADER_H
+#define SSAOBLURSHADER_H
+
+#include "ShaderProgram.h"
+
+class SSAOBlurShader
+{
+public:
+    SSAOBlurShader();
+    virtual ~SSAOBlurShader();
+    
+    bool init();
+    void resize();
+
+    void preRender();
+    
+    void bindTexture(unsigned int textureUnit);
+    
+private:
+    // shader
+    ShaderProgram program;
+    // framebuffer
+    GLuint framebuffer = 0;
+    // textures
+    GLuint texture = 0;
+};
+
+#endif
+

+ 135 - 0
engine/shader/SSAOShader.cpp

@@ -0,0 +1,135 @@
+#include "SSAOShader.h"
+#include "../Wrapper.h"
+#include <random>
+
+SSAOShader::SSAOShader()
+{
+}
+
+SSAOShader::~SSAOShader()
+{
+    glDeleteFramebuffers(1, &framebuffer);
+    glDeleteTextures(1, &texture);
+    glDeleteTextures(1, &noiseTexture);
+}
+
+bool SSAOShader::init()
+{
+    program.compile("shader/ssaoVertex.vs", "shader/ssaoFragment.fs");
+    if(!program.isValid())
+    {
+        return false;
+    }
+    
+    // generate framebuffer
+    glGenFramebuffers(1, &framebuffer);
+    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
+    
+    // color texture
+    glGenTextures(1, &texture);
+    glBindTexture(GL_TEXTURE_2D, texture);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, Engine::getWidth(), Engine::getHeight(), 0, GL_RGB, GL_FLOAT, NULL);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    // attache color texture to framebuffer
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);  
+    
+    // check if framebuffer is okay
+    if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+    {
+	cout << "ssao frame buffer is not complete!" << endl;
+        return false;
+    }
+    // unbind framebuffer
+    glBindFramebuffer(GL_FRAMEBUFFER, 0);
+    
+    // generate noise data
+    std::uniform_real_distribution<float> randomF(0.0, 1.0);
+    std::default_random_engine gen;
+    float noise[48];
+    for(int i = 0; i < 16; i++)
+    {
+        noise[i * 3] = randomF(gen) * 2.0 - 1.0;
+        noise[i * 3 + 1] = randomF(gen) * 2.0 - 1.0;
+        noise[i * 3 + 2] = 0.0f;
+    }  
+    
+    // noise texture
+    glGenTextures(1, &noiseTexture);
+    glBindTexture(GL_TEXTURE_2D, noiseTexture);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, 4, 4, 0, GL_RGB, GL_FLOAT, noise);
+    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_REPEAT);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 
+    
+    // get uniform locations
+    unifProjMatrix = glGetUniformLocation(program.getProgram(), "projMatrix");
+    unifNumberOfSamples = glGetUniformLocation(program.getProgram(), "numberOfSamples");
+    unifRadius = glGetUniformLocation(program.getProgram(), "radius");
+    unifWidth = glGetUniformLocation(program.getProgram(), "width");
+    unifHeight = glGetUniformLocation(program.getProgram(), "height");
+    
+    return true;
+}
+
+void SSAOShader::resize()
+{
+    glBindTexture(GL_TEXTURE_2D, texture);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, Engine::getWidth(), Engine::getHeight(), 0, GL_RGB, GL_FLOAT, NULL);
+}
+
+void SSAOShader::preRender(const float* projMatrix)
+{
+    // bind ssao shader program
+    glUseProgram(program.getProgram());
+    
+    // set projection matrix uniform
+    glUniformMatrix4fv(unifProjMatrix, 1, 0, projMatrix);
+    // set other uniforms
+    glUniform1i(unifNumberOfSamples, numberOfSamples);
+    glUniform1f(unifRadius, radius);
+    glUniform1i(unifWidth, Engine::getWidth());
+    glUniform1i(unifHeight, Engine::getHeight());
+    
+    // bind ssao framebuffer
+    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
+    
+    // clear color buffer
+    glClear(GL_COLOR_BUFFER_BIT);
+    
+    // depth testing is not needed
+    glDisable(GL_DEPTH_TEST);
+}
+
+void SSAOShader::bindTexture(unsigned int textureUnit)
+{
+    glActiveTexture(GL_TEXTURE0 + textureUnit);
+    glBindTexture(GL_TEXTURE_2D, texture);
+}
+
+void SSAOShader::bindNoiseTexture(unsigned int textureUnit)
+{
+    glActiveTexture(GL_TEXTURE0 + textureUnit);
+    glBindTexture(GL_TEXTURE_2D, noiseTexture);
+}
+
+void SSAOShader::setNumberOfSamples(int amount)
+{
+    numberOfSamples = min(max(amount, 0), 64);
+}
+
+int SSAOShader::getNumberOfSamples() const
+{
+    return numberOfSamples;
+}
+
+void SSAOShader::setSampleRadius(float sampleRadius)
+{
+    numberOfSamples = min(max(sampleRadius, 0.05f), 20.0f);
+}
+
+float SSAOShader::getSampleRadius() const
+{
+    return radius;
+}

+ 45 - 0
engine/shader/SSAOShader.h

@@ -0,0 +1,45 @@
+#ifndef SSAOSHADER_H
+#define SSAOSHADER_H
+
+#include "ShaderProgram.h"
+
+class SSAOShader
+{
+public:
+    SSAOShader();
+    virtual ~SSAOShader();
+    
+    bool init();
+    void resize();
+
+    void preRender(const float* projMatrix);
+    
+    void bindTexture(unsigned int textureUnit);
+    void bindNoiseTexture(unsigned int textureUnit);
+    
+    void setNumberOfSamples(int amount);
+    int getNumberOfSamples() const;
+    void setSampleRadius(float sampleRadius);
+    float getSampleRadius() const;
+    
+private:
+    // shader
+    ShaderProgram program;
+    // framebuffer
+    GLuint framebuffer = 0;
+    // textures
+    GLuint texture = 0;
+    GLuint noiseTexture = 0;
+    // uniform data
+    int numberOfSamples = 48;
+    float radius = 1.5f;
+    // uniforms locations
+    GLint unifProjMatrix = 0;
+    GLint unifNumberOfSamples = 0;
+    GLint unifRadius = 0;
+    GLint unifWidth = 0;
+    GLint unifHeight = 0;
+};
+
+#endif
+

+ 21 - 28
engine/ShaderProgram.cpp → engine/shader/ShaderProgram.cpp

@@ -8,26 +8,17 @@ ShaderProgram::ShaderProgram()
 
 ShaderProgram::~ShaderProgram()
 {
-    if(vertexShader != 0)
-    {
-        glDeleteShader(vertexShader);
-    }
-    if(fragmentShader != 0)
-    {
-        glDeleteShader(fragmentShader);
-    }
-    if(program != 0)
-    {
-        glDeleteProgram(program);
-    }
+    glDeleteShader(vertexShader);
+    glDeleteShader(fragmentShader);
+    glDeleteProgram(program);
 }
 
-bool ShaderProgram::isValid()
+bool ShaderProgram::isValid() const
 {
     return valid;
 }
 
-GLuint ShaderProgram::getProgram()
+GLuint ShaderProgram::getProgram() const
 {
     return program;
 }
@@ -99,27 +90,28 @@ bool ShaderProgram::checkShaderErrors(const GLchar* name, GLuint shader)
 {
     bool returnValue = false;
     
-    cout << "compiling " << name << " shader ..." << endl;
+    //cout << "compiling " << name << " shader ..." << endl;
     GLenum error = glGetError();
     if(error)
     {
+        cout << "compiling of " << name << " failed" << endl;
         cout << "error: " << glGetError() << endl;
         returnValue = true;
     }
-    else
-    {
-        cout << "no error occured ..." << endl;
-    }
+    //else
+    //{
+    //    cout << "no error occured ..." << endl;
+    //}
     
     GLint compiled[1];
     glGetShaderiv(shader, GL_COMPILE_STATUS, compiled);
     if(compiled[0])
     {
-        cout << name << " shader successfully compiled" << endl;
+        //cout << name << " shader successfully compiled" << endl;
     }
     else
     {
-        cout << name << "compiling of " << name << " failed:" << endl;
+        cout << "compiling of " << name << " failed:" << endl;
         GLchar buffer[512];
         GLsizei bufferSize = 512;
         GLsizei charsUsed = 0;
@@ -157,28 +149,29 @@ void ShaderProgram::compile(const GLchar* vertexPath, const GLchar* vertexData,
     glAttachShader(program, fragmentShader);
     glLinkProgram(program);
     
-    cout << "linking shaders to program ..." << endl;
+    //cout << "linking shaders to program ..." << endl;
 
     GLenum error = glGetError();
     if(error)
     {
+        cout << "linking of " << vertexPath << " and " << fragmentPath << " failed" << endl;
         cout << "error: " << glGetError() << endl;
         return;
     }
-    else
-    {
-        cout << "no error occured ..." << endl;
-    }
+    //else
+    //{
+    //    cout << "no error occured ..." << endl;
+    //}
 
     GLint compiled[1];
     glGetProgramiv(program, GL_LINK_STATUS, compiled);
     if(compiled[0])
     {
-        cout << "shaders successfully linked" << endl;
+        //cout << "shaders successfully linked" << endl;
     }
     else
     {
-        cout << "linking of shaders failed:" << endl;
+        cout << "linking of " << vertexPath << " and " << fragmentPath << " failed:" << endl;
         GLchar buffer[512];
         GLsizei bufferSize = 512;
         GLsizei charsUsed = 0;

+ 2 - 2
engine/ShaderProgram.h → engine/shader/ShaderProgram.h

@@ -14,8 +14,8 @@ public:
     virtual ~ShaderProgram();
     
     void compile(const GLchar* vertexPath, const GLchar* fragmentPath);
-    bool isValid();
-    GLuint getProgram();
+    bool isValid() const;
+    GLuint getProgram() const;
 private:
     GLchar* readFile(const GLchar* name);
     bool checkShaderErrors(const GLchar* name, GLuint shader);

+ 72 - 0
engine/shader/WorldPostShader.cpp

@@ -0,0 +1,72 @@
+#include "WorldPostShader.h"
+#include "../Wrapper.h"
+
+WorldPostShader::WorldPostShader()
+{
+}
+
+WorldPostShader::~WorldPostShader()
+{
+    glDeleteFramebuffers(1, &framebuffer);
+    glDeleteTextures(1, &texture);
+}
+
+bool WorldPostShader::init()
+{
+    program.compile("shader/worldPostVertex.vs", "shader/worldPostFragment.fs");
+    if(!program.isValid())
+    {
+        return false;
+    }
+    
+    // generate framebuffer
+    glGenFramebuffers(1, &framebuffer);
+    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
+    
+    // color texture
+    glGenTextures(1, &texture);
+    glBindTexture(GL_TEXTURE_2D, texture);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Engine::getWidth(), Engine::getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    // attache color texture to framebuffer
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);  
+    
+    // check if framebuffer is okay
+    if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+    {
+	cout << "world post frame buffer is not complete!" << endl;
+        return false;
+    }
+    // unbind framebuffer
+    glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+    return true;
+}
+
+void WorldPostShader::resize()
+{
+    glBindTexture(GL_TEXTURE_2D, texture);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Engine::getWidth(), Engine::getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+}
+
+void WorldPostShader::preRender()
+{
+    // bind ssao shader program
+    glUseProgram(program.getProgram());
+    
+    // bind ssao framebuffer
+    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
+    
+    // clear color buffer
+    glClear(GL_COLOR_BUFFER_BIT);
+    
+    // depth testing is not needed
+    glDisable(GL_DEPTH_TEST);
+}
+
+void WorldPostShader::bindTexture(unsigned int textureUnit)
+{
+    glActiveTexture(GL_TEXTURE0 + textureUnit);
+    glBindTexture(GL_TEXTURE_2D, texture);
+}

+ 31 - 0
engine/shader/WorldPostShader.h

@@ -0,0 +1,31 @@
+#ifndef WORLDPOSTSHADER_H
+#define WORLDPOSTSHADER_H
+
+#include "ShaderProgram.h"
+
+class WorldPostShader
+{
+public:
+    WorldPostShader();
+    virtual ~WorldPostShader();
+    
+    bool init();
+    void resize();
+
+    void preRender();
+    
+    void bindTexture(unsigned int textureUnit);
+    
+private:
+    // shader
+    ShaderProgram program;
+    // framebuffer
+    GLuint framebuffer = 0;
+    // textures
+    GLuint texture = 0;
+};
+
+#endif
+
+
+

+ 159 - 0
engine/shader/WorldShader.cpp

@@ -0,0 +1,159 @@
+#include "WorldShader.h"
+#include "../Wrapper.h"
+
+WorldShader::WorldShader()
+{
+}
+
+WorldShader::~WorldShader()
+{
+    glDeleteFramebuffers(1, &framebuffer);
+    glDeleteTextures(1, &positionTexture);
+    glDeleteTextures(1, &normalTexture);
+    glDeleteTextures(1, &colorTexture);
+    glDeleteTextures(1, &depthTexture);
+}
+
+bool WorldShader::init()
+{
+    program.compile("shader/worldVertex.vs", "shader/worldFragment.fs");
+    if(!program.isValid())
+    {
+        return false;
+    }
+    
+    // generate framebuffer
+    glGenFramebuffers(1, &framebuffer);
+    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
+    
+    // position texture
+    glGenTextures(1, &positionTexture);
+    glBindTexture(GL_TEXTURE_2D, positionTexture);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, Engine::getWidth(), Engine::getHeight(), 0, GL_RGB, GL_FLOAT, NULL);
+    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);
+    // attache position texture to framebuffer
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, positionTexture, 0);   
+    
+    // normal texture
+    glGenTextures(1, &normalTexture);
+    glBindTexture(GL_TEXTURE_2D, normalTexture);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, Engine::getWidth(), Engine::getHeight(), 0, GL_RGB, GL_FLOAT, NULL);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    // attache normal texture to framebuffer
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, normalTexture, 0);   
+    
+    // color texture
+    glGenTextures(1, &colorTexture);
+    glBindTexture(GL_TEXTURE_2D, colorTexture);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Engine::getWidth(), Engine::getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    // attache color texture to framebuffer
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, colorTexture, 0);  
+    
+    // depth texture
+    glGenTextures(1, &depthTexture);
+    glBindTexture(GL_TEXTURE_2D, depthTexture);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, Engine::getWidth(), Engine::getHeight(), 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    // attache depth texture to framebuffer
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0); 
+    
+    // set color attachements for the framebuffer
+    GLuint attachments[3] = 
+    {
+        GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 
+    };
+    glDrawBuffers(3, attachments);   
+    
+    // check if framebuffer is okay
+    if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+    {
+	cout << "world frame buffer is not complete!" << endl;
+        return false;
+    }
+    // unbind framebuffer
+    glBindFramebuffer(GL_FRAMEBUFFER, 0);
+    
+    // get uniform locations
+    unifProjMatrix = glGetUniformLocation(program.getProgram(), "projMatrix");
+    unifViewMatrix = glGetUniformLocation(program.getProgram(), "viewMatrix");
+    unifModelMatrix = glGetUniformLocation(program.getProgram(), "modelMatrix");
+    
+    return true;
+}
+
+void WorldShader::resize()
+{
+    glBindTexture(GL_TEXTURE_2D, positionTexture);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, Engine::getWidth(), Engine::getHeight(), 0, GL_RGB, GL_FLOAT, NULL);
+   
+    glBindTexture(GL_TEXTURE_2D, normalTexture);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, Engine::getWidth(), Engine::getHeight(), 0, GL_RGB, GL_FLOAT, NULL);
+ 
+    glBindTexture(GL_TEXTURE_2D, colorTexture);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Engine::getWidth(), Engine::getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ 
+    glBindTexture(GL_TEXTURE_2D, depthTexture);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, Engine::getWidth(), Engine::getHeight(), 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL);
+}
+
+void WorldShader::preRender(const float* projMatrix)
+{
+    // bind world shader program
+    glUseProgram(program.getProgram());
+    
+    // set projection matrix uniform
+    glUniformMatrix4fv(unifProjMatrix, 1, 0, projMatrix);
+
+    // all textures bind to texture unit 0
+    glActiveTexture(GL_TEXTURE0);
+    
+    // bind world framebuffer
+    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
+    
+    // clear color, depth and stencil buffer
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+    
+    // depth testing is needed
+    glEnable(GL_DEPTH_TEST);
+}
+
+void WorldShader::bindPositionTexture(unsigned int textureUnit)
+{
+    glActiveTexture(GL_TEXTURE0 + textureUnit);
+    glBindTexture(GL_TEXTURE_2D, positionTexture);
+}
+
+void WorldShader::bindNormalTexture(unsigned int textureUnit)
+{
+    glActiveTexture(GL_TEXTURE0 + textureUnit);
+    glBindTexture(GL_TEXTURE_2D, normalTexture);
+}
+
+void WorldShader::bindColorTexture(unsigned int textureUnit)
+{
+    glActiveTexture(GL_TEXTURE0 + textureUnit);
+    glBindTexture(GL_TEXTURE_2D, colorTexture);
+}
+
+void WorldShader::bindDepthTexture(unsigned int textureUnit)
+{
+    glActiveTexture(GL_TEXTURE0 + textureUnit);
+    glBindTexture(GL_TEXTURE_2D, depthTexture);
+}
+
+void WorldShader::setViewMatrix(const float* data)
+{
+    glUniformMatrix4fv(unifViewMatrix, 1, 0, data);
+}
+
+void WorldShader::setModelMatrix(const float* data)
+{
+    glUniformMatrix4fv(unifModelMatrix, 1, 0, data);
+}

+ 42 - 0
engine/shader/WorldShader.h

@@ -0,0 +1,42 @@
+#ifndef WORLDSHADER_H
+#define WORLDSHADER_H
+
+#include "ShaderProgram.h"
+
+class WorldShader
+{
+public:
+    WorldShader();
+    virtual ~WorldShader();
+    
+    bool init();
+    void resize();
+
+    void preRender(const float* projMatrix);
+    
+    void bindPositionTexture(unsigned int textureUnit);
+    void bindNormalTexture(unsigned int textureUnit);
+    void bindColorTexture(unsigned int textureUnit);
+    void bindDepthTexture(unsigned int textureUnit);
+    
+    void setViewMatrix(const float* data);
+    void setModelMatrix(const float* data);
+    
+private:
+    // shader
+    ShaderProgram program;
+    // framebuffer
+    GLuint framebuffer = 0;
+    // textures
+    GLuint positionTexture = 0;
+    GLuint normalTexture = 0;
+    GLuint colorTexture = 0;
+    GLuint depthTexture = 0;
+    // uniforms locations
+    GLint unifProjMatrix = 0;
+    GLint unifViewMatrix = 0;
+    GLint unifModelMatrix = 0;
+};
+
+#endif
+

+ 226 - 0
math/Camera3D.cpp

@@ -0,0 +1,226 @@
+#include "Camera3D.h"
+#include "../engine/Wrapper.h"
+#include <cmath>
+#include "../engine/Utils.h"
+
+Camera3D::Camera3D()
+{
+}
+
+Camera3D::~Camera3D()
+{
+}
+
+const Vector3D& Camera3D::getFlatFront() const
+{
+    return flatFront;
+}
+
+const Vector3D& Camera3D::getFlatBack() const
+{
+    return flatBack;
+}
+
+const Vector3D& Camera3D::getFlatRight() const
+{
+    return flatRight;
+}
+
+const Vector3D& Camera3D::getFlatLeft() const
+{
+    return flatLeft;
+}
+
+const Vector3D& Camera3D::getFlatUp() const
+{
+    return flatUp;
+}
+
+const Vector3D& Camera3D::getFlatDown() const
+{
+    return flatDown;
+}
+
+void Camera3D::storePosition()
+{
+    oldCamera.set(camera);
+    oldLengthAngle = lengthAngle;
+    oldWidthAngle = widthAngle;
+}
+
+void Camera3D::setPosition(float x, float y, float z, float length, float width)
+{
+    camera.set(x, y, z);
+    lengthAngle = length;
+    widthAngle = width;
+}
+
+void Camera3D::update(float lag)
+{
+    // -------------------------------------------------------------------------
+    // calculate vectors for the view matrix
+    // -------------------------------------------------------------------------
+    
+    // front
+    front.setAngles(interpolate(lag, oldLengthAngle, lengthAngle), interpolate(lag, oldWidthAngle, widthAngle));
+
+    // back
+    back.setInverse(front);
+
+    // right
+    right.set(front);
+    right.cross(0.0f, 1.0f, 0.0f);
+    right.normalize();
+    
+    // left
+    left.setInverse(right);
+    
+    // up
+    up.set(front);
+    up.cross(left);
+    up.normalize();
+    
+    // down
+    down.setInverse(up);
+    
+    Vector3D interCamera = oldCamera;
+    interCamera.addMul(camera, lag);
+    interCamera.addMul(oldCamera, -lag);
+    
+    view.set(0, 0, right.getX());
+    view.set(0, 1, right.getY());
+    view.set(0, 2, right.getZ());
+    view.set(0, 3, right.dotInverse(interCamera));
+    
+    view.set(1, 0, up.getX());
+    view.set(1, 1, up.getY());
+    view.set(1, 2, up.getZ());
+    view.set(1, 3, up.dotInverse(interCamera));
+    
+    view.set(2, 0, back.getX());
+    view.set(2, 1, back.getY());
+    view.set(2, 2, back.getZ());
+    view.set(2, 3, back.dotInverse(interCamera));
+    
+    view.set(3, 0, 0.0f);
+    view.set(3, 1, 0.0f);
+    view.set(3, 0, 0.0f);
+    view.set(3, 3, 1.0f);
+   
+    // -------------------------------------------------------------------------
+    // calculate flat vectors for movement
+    // -------------------------------------------------------------------------
+    
+    // front
+    flatFront.set(front);
+    flatFront.setY(0.0f);
+    flatFront.normalize();
+    
+    // back
+    flatBack.setInverse(flatFront);
+
+    // right
+    flatRight.set(flatFront);
+    flatRight.cross(0.0f, 1.0f, 0.0f);
+    flatRight.normalize();
+    
+    // left
+    flatLeft.setInverse(flatRight);
+
+    // up
+    flatUp.set(0.0f, 1.0f, 0.0f);
+    
+    // down
+    flatDown.setInverse(flatUp);
+    
+    // -------------------------------------------------------------------------
+    // update frustum planes
+    // -------------------------------------------------------------------------
+    
+    // http://cgvr.informatik.uni-bremen.de/teaching/cg_literatur/lighthouse3d_view_frustum_culling/index.html
+    float tan = tanf((0.5f * Engine::getFieldOfView()) * M_PI / 180.0f);
+    float aspect = (float) Engine::getWidth() / Engine::getHeight();
+    
+    float nearHigh = tan * Engine::getNearClip();
+    float nearWidth = nearHigh * aspect;
+
+    float farHigh = tan * Engine::getFarClip();
+    float farWidth = farHigh * aspect;
+
+    Vector3D fc = interCamera;
+    fc.addMul(front, Engine::getFarClip());
+
+    Vector3D ftl = fc;
+    ftl.addMul(left, farWidth);
+    ftl.addMul(up, farHigh);
+
+    Vector3D fbl = fc;
+    fbl.addMul(left, farWidth);
+    fbl.addMul(down, farHigh);
+
+    Vector3D fbr = fc;
+    fbr.addMul(right, farWidth);
+    fbr.addMul(down, farHigh);
+
+    Vector3D nc = interCamera;
+    nc.addMul(front, Engine::getNearClip());
+
+    Vector3D ntl = nc;
+    ntl.addMul(left, nearWidth);
+    ntl.addMul(down, nearHigh);
+
+    Vector3D ntr = nc;
+    ntr.addMul(right, nearWidth);
+    ntr.addMul(up, nearHigh);
+
+    Vector3D nbr = nc;
+    nbr.addMul(right, nearWidth);
+    nbr.addMul(down, nearHigh);
+
+    // generating planes with counter clockwise vector order
+    frustumPlanes[0].set(fbl, ftl, fbr); // far
+    frustumPlanes[1].set(ntl, ftl, fbl); // left
+    frustumPlanes[2].set(fbr, ntr, nbr); // right
+    frustumPlanes[3].set(fbl, fbr, nbr); // bottom
+    frustumPlanes[4].set(ntr, ftl, ntl); // top
+    frustumPlanes[5].set(nbr, ntr, ntl); // near
+}
+
+const float* Camera3D::getViewMatrix()
+{
+    return view.getValues();
+}
+
+bool Camera3D::isInFrustum(float x, float y, float z, float x2, float y2, float z2) const
+{
+    //return true;
+    // http://cgvr.informatik.uni-bremen.de/teaching/cg_literatur/lighthouse3d_view_frustum_culling/index.html
+    // for each plane do ...
+    for(int fp = 0; fp < 6; fp++) 
+    {
+        // reset counters for corners in and out
+        int out = 0;
+        int in = 0;
+        // for each corner of the box do ...
+        // get out of the cycle as soon as a box as corners
+        // both inside and out of the frustum
+        for(int i = 0; i < 8 && (in == 0 || out == 0); i++) 
+        {
+            // is the corner outside or inside
+            if(frustumPlanes[fp].getSignedDistance(((i >> 2) & 1) ? x : x2, ((i >> 1) & 1) ? y : y2, (i & 1) ? z : z2) > 0)
+            {
+                out++;
+            }
+            else
+            {
+                in++;
+            }
+        }
+        //if all corners are out
+        if(in == 0)
+        {
+            return false;
+        }
+    }
+    return true;
+}

+ 56 - 0
math/Camera3D.h

@@ -0,0 +1,56 @@
+#ifndef CAMERA3D_H
+#define CAMERA3D_H
+
+#include "Vector3D.h"
+#include "Matrix3D.h"
+#include "Plane3D.h"
+
+class Camera3D
+{
+public:
+    Camera3D();
+    virtual ~Camera3D();
+    
+    bool isInFrustum(float x, float y, float z, float x2, float y2, float z2) const;
+    
+    void storePosition();
+    void setPosition(float x, float y, float z, float length, float width);
+    
+    const Vector3D& getFlatFront() const;
+    const Vector3D& getFlatBack() const;
+    const Vector3D& getFlatRight() const;
+    const Vector3D& getFlatLeft() const;
+    const Vector3D& getFlatUp() const;
+    const Vector3D& getFlatDown() const;
+    
+    void update(float lag);
+    const float* getViewMatrix();
+private:
+    Vector3D oldCamera;
+    Vector3D camera;
+    float oldLengthAngle;
+    float lengthAngle;
+    float oldWidthAngle;
+    float widthAngle;
+    
+    Vector3D front;
+    Vector3D back;
+    Vector3D right;
+    Vector3D left;
+    Vector3D up;
+    Vector3D down;  
+    
+    Vector3D flatFront;
+    Vector3D flatBack;
+    Vector3D flatRight;
+    Vector3D flatLeft;
+    Vector3D flatUp;
+    Vector3D flatDown; 
+    
+    Matrix3D view;
+    
+    Plane3D frustumPlanes[6];
+};
+
+#endif
+

+ 0 - 15
math/Matrix3D.cpp

@@ -7,14 +7,6 @@ Matrix3D::Matrix3D()
     setToIdentity();
 }
 
-Matrix3D::Matrix3D(const Matrix3D& orig)
-{
-}
-
-Matrix3D::~Matrix3D()
-{
-}
-
 void Matrix3D::setToIdentity()
 {
     data[0] = 1.0f;
@@ -145,13 +137,6 @@ void Matrix3D::translateTo(float tx, float ty, float tz)
     data[15] = 1.0f;
 }
 
-void Matrix3D::rotate(float xDegrees, float yDegrees, float zDegrees) 
-{
-    rotateX(xDegrees);
-    rotateY(yDegrees);
-    rotateZ(zDegrees);
-}
-
 void Matrix3D::rotateX(float degrees) 
 {
     degrees *= M_PI / 180.0f;

+ 0 - 3
math/Matrix3D.h

@@ -7,8 +7,6 @@ class Matrix3D
 {
 public:
     Matrix3D();
-    Matrix3D(const Matrix3D& orig);
-    virtual ~Matrix3D();
     
     void setToIdentity();
     void set(const Matrix3D& m);
@@ -28,7 +26,6 @@ public:
     void translateZ(float tz);
     void translateTo(float tx, float ty, float tz);
     
-    void rotate(float xDegrees, float yDegrees, float zDegrees);
     void rotateX(float degrees);
     void rotateY(float degrees);
     void rotateZ(float degrees);

+ 0 - 8
math/Matrix3DStack.cpp

@@ -6,14 +6,6 @@ Matrix3DStack::Matrix3DStack()
 {
 }
 
-Matrix3DStack::Matrix3DStack(const Matrix3DStack& orig)
-{
-}
-
-Matrix3DStack::~Matrix3DStack()
-{
-}
-
 void Matrix3DStack::pop()
 {
     if(index <= 0)

+ 0 - 2
math/Matrix3DStack.h

@@ -7,8 +7,6 @@ class Matrix3DStack
 {
 public:
     Matrix3DStack();
-    Matrix3DStack(const Matrix3DStack& orig);
-    virtual ~Matrix3DStack();
     
     void pop();
     void push();

+ 27 - 0
shader/overlayFragment.fs

@@ -0,0 +1,27 @@
+#version 430
+
+layout (binding = 0) uniform sampler2D samp;
+
+uniform bool useTexture;
+uniform bool useColor;
+
+in vec4 varColor;
+in vec2 varTextureCoord;
+
+out vec4 color;
+
+void main()
+{
+    if(useTexture)
+    {
+        color = texture(samp, varTextureCoord);
+        if(useColor)
+        {
+            color = vec4(varColor.xyz, color.w);
+        }
+    }
+    else
+    {
+        color = varColor;
+    }
+}  

+ 19 - 0
shader/overlayVertex.vs

@@ -0,0 +1,19 @@
+#version 430
+
+layout (location = 0) in vec3 position;
+layout (location = 1) in vec4 color;
+layout (location = 2) in vec2 textureCoord;
+layout (location = 3) in vec3 normal;
+
+uniform mat4 viewMatrix;
+uniform mat4 modelMatrix;
+
+out vec2 varTextureCoord;
+out vec4 varColor;
+
+void main(void)
+{ 
+    varTextureCoord = textureCoord;
+    varColor = color;
+    gl_Position = viewMatrix * modelMatrix * vec4(position, 1.0);
+}

+ 0 - 12
shader/postVertex.vs

@@ -1,12 +0,0 @@
-#version 430
-
-layout (location = 0) in vec2 pos;
-layout (location = 1) in vec2 tex;
-
-out vec2 varTextureCoord;
-
-void main(void)
-{ 
-    gl_Position = vec4(pos, 0.0, 1.0);
-    varTextureCoord = tex;
-}

+ 5 - 2
shader/postFragment.fs → shader/ssaoBlurFragment.fs

@@ -8,7 +8,7 @@ layout (binding = 5) uniform sampler2D noiseSamp;
 layout (binding = 6) uniform sampler2D ssaoSamp;
 
 in vec2 varTextureCoord;
-out vec4 color;
+out float color;
 
 void main()
 {
@@ -24,5 +24,8 @@ void main()
         }
     }
     result /= (radius * radius * 4);
-    color = texture(worldColorSamp, varTextureCoord) * vec4(result, result, result, 1);
+    color = result;//texture(worldColorSamp, varTextureCoord) * vec4(result, result, result, 1);
+
+    //float occ = texture(ssaoSamp, varTextureCoord).r;
+    //color = texture(worldColorSamp, varTextureCoord) * vec4(occ, occ, occ, 1);
 }  

+ 14 - 0
shader/ssaoBlurVertex.vs

@@ -0,0 +1,14 @@
+#version 430
+
+layout (location = 0) in vec3 position;
+layout (location = 1) in vec4 color;
+layout (location = 2) in vec2 textureCoord;
+layout (location = 3) in vec3 normal;
+
+out vec2 varTextureCoord;
+
+void main(void)
+{ 
+    gl_Position = vec4(position, 1.0);
+    varTextureCoord = textureCoord;
+}

+ 37 - 17
shader/ssaoFragment.fs

@@ -7,48 +7,68 @@ layout (binding = 4) uniform sampler2D worldDepthSamp;
 layout (binding = 5) uniform sampler2D noiseSamp;
 
 const float bias = 0.025;
-const float radius = 0.5;
-const int kernelSize = 64;
-uniform vec3 ssaoKernel[kernelSize];
+uniform float radius;
+
+// ssao kernel is pre generated for simplicity and performance
+// for(int i = 0; i < ssaoKernelAmount; i++)
+// {
+//     vec3 v = (random(-1, 1), random(-1, 1), random(0, 1));
+//     normalize(v);
+//     v *= random(0, 1);
+// 
+//     float scale = (float) i / ssaoKernelAmount; 
+//     scale  = 0.1f + (scale * scale) * 0.9f;
+//     v *= scale;
+// }
+
+uniform int numberOfSamples;
+const vec3 ssaoKernel[64] =
+{
+    vec3(0.0261425, -0.0376851, 4.00204e-07), vec3(-0.0517141, -0.0320865, 0.0304131), vec3(-0.0108267, 0.040398, 0.0315651), vec3(-0.0314388, -0.0327688, 0.0292523), vec3(-0.00132874, -0.0056109, 0.00382464), vec3(0.0297163, 0.062378, 0.0697156), vec3(-0.0489338, 0.00322945, 0.0507385), vec3(0.0689938, 0.0338294, 0.0349743), 
+    vec3(0.0167713, -0.0321483, 0.00932237), vec3(0.0331278, 0.0172987, 0.0213404), vec3(0.0374994, 0.0812687, 0.0208025), vec3(0.0266481, -0.0865055, 0.0659467), vec3(0.0547641, -0.0130673, 0.0280206), vec3(-0.0110478, -0.01767, 0.00933272), vec3(0.00571618, 0.00555481, 0.00339805), vec3(0.001716, 0.000476389, 0.0476425), 
+    vec3(-0.00607237, -0.000156404, 0.0128097), vec3(6.96767e-05, -0.0420028, 0.0466964), vec3(0.00540731, 0.0752215, 0.0251832), vec3(0.0514841, -0.0885747, 0.0926251), vec3(-0.0847474, -0.0655798, 0.0724548), vec3(0.0660382, 0.0362147, 0.121362), vec3(-0.0245497, 0.0357539, 0.0459818), vec3(0.084097, 0.0122515, 0.161992), 
+    vec3(-0.0471186, 0.069756, 0.0420852), vec3(-0.0261632, -0.0039447, 0.0330319), vec3(0.00775989, 0.0018387, 0.00197227), vec3(0.167912, -0.000560453, 0.0985381), vec3(0.0578085, 0.180922, 0.128394), vec3(0.0217065, -0.0290399, 0.00807598), vec3(-0.111954, -0.0507763, 0.0102483), vec3(0.0672952, 0.0322446, 0.00206515), 
+    vec3(0.187537, -0.0884211, 0.0438314), vec3(-0.0661418, 0.105045, 0.0435408), vec3(0.0592117, -0.239374, 0.169697), vec3(0.00562892, 0.045657, 0.0295806), vec3(-0.126569, -0.0322389, 0.173734), vec3(-0.105291, -0.0336205, 0.369015), vec3(-0.133294, -0.221413, 0.0464706), vec3(0.207733, 0.25832, 0.108203), 
+    vec3(-0.0605341, -0.0128894, 0.0677724), vec3(-0.0119915, 0.0655307, 0.00231462), vec3(-0.262367, -0.063802, 0.337014), vec3(-0.144795, -0.114031, 0.0155575), vec3(0.141442, -0.182272, 0.0632041), vec3(0.437972, -0.0676212, 0.24775), vec3(0.196835, -0.312091, 0.357106), vec3(-0.0222231, 0.279056, 0.0967121), 
+    vec3(0.141587, 0.175742, 0.166133), vec3(-0.0631059, 0.138069, 0.494785), vec3(0.479211, 0.198913, 0.33888), vec3(0.0271384, -0.152772, 0.308639), vec3(0.369594, -0.414181, 0.249154), vec3(0.38887, 0.241946, 0.231701), vec3(0.0066864, 0.00571323, 0.0110748), vec3(-0.00410669, 0.0027978, 0.0496037), 
+    vec3(0.228858, -0.015091, 0.486861), vec3(0.470433, 0.535686, 0.128289), vec3(-0.0906902, -0.659009, 0.49676), vec3(-0.372504, -0.109116, 0.217853), vec3(-0.0523188, -0.0971253, 0.710221), vec3(0.116336, -0.0672402, 0.0425562), vec3(-0.000688899, 0.000160498, 0.00043486), vec3(-0.151823, 0.190876, 0.324663)
+};
 uniform mat4 projMatrix;
 
 in vec2 varTextureCoord;
-out vec4 color;
-
-uniform vec3 viewPos;
+out float color;
 
-const vec2 noiseScale = vec2(1024.0 / 4.0, 620.0 / 4.0);
+uniform int width;
+uniform int height;
 
 void main()
 {     
     vec3 fragPos = texture(worldPositionSamp, varTextureCoord).xyz;
     vec3 normal = texture(worldNormalSamp, varTextureCoord).rgb;
-    vec3 randomVec = texture(noiseSamp, varTextureCoord * noiseScale).xyz; 
+    vec3 randomVec = texture(noiseSamp, varTextureCoord * vec2(width / 4.0, height / 4.0)).xyz; 
 
     vec3 tangent = normalize(randomVec - normal * dot(randomVec, normal));
     vec3 bitangent = cross(normal, tangent);
     mat3 TBN = mat3(tangent, bitangent, normal);  
 
     float occlusion = 0.0;
-    for(int i = 0; i < kernelSize; i++)
+    for(int i = 0; i < numberOfSamples; i++)
     {
-        // get sample position
         vec3 sampl = TBN * ssaoKernel[i]; // From tangent to view-space
         sampl = fragPos + sampl * radius; 
 
         vec4 offset = vec4(sampl, 1.0);
-        offset = projMatrix * offset;    // from view to clip-space
-        offset.xyz /= offset.w;               // perspective divide
+        offset = projMatrix * offset; // from view to clip-space
+        offset.xyz /= offset.w; // perspective divide
         offset.xyz = offset.xyz * 0.5 + 0.5; // transform to range 0.0 - 1.0  
 
         float sampleDepth = texture(worldPositionSamp, offset.xy).z; 
 
-        //float rangeCheck = smoothstep(0.0, 1.0, radius / abs(fragPos.z - sampleDepth));
-        //occlusion += float(sampleDepth >= sampl.z + bias) * rangeCheck;   
-        occlusion += float(sampleDepth >= sampl.z + bias);  
+        float rangeCheck = smoothstep(0.0, 1.0, radius / abs(fragPos.z - sampleDepth));
+        occlusion += float(sampleDepth >= sampl.z + bias) * rangeCheck;   
     }  
     
-    occlusion /= kernelSize;
+    occlusion /= numberOfSamples;
     occlusion = 1 - occlusion;
-    color = vec4(occlusion, occlusion, occlusion, 1);
+    color = occlusion;
 } 

+ 6 - 4
shader/ssaoVertex.vs

@@ -1,12 +1,14 @@
 #version 430
 
-layout (location = 0) in vec2 pos;
-layout (location = 1) in vec2 tex;
+layout (location = 0) in vec3 position;
+layout (location = 1) in vec4 color;
+layout (location = 2) in vec2 textureCoord;
+layout (location = 3) in vec3 normal;
 
 out vec2 varTextureCoord;
 
 void main(void)
 { 
-    gl_Position = vec4(pos, 0.0, 1.0);
-    varTextureCoord = tex;
+    gl_Position = vec4(position, 1.0);
+    varTextureCoord = textureCoord;
 }

+ 0 - 41
shader/vertex.vs

@@ -1,41 +0,0 @@
-#version 430
-
-layout (location = 0) in vec3 pos;
-layout (location = 1) in vec4 color;
-layout (location = 2) in vec2 tex;
-layout (location = 3) in vec3 normal;
-
-uniform sampler2D samp;
-
-uniform mat4 projMatrix;
-uniform mat4 viewMatrix;
-uniform mat4 modelMatrix;
-
-uniform bool useTexture;
-uniform bool useColor;
-uniform bool useMixColor;
-uniform vec4 mixColor;
-uniform bool useNormals;
-
-out vec2 tc;
-out vec4 outColor;
-
-void main(void)
-{ 
-    tc = tex; 
-    outColor = vec4(color.xyz, 1);
-
-    if(useNormals)
-    {
-        if(abs(normal.x) == 1)
-        {
-            outColor = outColor * 0.8;
-        }
-        if(abs(normal.z) == 1)
-        {
-            outColor = outColor * 0.9;
-        }
-    }
-    
-    gl_Position = projMatrix * viewMatrix * modelMatrix * vec4(pos, 1.0);
-}

+ 4 - 27
shader/worldFragment.fs

@@ -6,11 +6,9 @@ layout (location = 2) out vec4 worldColor;
 
 layout (binding = 0) uniform sampler2D samp;
 
-uniform bool useTexture;
-uniform bool useColor;
-uniform bool useMixColor;
-uniform vec4 mixColor;
-uniform bool useNormals;
+uniform mat4 projMatrix;
+uniform mat4 viewMatrix;
+uniform mat4 modelMatrix;
 
 in vec3 varPosition;
 in vec2 varTextureCoord;
@@ -19,28 +17,7 @@ in vec3 varNormal;
 
 void main(void)
 {
-    vec4 color = vec4(0, 0, 0, 1);
-    if(useTexture)
-    {
-        color = texture(samp, varTextureCoord);
-        if(useColor)
-        {
-            if(useMixColor)
-            {
-                color = (color + mixColor) * 0.5;
-            }
-            else
-            {
-                color = vec4(varColor.xyz, color.w);
-            }
-        }
-    }
-    else
-    {
-        color = varColor;
-    }
-
     worldPosition = varPosition;
     worldNormal = normalize(varNormal);
-    worldColor = color;
+    worldColor = varColor; //texture(samp, varTextureCoord);
 }

+ 18 - 0
shader/worldPostFragment.fs

@@ -0,0 +1,18 @@
+#version 430
+
+layout (binding = 1) uniform sampler2D worldPositionSamp;
+layout (binding = 2) uniform sampler2D worldNormalSamp;
+layout (binding = 3) uniform sampler2D worldColorSamp;
+layout (binding = 4) uniform sampler2D worldDepthSamp;
+layout (binding = 5) uniform sampler2D noiseSamp;
+layout (binding = 6) uniform sampler2D ssaoSamp;
+layout (binding = 7) uniform sampler2D ssaoBlurSamp;
+
+in vec2 varTextureCoord;
+out vec4 color;
+
+void main()
+{
+    float ssaoBlur = texture(ssaoBlurSamp, varTextureCoord).r;
+    color = vec4(texture(worldColorSamp, varTextureCoord).xyz * ssaoBlur, 1);
+}  

+ 14 - 0
shader/worldPostVertex.vs

@@ -0,0 +1,14 @@
+#version 430
+
+layout (location = 0) in vec3 position;
+layout (location = 1) in vec4 color;
+layout (location = 2) in vec2 textureCoord;
+layout (location = 3) in vec3 normal;
+
+out vec2 varTextureCoord;
+
+void main(void)
+{ 
+    gl_Position = vec4(position, 1.0);
+    varTextureCoord = textureCoord;
+}

+ 8 - 18
shader/worldVertex.vs

@@ -9,12 +9,6 @@ uniform mat4 projMatrix;
 uniform mat4 viewMatrix;
 uniform mat4 modelMatrix;
 
-uniform bool useTexture;
-uniform bool useColor;
-uniform bool useMixColor;
-uniform vec4 mixColor;
-uniform bool useNormals;
-
 out vec3 varPosition;
 out vec2 varTextureCoord;
 out vec4 varColor;
@@ -22,23 +16,19 @@ out vec3 varNormal;
 
 void main(void)
 { 
-    // model matrix should be used here ...
-    varNormal = (viewMatrix * vec4(normal, 1.0)).xyz;
-    //varNormal = (viewMatrix * modelMatrix * vec4(normal, 1.0)).xyz;
+    // transforming normals must not use the fourth dimension
+    varNormal = (viewMatrix * modelMatrix * vec4(normal, 0.0)).xyz;
     
     varTextureCoord = textureCoord; 
     varColor = vec4(color.xyz, 1);
 
-    if(useNormals)
+    if(abs(normal.x) == 1)
+    {
+        varColor = varColor * 0.8;
+    }
+    if(abs(normal.z) == 1)
     {
-        if(abs(normal.x) == 1)
-        {
-            varColor = varColor * 0.8;
-        }
-        if(abs(normal.z) == 1)
-        {
-            varColor = varColor * 0.9;
-        }
+        varColor = varColor * 0.9;
     }
     
     vec4 viewPos = viewMatrix * modelMatrix * vec4(position, 1.0);