Browse Source

normal mapping

Kajetan Johannes Hammerle 1 year ago
parent
commit
b6fffc1478

+ 16 - 21
client/rendering/Engine.cpp

@@ -8,7 +8,7 @@
 #include "client/math/Plane.h"
 
 Engine::Engine(Shaders& shaders, Framebuffers& fb, const WindowSize& size, RenderSettings& renderSettings) :
-shaders(shaders), fb(fb), size(size), renderSettings(renderSettings), frustum(60.0f, 0.1f, 80.0f) {
+shaders(shaders), framebuffers(fb), size(size), renderSettings(renderSettings), frustum(60.0f, 0.1f, 80.0f) {
     rectangle.add(Triangle(
             Vertex(Vector3(-1, -1, 0), Vector2(0, 0)),
             Vertex(Vector3(1, 1, 0), Vector2(1, 1)),
@@ -23,7 +23,7 @@ shaders(shaders), fb(fb), size(size), renderSettings(renderSettings), frustum(60
 void Engine::renderTick(float lag, const Game& game) {
     updateWorldProjection();
     updateWorldView();
-    
+
     if(renderSettings.shadows) {
         renderShadow(lag, game);
     }
@@ -37,8 +37,7 @@ void Engine::renderTick(float lag, const Game& game) {
 }
 
 void Engine::renderShadow(float lag, const Game& game) {
-
-    fb.shadow.bind();
+    framebuffers.shadow.bind();
     GLWrapper::enableDepthTesting();
     shaders.shadow.use();
     worldShadowProjView.set(worldShadowProj).mul(worldShadowView);
@@ -50,8 +49,7 @@ void Engine::renderShadow(float lag, const Game& game) {
 }
 
 void Engine::renderWorld(float lag, const Game& game) {
-
-    fb.world.bind();
+    framebuffers.world.bind();
     GLWrapper::enableDepthTesting();
     shaders.world.use();
 
@@ -63,7 +61,7 @@ void Engine::renderWorld(float lag, const Game& game) {
     shaders.world.setMatrix("view", worldView.setToIdentity().getValues());
     model.clear();
     shaders.world.setMatrix("model", model.get().getValues());
-    fb.shadow.bindDepthTexture(1);
+    framebuffers.shadow.bindDepthTexture(1);
     shaders.world.setInt("shadows", renderSettings.shadows);
     shaders.world.setFloat("radius", renderSettings.testRadius);
     shaders.world.setFloat("zbias", renderSettings.testBias);
@@ -72,7 +70,6 @@ void Engine::renderWorld(float lag, const Game& game) {
 }
 
 void Engine::renderSSAO() {
-
     shaders.ssao.use();
 
     Matrix rProj;
@@ -81,35 +78,33 @@ void Engine::renderSSAO() {
     shaders.ssao.setMatrix("proj", rProj.getValues());
     shaders.ssao.setInt("width", size.width);
     shaders.ssao.setInt("height", size.height);
-    fb.world.bindPositionTexture(0);
-    fb.world.bindNormalTexture(1);
-    fb.world.bindColorTexture(2);
-    fb.world.bindDepthTexture(3);
+    framebuffers.world.bindPositionTexture(0);
+    framebuffers.world.bindNormalTexture(1);
+    framebuffers.world.bindColorTexture(2);
+    framebuffers.world.bindDepthTexture(3);
     ssaoNoise.bind(4);
-    fb.ssao.bind();
+    framebuffers.ssao.bind();
     rectangle.draw();
 
     shaders.ssaoBlur.use();
-    fb.ssao.bindRedTexture(0);
-    fb.ssaoBlur.bind();
+    framebuffers.ssao.bindRedTexture(0);
+    framebuffers.ssaoBlur.bind();
     rectangle.draw();
 }
 
 void Engine::renderPostWorld() {
-
     GLWrapper::prepareMainFramebuffer();
     shaders.postWorld.use();
-    fb.world.bindColorTexture(0);
-    fb.ssaoBlur.bindRedTexture(1);
-    fb.world.bindRedTexture(2);
-    fb.world.bindNormalTexture(3);
+    framebuffers.world.bindColorTexture(0);
+    framebuffers.ssaoBlur.bindRedTexture(1);
+    framebuffers.world.bindRedTexture(2);
+    framebuffers.world.bindNormalTexture(3);
     shaders.postWorld.setInt("ssao", renderSettings.ssao);
     shaders.postWorld.setInt("shadows", renderSettings.shadows);
     rectangle.draw();
 }
 
 void Engine::renderTextOverlay(float lag, const Game& game) {
-
     GLWrapper::disableDepthTesting();
     shaders.text.use();
 

+ 1 - 1
client/rendering/Engine.h

@@ -25,7 +25,7 @@ private:
     void updateWorldView();
 
     Shaders& shaders;
-    Framebuffers& fb;
+    Framebuffers& framebuffers;
     const WindowSize& size;
     RenderSettings& renderSettings;
 

+ 4 - 3
client/rendering/Mesh.cpp

@@ -2,9 +2,10 @@
 
 Mesh::Mesh() {
     vertexBuffer.bind();
-    vertexBuffer.setFloatAttribute(0, 3, 0, 8);
-    vertexBuffer.setFloatAttribute(1, 2, 3, 8);
-    vertexBuffer.setFloatAttribute(2, 3, 5, 8);
+    vertexBuffer.setFloatAttribute(0, 3, 0, 11);
+    vertexBuffer.setFloatAttribute(1, 2, 3, 11);
+    vertexBuffer.setFloatAttribute(2, 3, 5, 11);
+    vertexBuffer.setFloatAttribute(3, 3, 8, 11);
 }
 
 void Mesh::add(const Triangle& data) {

+ 5 - 19
client/rendering/NormalTexture.cpp

@@ -4,28 +4,14 @@
 #include "client/rendering/NormalTexture.h"
 #include "client/utils/PNGReader.h"
 
-NormalTexture::NormalTexture(const char* path) : texture(Texture::NEAREST) {
-    u32 maxWidth = 256;
-    u32 maxHeight = 256;
-    u32 buffer[256 * 256];
+NormalTexture::NormalTexture(const char* path) : texture(Texture::LINEAR) {
+    u32 maxWidth = 512;
+    u32 maxHeight = 512;
+    u32* buffer = new u32[maxWidth * maxHeight];
     if(PNGReader::load(path, buffer, maxWidth, maxHeight)) {
-        for(uint x = 0; x < maxWidth; x++) {
-            for(uint y = 0; y < maxHeight; y++) {
-                /*float fx = (x % 16) * (2.0f * M_PIf32 / 15.0f);
-                
-                float fb = (sinf(fx) + 1.0f) * 0.5f;
-                
-                uint r = 0;
-                uint g = sqrtf(1 - fb * fb) * 255.0f;
-                uint b = fb * 255.0f;
-                if(y == 0)
-                    std::cout << x << " " << fb << "\n";
-                buffer[y * maxWidth + x] = (b << 16) | (g << 8) | r;*/
-                buffer[y * maxWidth + x] = 0x00FF00;
-            }
-        }
         texture.setRGBAData(maxWidth, maxHeight, buffer);
     }
+    delete[] buffer;
 }
 
 void NormalTexture::bind(uint index) const {

+ 11 - 1
client/rendering/Triangle.cpp

@@ -4,9 +4,19 @@ Triangle::Triangle() {
 }
 
 Triangle::Triangle(const Vertex& a, const Vertex& b, const Vertex& c) : a(a), b(b), c(c) {
-    Vector3 ac = c.position - a.position;
     Vector3 ab = b.position - a.position;
+    Vector3 ac = c.position - a.position;
     normalA = ab.cross(ac);
     normalB = normalA;
     normalC = normalA;
+    
+    Vector2 abt = b.texture - a.texture;
+    Vector2 act = c.texture - a.texture;
+    
+    float f = 1.0f / (abt[0] * act[1] - act[0] * abt[1]);
+    
+    tangentA = f * (act[1] * ab - abt[1] * ac);
+    tangentA.normalize();
+    tangentB = tangentA;
+    tangentC = tangentA;
 }

+ 3 - 3
client/rendering/Triangle.h

@@ -10,13 +10,13 @@ struct Triangle final {
 private:
     Vertex a;
     Vector3 normalA;
-    //Vector3 tangentA;
+    Vector3 tangentA;
     Vertex b;
     Vector3 normalB;
-    //Vector3 tangentB;
+    Vector3 tangentB;
     Vertex c;
     Vector3 normalC;
-    //Vector3 tangentC;
+    Vector3 tangentC;
 };
 
 #endif

+ 1 - 1
client/rendering/renderer/WorldRenderer.cpp

@@ -1,7 +1,7 @@
 #include "client/rendering/renderer/WorldRenderer.h"
 
 WorldRenderer::WorldRenderer(const World& world) : world(world), texture("resources/textures.png"),
-normalTexture("resources/textures.png") {
+normalTexture("resources/normal.png") {
     for(uint x = 0; x < World::WORLD_SIZE; x++) {
         for(uint y = 0; y < World::WORLD_SIZE; y++) {
             for(uint z = 0; z < World::WORLD_SIZE; z++) {

+ 12 - 7
client/rendering/wrapper/Framebuffer.cpp

@@ -11,22 +11,23 @@ buffer(0), error(false) {
     data[1] = {NORMAL, GL_RGB16F, GL_RGB, GL_FLOAT};
     data[2] = {COLOR, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE};
     data[3] = {RED, GL_R32F, GL_RGB, GL_FLOAT};
-    data[4] = {DEPTH, GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, GL_FLOAT};
+    data[4] = {TANGENT, GL_RGB16F, GL_RGB, GL_FLOAT};
+    data[5] = {DEPTH, GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, GL_FLOAT};
 
-    GLuint attachments[4];
+    GLuint attachments[5];
     uint counter = 0;
-    for(uint i = 0; i < 4; i++) {
+    for(uint i = 0; i < 5; i++) {
         if(mode & data[i].mask) {
             setupTexture(i, size.width, size.height, attachments, counter);
         }
     }
     if(mode & DEPTH) {
-        genTexture(4, size.width, size.height);
+        genTexture(5, size.width, size.height);
         if(texCompare) {
             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
         }
-        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, textures[4], 0);
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, textures[5], 0);
     }
     glDrawBuffers(counter, attachments);
 
@@ -54,7 +55,7 @@ void Framebuffer::bind() const {
 }
 
 void Framebuffer::resize(uint width, uint height) const {
-    for(uint i = 0; i < 5; i++) {
+    for(uint i = 0; i < 6; i++) {
         if(mode & data[i].mask) {
             glBindTexture(GL_TEXTURE_2D, textures[i]);
             glTexImage2D(GL_TEXTURE_2D, 0, data[i].internalFormat, width, height, 0, data[i].format, data[i].type, nullptr);
@@ -83,10 +84,14 @@ void Framebuffer::bindRedTexture(uint textureUnit) const {
     bindTexture(textureUnit, textures[3]);
 }
 
-void Framebuffer::bindDepthTexture(uint textureUnit) const {
+void Framebuffer::bindTangentTexture(uint textureUnit) const {
     bindTexture(textureUnit, textures[4]);
 }
 
+void Framebuffer::bindDepthTexture(uint textureUnit) const {
+    bindTexture(textureUnit, textures[5]);
+}
+
 void Framebuffer::genTexture(uint index, uint width, uint height) {
     glGenTextures(1, textures + index);
     glBindTexture(GL_TEXTURE_2D, textures[index]);

+ 5 - 3
client/rendering/wrapper/Framebuffer.h

@@ -13,7 +13,8 @@ public:
     static const uint NORMAL = 2;
     static const uint COLOR = 4;
     static const uint RED = 8;
-    static const uint DEPTH = 16;
+    static const uint TANGENT = 16;
+    static const uint DEPTH = 32;
 
     Framebuffer(const WindowSize& size, uint mode, bool texCompare = false);
     ~Framebuffer();
@@ -31,6 +32,7 @@ public:
     void bindNormalTexture(uint textureUnit) const;
     void bindColorTexture(uint textureUnit) const;
     void bindRedTexture(uint textureUnit) const;
+    void bindTangentTexture(uint textureUnit) const;
     void bindDepthTexture(uint textureUnit) const;
 
 private:
@@ -40,7 +42,7 @@ private:
     const char* getErrorString(GLenum error) const;
 
     uint mode;
-    Array<GLuint, 5> textures;
+    Array<GLuint, 6> textures;
     GLuint buffer;
     bool error;
 
@@ -50,7 +52,7 @@ private:
         GLenum format;
         GLenum type;
     };
-    Data data[5];
+    Data data[6];
 };
 
 #endif

BIN
resources/normal.png


+ 8 - 2
resources/shader/worldFragment.fs

@@ -13,6 +13,7 @@ in vec3 varPosition;
 in vec2 varTex;
 in vec3 varNormal;
 in vec4 varShadow;
+in vec3 varTangent;
 
 uniform bool shadows;
 uniform float radius;
@@ -42,8 +43,13 @@ const vec3 light = vec3(-0.280166, -0.573576, -0.769751);
 
 void main(void) {
     worldPosition = varPosition;
-    //worldNormal = texture(normalSamp, varTex).xyz; //normalize(varNormal);
-    worldNormal = normalize(varNormal);
+
+    vec3 tangent = normalize(varTangent);
+    vec3 normal = normalize(varNormal);
+    vec3 biTangent = cross(normal, tangent);
+    mat3 tbn = mat3(tangent, biTangent, normal);
+
+    worldNormal = tbn * normalize(texture(normalSamp, varTex).xyz * 2.0 - 1.0);
 
     if(shadows) {
         vec3 pos = varShadow.xyz / varShadow.w;

+ 2 - 2
resources/shader/worldPostFragment.fs

@@ -25,6 +25,6 @@ void main() {
         float f = diffuseLight * texture(shadowSamp, varTex).r;
         color *= f * 0.5 + 0.5;
     }
-    //float diffuseLight = max(dot(texture(worldNormalSamp, varTex).xyz, -light), 0.0);
-    //color *= diffuseLight;
+    float diffuseLight = max(dot(texture(worldNormalSamp, varTex).xyz, -light), 0.0) * 0.5 + 0.5;
+    color *= diffuseLight;
 }  

+ 3 - 0
resources/shader/worldVertex.vs

@@ -3,6 +3,7 @@
 layout (location = 0) in vec3 position;
 layout (location = 1) in vec2 tex;
 layout (location = 2) in vec3 normal;
+layout (location = 3) in vec3 tangent;
 
 uniform mat4 proj;
 uniform mat4 view;
@@ -14,11 +15,13 @@ out vec3 varPosition;
 out vec2 varTex;
 out vec3 varNormal;
 out vec4 varShadow;
+out vec3 varTangent;
 
 void main(void) { 
     // transforming normals must not use the fourth dimension
     // should be the inverse transposed matrix
     varNormal = (model * vec4(normal, 0.0)).xyz;
+    varTangent = (model * vec4(tangent, 0.0)).xyz;
     
     varTex = tex;