Przeglądaj źródła

class for shader programs, new framebuffers (position, color, normals)

Kajetan Johannes Hammerle 5 lat temu
rodzic
commit
4e95af1a2d

+ 4 - 1
Makefile

@@ -8,7 +8,7 @@ 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\
+	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\
 	Client.o\
 	Chunk.o World.o ChunkRenderer.o ClientChunkProvider.o
@@ -45,6 +45,9 @@ 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 $@
+	
 # ------------------------------------------------------------------------------	
 # Client
 # ------------------------------------------------------------------------------

+ 1 - 1
client/Client.cpp

@@ -47,7 +47,7 @@ void Client::tick()
     
     shader.storeCamera();
     
-    float factor = 10.0f;
+    float factor = 2.0f;
     if(keyManager.isDown(KEY_LEFT))
     {
         position.addMul(shader.getLeft(), factor);

+ 2 - 2
client/rendering/ChunkRenderer.cpp

@@ -212,7 +212,7 @@ void ChunkRenderer::buildChunk(int partionY, Chunk& c, Chunk* north, Chunk* east
 
                         for(int i = 0; i < 6; i++)
                         {
-                            m.addNormal(0.0f, 0.0f, -1.0f);
+                            m.addNormal(0.0f, 0.0f, 1.0f);
                         }
 
                         m.addPosition(x + 0.0f, y + 0.0f, z + 1.0f);
@@ -241,7 +241,7 @@ void ChunkRenderer::buildChunk(int partionY, Chunk& c, Chunk* north, Chunk* east
 
                         for(int i = 0; i < 6; i++)
                         {
-                            m.addNormal(0.0f, 0.0f, 1.0f);
+                            m.addNormal(0.0f, 0.0f, -1.0f);
                         }
 
                         m.addPosition(x + 0.0f, y + 0.0f, z + 0.0f);

+ 2 - 2
client/rendering/ChunkRenderer.h

@@ -17,8 +17,8 @@ public:
 private:
     void buildChunk(int partionY, Chunk& c, Chunk* north, Chunk* east, Chunk* south, Chunk* west);
     
-    const int chunkX = 16;
-    const int chunkZ = 16;
+    const int chunkX = 2;
+    const int chunkZ = 2;
     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 = 16;
-    const int chunkZ = 16;
+    const int chunkX = 2;
+    const int chunkZ = 2;
     Chunk** chunks;
 };
 

+ 6 - 2
engine/Shader.cpp

@@ -69,6 +69,10 @@ void Shader::set3DMode(float lag)
     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());
@@ -89,6 +93,8 @@ void Shader::set3DMode(float lag)
     view.set(3, 0, 0.0f);
     view.set(3, 3, 1.0f);
     
+    Engine::setMatrix(unifViewMatrix, view.getValues());
+    
     // -------------------------------------------------------------------------
     // update frustum planes
     // -------------------------------------------------------------------------
@@ -162,8 +168,6 @@ void Shader::set3DMode(float lag)
     
     // down
     down.setInverse(up);
-    
-    Engine::setMatrix(unifViewMatrix, view.getValues());
 }
 
 void Shader::set2DMode()

+ 193 - 0
engine/ShaderProgram.cpp

