Skip to content
Permalink
Browse files

Add basic SSAO

It is not working as it should, consider it experimental at best.
  • Loading branch information...
enginmanap committed Dec 10, 2018
1 parent 76ee172 commit adc4756094112ca3dda7d23d6c4c8e6549b62d9e
@@ -7,7 +7,9 @@ layout (std140) uniform PlayerTransformBlock {
mat4 camera;
mat4 projection;
mat4 cameraProjection;
mat4 inverseTransposeProjection;
vec3 position;
vec2 noiseScale;
} playerTransforms;

struct LightSource
@@ -44,14 +46,16 @@ out vec4 finalColor;

uniform sampler2DArray shadowSamplerDirectional;
uniform samplerCubeArray shadowSamplerPoint;
uniform sampler2D ssaoSampler;
uniform sampler2D ssaoNoiseSampler;

uniform sampler2D ambientSampler;
uniform sampler2D diffuseSampler;
uniform sampler2D specularSampler;
uniform sampler2D opacitySampler;
uniform sampler2D normalSampler;

uniform vec3 pointSampleOffsetDirections[20] = vec3[]
vec3 pointSampleOffsetDirections[20] = vec3[]
(
vec3( 1, 1, 1), vec3( 1, -1, 1), vec3(-1, -1, 1), vec3(-1, 1, 1),
vec3( 1, 1, -1), vec3( 1, -1, -1), vec3(-1, -1, -1), vec3(-1, 1, -1),
@@ -60,6 +64,9 @@ uniform vec3 pointSampleOffsetDirections[20] = vec3[]
vec3( 0, 1, 1), vec3( 0, -1, 1), vec3( 0, -1, -1), vec3( 0, 1, -1)
);

uniform vec3 ssaoKernel[128];
uniform int ssaoSampleCount;

