The ssao works but there is a weird red colour overlay due to the ssao only using the red channel of course this is shown in the image below..
However, when I do glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); the red colour goes but the ssao goes as well.
Result after doing glClear(). No SSAO anymore
Here is all the code that you need...
// ------------------------------ LIGHT PASS -------------------------------- //
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
shaders[LIGHT_PASS]->UseProgram(); // Bind light pass shader
// Parse the camera position
LightPass::Render(Content::_map->GetCamera(), Content::_map->GetCamera()->GetPosition());
GBuffer::Render(); // bind the gbuffer textures (includes SSAO)
renderQuad(); // Render the screen rectangle
// -------------------------------------------------------------------- //
Geometry Pass code..
// ----------------------------- GEOMETRY PASS ----------------------------- //
GBuffer::Bind(); // Bind the world gbuffer frame buffer
shaders[GEOMETRY_PASS]->UseProgram(); // Bind geometry shader
GeometryPass::Render(); // Render geometry
glBindFramebuffer(GL_FRAMEBUFFER, 0); // Unbind the gbuffer
// --------------------------------------------------------------------- //
SSAO Pass code..
static inline void Initialise(unsigned int ssao_program, unsigned int ssaoblur_program)
{
program = ssao_program;
program2 = ssaoblur_program;
// SSAO color fbo
glGenTextures(1, &ssaoColorBuffer);
glBindTexture(GL_TEXTURE_2D, ssaoColorBuffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 1920, 1080, 0, GL_RGB, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ssaoColorBuffer, 0);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
std::cout << "SSAO Framebuffer not complete!" << std::endl;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// blur fbo
glGenFramebuffers(1, &ssaoBlurFBO);
glBindFramebuffer(GL_FRAMEBUFFER, ssaoBlurFBO);
// SSAO color buffer
glGenTextures(1, &ssaoColorBufferBlur);
glBindTexture(GL_TEXTURE_2D, ssaoColorBufferBlur);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 1920, 1080, 0, GL_RGB, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ssaoColorBufferBlur, 0);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
std::cout << "SSAO Framebuffer not complete!" << std::endl;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
std::uniform_real_distribution<GLfloat> randomFloats(0.0, 1.0); // generates random floats between 0.0 and 1.0
std::default_random_engine generator;
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 samples s.t. they're more aligned to center of kernel
scale = lerp(0.1f, 1.0f, scale * scale);
sample *= scale;
ssaoKernel.push_back(sample);
}
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);
glUseProgram(ssao_program);
glUniform1i(glGetUniformLocation(ssao_program, "gPosition"), 0); // the positions texture in the gbuffer
glUniform1i(glGetUniformLocation(ssao_program, "gNormal"), 1); // the normals texture in the gbuffer
glUniform1i(glGetUniformLocation(ssao_program, "texNoise"), 2); // the albedospec texture within the gbuffe
glUseProgram(ssaoblur_program);
glUniform1i(glGetUniformLocation(ssaoblur_program, "ssaoInput"), 0); // the positions texture in the gbuffer
}
static inline void Render(Camera* _camera)
{
// generate SSAO texture
glBindFramebuffer(GL_FRAMEBUFFER, ssaoFBO);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(program);
for (unsigned int i = 0; i < 64; ++i)
glUniform3fv(glGetUniformLocation(program, ("samples[" + std::to_string(i) + "]").c_str()), 1, glm::value_ptr(ssaoKernel[i]));
glUniformMatrix4fv(glGetUniformLocation(program, "proj"), 1, GL_FALSE, glm::value_ptr(_camera->GetProjectionMatrix()));
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, GBuffer::GetPositions());
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, GBuffer::GetNormals());
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, noiseTexture);
renderQuad();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// Blur ssao texture
glBindFramebuffer(GL_FRAMEBUFFER, ssaoBlurFBO);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(program2);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, ssaoColorBuffer);
renderQuad();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
GBuffer vertex shader..
#version 420 core
layout(location = 0) in vec3 position;
layout(location = 1) in vec3 texcoord;
layout(location = 2) in vec3 normal;
layout(location = 3) in vec3 tangent;
out vec3 _texcoord;
out vec3 _normal;
out vec3 _tangent;
out vec3 _frag_pos;
uniform mat4 mod;
uniform mat4 view;
uniform mat4 proj;
void main()
{
vec4 view_space = view * mod * vec4(position, 1.0);
_frag_pos = view_space.xyz;
_texcoord = texcoord;
_normal = ((view * mod) * vec4(normal, 0.0)).xyz;
_tangent = (mod * vec4(tangent, 0.0)).xyz;
gl_Position = proj * view_space;
}
GBuffer fragment shader...
#version 420 core
layout(location = 0) out vec3 gPosition; // Position texel colour
layout(location = 1) out vec3 gNormal; // Normal texel colour
layout(location = 2) out vec4 gAlbedo; // Albedo texel colour
layout(location = 3) out vec3 gSpecular; // Cubemap texel colour
layout(location = 4) out vec3 gMetalness; // Cubemap texel colour
in vec3 _texcoord;
in vec3 _normal;
in vec3 _tangent;
in vec3 _frag_pos;
uniform vec3 camera_pos;
uniform sampler2D normal; // Normal map
uniform sampler2D albedo; // Albedo and specular map
uniform sampler2D specular; // Specular map
uniform sampler2D metalness; // Metalness map
uniform samplerCube cubemap; // Local cubemap reflection sampler
vec3 TBN()
{
vec3 Normal = normalize(_normal); // Optimise normal
vec3 Tangent = normalize(_tangent); // Optimise tangent
vec3 Bitangent = cross(Tangent, Normal); // Calculate bitangent
vec3 BumpMapNormal = texture(normal, vec2(_texcoord).st).rgb; // Assign rgb values from normal map
BumpMapNormal = 2.0 * BumpMapNormal - vec3(1.0, 1.0, 1.0); // normalise the normal map between -1 to 1
mat3 TBN = mat3(Tangent, Bitangent, Normal); // Create tangent, bitangent and normal matrix
vec3 NewNormal; // Create a new normal variable
NewNormal = TBN * vec3(BumpMapNormal.r, -BumpMapNormal.g, BumpMapNormal.b); // Flip green component for OpenGL
NewNormal = normalize(NewNormal); // Normalise the new normal
return NewNormal; // Return the newly calculated normal
}
vec4 Convolute()
{
vec4 result = vec4(0.0);
const float kernel[] = float[25] ( 0,1,2,1,0,
1,2,3,2,1,
2,3,4,3,2,
1,2,3,2,1,
0,1,2,1,0);
vec2 delta = 1.0 / textureSize(albedo, 0);
int index = 24;
for (int j = -1; j <= 1; j++)
{
for (int i = -1; i <= 1; i++)
{
//for (int k = -1; k <= 1; k++)
result += kernel[index--] * texture(albedo, vec2(_texcoord).st + (vec2(i, j) * delta));
}
}
result /= 25.0;
return result;
}
void main()
{
gPosition = _frag_pos;
gNormal = normalize(TBN());
vec3 I = normalize(_frag_pos - camera_pos); // Calculate eye to fragment direction
vec3 R = reflect(I, normalize(TBN())); // Reflect I with the vertex normal
float M = texture(metalness, vec2(_texcoord.st)).r;
//vec4 gaussian = Convolute();
gAlbedo = texture(albedo, vec2(_texcoord.st)); // Assign albedo
gSpecular = texture(specular, vec2(_texcoord.st)).rgb; // Assign specular
gMetalness = (texture(cubemap, R).rgb) * M; // Assign metalness
}
light shader...
#version 420 core
out vec4 FragColor;
in vec2 _texcoord;
uniform vec3 camera_pos;
uniform sampler2D gPosition;
uniform sampler2D gNormal;
uniform sampler2D gAlbedo;
uniform sampler2D gSpecular;
uniform sampler2D gMetalness;
uniform sampler2D gSsao;
uniform vec3 lightPos;
void main(void)
{
vec3 FragPos = texture(gPosition, _texcoord).rgb;
vec3 Normal = texture(gNormal, _texcoord).rgb;
vec3 Diffuse = texture(gAlbedo, _texcoord).rgb;
float Emissive = texture(gAlbedo, _texcoord).a;
vec3 Specular = texture(gAlbedo, _texcoord).rgb;
vec3 Metalness = texture(gMetalness, _texcoord).rgb; // Reflection pass
float AmbientOcclusion = texture(gSsao, _texcoord).r;
vec3 light_colour = vec3(1.0f, 0.8, 0.7);
vec3 lighting = vec3(0.3 * Diffuse * AmbientOcclusion);
vec3 viewDir = normalize(-FragPos);
vec3 lightDir = normalize(lightPos - FragPos);
vec3 diffuse = max(dot(Normal, lightDir), 0.0) * Diffuse * light_colour; // Light colour
vec3 halfwayDir = normalize(lightDir + viewDir);
float spec = pow(max(dot(Normal, halfwayDir), 0.0), 32.0);
vec3 specular = (Specular * light_colour) * spec;
vec3 metalness = Metalness * Diffuse;
lighting += diffuse + specular + metalness;
FragColor = vec4(lighting, 1.0);
}
Any more code needed just ask. thanks for any help given
EDIT Problem fixed, was due to cubemap reflection, all working now
If a texture is looked up, and a specific texture channel is not present in the texture, then the function texture
will return 0.0 for the green and blue channel and 1.0 for the alpha channel.
This can be changed by the texture swizzle parameters GL_TEXTURE_SWIZZLE_R
, GL_TEXTURE_SWIZZLE_G
, GL_TEXTURE_SWIZZLE_B
and GL_TEXTURE_SWIZZLE_A
.
If you want that the green and blue channel return the same value as the red channel then this can be done like this:
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_RED );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED );
Apply this paramters to the texture objects ssaoColorBuffer
and ssaoColorBufferBlur
, to solve the issue.
See OpenGL 4.6 API Core Profile Specification; 15.2. SHADER EXECUTION; page 487]:
When a texture lookup is performed in a fragment shader, the GL computes the filtered texture value ... and converts it to a texture base color Cb as shown in table 15.1,
Texture Base Texture base color Internal Format Cb Ab RED (Rt, 0, 0) 1 RG (Rt, Gt, 0) 1 RGB (Rt, Gt, Bt) 1 RGBA (Rt, Gt, Bt) At
Table 15.1: Correspondence of filtered texture components to texture base components.
followed by swizzling the components of Cb, controlled by the values of the texture parameters
TEXTURE_SWIZZLE_R
,TEXTURE_SWIZZLE_G
,TEXTURE_SWIZZLE_B
, andTEXTURE_SWIZZLE_A
. If the value ofTEXTURE_SWIZZLE_R
is denoted by swizzler, swizzling computes the first component of Cs according toif (swizzler == RED) Cs[0] = Cb[0]; else if (swizzler == GREEN) Cs[0] = Cb[1]; else if (swizzler == BLUE) Cs[0] = Cb[2]; else if (swizzler == ALPHA) Cs[0] = Ab; else if (swizzler == ZERO) Cs[0] = 0; else if (swizzler == ONE) Cs[0] = 1; // float or int depending on texture component type