@@ -0,0 +1,193 @@
+#include "ShaderProgram.h"
+#include <fstream>
+#include <cstring>
+
+ShaderProgram::ShaderProgram()
+{
+}
+
+ShaderProgram::~ShaderProgram()
+{
+    if(vertexShader != 0)
+    {
+        glDeleteShader(vertexShader);
+    }
+    if(fragmentShader != 0)
+    {
+        glDeleteShader(fragmentShader);
+    }
+    if(program != 0)
+    {
+        glDeleteProgram(program);
+    }
+}
+
+bool ShaderProgram::isValid()
+{
+    return valid;
+}
+
+GLuint ShaderProgram::getProgram()
+{
+    return program;
+}
+
+void ShaderProgram::compile(const GLchar* vertexPath, const GLchar* fragmentPath)
+{
+    if(valid)
+    {
+        return;
+    }
+    GLchar* vertexData = readFile(vertexPath);
+    if(vertexData == nullptr)
+    {
+        cout << "cannot read " << vertexPath << endl;
+        return;
+    }
+    GLchar* fragmentData = readFile(fragmentPath);
+    if(fragmentData == nullptr)
+    {
+        cout << "cannot read " << fragmentPath << endl;
+        delete[] vertexData;
+        return;
+    }
+    
+    compile(vertexPath, vertexData, fragmentPath, fragmentData);
+    delete[] vertexData;
+    delete[] fragmentData;
+}
+
+GLchar* ShaderProgram::readFile(const GLchar* name)
+{
+    ifstream in;
+    in.open(name);
+    if(!in.fail())
+    {
+        int size = 128;
+        int index = 0;
+        GLchar* content = new GLchar[size];
+        
+        while(true)
+        {
+            GLchar c = in.get();
+            if(in.eof())
+            {
+                break;
+            }
+            if(index >= size - 1)
+            {
+                GLchar* newContent = new GLchar[size * 2];
+                memcpy(newContent, content, size);
+                size *= 2;
+                delete[] content;
+                content = newContent;
+            }
+            content[index] = c;
+            index++;
+        }
+        
+        content[index] = '\0';
+        index++;
+        
+        in.close();
+        return content;
+    }
+    return nullptr;
+}
+
+bool ShaderProgram::checkShaderErrors(const GLchar* name, GLuint shader)
+{
+    bool returnValue = false;
+    
+    cout << "compiling " << name << " shader ..." << endl;
+    GLenum error = glGetError();
+    if(error)
+    {
+        cout << "error: " << glGetError() << endl;
+        returnValue = true;
+    }
+    else
+    {
+        cout << "no error occured ..." << endl;
+    }
+    
+    GLint compiled[1];
+    glGetShaderiv(shader, GL_COMPILE_STATUS, compiled);
+    if(compiled[0])
+    {
+        cout << name << " shader successfully compiled" << endl;
+    }
+    else
+    {
+        cout << name << "compiling of " << name << " failed:" << endl;
+        GLchar buffer[512];
+        GLsizei bufferSize = 512;
+        GLsizei charsUsed = 0;
+        glGetShaderInfoLog(shader, bufferSize, &charsUsed, buffer);
+        // glGetProgramInfoLog should be null terminated ...
+        buffer[bufferSize - 1] = '\0';
+        cout << buffer << endl;
+        returnValue = true;
+    }
+    return returnValue;
+}
+
+void ShaderProgram::compile(const GLchar* vertexPath, const GLchar* vertexData, const GLchar* fragmentPath, const GLchar* fragmentData)
+{
+    vertexShader = glCreateShader(GL_VERTEX_SHADER);
+    glShaderSource(vertexShader, 1, &vertexData, nullptr);
+    glCompileShader(vertexShader);
+
+    if(checkShaderErrors(vertexPath, vertexShader))
+    {
+        return;
+    }    
+    
+    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
+    glShaderSource(fragmentShader, 1, &fragmentData, nullptr);
+    glCompileShader(fragmentShader);
+
+    if(checkShaderErrors(fragmentPath, fragmentShader))
+    {
+        return;
+    }    
+
+    program = glCreateProgram();
+    glAttachShader(program, vertexShader);
+    glAttachShader(program, fragmentShader);
+    glLinkProgram(program);
+    
+    cout << "linking shaders to program ..." << endl;
+
+    GLenum error = glGetError();
+    if(error)
+    {
+        cout << "error: " << glGetError() << endl;
+        return;
+    }
+    else
+    {
+        cout << "no error occured ..." << endl;
+    }
+
+    GLint compiled[1];
+    glGetProgramiv(program, GL_LINK_STATUS, compiled);
+    if(compiled[0])
+    {
+        cout << "shaders successfully linked" << endl;
+    }
+    else
+    {
+        cout << "linking of shaders failed:" << endl;
+        GLchar buffer[512];
+        GLsizei bufferSize = 512;
+        GLsizei charsUsed = 0;
+        glGetProgramInfoLog(program, bufferSize, &charsUsed, buffer);
+        // glGetProgramInfoLog should be null terminated ...
+        buffer[bufferSize - 1] = '\0';
+        cout << buffer << endl;
+        return;
+    }
+    valid = true;
+}
+