float ShadowCalculationDirectional(vec4 fragPosLightSpace, float bias, float lightIndex){
// perform perspective divide
vec3 projectedCoordinates = fragPosLightSpace.xyz / fragPosLightSpace.w;
@@ -112,6 +119,13 @@ float ShadowCalculationPoint(vec3 fragPos, float bias, float viewDistance, int l
return shadow;
}

vec3 calcViewSpacePos(vec3 screen) {
vec4 temp = vec4(screen.x, screen.y, screen.z, 1);
temp *= playerTransforms.inverseTransposeProjection;
vec3 camera_space = temp.xyz / temp.w;
return camera_space;
}

void main(void) {
vec4 objectColor;
if((material.isMap & 0x0004)!=0) {
@@ -132,16 +146,51 @@ void main(void) {
objectColor = vec4(material.diffuse, 1.0);
}

vec3 lightingColorFactor = material.ambient;
if((material.isMap & 0x0008)!=0) {
lightingColorFactor = vec3(texture(ambientSampler, from_vs.textureCoord));
}

vec3 normal = from_vs.normal;

if((material.isMap & 0x0010) != 0) {
normal = -1 * vec3(texture(normalSampler, from_vs.textureCoord));
}

float occlusion = 0.0;

if(length(playerTransforms.position - from_vs.fragPos) < 100) {
vec3 randomVec = texture(ssaoNoiseSampler, from_vs.fragPos.xy * playerTransforms.noiseScale).xyz;

vec3 tangent = normalize(randomVec - normal * dot(randomVec, normal));
vec3 bitangent = cross(normal, tangent);
mat3 TBN = mat3(tangent, bitangent, normal);

float uRadius = 0.5f;
for(int i = 0; i < ssaoSampleCount; ++i){
// get sample position
vec3 samplePosition = TBN * ssaoKernel[i]; // From tangent to view-space
samplePosition = samplePosition * uRadius;
samplePosition += vec3(from_vs.fragPos);

vec4 offset = vec4(samplePosition, 1.0);
offset = playerTransforms.cameraProjection * offset; // from view to clip-space
offset.xyz /= offset.w; // perspective divide
offset.xyz = offset.xyz * 0.5 + 0.5; // transform to range 0.0 - 1.0

float sampleDepth = texture(ssaoSampler, offset.xy).r;

vec3 realElement = calcViewSpacePos(vec3(offset.xy, sampleDepth));
vec3 kernelElement = calcViewSpacePos(offset.xyz);

float rangeCheck= abs(realElement.z - kernelElement.z) < 1 ? 1.0 : 0.0;
occlusion += (realElement.z >= kernelElement.z ? 1.0 : 0.0) * rangeCheck;
}

occlusion = occlusion / ssaoSampleCount;
}
occlusion = 1 - occlusion;

vec3 lightingColorFactor = (material.ambient) * occlusion;
if((material.isMap & 0x0008)!=0) {
lightingColorFactor = vec3(texture(ambientSampler, from_vs.textureCoord));
}

float shadow;
for(int i=0; i < NR_POINT_LIGHTS; ++i){
if(LightSources.lights[i].type != 0) {
@@ -19,7 +19,9 @@ layout (std140) uniform PlayerTransformBlock {
mat4 camera;
mat4 projection;
mat4 cameraProjection;
mat4 inverseTransposeProjection;
vec3 position;
vec2 noiseScale;
} playerTransforms;

struct LightSource
@@ -23,7 +23,9 @@ layout (std140) uniform PlayerTransformBlock {
mat4 camera;
mat4 projection;
mat4 cameraProjection;
mat4 inverseTransposeProjection;
vec3 position;
vec2 noiseScale;
} playerTransforms;

struct LightSource
@@ -0,0 +1,6 @@
#version 330 core
#define NR_POINT_LIGHTS 4

void main() {
//gl_FragDepth = FragPos.z;
}
@@ -0,0 +1,43 @@
#version 330 core

#define NR_POINT_LIGHTS 4
#define NR_BONE 128
#define NR_MAX_MODELS 1000


layout (location = 2) in vec4 position;
layout (location = 5) in uvec4 boneIDs;
layout (location = 6) in vec4 boneWeights;

layout (std140) uniform PlayerTransformBlock {
mat4 camera;
mat4 projection;
mat4 cameraProjection;
mat4 inverseTransposeProjection;
vec3 position;
vec2 noiseScale;
} playerTransforms;

layout (std140) uniform ModelInformationBlock {
mat4 worldTransform[NR_MAX_MODELS];
} model;

layout (std140) uniform ModelIndexBlock {
uvec4 models[NR_MAX_MODELS];
} instance;

uniform mat4 boneTransformArray[NR_BONE];
uniform int isAnimated;

void main() {
if(isAnimated==1) {
mat4 BoneTransform = mat4(1.0);
BoneTransform = boneTransformArray[boneIDs[0]] * boneWeights[0];
BoneTransform += boneTransformArray[boneIDs[1]] * boneWeights[1];
BoneTransform += boneTransformArray[boneIDs[2]] * boneWeights[2];
BoneTransform += boneTransformArray[boneIDs[3]] * boneWeights[3];
gl_Position = playerTransforms.cameraProjection * (model.worldTransform[instance.models[gl_InstanceID].x] * (BoneTransform * vec4(vec3(position), 1.0)));
} else {
gl_Position = playerTransforms.cameraProjection * (model.worldTransform[instance.models[gl_InstanceID].x] * position);
}
}
@@ -2,6 +2,7 @@
// Created by Engin Manap on 10.02.2016.
//

#include <random>
#include "GLHelper.h"
#include "GLSLProgram.h"

@@ -222,6 +223,9 @@ void GLHelper::attachGeneralUBOs(const GLuint program){//Attach the light block


GLHelper::GLHelper(Options *options): options(options) {

this->screenHeight = options->getScreenHeight();
this->screenWidth = options->getScreenWidth();
GLenum rev;
error = GL_NO_ERROR;
glewExperimental = GL_TRUE;
@@ -389,8 +393,48 @@ GLHelper::GLHelper(Options *options): options(options) {
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);

glBindFramebuffer(GL_FRAMEBUFFER, 0);
checkErrors("Constructor bf ssao");

//create depth buffer for SSAO
glGenFramebuffers(1, &depthOnlyFrameBufferSSAO);
glGenTextures(1, &depthMapSSAO);
glBindTexture(GL_TEXTURE_2D, depthMapSSAO);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, screenWidth, screenHeight, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);

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_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
glBindTexture(GL_TEXTURE_2D, 0);

glBindFramebuffer(GL_FRAMEBUFFER, depthOnlyFrameBufferSSAO);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthMapSSAO, 0);
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
glBindFramebuffer(GL_FRAMEBUFFER, 0);

/****************************** SSAO KERNEL AND NOISE **************************************/
std::uniform_real_distribution<GLfloat> randomFloats(0.0, 1.0); // generates random floats between 0.0 and 1.0
std::default_random_engine generator;
// generate noise texture
// ----------------------
std::vector<glm::vec3> ssaoNoise;
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); // rotate around z-axis (in tangent space)
ssaoNoise.push_back(noise);
}
glGenTextures(1, &noiseTexture);
glBindTexture(GL_TEXTURE_2D, noiseTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, 4, 4, 0, GL_RGB, 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);
/****************************** SSAO KERNEL AND NOISE **************************************/

frustumPlanes.resize(6);

checkErrors("Constructor");
@@ -573,15 +617,25 @@ void GLHelper::switchRenderToShadowMapPoint() {
checkErrors("switchRenderToShadowMapPoint");
}

void GLHelper::switchRenderToSSAO() {
glViewport(0, 0, screenWidth, screenHeight);
glBindFramebuffer(GL_FRAMEBUFFER, depthOnlyFrameBufferSSAO);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthMapSSAO, 0);

glCullFace(GL_BACK);
checkErrors("switchRenderToSSAO");
}

void GLHelper::switchRenderToDefault() {
glViewport(0, 0, screenWidth, screenHeight);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
//we bind shadow map to last texture unit
state->attach2DTextureArray(depthMapDirectional, maxTextureImageUnits - 1);
state->attachCubemapArray(depthCubemapPoint, maxTextureImageUnits - 2);
state->attachTexture(depthMapSSAO, maxTextureImageUnits - 3);
state->attachTexture(noiseTexture, maxTextureImageUnits - 4);

glCullFace(GL_BACK);
//glEnable(GL_CULL_FACE);
checkErrors("switchRenderToDefault");
}

@@ -722,7 +776,11 @@ GLHelper::~GLHelper() {
deleteBuffer(1, playerUBOLocation);
deleteBuffer(1, allMaterialsUBOLocation);
deleteBuffer(1, depthMapDirectional);
deleteBuffer(1, depthCubemapPoint);
deleteBuffer(1, depthMapSSAO);
glDeleteFramebuffers(1, &depthOnlyFrameBufferDirectional); //maybe we should wrap this up too
glDeleteFramebuffers(1, &depthOnlyFrameBufferPoint);
glDeleteFramebuffers(1, &depthOnlyFrameBufferSSAO);
//state->setProgram(0);
}

@@ -732,7 +790,8 @@ void GLHelper::reshape() {
this->screenWidth = options->getScreenWidth();
glViewport(0, 0, options->getScreenWidth(), options->getScreenHeight());
aspect = float(options->getScreenHeight()) / float(options->getScreenWidth());
perspectiveProjectionMatrix = glm::perspective(options->PI/3.0f, 1.0f / aspect, 0.01f, 1000.0f);
perspectiveProjectionMatrix = glm::perspective(options->PI/3.0f, 1.0f / aspect, 0.01f, 10000.0f);
inverseTransposeProjection = glm::transpose(glm::inverse(perspectiveProjectionMatrix));
orthogonalProjectionMatrix = glm::ortho(0.0f, (float) options->getScreenWidth(), 0.0f, (float) options->getScreenHeight());
checkErrors("reshape");
}
@@ -962,11 +1021,14 @@ void GLHelper::setModelIndexesUBO(std::vector<uint32_t> &modelIndicesList) {
void GLHelper::setPlayerMatrices(const glm::vec3 &cameraPosition, const glm::mat4 &cameraTransform) {
this->cameraMatrix = cameraTransform;
glBindBuffer(GL_UNIFORM_BUFFER, playerUBOLocation);
glBufferSubData(GL_UNIFORM_BUFFER, 0 * sizeof(glm::mat4), sizeof(glm::mat4), &cameraMatrix);//changes with camera
glBufferSubData(GL_UNIFORM_BUFFER, 1 * sizeof(glm::mat4), sizeof(glm::mat4), &perspectiveProjectionMatrix);//never changes
glBufferSubData(GL_UNIFORM_BUFFER, 0 * sizeof(glm::mat4), sizeof(glm::mat4), glm::value_ptr(cameraMatrix));//changes with camera
glBufferSubData(GL_UNIFORM_BUFFER, 1 * sizeof(glm::mat4), sizeof(glm::mat4), glm::value_ptr(perspectiveProjectionMatrix));//never changes
glm::mat4 viewMatrix = perspectiveProjectionMatrix * cameraMatrix;
glBufferSubData(GL_UNIFORM_BUFFER, 2 * sizeof(glm::mat4), sizeof(glm::mat4), &viewMatrix);//changes with camera
glBufferSubData(GL_UNIFORM_BUFFER, 3 * sizeof(glm::mat4), sizeof(glm::vec3), &cameraPosition);//changes with camera
glBufferSubData(GL_UNIFORM_BUFFER, 2 * sizeof(glm::mat4), sizeof(glm::mat4), glm::value_ptr(viewMatrix));//changes with camera
glBufferSubData(GL_UNIFORM_BUFFER, 3 * sizeof(glm::mat4), sizeof(glm::mat4), glm::value_ptr(inverseTransposeProjection));//never changes
glBufferSubData(GL_UNIFORM_BUFFER, 4 * sizeof(glm::mat4), sizeof(glm::vec3), glm::value_ptr(cameraPosition));//changes with camera
glm::vec2 noiseScale(this->screenWidth / 4, this->screenHeight / 4);
glBufferSubData(GL_UNIFORM_BUFFER, 4 * sizeof(glm::mat4)+ sizeof(glm::vec4), sizeof(glm::vec2), glm::value_ptr(noiseScale));//never changes
glBindBuffer(GL_UNIFORM_BUFFER, 0);

calculateFrustumPlanes(cameraMatrix, perspectiveProjectionMatrix, frustumPlanes);
@@ -197,15 +197,21 @@ class GLHelper {
GLuint depthOnlyFrameBufferPoint;
GLuint depthCubemapPoint;

GLuint depthOnlyFrameBufferSSAO;
GLuint depthMapSSAO;

unsigned int noiseTexture;

Options *options;

const uint_fast32_t lightUniformSize = (sizeof(glm::mat4) * 7) + (2 * sizeof(glm::vec4));
const uint32_t playerUniformSize = 3 * sizeof(glm::mat4) + sizeof(glm::vec4);
const uint32_t playerUniformSize = 4 * sizeof(glm::mat4) + sizeof(glm::vec4) + sizeof(glm::vec4);
int32_t materialUniformSize = 2 * sizeof(glm::vec3) + sizeof(float) + sizeof(GLuint);
int32_t modelUniformSize = sizeof(glm::mat4);

glm::mat4 cameraMatrix;
glm::mat4 perspectiveProjectionMatrix;
glm::mat4 inverseTransposeProjection;
std::vector<glm::vec4>frustumPlanes;
glm::mat4 orthogonalProjectionMatrix;
glm::mat4 lightProjectionMatrixDirectional;
@@ -234,7 +240,7 @@ class GLHelper {
#ifndef NDEBUG
GLenum fbStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (fbStatus != GL_FRAMEBUFFER_COMPLETE) {
std::cerr << "FB status is " << fbStatus << std::endl;
std::cerr << "FB status while " << callerFunc << " is " << fbStatus << std::endl;
}
bool hasError = false;
while ((error = glGetError()) != GL_NO_ERROR) {
@@ -311,6 +317,8 @@ class GLHelper {
glClear(GL_DEPTH_BUFFER_BIT);
glBindFramebuffer(GL_FRAMEBUFFER, depthOnlyFrameBufferDirectional);
glClear(GL_DEPTH_BUFFER_BIT);
glBindFramebuffer(GL_FRAMEBUFFER, depthOnlyFrameBufferSSAO);
glClear(GL_DEPTH_BUFFER_BIT);
glBindFramebuffer(GL_FRAMEBUFFER, 0);

renderTriangleCount = 0;
@@ -382,6 +390,8 @@ class GLHelper {

void switchRenderToShadowMapPoint();

void switchRenderToSSAO();

void switchRenderToDefault();

int getMaxTextureImageUnits() const {
Oops, something went wrong.

0 comments on commit adc4756

Please sign in to comment.
You can’t perform that action at this time.