Compare commits

...

2 Commits

4 changed files with 177 additions and 39 deletions
+1 -3
View File
@@ -29,8 +29,6 @@ private:
void InitializeShaderProgram(); void InitializeShaderProgram();
void InitializeBuffer(); void InitializeBuffer();
void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const;
void ComputeAO(GLuint depthBuffer, Camera* camera); void ComputeAO(GLuint depthBuffer, Camera* camera);
//void blurHorizontal(GLuint depthBuffer); //void blurHorizontal(GLuint depthBuffer);
//void blurVertical(GLuint depthBuffer); //void blurVertical(GLuint depthBuffer);
@@ -38,7 +36,7 @@ private:
Model* m_ScreenQuad; Model* m_ScreenQuad;
const IRenderer* m_Renderer; const IRenderer* m_Renderer;
static const GLint MAX_MIP_LEVEL = 5;
float m_Radius; float m_Radius;
float m_Bias; float m_Bias;
float m_Contrast; float m_Contrast;
+25 -16
View File
@@ -1,12 +1,15 @@
#version 430 #version 430
#define MIP_MAPS_LEVELS (3)
#define MAX_PIXEL_BEFOR_LOWER_MIP_LEVEL (3)
//Number of samples per pixel //Number of samples per pixel
uniform int uNumOfSamples; uniform int uNumOfSamples;
//#define NUM_SAMPLES (11) //#define uNumOfSamples (11)
//Number of turns around the cirle //Number of turns around the cirle
uniform int uNumOfTurns; uniform int uNumOfTurns;
//#define NUM_TURNS (7) //#define uNumOfTurns (7)
layout (binding = 0) uniform sampler2D ViewSpaceZ; layout (binding = 0) uniform sampler2D ViewSpaceZ;
@@ -42,42 +45,41 @@ vec3 getVSFaceNormal(vec3 ViewSpacePosition) {
vec3 getSampleViewSpacePos(ivec2 ScreenSpaceCoord, int SampleIndex, float RotationAngle, float ScreenSpaceSampleRadius){ vec3 getSampleViewSpacePos(ivec2 ScreenSpaceCoord, int SampleIndex, float RotationAngle, float ScreenSpaceSampleRadius){
// Pure Magic... // SampleIndex + 0.5f so that we alpha != 0, since if alpha = 0 then screenSpaceSampleTexel will be the same texel as origin.
float alpha = float(SampleIndex) * (1.0 / uNumOfSamples); float alpha = float(SampleIndex + 0.5f) * (1.0f / uNumOfSamples);
// Angle to where to sample // Angle to where to sample
float angle = alpha * (uNumOfTurns * 6.28) + RotationAngle; float angle = alpha * (uNumOfTurns * 6.28f) + RotationAngle;
//Lenght to were to sample //Lenght to were to sample
ScreenSpaceSampleRadius = ScreenSpaceSampleRadius * alpha; ScreenSpaceSampleRadius = ScreenSpaceSampleRadius * alpha;
vec2 screenSpaceSampleOffsetVecor = vec2(cos(angle), sin(angle)); vec2 screenSpaceSampleOffsetVecor = vec2(cos(angle), sin(angle));
//int mipmapLevel = clamp(int(floor(log2(-ScreenSpaceSampleRadius))) - MAX_PIXEL_BEFOR_LOWER_MIP_LEVEL, 0, MIP_MAPS_LEVELS);
// Get texel coordinate on where to sample by going screenSpaceSampleOffsetVecor direction in ScreenSpaceSampleRadius units from ScreenSpaceCoord (the point being shaded); // Get texel coordinate on where to sample by going screenSpaceSampleOffsetVecor direction in ScreenSpaceSampleRadius units from ScreenSpaceCoord (the point being shaded);
ivec2 screenSpaceSampleTexel = ivec2(ScreenSpaceSampleRadius * screenSpaceSampleOffsetVecor) + ScreenSpaceCoord; ivec2 screenSpaceSampleTexel = (ivec2(ScreenSpaceSampleRadius * screenSpaceSampleOffsetVecor) + ScreenSpaceCoord);// >> mipmapLevel;
return getVSPosition(screenSpaceSampleTexel); return getVSPosition(screenSpaceSampleTexel);
} }
float sampleAO(ivec2 ScreenSpaceCoord, vec3 Origin, vec3 OriginNormal, float ScreenSpaceSampleRadius, int SampleIndex, float RotationAngle, float Radius) { float sampleAO(ivec2 ScreenSpaceCoord, vec3 Origin, vec3 OriginNormal, float ScreenSpaceSampleRadius, int SampleIndex, float RotationAngle, float Radius, float Radius2) {
float radius2 = Radius * Radius;
vec3 sampleViewSpacePosition = getSampleViewSpacePos(ScreenSpaceCoord, SampleIndex, RotationAngle, ScreenSpaceSampleRadius); vec3 sampleViewSpacePosition = getSampleViewSpacePos(ScreenSpaceCoord, SampleIndex, RotationAngle, ScreenSpaceSampleRadius);
vec3 sampleVector = Origin - sampleViewSpacePosition; vec3 sampleVector = Origin - sampleViewSpacePosition;
// vv = sampleVectorLenght ^ 2 // vv = sampleVectorLenght ^ 2
float vv = dot(sampleVector, sampleVector); float vv = dot(sampleVector, sampleVector);
// vn = angle between sampleVector and Normal // vn = angle between sampleVector and Normal
float vn = dot(sampleVector, OriginNormal); float vn = dot(sampleVector, OriginNormal);
const float epsilon = 0.0001f; const float epsilon = 0.01f;
// vv < radius2 if the vector is shorter then the radius; // vv < radius2 if the vector is shorter then the radius;
// vn - bias, offset the angle to reduse self occlusion. // vn - bias, offset the angle to reduse self occlusion.
// epsilon is here to make divison by 0 impossible. // epsilon is here to make divison by 0 impossible.
return float(vv < radius2) * max((vn - uBias) / (epsilon + vv), 0.0); return float(vv < Radius2) * max((vn - uBias) / (epsilon + vv), 0.0);
//float f = max(radius2 - vv, 0.0); //float f = max(radius2 - vv, 0.0);
//return f * f * f * max((vn - uBias) / (epsilon + vv), 0.0); //return f * f * f * max((vn - uBias) / (epsilon + vv), 0.0);
} }
@@ -86,9 +88,11 @@ float sampleAO(ivec2 ScreenSpaceCoord, vec3 Origin, vec3 OriginNormal, float Scr
void main() { void main() {
ivec2 originScreenCoord = ivec2(gl_FragCoord.xy); ivec2 originScreenCoord = ivec2(gl_FragCoord.xy);
// We always get the Orginin from the level 0 of the mipmaps
vec3 origin = getVSPosition(originScreenCoord); vec3 origin = getVSPosition(originScreenCoord);
float radius; float radius;
if(origin.z < uRadius){ if(origin.z < uRadius){
radius = origin.z; radius = origin.z;
} else { } else {
@@ -96,19 +100,24 @@ void main() {
} }
float radius2 = radius * radius;
vec3 originNormal = getVSFaceNormal(origin); vec3 originNormal = getVSFaceNormal(origin);
//screenSpaceSampleRadius is in pixels
float screenSpaceSampleRadius = -uProjScale * radius / origin.z; float screenSpaceSampleRadius = -uProjScale * radius / origin.z;
//screenSpaceSampleRadius = clamp(screenSpaceSampleRadius, 0.0f, -uProjScale * radius);
float rotationAngleOffset = 30 * originScreenCoord.x ^ originScreenCoord.y + 10 * originScreenCoord.x * originScreenCoord.y; float rotationAngleOffset = 30 * originScreenCoord.x ^ originScreenCoord.y + 10 * originScreenCoord.x * originScreenCoord.y;
float sum = 0.0; float sum = 0.0f;
for (int i = 0; i < uNumOfSamples; i++) { for(int i = 0; i < uNumOfSamples; i++) {
sum += sampleAO(originScreenCoord, origin, originNormal, screenSpaceSampleRadius, i, rotationAngleOffset, radius); sum += sampleAO(originScreenCoord, origin, originNormal, screenSpaceSampleRadius, i, rotationAngleOffset, radius, radius2);
} }
//float A = max(0.0, 1.0 - sum * (2.0f / uNumOfSamples)); //float A = max(0.0, 1.0 - sum * (2.0f / uNumOfSamples));
float A = 1.0 - sum * (2.0f * uIntensityScale / float(uNumOfSamples)); float A = 1.0f - sum * (2.0f * uIntensityScale / float(uNumOfSamples));
AO = clamp(pow(A, uContrast), 0.0f, 1.0f); AO = clamp(pow(A, uContrast), 0.0f, 1.0f);
//AO = screenSpaceSampleRadius;
//AO = vec4(originNormal, 1.0f); //AO = vec4(originNormal, 1.0f);
} }
+123
View File
@@ -0,0 +1,123 @@
#version 430
#define MIP_MAPS_LEVELS (5)
#define LOWER_MIP_LEVEL (2)
//Number of samples per pixel
uniform int uNumOfSamples;
//#define uNumOfSamples (11)
//Number of turns around the cirle
uniform int uNumOfTurns;
//#define uNumOfTurns (7)
layout (binding = 0) uniform sampler2D ViewSpaceZ;
uniform vec4 uProjInfo;
uniform float uProjScale;
//#define ProjScale 500
uniform float uRadius;
//#define Radius 1.0f
uniform float uBias;
//#define Bias 0.012f
uniform float uContrast;
//#define IntensityDivR6 1
uniform float uIntensityScale;
out float AO;
vec3 getVSPosition(ivec2 ScreenSpaceCoord, int mipmaplevel) {
float z = texelFetch(ViewSpaceZ, ScreenSpaceCoord, mipmaplevel).r;
//Get the xy view space coordinates and add the z value from ViewSpaceZ buffer.
return vec3((uProjInfo[0] + (ScreenSpaceCoord.x * uProjInfo[1])) * z, (uProjInfo[2] + (ScreenSpaceCoord.y * uProjInfo[3])) * z, z);
}
vec3 getVSFaceNormal(vec3 ViewSpacePosition) {
// Get tangets vector for the plane and ViewSpacePositin... don't ask how this functions works. It's pure magic.
// They do this and it just works... I would guess that they approximate the function of a plane from pixels close to the pixel were on now.
return normalize(cross(dFdx(ViewSpacePosition), dFdy(ViewSpacePosition)));
}
vec3 getSampleViewSpacePos(ivec2 ScreenSpaceCoord, int SampleIndex, float RotationAngle, float ScreenSpaceSampleRadius){
// SampleIndex + 0.5f so that we alpha != 0, since if alpha = 0 then screenSpaceSampleTexel will be the same texel as origin.
float alpha = float(SampleIndex + 0.5f) * (1.0f / uNumOfSamples);
// Angle to where to sample
float angle = alpha * (uNumOfTurns * 6.28f) + RotationAngle;
//Lenght to were to sample
ScreenSpaceSampleRadius = ScreenSpaceSampleRadius * alpha;
vec2 screenSpaceSampleOffsetVecor = vec2(cos(angle), sin(angle));
int mipmapLevel = clamp(int(floor(log2(-ScreenSpaceSampleRadius))) - LOWER_MIP_LEVEL, 0, MIP_MAPS_LEVELS);
// Get texel coordinate on where to sample by going screenSpaceSampleOffsetVecor direction in ScreenSpaceSampleRadius units from ScreenSpaceCoord (the point being shaded);
ivec2 screenSpaceSampleTexel = (ivec2(ScreenSpaceSampleRadius * screenSpaceSampleOffsetVecor) + ScreenSpaceCoord) >> mipmapLevel;
return getVSPosition(screenSpaceSampleTexel, mipmapLevel);
}
float sampleAO(ivec2 ScreenSpaceCoord, vec3 Origin, vec3 OriginNormal, float ScreenSpaceSampleRadius, int SampleIndex, float RotationAngle, float Radius, float Radius2) {
vec3 sampleViewSpacePosition = getSampleViewSpacePos(ScreenSpaceCoord, SampleIndex, RotationAngle, ScreenSpaceSampleRadius);
vec3 sampleVector = Origin - sampleViewSpacePosition;
// vv = sampleVectorLenght ^ 2
float vv = dot(sampleVector, sampleVector);
// vn = angle between sampleVector and Normal
float vn = dot(sampleVector, OriginNormal);
const float epsilon = 0.01f;
// vv < radius2 if the vector is shorter then the radius;
// vn - bias, offset the angle to reduse self occlusion.
// epsilon is here to make divison by 0 impossible.
return float(vv < Radius2) * max((vn - uBias) / (epsilon + vv), 0.0);
}
void main() {
ivec2 originScreenCoord = ivec2(gl_FragCoord.xy);
// We always get the Orginin from the level 0 of the mipmaps
vec3 origin = getVSPosition(originScreenCoord, 0);
float radius;
if(origin.z < uRadius){
radius = origin.z;
} else {
radius = uRadius;
}
float radius2 = radius * radius;
vec3 originNormal = getVSFaceNormal(origin);
//AO = originNormal;
//return;
//screenSpaceSampleRadius is in pixels
float screenSpaceSampleRadius = -uProjScale * radius / origin.z;
//screenSpaceSampleRadius = clamp(screenSpaceSampleRadius, 0.0f, pow(2, MIP_MAPS_LEVELS * LOWER_MIP_LEVEL + 1));
//AO = clamp(int(floor(log2(screenSpaceSampleRadius))) - LOWER_MIP_LEVEL, 0, MIP_MAPS_LEVELS);
//return;
float rotationAngleOffset = 30 * originScreenCoord.x ^ originScreenCoord.y + 10 * originScreenCoord.x * originScreenCoord.y;
float sum = 0.0f;
for(int i = 0; i < uNumOfSamples; i++) {
sum += sampleAO(originScreenCoord, origin, originNormal, screenSpaceSampleRadius, i, rotationAngleOffset, radius, radius2);
}
//float A = max(0.0, 1.0 - sum * (2.0f / uNumOfSamples));
float A = 1.0f - sum * (2.0f * uIntensityScale / float(uNumOfSamples));
AO = clamp(pow(A, uContrast), 0.0f, 1.0f);
//AO = vec4(originNormal, 1.0f);
}
+28 -20
View File
@@ -31,12 +31,30 @@ void SSAOPass::InitializeShaderProgram()
void SSAOPass::InitializeBuffer() void SSAOPass::InitializeBuffer()
{ {
GenerateTexture(&m_SSAOTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_R8, GL_RED, GL_FLOAT); glGenTextures(1, &m_SSAOTexture);
glBindTexture(GL_TEXTURE_2D, m_SSAOTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height, 0, GL_RED, GL_FLOAT, nullptr);
//glTexImage2D(GL_TEXTURE_2D, 0, GL_R32I, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height, 0, GL_RED_INTEGER, GL_INT, nullptr);
//glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height, 0, GL_RGB, GL_FLOAT, nullptr);
m_SSAOFramBuffer.AddResource(std::shared_ptr<BufferResource>(new Texture2D(&m_SSAOTexture, GL_COLOR_ATTACHMENT0))); m_SSAOFramBuffer.AddResource(std::shared_ptr<BufferResource>(new Texture2D(&m_SSAOTexture, GL_COLOR_ATTACHMENT0)));
m_SSAOFramBuffer.Generate(); m_SSAOFramBuffer.Generate();
GenerateTexture(&m_SSAOViewSpaceZTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_R32F, GL_RED, GL_FLOAT); glGenTextures(1, &m_SSAOViewSpaceZTexture);
glBindTexture(GL_TEXTURE_2D, m_SSAOViewSpaceZTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height, 0, GL_RED, GL_FLOAT, nullptr);
//glTexStorage2D(GL_TEXTURE_2D, MAX_MIP_LEVEL, GL_R32F, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height);;
//glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height, GL_RED, GL_FLOAT, nullptr);
//glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
m_SSAOViewSpaceZFramBuffer.AddResource(std::shared_ptr<BufferResource>(new Texture2D(&m_SSAOViewSpaceZTexture, GL_COLOR_ATTACHMENT0))); m_SSAOViewSpaceZFramBuffer.AddResource(std::shared_ptr<BufferResource>(new Texture2D(&m_SSAOViewSpaceZTexture, GL_COLOR_ATTACHMENT0)));
m_SSAOViewSpaceZFramBuffer.Generate(); m_SSAOViewSpaceZFramBuffer.Generate();
@@ -45,12 +63,12 @@ void SSAOPass::InitializeBuffer()
void SSAOPass::ClearBuffer() void SSAOPass::ClearBuffer()
{ {
m_SSAOFramBuffer.Bind(); m_SSAOFramBuffer.Bind();
glClearColor(0.f, 0.f, 0.f, 0.f); glClearColor(1.f, 1.f, 1.f, 1.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
m_SSAOFramBuffer.Unbind(); m_SSAOFramBuffer.Unbind();
m_SSAOViewSpaceZFramBuffer.Bind(); m_SSAOViewSpaceZFramBuffer.Bind();
glClearColor(0.f, 0.f, 0.f, 0.f); glClearColor(1.f, 1.f, 1.f, 1.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
m_SSAOViewSpaceZFramBuffer.Unbind(); m_SSAOViewSpaceZFramBuffer.Unbind();
} }
@@ -64,17 +82,6 @@ void SSAOPass::Setting(float radius, float bias, float contrast, float intensity
m_NumOfTurns = NumOfTurns; m_NumOfTurns = NumOfTurns;
} }
void SSAOPass::GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const
{
glGenTextures(1, texture);
glBindTexture(GL_TEXTURE_2D, *texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapping);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapping);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, dimensions.x, dimensions.y, 0, format, type, nullptr);
GLERROR("Texture initialization failed");
}
void SSAOPass::Draw(GLuint depthBuffer, Camera* camera) void SSAOPass::Draw(GLuint depthBuffer, Camera* camera)
{ {
@@ -111,6 +118,11 @@ void SSAOPass::Draw(GLuint depthBuffer, Camera* camera)
(-2.0 / (m_Renderer->GetViewportSize().Height * camera->ProjectionMatrix()[1][1])) (-2.0 / (m_Renderer->GetViewportSize().Height * camera->ProjectionMatrix()[1][1]))
); );
m_SSAOViewSpaceZFramBuffer.Unbind();
//glBindTexture(GL_TEXTURE_2D, m_SSAOViewSpaceZTexture);
//glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height, GL_RED, GL_FLOAT, &m_SSAOViewSpaceZTexture);
//glGenerateMipmap(GL_TEXTURE_2D);
m_SSAOFramBuffer.Bind(); m_SSAOFramBuffer.Bind();
m_SSAOProgram->Bind(); m_SSAOProgram->Bind();
@@ -119,7 +131,7 @@ void SSAOPass::Draw(GLuint depthBuffer, Camera* camera)
glBindTexture(GL_TEXTURE_2D, m_SSAOViewSpaceZTexture); glBindTexture(GL_TEXTURE_2D, m_SSAOViewSpaceZTexture);
// How many pixel there are in a 1m long object 1m away from the camera // How many pixel there are in a 1m long object 1m away from the camera
glUniform1f(glGetUniformLocation(SSAOShaderHandle, "uProjScale"), m_Renderer->GetViewportSize().Height / (-2.0f * glm::tan(camera->FOV() * 0.5f))); glUniform1f(glGetUniformLocation(SSAOShaderHandle, "uProjScale"), m_Renderer->GetViewportSize().Height / (-2.0f * glm::tan(glm::radians(camera->FOV()) * 0.5f)));
glUniform1f(glGetUniformLocation(SSAOShaderHandle, "uRadius"), m_Radius); glUniform1f(glGetUniformLocation(SSAOShaderHandle, "uRadius"), m_Radius);
glUniform1f(glGetUniformLocation(SSAOShaderHandle, "uBias"), m_Bias); glUniform1f(glGetUniformLocation(SSAOShaderHandle, "uBias"), m_Bias);
@@ -135,7 +147,3 @@ void SSAOPass::Draw(GLuint depthBuffer, Camera* camera)
m_DrawBloomPass->ClearBuffer(); m_DrawBloomPass->ClearBuffer();
m_DrawBloomPass->Draw(m_SSAOTexture); m_DrawBloomPass->Draw(m_SSAOTexture);
} }
void ComputeAO(GLuint depthBuffer, Camera* camera) {
}