+ 31 - 0
engine/ShaderProgram.h

@@ -0,0 +1,31 @@
+#ifndef SHADERPROGRAM_H
+#define SHADERPROGRAM_H
+
+#include <GL/glew.h>
+#include <GLFW/glfw3.h>
+#include <iostream>
+
+using namespace std;
+
+class ShaderProgram
+{
+public:
+    ShaderProgram();
+    virtual ~ShaderProgram();
+    
+    void compile(const GLchar* vertexPath, const GLchar* fragmentPath);
+    bool isValid();
+    GLuint getProgram();
+private:
+    GLchar* readFile(const GLchar* name);
+    bool checkShaderErrors(const GLchar* name, GLuint shader);
+    void compile(const GLchar* vertexPath, const GLchar* vertexData, const GLchar* fragmentPath, const GLchar* fragmentData);
+    
+    GLuint vertexShader = 0;
+    GLuint fragmentShader = 0;
+    GLuint program = 0;
+    bool valid = false;
+};
+
+#endif
+

+ 0 - 4
engine/Texture.cpp

@@ -14,10 +14,6 @@ Texture::Texture(const char* path)
     }
 }
 
-Texture::Texture(const Texture& orig)
-{
-}
-
 Texture::~Texture()
 {
     if(data != nullptr)

+ 0 - 1
engine/Texture.h

@@ -9,7 +9,6 @@ class Texture
 {
 public:
     Texture(const char* path);
-    Texture(const Texture& orig);
     virtual ~Texture();
     
     void bind();

+ 122 - 271
engine/Wrapper.cpp

@@ -1,34 +1,36 @@
 #include "Wrapper.h"
-#include <fstream>
-#include <cstring>
-#include <iostream>
-
-using namespace std;
 
 DummyClient DummyClient::dummy;
 
 IClient* Engine::client = &DummyClient::dummy;
 GLFWwindow* Engine::window = nullptr;
 
-GLuint Engine::vShader = 0;
-GLuint Engine::fShader = 0;
-GLuint Engine::program = 0;
+// 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::worldDepthRenderBuffer = 0;
 
+// post shader
 GLuint Engine::postVba = 0;
 GLuint Engine::postVbo = 0;
-GLuint Engine::postVShader = 0;
-GLuint Engine::postFShader = 0;
-GLuint Engine::postProgram = 0;
+ShaderProgram Engine::postShader;
 
-GLuint Engine::frameBuffer = 0;
-GLuint Engine::frameTexture = 0;
-GLuint Engine::depthTexture = 0;
 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;
+
 bool Engine::init(int width, int height, const char* name)
 {
     Engine::width = width;
@@ -65,39 +67,18 @@ bool Engine::init(int width, int height, const char* name)
     }
     cout << "Status: Using GLEW " << glewGetString(GLEW_VERSION) << endl;
 
-    vShader = 0;
-    fShader = 0;
-    program = createProgram("shader/vertex.vs", "shader/fragment.fs", vShader, program);
-    
-    if(program == 0)
+    worldShader.compile("shader/worldVertex.vs", "shader/worldFragment.fs");
+    if(!worldShader.isValid())
     {
-        if(vShader != 0)
-        {
-            glDeleteShader(vShader);
-        }
-        if(fShader != 0)
-        {
-            glDeleteShader(fShader);
-        }
         glfwDestroyWindow(window);
         glfwTerminate();
         return false;
     }
-    
-    postVShader = 0;
-    postFShader = 0;
-    postProgram = createProgram("shader/postVertex.vs", "shader/postFragment.fs", postVShader, postFShader);
-    
-    if(postProgram == 0)
+    activeProgram = worldShader.getProgram();
+
+    postShader.compile("shader/postVertex.vs", "shader/postFragment.fs");
+    if(!postShader.isValid())
     {
-        if(postVShader != 0)
-        {
-            glDeleteShader(postVShader);
-        }
-        if(postFShader != 0)
-        {
-            glDeleteShader(postFShader);
-        }
         glfwDestroyWindow(window);
         glfwTerminate();
         return false;
@@ -118,8 +99,7 @@ void Engine::start(IClient* client)
         Engine::client = client;
     }
     
-    generateFramebuffer();
-    generatePostData();
+    onInit();
 
     glEnable(GL_CULL_FACE);
     glDepthFunc(GL_LEQUAL);
@@ -153,51 +133,13 @@ void Engine::start(IClient* client)
             }
         }
 
