Commit b2db9411 authored by Dario Seyb's avatar Dario Seyb

started on ssao

parent 94c46d3b
......@@ -9,6 +9,9 @@ uniform sampler2D uSamplerSpecularSmoothness;
uniform sampler2DShadow uSamplerShadowMap;
uniform sampler2D uSamplerSSAO;
uniform bool uHasSSAO;
uniform bool uLightHasShadow;
uniform vec2 uOneOverShadowTexSize;
uniform vec3 uLightPosition;
......@@ -72,6 +75,11 @@ float shadowFactor(vec3 worldPosition) {
return shadow;
}
float ssaoFactor() {
if(!uHasSSAO) return 1;
return texture(uSamplerSSAO, vTexCoord).r;
}
void main()
{
vec4 albedo = texture(uSamplerColor, vTexCoord);
......@@ -104,5 +112,8 @@ void main()
float lightNdotL = max(0, dot(lightDir, normal));
vec4 lighting = BRDF (albedo.rgb, specularSmoothness.rgb, oneMinusReflectivity, specularSmoothness.a, normal, viewDir, lightDir, lightNdotL, uLightColor.rgb * uLightColor.a);
oColor = vec4(lighting.rgb * shadowFactor(worldPosition) + emissive.rgb, uOneOverLightCount * albedo.a);
float ssao = ssaoFactor();
oColor = vec4(lighting.rgb * ssao * shadowFactor(worldPosition) + emissive.rgb, uOneOverLightCount * albedo.a);
}
uniform sampler2D uSamplerSSAO;
uniform int uBlurSize = 4; // use size of noise texture
in vec2 vTexCoord; // input from vertex shader
out vec4 oResult;
void main() {
vec2 texelSize = 1.0 / vec2(textureSize(uSamplerSSAO, 0));
float result = 0.0;
vec2 hlim = vec2(float(-uBlurSize) * 0.5 + 0.5);
for (int i = 0; i < uBlurSize; ++i) {
for (int j = 0; j < uBlurSize; ++j) {
vec2 offset = (hlim + vec2(float(i), float(j))) * texelSize;
result += texture(uSamplerSSAO, vTexCoord + offset).r;
}
}
oResult.r = result / float(uBlurSize * uBlurSize);
}
\ No newline at end of file
#version 330
out vec2 vTexCoord;
const vec2 quad[4] = vec2[] (
vec2(-1.0, 1.0),
vec2(-1.0,-1.0),
vec2( 1.0, 1.0),
vec2( 1.0,-1.0)
);
void main()
{
vec2 p = quad[ gl_VertexID ];
vTexCoord = p * vec2(0.5, 0.5) + vec2(0.5, 0.5);
gl_Position = vec4(p, 0.0, 1.0);
}
#pragma import "../Utils.glsl"
uniform sampler2D uSamplerNormalMotion;
uniform sampler2D uSamplerDepth;
uniform sampler2D uSamplerKernel;
uniform sampler2D uSamplerNoise;
uniform mat4 uViewProjectionMatrix;
uniform mat4 uViewProjectionInverseMatrix;
uniform mat4 uViewInverseMatrix;
uniform mat4 uProjectionMatrix;
uniform float uNear;
uniform float uFar;
uniform float uTime;
uniform float uNoiseScale = 0.002;
uniform int uSampleKernelSize = 16;
uniform float uRadius = 0.025;
in vec2 vTexCoord;
out vec4 oColor;
vec3 unpackWorldPosition(float depth) {
vec4 clipSpaceLocation;
clipSpaceLocation.xy = vTexCoord * 2.0 - 1.0;
clipSpaceLocation.z = depth * 2.0 - 1.0;
clipSpaceLocation.w = 1.0;
vec4 homogenousLocation = uViewProjectionInverseMatrix * clipSpaceLocation;
return homogenousLocation.xyz / homogenousLocation.w;
}
float linearizeDepth(float depth) {
return (2.0 * uNear) / (uFar + uNear - depth * (uFar - uNear)); // convert to linear values
}
void main() {
vec3 origin = unpackWorldPosition(texture(uSamplerDepth, vTexCoord).r);
vec3 normal = normalize((transpose(uViewInverseMatrix) *
vec4(unpackNormal(texture(uSamplerNormalMotion, vTexCoord)), 0)).xyz);
vec3 rvec = texture(uSamplerNoise, vTexCoord * uNoiseScale).xyz * 2.0 - 1.0;
vec3 tangent = normalize(rvec - normal * dot(rvec, normal));
vec3 bitangent = cross(normal, tangent);
mat3 tbn = mat3(tangent, bitangent, normal);
float occlusion = 0.0;
for (int i = 0; i < uSampleKernelSize; ++i) {
vec3 sample = tbn * texture(uSamplerKernel, vec2(float(i)/uSampleKernelSize, 0)).xyz;
sample = sample * uRadius + origin;
// project sample position:
vec4 offset = vec4(sample, 1.0);
offset = uViewProjectionMatrix * offset;
offset.xy /= offset.w;
offset.xy = offset.xy * 0.5 + 0.5;
// get sample depth:
vec3 samplePos = unpackWorldPosition(texture(uSamplerDepth, offset.xy).r);
// range check & accumulate:
float rangeCheck= length(samplePos-origin) > uRadius ? 1.0 : 0.0;
occlusion += (samplePos.z >= sample.z ? 1.0 : 0.0) * rangeCheck ;
}
occlusion = 1.0 - (occlusion / uSampleKernelSize);
oColor.r = occlusion;
}
#version 330
out vec2 vTexCoord;
const vec2 quad[4] = vec2[] (
vec2(-1.0, 1.0),
vec2(-1.0,-1.0),
vec2( 1.0, 1.0),
vec2( 1.0,-1.0)
);
void main()
{
vec2 p = quad[ gl_VertexID ];
vTexCoord = p * vec2(0.5, 0.5) + vec2(0.5, 0.5);
gl_Position = vec4(p, 0.0, 1.0);
}
......@@ -38,6 +38,7 @@ struct RenderPass {
Entity camera;
bool active;
bool renderToTextureOnly;
bool hasSSAO;
};
class RendererSystem : public System {
......@@ -65,6 +66,12 @@ private:
SharedTexture2D m_depthBuffer;
SharedTexture2D m_specularBuffer;
SharedTexture2D m_ssaoNoise;
SharedTexture2D m_ssaoKernel;
ACGL::OpenGL::SharedFrameBufferObject m_ssaoTarget;
ACGL::OpenGL::SharedFrameBufferObject m_gBufferObject;
ACGL::OpenGL::SharedFrameBufferObject m_primaryCompositingBuffer;
......@@ -80,6 +87,9 @@ private:
SharedShaderProgram m_passBlitProgram;
SharedShaderProgram m_shadowMapProg;
SharedShaderProgram m_ssaoComputeProg;
SharedShaderProgram m_ssaoBlurProg;
SharedShaderProgram m_txaaProg;
SharedShaderProgram m_tfShaderProg;
......@@ -121,9 +131,19 @@ public:
txaa->validate();
m_passIds[name] = m_passes.size();
m_passes.push_back({ kilobytes(4), kilobytes(4), kilobytes(4), target, txaa, cam, true, false });
m_passes.push_back({ kilobytes(4), kilobytes(4), kilobytes(4), target, txaa, cam, true, false, false });
}
void setRenderPassSSAO(StringHash pass, bool active) {
auto id = getRenderPassId(pass);
if (id == -1) {
return;
}
m_passes[id].hasSSAO = active;
}
void setRenderPassActive(StringHash pass, bool active) {
auto id = getRenderPassId(pass);
if (id == -1) {
......
......@@ -31,6 +31,10 @@ glm::mat4 interpolate(TransformData a, TransformData b, double t, glm::dvec3 cam
return glm::translate(pos) * glm::mat4_cast(rot) * glm::scale(s);
}
float random(float start, float end) {
return start + (float(rand()) / RAND_MAX) * (end - start);
}
bool RendererSystem::startup() {
RESOLVE_DEPENDENCY(m_events);
RESOLVE_DEPENDENCY(m_window);
......@@ -68,6 +72,10 @@ bool RendererSystem::startup() {
m_secondaryCompositingBuffer->attachColorTexture("oColor", createScreenspaceTexture(ScreenSpaceSize::FULL, GL_RGBA32F));
m_secondaryCompositingBuffer->validate();
m_ssaoTarget = SharedFrameBufferObject(new FrameBufferObject());
m_ssaoTarget->attachColorTexture("oColor", createScreenspaceTexture(ScreenSpaceSize::HALF, GL_R8));
m_ssaoTarget->validate();
m_postfxTargetBuffer = SharedFrameBufferObject(new FrameBufferObject());
m_postfxTargetBuffer->attachColorTexture("oColor", createScreenspaceTexture(ScreenSpaceSize::FULL, GL_RGBA32F));
......@@ -125,6 +133,9 @@ bool RendererSystem::startup() {
m_shadowMapProg = ShaderProgramFileManager::the()->get(ShaderProgramCreator("ShadowMap"));
m_txaaProg = ShaderProgramFileManager::the()->get(ShaderProgramCreator("TXAA").fragmentDataLocations(m_secondaryCompositingBuffer->getAttachmentLocations()));
m_ssaoComputeProg = ShaderProgramFileManager::the()->get(ShaderProgramCreator("SSAO/SSAOCompute").fragmentDataLocations(m_ssaoTarget->getAttachmentLocations()));
m_ssaoBlurProg = ShaderProgramFileManager::the()->get(ShaderProgramCreator("SSAO/SSAOBlur"));
m_tfShaderProg = ShaderProgramFileManager::the()->get(ShaderProgramCreator("TerrainTransformFeedback"));
char * outs[] = { "gNormal", "gPosition", "gTexCoord"};
......@@ -161,6 +172,70 @@ bool RendererSystem::startup() {
m_shadowMaps.push_back(shadowFbo);
}
const int kernelSize = 16;
GLubyte* kernel = new GLubyte[kernelSize * 4];
GLubyte* pixel = kernel;
for (int i = 0; i < kernelSize; ++i) {
glm::vec4 kern = glm::vec4(
random(-1.0f, 1.0f),
random(-1.0f, 1.0f),
random(0.0f, 1.0f), 0);
kern = glm::normalize(kern);
float scale = float(i) / float(kernelSize);
scale = glm::lerp(0.1f, 1.0f, scale * scale);
kern *= scale;
pixel[0] = (GLubyte)(kern.r * 255);
pixel[1] = (GLubyte)(kern.g * 255);
pixel[2] = (GLubyte)(kern.b * 255);
pixel[3] = (GLubyte)(kern.a * 255);
pixel += 4;
}
SharedTextureData kernelData = std::make_shared<TextureData>();
kernelData->setWidth(kernelSize);
kernelData->setHeight(1);
kernelData->setData(kernel);
kernelData->setFormat(GL_RGBA);
kernelData->setType(GL_UNSIGNED_BYTE);
m_ssaoKernel = std::make_shared<Texture2D>(GL_RGBA);
m_ssaoKernel->setMinFilter(GL_NEAREST);
m_ssaoKernel->setMagFilter(GL_NEAREST);
m_ssaoKernel->setImageData(kernelData);
const int noiseSize = 16;
GLubyte* noise = new GLubyte[noiseSize * 4];
pixel = noise;
for (int i = 0; i < noiseSize; ++i) {
auto nos = glm::vec4(random(-1.0f, 1.0f), random(-1.0f, 1.0f), 0.0f, 0);
nos = glm::normalize(nos);
pixel[0] = (GLubyte)(nos.r * 255);
pixel[1] = (GLubyte)(nos.g * 255);
pixel[2] = (GLubyte)(nos.b * 255);
pixel[3] = (GLubyte)(nos.a * 255);
pixel += 4;
}
SharedTextureData noiseData = std::make_shared<TextureData>();
noiseData->setWidth(noiseSize);
noiseData->setHeight(1);
noiseData->setData(noise);
noiseData->setFormat(GL_RGBA);
noiseData->setType(GL_UNSIGNED_BYTE);
m_ssaoNoise = std::make_shared<Texture2D>(GL_RGBA);
m_ssaoNoise->setMinFilter(GL_NEAREST);
m_ssaoNoise->setMagFilter(GL_NEAREST);
m_ssaoNoise->setImageData(noiseData);
m_events->subscribe<"DrawUI"_sh>([this]() {
ImGui::Begin("Reload");
if (ImGui::Button("Shaders", {100, 20})) {
......@@ -173,6 +248,7 @@ bool RendererSystem::startup() {
ImGui::Image((void*)m_emissiveBuffer->getObjectName(), glm::vec2{ 1280, 720 } *0.2f, { 0, 1 }, { 1, 0 });
ImGui::Image((void*)m_normalMotionBuffer->getObjectName(), glm::vec2{ 1280, 720 } *0.2f, { 0, 1 }, { 1, 0 });
ImGui::Image((void*)m_specularBuffer->getObjectName(), glm::vec2{ 1280, 720 } *0.2f, { 0, 1 }, { 1, 0 });
ImGui::Image((void*)m_ssaoTarget->getColorAttachments()[0].texture->getObjectName(), glm::vec2{ 1280, 720 } *0.2f, { 0, 1 }, { 1, 0 });
ImGui::End();
ImGui::Begin("Render Passes", 0, ImGuiWindowFlags_AlwaysAutoResize);
......@@ -245,10 +321,15 @@ void RendererSystem::render(RenderPass& pass, double interp, double totalTime) {
currentOffset.z = 0;
aaProj = glm::perspectiveFov<float>(glm::radians(cam->fov), windowSize.x, windowSize.y, cam->near, cam->far);
glm::mat4 viewProjectionMatrixNoOffset = aaProj * glm::inverse(camTransform);
glm::mat4 viewMatrix = glm::inverse(camTransform);
glm::mat4 viewMatrixInverse = camTransform;
glm::mat4 viewProjectionMatrixNoOffset = aaProj * viewMatrix;
glm::mat4 viewProjectionMatrix = glm::translate(currentOffset) * viewProjectionMatrixNoOffset;
glm::mat4 prevViewProjectionMatrix = glm::translate(currentOffset) * aaProj * static_cast<glm::mat4>(glm::inverse(trans->lastRenderTransform));
m_lastGBufferRenderSetupTime = 0;
m_lastGBufferRenderSubmitTime = 0;
......@@ -430,6 +511,44 @@ void RendererSystem::render(RenderPass& pass, double interp, double totalTime) {
m_lastShadowMapRenderTime = (double)(SDL_GetPerformanceCounter() - counterStart) * 1000.0 / SDL_GetPerformanceFrequency();
counterStart = SDL_GetPerformanceCounter();
// attribute-less rendering:
VertexArrayObject vao;
vao.bind(); // 'empty' VAO -> no attributes are defined
if (pass.hasSSAO) {
auto ssaoRes = glm::vec2(m_ssaoTarget->getSize());
glViewport(0, 0, ssaoRes.x, ssaoRes.y);
m_ssaoTarget->bind();
m_ssaoTarget->setClearColor(glm::vec4{ 0, 0, 0, 0 });
m_ssaoTarget->clearBuffers();
glCullFace(GL_BACK);
glDisable(GL_BLEND);
m_ssaoComputeProg->use();
m_ssaoComputeProg->setTexture("uSamplerNormalMotion", m_normalMotionBuffer, 0);
m_ssaoComputeProg->setTexture("uSamplerDepth", m_depthBuffer, 1);
m_ssaoComputeProg->setTexture("uSamplerKernel", m_ssaoKernel, 2);
m_ssaoComputeProg->setTexture("uSamplerNoise", m_ssaoNoise, 3);
m_ssaoComputeProg->setUniform("uProjectionMatrix", aaProj);
m_ssaoComputeProg->setUniform("uViewProjectionMatrix", viewProjectionMatrix);
m_ssaoComputeProg->setUniform("uViewInverseMatrix", viewMatrixInverse);
m_ssaoComputeProg->setUniform("uViewProjectionInverseMatrix", glm::inverse(viewProjectionMatrix));
m_ssaoComputeProg->setUniform("uNear", cam->near);
m_ssaoComputeProg->setUniform("uFar", cam->far);
m_ssaoComputeProg->setUniform("uTime", (float)totalTime);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
pass.compositingTarget->bind();
glViewport(0, 0, pass.compositingTarget->getSize().x, pass.compositingTarget->getSize().y);
m_ssaoBlurProg->use();
m_ssaoBlurProg->setTexture("uSamplerSSAO", m_ssaoTarget->getColorAttachments()[0].texture, 0);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
// Deferred lighting (accumulation)
m_secondaryCompositingBuffer->setClearColor(glm::vec4{ 0, 0, 0, 0 });
m_secondaryCompositingBuffer->bind();
......@@ -451,6 +570,13 @@ void RendererSystem::render(RenderPass& pass, double interp, double totalTime) {
m_deferredCombineProgram->setTexture("uSamplerDepth", m_depthBuffer, 3);
m_deferredCombineProgram->setTexture("uSamplerSpecularSmoothness", m_specularBuffer, 4);
if (pass.hasSSAO) {
m_deferredCombineProgram->setTexture("uSamplerSSAO", pass.compositingTarget->getColorAttachments()[0].texture, 6);
m_deferredCombineProgram->setUniform("uHasSSAO", true);
} else {
m_deferredCombineProgram->setUniform("uHasSSAO", false);
}
m_deferredCombineProgram->setUniform("uNear", cam->near);
m_deferredCombineProgram->setUniform("uFar", cam->far);
......@@ -463,9 +589,7 @@ void RendererSystem::render(RenderPass& pass, double interp, double totalTime) {
m_deferredCombineProgram->setUniform("uViewProjectionInverseMatrix",
invViewProj);
// attribute-less rendering:
VertexArrayObject vao;
vao.bind(); // 'empty' VAO -> no attributes are defined
const static glm::mat4 biasMatrix(0.5, 0.0, 0.0, 0.0,
0.0, 0.5, 0.0, 0.0,
......@@ -515,6 +639,9 @@ void RendererSystem::render(RenderPass& pass, double interp, double totalTime) {
vao.bind(); // 'empty' VAO -> no attributes are defined
pass.compositingTarget->bind();
int width = pass.compositingTarget->getSize().x;
int height = pass.compositingTarget->getSize().y;
......
......@@ -476,7 +476,7 @@ computeInscatteringTexture(GLubyte* transmittance,
for (int z = 0; z < DEPTH; z++) {
computeThreads[z] = std::thread([&]() {
computeThreads[z] = std::thread([&](int z) {
double r = double(z + 1) / (DEPTH);
r = r * r;
......@@ -531,7 +531,7 @@ computeInscatteringTexture(GLubyte* transmittance,
pixel += 4;
}
}
});
}, z);
//stbi_write_png(("inscattering_" + std::to_string(z) + ".png").c_str(), WIDTH, HEIGHT, 4, inscattering + z * WIDTH * HEIGHT * 4, 0);
}
......
......@@ -81,6 +81,8 @@ bool AtmosphereTestScene::startup() {
m_renderer->setRenderPassActive("Skybox"_sh, false);
m_renderer->setRenderPassActive("Minimap"_sh, false);
m_renderer->setRenderPassSSAO("Cockpit"_sh, false);
m_renderer->addRenderPass(consoleCamera, "Console"_sh, ScreenSpaceSize::HALF);
m_console.m_events = m_events;
......@@ -463,8 +465,8 @@ void AtmosphereTestScene::loadMainSceneResources() {
consoleMiddleRightGeom = Geometry{ VertexArrayObjectCreator("cockpit/cockpit_v2_console_middle_right.obj").create() };
windShieldGeom = Geometry{ VertexArrayObjectCreator("cockpit/cockpit_v2_windshield.obj").create() };
soundTrackIntro = m_audio->createSound("chipzel - Spectra - 04 Formed in the Clouds (Interlude).mp3", SoundMode::MODE_2D);
soundTrackMain = m_audio->createSound("chipzel - Spectra - 01 Spectra.mp3", SoundMode::MODE_2D);
soundTrackIntro = m_audio->createSound("GameAmbient.mp3", SoundMode::MODE_2D);
soundTrackMain = m_audio->createSound("SpaceTheme.mp3", SoundMode::MODE_2D);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment