mirror of
https://github.com/antopilo/Nuake.git
synced 2026-09-04 11:35:06 +03:00
Added SSAO
This commit is contained in:
36
Editor/resources/Shaders/blur.shader
Normal file
36
Editor/resources/Shaders/blur.shader
Normal file
@@ -0,0 +1,36 @@
|
||||
#shader vertex
|
||||
#version 460 core
|
||||
|
||||
layout(location = 0) in vec3 VertexPosition;
|
||||
layout(location = 1) in vec2 UVPosition;
|
||||
|
||||
out flat vec2 UV;
|
||||
|
||||
void main()
|
||||
{
|
||||
UV = UVPosition;
|
||||
gl_Position = vec4(VertexPosition, 1.0f);
|
||||
}
|
||||
|
||||
#shader fragment
|
||||
#version 460 core
|
||||
out vec4 FragColor;
|
||||
|
||||
in vec2 UV;
|
||||
|
||||
uniform sampler2D u_Input;
|
||||
|
||||
void main() {
|
||||
vec2 texelSize = 1.0 / vec2(textureSize(u_Input, 0));
|
||||
float result = 0.0;
|
||||
for (int x = -2; x < 2; ++x)
|
||||
{
|
||||
for (int y = -2; y < 2; ++y)
|
||||
{
|
||||
vec2 offset = vec2(float(x), float(y)) * texelSize;
|
||||
result += texture(u_Input, UV + offset).r;
|
||||
}
|
||||
}
|
||||
float channel = result / (4.0 * 4.0);
|
||||
FragColor = vec4(channel, channel, channel, 1.0);
|
||||
}
|
||||
@@ -37,6 +37,7 @@ uniform sampler2D m_Depth;
|
||||
uniform sampler2D m_Albedo;
|
||||
uniform sampler2D m_Material;
|
||||
uniform sampler2D m_Normal;
|
||||
uniform sampler2D m_SSAO;
|
||||
|
||||
// Lights
|
||||
const int MaxLight = 29;
|
||||
@@ -221,7 +222,7 @@ void main()
|
||||
float metallic = texture(m_Material, UV).r;
|
||||
float roughness = texture(m_Material, UV).b;
|
||||
float ao = texture(m_Material, UV).g;
|
||||
|
||||
float ssao = texture(m_SSAO, UV).r;
|
||||
vec3 N = normal;
|
||||
vec3 V = normalize(u_EyePosition - worldPos);
|
||||
vec3 R = reflect(-V, N);
|
||||
@@ -280,8 +281,8 @@ void main()
|
||||
vec3 kD = 1.0 - kS;
|
||||
kD *= 1.0 - metallic;
|
||||
|
||||
vec3 ambient = (kD * albedo) * ao;
|
||||
vec3 color = ambient + Lo;
|
||||
vec3 ambient = (kD * albedo) * (ao);
|
||||
vec3 color = (ambient * ssao) + Lo;
|
||||
|
||||
// Display CSM splits..
|
||||
/*float depth = length(worldPos - u_EyePosition);
|
||||
|
||||
115
Editor/resources/Shaders/ssao.shader
Normal file
115
Editor/resources/Shaders/ssao.shader
Normal file
@@ -0,0 +1,115 @@
|
||||
#shader vertex
|
||||
#version 460 core
|
||||
|
||||
layout(location = 0) in vec3 VertexPosition;
|
||||
layout(location = 1) in vec2 UVPosition;
|
||||
|
||||
out flat vec2 UV;
|
||||
out mat4 v_InvView;
|
||||
out mat4 v_InvProjection;
|
||||
out mat4 v_View;
|
||||
|
||||
uniform mat4 u_View;
|
||||
uniform mat4 u_Projection;
|
||||
|
||||
void main()
|
||||
{
|
||||
v_View = u_View;
|
||||
v_InvView = inverse(u_View);
|
||||
v_InvProjection = inverse(u_Projection);
|
||||
|
||||
UV = UVPosition;
|
||||
gl_Position = vec4(VertexPosition, 1.0f);
|
||||
}
|
||||
|
||||
#shader fragment
|
||||
#version 460 core
|
||||
|
||||
uniform sampler2D u_Depth;
|
||||
uniform sampler2D u_Normal;
|
||||
uniform sampler2D u_Noise;
|
||||
|
||||
uniform int u_KernelSize = 64;
|
||||
|
||||
uniform vec3 u_Samples[64];
|
||||
uniform mat4 u_Projection;
|
||||
uniform vec2 u_NoiseScale;
|
||||
uniform float u_Radius = 0.5f;
|
||||
uniform float u_Bias = 0.025f;
|
||||
uniform float u_Area;
|
||||
in vec2 UV;
|
||||
in mat4 v_View;
|
||||
in mat4 v_InvView;
|
||||
in mat4 v_InvProjection;
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
vec3 WorldPosFromDepth(float depth)
|
||||
{
|
||||
float z = depth * 2.0 - 1.0;
|
||||
|
||||
vec4 clipSpacePosition = vec4(UV * 2.0 - 1.0, z, 1.0);
|
||||
vec4 viewSpacePosition = v_InvProjection * clipSpacePosition;
|
||||
|
||||
// Perspective division
|
||||
viewSpacePosition /= viewSpacePosition.w;
|
||||
|
||||
vec4 worldSpacePosition = v_InvView * viewSpacePosition;
|
||||
|
||||
return worldSpacePosition.xyz;
|
||||
}
|
||||
|
||||
vec3 ViewPosFromDepth(float depth)
|
||||
{
|
||||
float z = depth * 2.0 - 1.0;
|
||||
|
||||
vec4 clipSpacePosition = vec4(UV * 2.0 - 1.0, z, 1.0);
|
||||
vec4 viewSpacePosition = v_InvProjection * clipSpacePosition;
|
||||
viewSpacePosition.xyz /= viewSpacePosition.w;
|
||||
|
||||
return viewSpacePosition.xyz;
|
||||
}
|
||||
|
||||
vec3 normal_from_depth(float depth, vec2 texcoords) {
|
||||
|
||||
const vec2 offset1 = vec2(0.0,0.0002);
|
||||
const vec2 offset2 = vec2(0.0002,0.0);
|
||||
|
||||
float depth1 = texture(u_Depth, UV + offset1).r;
|
||||
float depth2 = texture(u_Depth, UV + offset2).r;
|
||||
|
||||
vec3 p1 = vec3(offset1, depth1 - depth);
|
||||
vec3 p2 = vec3(offset2, depth2 - depth);
|
||||
|
||||
vec3 normal = cross(p1, p2);
|
||||
normal.z = -normal.z;
|
||||
|
||||
return normalize(normal);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
float depth = texture(u_Depth, UV).r ;
|
||||
vec3 fragPos = ViewPosFromDepth(depth);
|
||||
|
||||
vec3 normal = normal_from_depth(depth, UV) ;
|
||||
vec3 randomVec = texture(u_Noise, UV * u_NoiseScale).xyz;
|
||||
float radius_depth = u_Radius/depth;
|
||||
float occlusion = 0.0;
|
||||
vec3 position = vec3(UV, depth);
|
||||
const float falloff = 0.0002;
|
||||
const float area = 0.0075;
|
||||
for(int i=0; i < 64; i++)
|
||||
{
|
||||
vec3 ray = radius_depth * reflect(u_Samples[i], randomVec);
|
||||
vec3 hemi_ray = position + sign(dot(ray,normal)) * ray;
|
||||
|
||||
float occ_depth = texture(u_Depth, hemi_ray.xy).r;
|
||||
float difference = depth - occ_depth ;
|
||||
occlusion += step(falloff, difference) * (1.0 - smoothstep(falloff, u_Bias, difference));
|
||||
}
|
||||
|
||||
float ao = 1.0 - 2.0 * occlusion * (1.0 / 64);
|
||||
|
||||
FragColor = vec4(ao, ao, ao , 1.0);
|
||||
}
|
||||
@@ -507,6 +507,41 @@ namespace Nuake {
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
|
||||
if (env->SSAOEnabled)
|
||||
{
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
// Title
|
||||
ImGui::Text("SSAO Radius");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::DragFloat("##SSAORadius", &env->mSSAO->Radius, 0.01f, 0.0f, 1.0f);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
// Reset button
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0));
|
||||
std::string resetRadius = ICON_FA_UNDO + std::string("##resetRadius");
|
||||
if (ImGui::Button(resetRadius.c_str())) env->mSSAO->Radius = 0.5f;
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
// Title
|
||||
ImGui::Text("SSAO Bias");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::DragFloat("##SSAOBias", &env->mSSAO->Bias, 0.0001f, 0.0f, 0.5f);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
// Reset button
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0));
|
||||
std::string resetBloomThreshold = ICON_FA_UNDO + std::string("##resetSSAOBias");
|
||||
if (ImGui::Button(resetBloomThreshold.c_str())) env->mSSAO->Bias = 0.025f;
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
}
|
||||
|
||||
if (env->BloomEnabled)
|
||||
{
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
@@ -1,5 +1,143 @@
|
||||
#include "SSAO.h"
|
||||
#include "src/Core/Core.h"
|
||||
#include "src/Rendering/Textures/Texture.h"
|
||||
#include <src/Rendering/Shaders/Shader.h>
|
||||
#include "src/Rendering/Shaders/ShaderManager.h"
|
||||
#include "src/Rendering/Renderer.h"
|
||||
|
||||
namespace Nuake {
|
||||
#include <GL\glew.h>
|
||||
|
||||
#include <random>
|
||||
#include <src/Vendors/imgui/imgui.h>
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
SSAO::SSAO()
|
||||
{
|
||||
GenerateKernel();
|
||||
GenerateNoise();
|
||||
|
||||
_size = { 1280, 720 };
|
||||
|
||||
_ssaoFramebuffer = CreateRef<FrameBuffer>(false, Vector2(_size));
|
||||
|
||||
auto& renderTarget = CreateRef<Texture>(_size, GL_RGBA, GL_RGBA16F, GL_FLOAT);
|
||||
_ssaoFramebuffer->SetTexture(renderTarget, GL_COLOR_ATTACHMENT0);
|
||||
|
||||
_ssaoBlurFramebuffer = CreateRef<FrameBuffer>(false, Vector2(_size));
|
||||
|
||||
auto& renderTargetBlur = CreateRef<Texture>(_size, GL_RGBA, GL_RGBA16F, GL_FLOAT);
|
||||
_ssaoBlurFramebuffer->SetTexture(renderTargetBlur);
|
||||
}
|
||||
|
||||
void SSAO::Resize(const Vector2& size)
|
||||
{
|
||||
if (_size == size)
|
||||
return;
|
||||
|
||||
_size = size;
|
||||
_ssaoFramebuffer->QueueResize(size);
|
||||
_ssaoBlurFramebuffer->QueueResize(size);
|
||||
}
|
||||
|
||||
void SSAO::GenerateKernel()
|
||||
{
|
||||
std::uniform_real_distribution<float> randomFloats(0.0, 1.0); // random floats between [0.0, 1.0]
|
||||
std::default_random_engine generator;
|
||||
std::vector<glm::vec3> ssaoKernel;
|
||||
for (unsigned int i = 0; i < 64; ++i)
|
||||
{
|
||||
glm::vec3 sample(
|
||||
randomFloats(generator) * 2.0 - 1.0,
|
||||
randomFloats(generator) * 2.0 - 1.0,
|
||||
randomFloats(generator)
|
||||
);
|
||||
|
||||
sample = glm::normalize(sample);
|
||||
sample *= randomFloats(generator);
|
||||
|
||||
float scale = (float)i / 64.0;
|
||||
scale = lerp(0.1f, 1.0f, scale * scale);
|
||||
sample *= scale;
|
||||
_ssaoKernel.push_back(sample);
|
||||
}
|
||||
}
|
||||
|
||||
void SSAO::GenerateNoise()
|
||||
{
|
||||
std::uniform_real_distribution<float> randomFloats(0.0, 1.0);
|
||||
std::default_random_engine generator;
|
||||
|
||||
for (unsigned int i = 0; i < 16; i++)
|
||||
{
|
||||
glm::vec3 noise(
|
||||
randomFloats(generator) * 2.0 - 1.0,
|
||||
randomFloats(generator) * 2.0 - 1.0,
|
||||
0.0f);
|
||||
_ssaoNoise.push_back(noise);
|
||||
}
|
||||
|
||||
_ssaoNoiseTexture = CreateRef<Texture>(Vector2(4, 4), GL_RGB, GL_RGBA16F, GL_FLOAT, &_ssaoNoise[0]);
|
||||
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);
|
||||
}
|
||||
|
||||
void SSAO::Draw(FrameBuffer* gBuffer, const Matrix4& projection, const Matrix4& view)
|
||||
{
|
||||
_ssaoFramebuffer->Bind();
|
||||
{
|
||||
_ssaoFramebuffer->Clear();
|
||||
const auto& depthTexture = gBuffer->GetTexture(GL_DEPTH_ATTACHMENT);
|
||||
const auto& normalTexture = gBuffer->GetTexture(GL_COLOR_ATTACHMENT1);
|
||||
Shader* shader = ShaderManager::GetShader("resources/Shaders/ssao.shader");
|
||||
shader->Bind();
|
||||
shader->SetUniformMat4f("u_Projection", projection);
|
||||
shader->SetUniformMat4f("u_View", view);
|
||||
shader->SetUniformTex("u_Depth", depthTexture.get(), 2);
|
||||
shader->SetUniformTex("u_Normal", normalTexture.get(), 3);
|
||||
shader->SetUniformTex("u_Noise", _ssaoNoiseTexture.get(), 6);
|
||||
shader->SetUniform1i("u_KernelSize", 64);
|
||||
shader->SetUniform1f("u_Radius", Radius);
|
||||
shader->SetUniform1f("u_Bias", Bias);
|
||||
shader->SetUniformVec2("u_NoiseScale", Vector2(_size.x / 4, _size.y / 4) );
|
||||
|
||||
int i = 0;
|
||||
for (const auto& k : _ssaoKernel)
|
||||
{
|
||||
const std::string& uniformName = "u_Samples[" + std::to_string(i) + "]";
|
||||
shader->SetUniform3f(uniformName, k.x, k.y, k.z);
|
||||
i++;
|
||||
}
|
||||
|
||||
//shader->SetUniform1fv("u_Samples", 64 * 3, (float*)&(_ssaoKernel.begin()));
|
||||
Renderer::DrawQuad(Matrix4(1.0));
|
||||
}
|
||||
_ssaoFramebuffer->Unbind();
|
||||
|
||||
_ssaoBlurFramebuffer->Bind();
|
||||
{
|
||||
Shader* shader = ShaderManager::GetShader("resources/Shaders/blur.shader");
|
||||
shader->Bind();
|
||||
|
||||
shader->SetUniformTex("u_Input", _ssaoFramebuffer->GetTexture().get(), 2);
|
||||
|
||||
Renderer::DrawQuad(Matrix4(1.0));
|
||||
}
|
||||
_ssaoBlurFramebuffer->Unbind();
|
||||
|
||||
/*
|
||||
if (ImGui::Begin("SSAO debug"))
|
||||
{
|
||||
ImGui::Image((void*)(uintptr_t)(_ssaoFramebuffer->GetTexture(GL_COLOR_ATTACHMENT0)->GetID()), ImGui::GetContentRegionAvail(), ImVec2(0, 1), ImVec2(1, 0));
|
||||
}
|
||||
ImGui::End();
|
||||
*/
|
||||
}
|
||||
|
||||
Ref<FrameBuffer> SSAO::GetOuput() const
|
||||
{
|
||||
return _ssaoBlurFramebuffer;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,38 @@
|
||||
#pragma once
|
||||
#include "src/Core/Maths.h"
|
||||
#include "src/Core/Core.h"
|
||||
#include "src/Rendering/Buffers/Framebuffer.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace Nuake {
|
||||
class SSAO {
|
||||
namespace Nuake
|
||||
{
|
||||
class SSAO
|
||||
{
|
||||
private:
|
||||
std::vector<glm::f32vec3> _ssaoKernel;
|
||||
std::vector<Vector3> _ssaoNoise;
|
||||
|
||||
Ref<FrameBuffer> _ssaoFramebuffer;
|
||||
Ref<FrameBuffer> _ssaoBlurFramebuffer;
|
||||
Ref<Texture> _ssaoNoiseTexture;
|
||||
|
||||
Vector2 _size;
|
||||
|
||||
void GenerateKernel();
|
||||
void GenerateNoise();
|
||||
float lerp(float a, float b, float f)
|
||||
{
|
||||
return a + f * (b - a);
|
||||
}
|
||||
|
||||
public:
|
||||
float Radius = 0.07f;
|
||||
float Bias = 0.003f;
|
||||
|
||||
void Resize(const Vector2& size);
|
||||
SSAO();
|
||||
void Draw(FrameBuffer* gBuffer, const Matrix4& projection, const Matrix4& view);
|
||||
Ref<FrameBuffer> GetOuput() const;
|
||||
};
|
||||
}
|
||||
@@ -64,6 +64,7 @@ namespace Nuake {
|
||||
Renderer::DrawQuad();
|
||||
mFinalFramebuffer->Unbind();
|
||||
|
||||
/*
|
||||
if (ImGui::Begin("Volumetric debug"))
|
||||
{
|
||||
ImGui::Image((void*)(uintptr_t)(mFinalFramebuffer->GetTexture()->GetID()), ImGui::GetContentRegionAvail(), ImVec2(0, 1), ImVec2(1, 0));
|
||||
@@ -73,6 +74,7 @@ namespace Nuake {
|
||||
{
|
||||
ImGui::Image((void*)(uintptr_t)(mDepth->GetID()), ImGui::GetContentRegionAvail(), ImVec2(0, 1), ImVec2(1, 0));
|
||||
}
|
||||
*/
|
||||
ImGui::End();
|
||||
}
|
||||
}
|
||||
@@ -90,7 +90,10 @@ namespace Nuake {
|
||||
}
|
||||
|
||||
finalOutput = framebuffer.GetTexture().get();
|
||||
|
||||
// SSAO
|
||||
sceneEnv->mSSAO->Resize(framebuffer.GetSize());
|
||||
sceneEnv->mSSAO->Draw(mGBuffer.get(), mProjection, mView);
|
||||
|
||||
// Copy final output to target framebuffer
|
||||
mToneMapBuffer->QueueResize(framebuffer.GetSize());
|
||||
mToneMapBuffer->Bind();
|
||||
@@ -253,6 +256,8 @@ namespace Nuake {
|
||||
shadingShader->SetUniformMat4f("u_View", mView);
|
||||
shadingShader->SetUniformVec3("u_EyePosition", scene.GetCurrentCamera()->Translation);
|
||||
|
||||
shadingShader->SetUniformTex("m_SSAO", scene.GetEnvironment()->mSSAO->GetOuput()->GetTexture().get(), 9);
|
||||
|
||||
Ref<Environment> env = scene.GetEnvironment();
|
||||
|
||||
auto view = scene.m_Registry.view<TransformComponent, LightComponent, ParentComponent>();
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace Nuake
|
||||
std::cout << "Error: failed to load texture: " << path << std::endl;
|
||||
}
|
||||
|
||||
Texture::Texture(glm::vec2 size, GLenum format, GLenum format2, GLenum format3)
|
||||
Texture::Texture(glm::vec2 size, GLenum format, GLenum format2, GLenum format3, void* data)
|
||||
{
|
||||
m_RendererId = 0;
|
||||
m_Format = format;
|
||||
@@ -54,7 +54,7 @@ namespace Nuake
|
||||
|
||||
glGenTextures(1, &m_RendererId);
|
||||
glBindTexture(GL_TEXTURE_2D, m_RendererId);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, format2, size.x, size.y, 0, format, format3, NULL);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, format2, size.x, size.y, 0, format, format3, data);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace Nuake
|
||||
public:
|
||||
Texture(const std::string& path);
|
||||
Texture(glm::vec2 size, msdfgen::BitmapConstRef<unsigned char, 4>& bitmap, bool t);
|
||||
Texture(glm::vec2 size, GLenum format, GLenum format2 = 0, GLenum format3 = 0);
|
||||
Texture(glm::vec2 size, GLenum format, GLenum format2 = 0, GLenum format3 = 0, void* data = NULL);
|
||||
Texture(Vector2 size, unsigned char* data, int len);
|
||||
~Texture();
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace Nuake {
|
||||
ProceduralSkybox = CreateRef<ProceduralSky>();
|
||||
mBloom = CreateScope<Bloom>(4);
|
||||
mVolumetric = CreateScope<Volumetric>();
|
||||
mSSAO = CreateScope<SSAO>();
|
||||
}
|
||||
|
||||
glm::vec4 Environment::GetAmbientColor()
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
#include "src/Core/Core.h"
|
||||
#include "src/Scene/Environment/ProceduralSky.h"
|
||||
#include "src/Resource/Serializable.h"
|
||||
|
||||
#include "src/Rendering/PostFX/Bloom.h"
|
||||
#include "src/Rendering/PostFX/Volumetric.h"
|
||||
#include "src/Rendering/PostFX/SSAO.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
@@ -26,7 +28,7 @@ namespace Nuake
|
||||
Color AmbientColor = Color(0, 0, 0, 1);
|
||||
Ref<ProceduralSky> ProceduralSkybox;
|
||||
|
||||
bool VolumetricEnabled = false;
|
||||
bool VolumetricEnabled = true;
|
||||
float VolumetricFog = 0.90f;
|
||||
float VolumetricStepCount = 50.f;
|
||||
|
||||
@@ -37,6 +39,9 @@ namespace Nuake
|
||||
Scope<Bloom> mBloom;
|
||||
Scope<Volumetric> mVolumetric;
|
||||
|
||||
bool SSAOEnabled = true;
|
||||
Scope<SSAO> mSSAO;
|
||||
|
||||
Vector3 ClearColor;
|
||||
|
||||
glm::vec4 m_AmbientColor;
|
||||
|
||||
Reference in New Issue
Block a user