-        // draw scene in framebuffer
-        glActiveTexture(GL_TEXTURE0);
-        glUseProgram(program);
-        glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
-        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-        glEnable(GL_DEPTH_TEST);
-        if(lineMode)
-        {
-            glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
-            Engine::client->renderTick((float) lag / NANOS_PER_TICK);
-            glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
-        }
-        else
-        {
-            Engine::client->renderTick((float) lag / NANOS_PER_TICK);
-        }
+        onRenderTick((float) lag / NANOS_PER_TICK);
         
-        // draw textured framebuffer
-        glActiveTexture(GL_TEXTURE1);
-        glBindTexture(GL_TEXTURE_2D, frameTexture);
-        
-        glActiveTexture(GL_TEXTURE2);
-        glBindTexture(GL_TEXTURE_2D, depthTexture);
-        
-        glUseProgram(postProgram);
-        glBindFramebuffer(GL_FRAMEBUFFER, 0);
-        glClear(GL_COLOR_BUFFER_BIT);
-        glDisable(GL_DEPTH_TEST);
-        glBindVertexArray(postVba);
-        glBindBuffer(GL_ARRAY_BUFFER, postVbo);
-        glDrawArrays(GL_TRIANGLES, 0, 6);
-        
-
         glfwSwapBuffers(window);
         glfwPollEvents();
     }
     
-    destroyPostData();
-    glDeleteFramebuffers(1, &frameBuffer);
-    glDeleteShader(vShader);
-    glDeleteShader(fShader);
-    glDeleteProgram(program);
-    glDeleteShader(postVShader);
-    glDeleteShader(postFShader);
-    glDeleteProgram(postProgram);
+    onTerm();
     glfwDestroyWindow(window);
     glfwTerminate();
 }
@@ -207,162 +149,6 @@ void Engine::stop()
     glfwSetWindowShouldClose(window, 1);
 }
 
