diff --git a/res/shaders/effect.glslf b/res/shaders/effect.glslf index be50d779..2b6307ef 100644 --- a/res/shaders/effect.glslf +++ b/res/shaders/effect.glslf @@ -4,6 +4,7 @@ out vec4 f_color; uniform sampler2D u_screen; uniform sampler2D u_position; uniform sampler2D u_normal; +uniform sampler2D u_emission; uniform sampler2D u_noise; uniform sampler2D u_ssao; uniform samplerCube u_skybox; diff --git a/res/shaders/effects/deferred_lighting.glsl b/res/shaders/effects/deferred_lighting.glsl index f21b1b4a..5df6b148 100644 --- a/res/shaders/effects/deferred_lighting.glsl +++ b/res/shaders/effects/deferred_lighting.glsl @@ -16,7 +16,7 @@ vec4 effect() { vec3 normal = transpose(mat3(u_view)) * texture(u_normal, v_uv).xyz; vec3 dir = modelpos.xyz - u_cameraPos; #ifdef ENABLE_SHADOWS - ssao *= calc_shadow(modelpos, normal, length(pos)); + ssao *= max(calc_shadow(modelpos, normal, length(pos)), texture(u_emission, v_uv).r); #endif vec3 fogColor = texture(u_skybox, dir).rgb; float fog = calc_fog(length(u_view * vec4((modelpos.xyz - u_cameraPos) * FOG_POS_SCALE, 0.0)) / 256.0); diff --git a/res/shaders/effects/ssao.glsl b/res/shaders/effects/ssao.glsl index 399f2fde..508d74e7 100644 --- a/res/shaders/effects/ssao.glsl +++ b/res/shaders/effects/ssao.glsl @@ -29,6 +29,7 @@ vec4 effect() { occlusion += (sampleDepth >= samplePos.z + u_bias ? 1.0 : 0.0) * rangeCheck; } occlusion = min(1.0, 1.05 - (occlusion / u_kernelSize)); + occlusion = max(occlusion, texture(u_emission, v_uv).r); float z = -position.z * 0.01; z = max(0.0, 1.0 - z); diff --git a/res/shaders/entity.glslf b/res/shaders/entity.glslf index 7c916955..f9675708 100644 --- a/res/shaders/entity.glslf +++ b/res/shaders/entity.glslf @@ -1,6 +1,7 @@ layout (location = 0) out vec4 f_color; layout (location = 1) out vec4 f_position; layout (location = 2) out vec4 f_normal; +layout (location = 3) out vec4 f_emission; in float a_distance; in float a_fog; @@ -40,4 +41,5 @@ void main() { f_color.a = alpha; f_position = vec4(a_position, 1.0); f_normal = vec4(a_normal, 1.0); + f_emission = vec4(0.0); } diff --git a/res/shaders/main.glslf b/res/shaders/main.glslf index ff6816a7..39797aa0 100644 --- a/res/shaders/main.glslf +++ b/res/shaders/main.glslf @@ -1,6 +1,7 @@ layout (location = 0) out vec4 f_color; layout (location = 1) out vec4 f_position; layout (location = 2) out vec4 f_normal; +layout (location = 3) out vec4 f_emission; in float a_distance; in float a_fog; @@ -12,6 +13,7 @@ in vec3 a_realnormal; in vec3 a_skyLight; in vec4 a_modelpos; in vec4 a_torchLight; +in float a_emission; uniform sampler2D u_texture0; uniform samplerCube u_skybox; @@ -47,8 +49,8 @@ void main() { vec3 fogColor = texture(u_skybox, a_dir).rgb; f_color = mix(f_color, vec4(fogColor, 1.0), a_fog); #endif - f_color.a = alpha; f_position = vec4(a_position, 1.0); f_normal = vec4(a_normal, 1.0); + f_emission = vec4(a_emission); } diff --git a/res/shaders/main.glslv b/res/shaders/main.glslv index 927b8519..8fd38d20 100644 --- a/res/shaders/main.glslv +++ b/res/shaders/main.glslv @@ -15,6 +15,7 @@ out vec3 a_realnormal; out vec4 a_torchLight; out vec3 a_skyLight; out vec4 a_modelpos; +out float a_emission; uniform mat4 u_model; uniform mat4 u_proj; @@ -51,6 +52,7 @@ void main() { mat4 viewmodel = u_view * u_model; a_distance = length(viewmodel * vec4(pos3d, 0.0)); a_fog = calc_fog(length(viewmodel * vec4(pos3d * FOG_POS_SCALE, 0.0)) / 256.0); + a_emission = v_normal.w; vec4 viewmodelpos = u_view * a_modelpos; a_position = viewmodelpos.xyz; diff --git a/src/graphics/core/GBuffer.cpp b/src/graphics/core/GBuffer.cpp index 8b154e91..6307a353 100644 --- a/src/graphics/core/GBuffer.cpp +++ b/src/graphics/core/GBuffer.cpp @@ -8,6 +8,8 @@ using namespace advanced_pipeline; static debug::Logger logger("gl-gbuffer"); +// TODO: REFACTOR + void GBuffer::createColorBuffer() { glGenTextures(1, &colorBuffer); glBindTexture(GL_TEXTURE_2D, colorBuffer); @@ -64,7 +66,7 @@ void GBuffer::createNormalsBuffer() { width, height, 0, - GL_RGBA, + GL_RGB, GL_FLOAT, nullptr ); @@ -77,6 +79,29 @@ void GBuffer::createNormalsBuffer() { ); } +void GBuffer::createEmissionBuffer() { + glGenTextures(1, &emissionBuffer); + glBindTexture(GL_TEXTURE_2D, emissionBuffer); + glTexImage2D( + GL_TEXTURE_2D, + 0, + GL_R8, + width, + height, + 0, + GL_RED, + GL_FLOAT, + nullptr + ); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_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_ATTACHMENT3, GL_TEXTURE_2D, emissionBuffer, 0 + ); +} + void GBuffer::createDepthBuffer() { glGenRenderbuffers(1, &depthBuffer); glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer); @@ -113,16 +138,21 @@ GBuffer::GBuffer(uint width, uint height) : width(width), height(height) { createColorBuffer(); createPositionsBuffer(); createNormalsBuffer(); + createEmissionBuffer(); - GLenum attachments[3] = { - GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 + GLenum attachments[4] = { + GL_COLOR_ATTACHMENT0, + GL_COLOR_ATTACHMENT1, + GL_COLOR_ATTACHMENT2, + GL_COLOR_ATTACHMENT3, }; - glDrawBuffers(3, attachments); + glDrawBuffers(4, attachments); createDepthBuffer(); - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { - logger.error() << "gbuffer is not complete!"; + int status; + if ((status = glCheckFramebufferStatus(GL_FRAMEBUFFER)) != GL_FRAMEBUFFER_COMPLETE) { + logger.error() << "gbuffer is not complete! (" << status << ")"; } glBindFramebuffer(GL_FRAMEBUFFER, 0); @@ -134,8 +164,10 @@ GBuffer::GBuffer(uint width, uint height) : width(width), height(height) { ); GLenum ssaoAttachments[1] = {GL_COLOR_ATTACHMENT0}; glDrawBuffers(1, ssaoAttachments); - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { - logger.error() << "SSAO framebuffer is not complete!"; + + + if ((status = glCheckFramebufferStatus(GL_FRAMEBUFFER)) != GL_FRAMEBUFFER_COMPLETE) { + logger.error() << "SSAO framebuffer is not complete! (" << status << ")"; } glBindFramebuffer(GL_FRAMEBUFFER, 0); } @@ -144,6 +176,7 @@ GBuffer::~GBuffer() { glDeleteTextures(1, &colorBuffer); glDeleteTextures(1, &positionsBuffer); glDeleteTextures(1, &normalsBuffer); + glDeleteTextures(1, &emissionBuffer); glDeleteTextures(1, &ssaoBuffer); glDeleteRenderbuffers(1, &depthBuffer); glDeleteFramebuffers(1, &fbo); @@ -164,6 +197,9 @@ void GBuffer::unbind() { } void GBuffer::bindBuffers() const { + glActiveTexture(GL_TEXTURE0 + TARGET_EMISSION); + glBindTexture(GL_TEXTURE_2D, emissionBuffer); + glActiveTexture(GL_TEXTURE0 + TARGET_NORMALS); glBindTexture(GL_TEXTURE_2D, normalsBuffer); @@ -227,12 +263,20 @@ void GBuffer::resize(uint width, uint height) { glBindTexture(GL_TEXTURE_2D, normalsBuffer); glTexImage2D( - GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGB, GL_FLOAT, nullptr + GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGBA, GL_FLOAT, nullptr ); glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, normalsBuffer, 0 ); + glBindTexture(GL_TEXTURE_2D, emissionBuffer); + glTexImage2D( + GL_TEXTURE_2D, 0, GL_INTENSITY, width, height, 0, GL_LUMINANCE, GL_FLOAT, nullptr + ); + glFramebufferTexture2D( + GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, emissionBuffer, 0 + ); + glBindTexture(GL_TEXTURE_2D, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0); diff --git a/src/graphics/core/GBuffer.hpp b/src/graphics/core/GBuffer.hpp index ec3cc045..fa3e13b3 100644 --- a/src/graphics/core/GBuffer.hpp +++ b/src/graphics/core/GBuffer.hpp @@ -32,6 +32,7 @@ private: uint colorBuffer; uint positionsBuffer; uint normalsBuffer; + uint emissionBuffer; uint depthBuffer; uint ssaoFbo; uint ssaoBuffer; @@ -39,6 +40,7 @@ private: void createColorBuffer(); void createPositionsBuffer(); void createNormalsBuffer(); + void createEmissionBuffer(); void createDepthBuffer(); void createSSAOBuffer(); }; diff --git a/src/graphics/core/PostProcessing.cpp b/src/graphics/core/PostProcessing.cpp index 1c343006..85b56067 100644 --- a/src/graphics/core/PostProcessing.cpp +++ b/src/graphics/core/PostProcessing.cpp @@ -102,6 +102,7 @@ void PostProcessing::configureEffect( if (gbuffer) { shader.uniform1i("u_position", TARGET_POSITIONS); shader.uniform1i("u_normal", TARGET_NORMALS); + shader.uniform1i("u_emission", TARGET_EMISSION); } shader.uniform1i("u_noise", TARGET_SSAO); // used in SSAO pass shader.uniform1i("u_ssao", TARGET_SSAO); diff --git a/src/graphics/core/commons.hpp b/src/graphics/core/commons.hpp index ffc89068..8785cec1 100644 --- a/src/graphics/core/commons.hpp +++ b/src/graphics/core/commons.hpp @@ -55,9 +55,10 @@ namespace advanced_pipeline { inline constexpr int TARGET_SKYBOX = 1; inline constexpr int TARGET_POSITIONS = 2; inline constexpr int TARGET_NORMALS = 3; - inline constexpr int TARGET_SSAO = 4; - inline constexpr int TARGET_SHADOWS0 = 5; - inline constexpr int TARGET_SHADOWS1 = 6; + inline constexpr int TARGET_EMISSION = 4; + inline constexpr int TARGET_SSAO = 5; + inline constexpr int TARGET_SHADOWS0 = 6; + inline constexpr int TARGET_SHADOWS1 = 7; } VC_ENUM_METADATA(CursorShape) diff --git a/src/graphics/render/BlocksRenderer.cpp b/src/graphics/render/BlocksRenderer.cpp index f7b1abe1..2fedd15b 100644 --- a/src/graphics/render/BlocksRenderer.cpp +++ b/src/graphics/render/BlocksRenderer.cpp @@ -39,9 +39,13 @@ BlocksRenderer::~BlocksRenderer() { /// Basic vertex add method void BlocksRenderer::vertex( - const glm::vec3& coord, float u, float v, const glm::vec4& light, const glm::vec3& normal + const glm::vec3& coord, + float u, + float v, + const glm::vec4& light, + const glm::vec3& normal, + float emission ) { - vertexBuffer[vertexCount].position = coord; vertexBuffer[vertexCount].uv = {u,v}; @@ -49,11 +53,13 @@ void BlocksRenderer::vertex( vertexBuffer[vertexCount].normal[0] = static_cast(normal.r * 127 + 128); vertexBuffer[vertexCount].normal[1] = static_cast(normal.g * 127 + 128); vertexBuffer[vertexCount].normal[2] = static_cast(normal.b * 127 + 128); + vertexBuffer[vertexCount].normal[3] = static_cast(emission * 255); vertexBuffer[vertexCount].color[0] = static_cast(light.r * 255); vertexBuffer[vertexCount].color[1] = static_cast(light.g * 255); vertexBuffer[vertexCount].color[2] = static_cast(light.b * 255); vertexBuffer[vertexCount].color[3] = static_cast(light.a * 255); + vertexCount++; } @@ -86,10 +92,10 @@ void BlocksRenderer::face( auto Y = axisY * h; auto Z = axisZ * d; float s = 0.5f; - vertex(coord + (-X - Y + Z) * s, region.u1, region.v1, lights[0] * tint, axisZ); - vertex(coord + ( X - Y + Z) * s, region.u2, region.v1, lights[1] * tint, axisZ); - vertex(coord + ( X + Y + Z) * s, region.u2, region.v2, lights[2] * tint, axisZ); - vertex(coord + (-X + Y + Z) * s, region.u1, region.v2, lights[3] * tint, axisZ); + vertex(coord + (-X - Y + Z) * s, region.u1, region.v1, lights[0] * tint, axisZ, 0); + vertex(coord + ( X - Y + Z) * s, region.u2, region.v1, lights[1] * tint, axisZ, 0); + vertex(coord + ( X + Y + Z) * s, region.u2, region.v2, lights[2] * tint, axisZ, 0); + vertex(coord + (-X + Y + Z) * s, region.u1, region.v2, lights[3] * tint, axisZ, 0); index(0, 1, 3, 1, 2, 3); } @@ -107,7 +113,7 @@ void BlocksRenderer::vertexAO( axisX, axisY ); - vertex(coord, u, v, light * tint, axisZ); + vertex(coord, u, v, light * tint, axisZ, 0.0f); } void BlocksRenderer::faceAO( @@ -140,10 +146,10 @@ void BlocksRenderer::faceAO( } else { auto axisZ = glm::normalize(Z); glm::vec4 tint(1.0f); - vertex(coord + (-X - Y + Z) * s, region.u1, region.v1, tint, axisZ); - vertex(coord + ( X - Y + Z) * s, region.u2, region.v1, tint, axisZ); - vertex(coord + ( X + Y + Z) * s, region.u2, region.v2, tint, axisZ); - vertex(coord + (-X + Y + Z) * s, region.u1, region.v2, tint, axisZ); + vertex(coord + (-X - Y + Z) * s, region.u1, region.v1, tint, axisZ, 1); + vertex(coord + ( X - Y + Z) * s, region.u2, region.v1, tint, axisZ, 1); + vertex(coord + ( X + Y + Z) * s, region.u2, region.v2, tint, axisZ, 1); + vertex(coord + (-X + Y + Z) * s, region.u1, region.v2, tint, axisZ, 1); } index(0, 1, 2, 0, 2, 3); } @@ -168,10 +174,10 @@ void BlocksRenderer::face( d = (1.0f - DIRECTIONAL_LIGHT_FACTOR) + d * DIRECTIONAL_LIGHT_FACTOR; tint *= d; } - vertex(coord + (-X - Y + Z) * s, region.u1, region.v1, tint, Z); - vertex(coord + ( X - Y + Z) * s, region.u2, region.v1, tint, Z); - vertex(coord + ( X + Y + Z) * s, region.u2, region.v2, tint, Z); - vertex(coord + (-X + Y + Z) * s, region.u1, region.v2, tint, Z); + vertex(coord + (-X - Y + Z) * s, region.u1, region.v1, tint, Z, lights ? 0 : 1); + vertex(coord + ( X - Y + Z) * s, region.u2, region.v1, tint, Z, lights ? 0 : 1); + vertex(coord + ( X + Y + Z) * s, region.u2, region.v2, tint, Z, lights ? 0 : 1); + vertex(coord + (-X + Y + Z) * s, region.u1, region.v2, tint, Z, lights ? 0 : 1); index(0, 1, 2, 0, 2, 3); } @@ -345,7 +351,8 @@ void BlocksRenderer::blockCustomModel( vertex.uv.x, vertex.uv.y, glm::vec4(d, d, d, d) * aoColor, - n + n, + 0.0f ); indexBuffer[indexCount++] = vertexOffset++; } diff --git a/src/graphics/render/BlocksRenderer.hpp b/src/graphics/render/BlocksRenderer.hpp index 0bb9b31d..b017a3f3 100644 --- a/src/graphics/render/BlocksRenderer.hpp +++ b/src/graphics/render/BlocksRenderer.hpp @@ -44,7 +44,14 @@ class BlocksRenderer { SortingMeshData sortingMesh; - void vertex(const glm::vec3& coord, float u, float v, const glm::vec4& light, const glm::vec3& normal); + void vertex( + const glm::vec3& coord, + float u, + float v, + const glm::vec4& light, + const glm::vec3& normal, + float emission + ); void index(uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint32_t e, uint32_t f); void vertexAO(