-GLchar* Engine::readFile(const char* name)
-{
-    ifstream in;
-    in.open(name);
-    if(!in.fail())
-    {
-        int size = 128;
-        int index = 0;
-        GLchar* content = new GLchar[size];
-        
-        while(true)
-        {
-            GLchar c = in.get();
-            if(in.eof())
-            {
-                break;
-            }
-            if(index >= size - 1)
-            {
-                GLchar* newContent = new GLchar[size * 2];
-                memcpy(newContent, content, size);
-                size *= 2;
-                delete[] content;
-                content = newContent;
-            }
-            content[index] = c;
-            index++;
-        }
-        
-        content[index] = '\0';
-        index++;
-        
-        in.close();
-        return content;
-    }
-    return nullptr;
-}
-
-bool Engine::checkShaderErrors(const char* name, GLuint shader)
-{
-    bool returnValue = false;
-    
-    cout << "compiling " << name << " shader ..." << endl;
-    GLenum error = glGetError();
-    if(error)
-    {
-        cout << "error: " << glGetError() << endl;
-        returnValue = true;
-    }
-    else
-    {
-        cout << "no error occured ..." << endl;
-    }
-    
-    GLint compiled[1];
-    glGetShaderiv(shader, GL_COMPILE_STATUS, compiled);
-    if(compiled[0])
-    {
-        cout << name << " shader successfully compiled" << endl;
-    }
-    else
-    {
-        cout << name << "compiling of " << name << " failed:" << endl;
-        GLchar buffer[512];
-        GLsizei bufferSize = 512;
-        GLsizei charsUsed = 0;
-        glGetShaderInfoLog(shader, bufferSize, &charsUsed, buffer);
-        // glGetProgramInfoLog should be null terminated ...
-        buffer[bufferSize - 1] = '\0';
-        cout << buffer << endl;
-        returnValue = true;
-    }
-    return returnValue;
-}
-
-GLuint Engine::compileProgram(GLuint& vShader, GLuint& fShader, const GLchar* v, const GLchar* f)
-{
-    vShader = glCreateShader(GL_VERTEX_SHADER);
-    glShaderSource(vShader, 1, &v, nullptr);
-    glCompileShader(vShader);
-
-    if(checkShaderErrors("vertex", vShader))
-    {
-        return 0;
-    }    
-    
-    fShader = glCreateShader(GL_FRAGMENT_SHADER);
-    glShaderSource(fShader, 1, &f, nullptr);
-    glCompileShader(fShader);
-
-    if(checkShaderErrors("fragment", fShader))
-    {
-        return 0;
-    }    
-
-    GLuint program = glCreateProgram();
-    glAttachShader(program, vShader);
-    glAttachShader(program, fShader);
-    glLinkProgram(program);
-    
-    cout << "linking shaders to program ..." << endl;
-
-    GLenum error = glGetError();
-    if(error)
-    {
-        cout << "error: " << glGetError() << endl;
-        return 0;
-    }
-    else
-    {
-        cout << "no error occured ..." << endl;
-    }
-
-    GLint compiled[1];
-    glGetProgramiv(program, GL_LINK_STATUS, compiled);
-    if(compiled[0])
-    {
-        cout << "shaders successfully linked" << endl;
-    }
-    else
-    {
-        cout << "linking of shaders failed:" << endl;
-        GLchar buffer[512];
-        GLsizei bufferSize = 512;
-        GLsizei charsUsed = 0;
-        glGetProgramInfoLog(program, bufferSize, &charsUsed, buffer);
-        // glGetProgramInfoLog should be null terminated ...
-        buffer[bufferSize - 1] = '\0';
-        cout << buffer << endl;
-        return 0;
-    }
-    return program;
-}
-
-GLuint Engine::createProgram(const char* v, const char* f, GLuint& vShader, GLuint& fShader)
-{
-    GLchar* vertex = readFile(v);
-    if(vertex == nullptr)
-    {
-        cout << "cannot read " << v << endl;
-        return 0;
-    }
-    GLchar* fragment = readFile(f);
-    if(fragment == nullptr)
-    {
-        cout << "cannot read " << f << endl;
-        delete[] vertex;
-        return 0;
-    }
-    
-    GLuint program = compileProgram(vShader, fShader, vertex, fragment);
-    delete[] vertex;
-    delete[] fragment;
-    return program;
-}
-
 void Engine::onKeyEvent(GLFWwindow* w, int key, int scancode, int action, int mods)
 {
     client->onKeyEvent(key, scancode, action, mods);
@@ -380,14 +166,14 @@ void Engine::onWindowResize(GLFWwindow* w, int width, int height)
     Engine::height = height;
     updateScale();
     
-    glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer); 
+    /*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);
+    glBindFramebuffer(GL_FRAMEBUFFER, 0);*/
 }
 
 void Engine::updateScale()
@@ -416,7 +202,7 @@ int Engine::getHeight()
 
 GLint Engine::getUniformLocation(const GLchar* name)
 {
-    return glGetUniformLocation(program, name);
+    return glGetUniformLocation(activeProgram, name);
 }
 
 void Engine::setMatrix(GLint location, const GLfloat* m)
@@ -468,40 +254,52 @@ void Engine::printError()
     }
 }
 
-void Engine::generateFramebuffer()
+void Engine::onInit()
 {
-    glGenFramebuffers(1, &frameBuffer);
-    glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer); 
-    
-    glGenTextures(1, &frameTexture);
-    glBindTexture(GL_TEXTURE_2D, frameTexture);
-    
+    // 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);
+    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_LINEAR);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-    glBindTexture(GL_TEXTURE_2D, 0);
-    
-    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, frameTexture, 0);   
-    
-    glGenTextures(1, &depthTexture);
-    glBindTexture(GL_TEXTURE_2D, depthTexture);
-    
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-    glBindTexture(GL_TEXTURE_2D, 0);
-    
-    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);   
-
+    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);
+    // generate depth render buffer
+    glGenRenderbuffers(1, &worldDepthRenderBuffer);
+    glBindRenderbuffer(GL_RENDERBUFFER, worldDepthRenderBuffer);
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);  
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, worldDepthRenderBuffer);
+    glBindRenderbuffer(GL_RENDERBUFFER, 0);
+    // check if world framebuffer is okay
     if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
     {
-	cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" << endl;
+	cout << "world frame buffer is not complete!" << endl;
     }
     glBindFramebuffer(GL_FRAMEBUFFER, 0);
-}
-
-void Engine::generatePostData()
-{
+    
+    // generate data for drawing previously generated framebuffer as rectangle
     glGenVertexArrays(1, &postVba);
     glBindVertexArray(postVba);
     
@@ -527,10 +325,63 @@ void Engine::generatePostData()
     glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 24, data, GL_STATIC_DRAW);
 }
 
-void Engine::destroyPostData()
+void Engine::onRenderTick(float lag)
+{
+    //--------------------------------------------------------------------------
+    // 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);
+
+    activeProgram = postShader.getProgram();
+    glUseProgram(activeProgram);
+    
+    glUniform3f(glGetUniformLocation(activeProgram, "viewPos"), testX, testY, testZ);
+
+    glBindFramebuffer(GL_FRAMEBUFFER, 0);
+    glClear(GL_COLOR_BUFFER_BIT);
+    glDisable(GL_DEPTH_TEST);
+    glBindVertexArray(postVba);
+    glBindBuffer(GL_ARRAY_BUFFER, postVbo);
+    glDrawArrays(GL_TRIANGLES, 0, 6);
+}
+
+void Engine::onTerm()
 {
     glDeleteVertexArrays(1, &postVba);
     glDeleteBuffers(1, &postVbo);
+    
+    glDeleteFramebuffers(1, &worldFrameBuffer);
+    glDeleteTextures(1, &worldPositionTexture);
+    glDeleteTextures(1, &worldNormalTexture);
+    glDeleteTextures(1, &worldColorTexture);
+    glDeleteRenderbuffers(1, &worldDepthRenderBuffer);
 }
 
 void Engine::setLineMode(bool mode)

+ 23 - 13
engine/Wrapper.h

@@ -3,6 +3,7 @@
 
 #include <GL/glew.h>
 #include <GLFW/glfw3.h>
+#include "ShaderProgram.h"
 
 #include <iostream>
 
@@ -49,13 +50,19 @@ public:
     static void setFloat(GLint location, GLfloat f1, GLfloat f2, GLfloat f3, GLfloat f4);
     
     static void setLineMode(bool mode);
+    
+    static float testX;
+    static float testY;
+    static float testZ;
 private:
     static const uint64_t NANOS_PER_TICK = 50000000;
     static const int MAX_TICKS_PER_FRAME = 5;
     
-    static void generateFramebuffer();
-    static void generatePostData();
-    static void destroyPostData();
+    static bool onProgramInit();
+    
+    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);
@@ -71,19 +78,22 @@ private:
     static IClient* client;    
     static GLFWwindow* window;   
     
-    static GLuint vShader;
-    static GLuint fShader;
-    static GLuint program;
+    // active program
+    static GLuint activeProgram;
+    
+    // world data
+    static ShaderProgram worldShader;
+    static GLuint worldFrameBuffer;
+    static GLuint worldPositionTexture;
+    static GLuint worldNormalTexture;
+    static GLuint worldColorTexture;
+    static GLuint worldDepthRenderBuffer;
     
+    // post shader
     static GLuint postVba;
     static GLuint postVbo;
-    static GLuint postVShader;
-    static GLuint postFShader;
-    static GLuint postProgram;
-    
-    static GLuint frameBuffer;
-    static GLuint frameTexture;
-    static GLuint depthTexture;
+    static ShaderProgram postShader;
+
     static int scale;
     static int width;
     static int height;

+ 29 - 7
shader/postFragment.fs

@@ -1,12 +1,34 @@
 #version 430
 
-layout (binding = 1) uniform sampler2D samp;
-layout (binding = 2) uniform sampler2D depthSamp;
+layout (binding = 1) uniform sampler2D worldPositionSamp;
+layout (binding = 2) uniform sampler2D worldNormalSamp;
+layout (binding = 3) uniform sampler2D worldColorSamp;
 
-in vec2 tc;
+in vec2 varTextureCoord;
 out vec4 color;
 
-void main(void)  
-{  
-    color = texture(samp, tc);
-}
+vec3 lightPosition = vec3(16, 20, 16);
+vec3 lightColor = vec3(1, 1, 1);
+uniform vec3 viewPos;
+
+void main()
+{             
+    // retrieve data from G-buffer
+    vec3 FragPos = texture(worldPositionSamp, varTextureCoord).rgb;
+    vec3 Normal = texture(worldNormalSamp, varTextureCoord).rgb;
+    vec3 Albedo = vec3(1, 1, 1);//texture(gAlbedoSpec, TexCoords).rgb;
+    float Specular = 0.7;//texture(gAlbedoSpec, TexCoords).a;
+    
+    // then calculate lighting as usual
+    vec3 lighting = Albedo * 0.1; // hard-coded ambient component
+    vec3 viewDir = normalize(viewPos - FragPos);
+    //for(int i = 0; i < NR_LIGHTS; ++i)
+    //{
+        // diffuse
+        vec3 lightDir = normalize(lightPosition - FragPos);
+        vec3 diffuse = max(dot(Normal, lightDir), 0.0) * Albedo * lightColor;
+        lighting += diffuse;
+    //}
+    
+    color = vec4(lighting, 1.0) * texture(worldColorSamp, varTextureCoord);
+}  

+ 2 - 2
shader/postVertex.vs

@@ -3,10 +3,10 @@
 layout (location = 0) in vec2 pos;
 layout (location = 1) in vec2 tex;
 
-out vec2 tc;
+out vec2 varTextureCoord;
 
 void main(void)
 { 
     gl_Position = vec4(pos, 0.0, 1.0);
-    tc = tex;
+    varTextureCoord = tex;
 }

+ 46 - 0
shader/worldFragment.fs

@@ -0,0 +1,46 @@
+#version 430
+
+layout (location = 0) out vec3 worldPosition;
+layout (location = 1) out vec3 worldNormal;
+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;
+
+in vec3 varPosition;
+in vec2 varTextureCoord;
+in vec4 varColor;
+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 = varNormal;
+    worldColor = color;
+}

+ 44 - 0
shader/worldVertex.vs

@@ -0,0 +1,44 @@
+#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 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;
+out vec3 varNormal;
+
+void main(void)
+{ 
+    varNormal = normal;
+    varTextureCoord = textureCoord; 
+    varColor = vec4(color.xyz, 1);
+
+    if(useNormals)
+    {
+        if(abs(normal.x) == 1)
+        {
+            varColor = varColor * 0.8;
+        }
+        if(abs(normal.z) == 1)
+        {
+            varColor = varColor * 0.9;
+        }
+    }
+    
+    vec4 worldPos = modelMatrix * vec4(position, 1.0);
+    varPosition = worldPos.xyz;
+    gl_Position = projMatrix * viewMatrix * worldPos;
+}