Hello!
As I am new here, I’d like to first greet everyone and wish you all a nice day!
Even though I am new here, I am not only here to say hello, because I got quite into a predicament, I have a serious issue with SSAO and ShadowMapping and I would kindly ask for any help I can get.
Therefor, I’d like to get startet and will now post a couple of screenshots as well as some code, mostly of what I think is creating the issue at hand.
[ATTACH=CONFIG]1190[/ATTACH][ATTACH=CONFIG]1191[/ATTACH]
That is my current progress, and it should be pretty obvious, the shadow is completely wrong.
There are two obvious issues, first, it looks like a rectangle has been placed in the front and everthing behind it is now covered in shadow and the second, the shadows generated by the shadowmap are not beneith their objects anymore.
The shadows from the shadowmap look like the are flying and placed further to the back and generated multiple times…
So, I would like to start with the code, first, the initialization of my ssao.
void initSSAO()
{
ball->bindSSAOs();
plane->bindSSAOs();
item->bindSSAOs();
enemy->bindSSAOs();
//prepare GEOMETRY: fbo, depth and texture
{
geoPassShader->useShader();
geo_fbo = 0;
geo_depth = 0;
geo_texture = 0;
geo_normal = 0;
geo_posdepth = 0;
// Create the FBO
glGenFramebuffers(1, &geo_fbo);
glBindFramebuffer(GL_FRAMEBUFFER, geo_fbo);
// Create the textures - Position + linear depth color buffer
glGenTextures(1, &geo_posdepth);
glBindTexture(GL_TEXTURE_2D, geo_posdepth);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 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);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, geo_posdepth, 0);
// Create the textures - normal color buffer
glGenTextures(1, &geo_normal);
glBindTexture(GL_TEXTURE_2D, geo_normal);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 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_ATTACHMENT1, GL_TEXTURE_2D, geo_normal, 0);
// Create the textures - Albedo color buffer
glGenTextures(1, &geo_texture);
glBindTexture(GL_TEXTURE_2D, geo_texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA, 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_ATTACHMENT2, GL_TEXTURE_2D, geo_texture, 0);
// - Tell OpenGL which color attachments we'll use (of this framebuffer) for rendering
GLuint attachments[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
glDrawBuffers(3, attachments);
// Create the textures - depth buffer (renderbuffer)
glGenRenderbuffers(1, &geo_depth);
glBindRenderbuffer(GL_RENDERBUFFER, geo_depth);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, geo_depth);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
std::cout << "Framebufferstatus not ok" << std::endl;
system("PAUSE");
exit(EXIT_FAILURE);
}
// restore default FBO
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
//glUseProgram(0);
}
//prepare SSAO: fbo, texture
{
ssaoShader->useShader();
ssao_fbo = 0;
ssao_texture = 0;
// Create the FBO
glGenFramebuffers(1, &ssao_fbo);
glBindFramebuffer(GL_FRAMEBUFFER, ssao_fbo);
// Create the textures
glGenTextures(1, &ssao_texture);
glBindTexture(GL_TEXTURE_2D, ssao_texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width, height, 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, ssao_texture, 0);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
std::cout << "Framebufferstatus not ok" << std::endl;
system("PAUSE");
exit(EXIT_FAILURE);
}
// create KERNEL
for (int i = 0; i < KERNEL_SIZE; i++)
{
glm::vec3 tmp;
tmp.x = 2.0f * (float)rand() / RAND_MAX - 1.0f;
tmp.y = 2.0f * (float)rand() / RAND_MAX - 1.0f;
tmp.z = 2.0f * (float)rand() / RAND_MAX - 1.0f;
// Create a scale value between [0;1[ .
GLfloat scale = (GLfloat)i / (GLfloat)KERNEL_SIZE;
scale = (0.1f + (scale * scale)) * (1.0f - 0.1f);
tmp *= scale;
ssaoKernel.push_back(tmp);
}
//glUseProgram(0);
}
//prepare BLUR: fbo, texture
{
blurShader->useShader();
blur_fbo = 0;
blur_texture = 0;
// Create the FBO
glGenFramebuffers(1, &blur_fbo);
glBindFramebuffer(GL_FRAMEBUFFER, blur_fbo);
// Create the textures
glGenTextures(1, &blur_texture);
glBindTexture(GL_TEXTURE_2D, blur_texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width, height, 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, blur_texture, 0);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
std::cout << "Framebufferstatus not ok" << std::endl;
system("PAUSE");
exit(EXIT_FAILURE);
}
}
// restore default FBO
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
// Noise texture
{
std::vector<glm::vec3> ssaoNoise;
for (GLuint i = 0; i < 16; i++)
{
glm::vec3 tmp;
tmp.x = 2.0f * (float)rand() / RAND_MAX - 1.0f;
tmp.y = 2.0f * (float)rand() / RAND_MAX - 1.0f;
tmp.z = 2.0f * (float)rand() / RAND_MAX - 1.0f;
ssaoNoise.push_back(tmp);
}
glGenTextures(1, &noise_texture);
glBindTexture(GL_TEXTURE_2D, noise_texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, 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(0);
}
Now the follow up code for the periodically called ssao execution
void ssaoExec()
{
glm::mat4 model;
vl = glm::lookAt(cameraPosition, glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
pl = glm::perspective(glm::radians(45.0f), 1.0f, 20.0f, 80.0f);
//------------GEOMETRY--------------
geoPassShader->useShader();
glBindFramebuffer(GL_FRAMEBUFFER, geo_fbo);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
auto geo_proj = glGetUniformLocation(geoPassShader->programHandle, "projection");
glUniformMatrix4fv(geo_proj, 1, GL_FALSE, glm::value_ptr(pl));
auto geo_view = glGetUniformLocation(geoPassShader->programHandle, "view");
glUniformMatrix4fv(geo_view, 1, GL_FALSE, glm::value_ptr(vl));
//BALL
model = ball->modelMatrix;
auto wvp_ball_loc = glGetUniformLocation(geoPassShader->programHandle, "model");
glUniformMatrix4fv(wvp_ball_loc, 1, GL_FALSE, glm::value_ptr(model));
ball->draw();
//PLANE
model = plane->modelMatrix;
auto wvp_plane_loc = glGetUniformLocation(geoPassShader->programHandle, "model");
glUniformMatrix4fv(wvp_plane_loc, 1, GL_FALSE, glm::value_ptr(model));
plane->draw();
//ITEM
model = item->modelMatrix;
auto wvp_item_loc = glGetUniformLocation(geoPassShader->programHandle, "model");
glUniformMatrix4fv(wvp_item_loc, 1, GL_FALSE, glm::value_ptr(model));
item->draw();
//ENEMY
model = enemy->modelMatrix;
auto wvp_enemy_loc = glGetUniformLocation(geoPassShader->programHandle, "model");
glUniformMatrix4fv(wvp_enemy_loc, 1, GL_FALSE, glm::value_ptr(model));
enemy->draw();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
//glUseProgram(0);
//------------SSAO--------------
ssaoShader->useShader();
glBindFramebuffer(GL_FRAMEBUFFER, ssao_fbo);
glClear(GL_COLOR_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, geo_posdepth);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, geo_normal);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, noise_texture);
auto kernel_loc = glGetUniformLocation(ssaoShader->programHandle, "samples");
glUniform3fv(kernel_loc, KERNEL_SIZE, (const GLfloat*)&ssaoKernel[0]);
auto ssao_proj = glGetUniformLocation(ssaoShader->programHandle, "projection");
glUniformMatrix4fv(ssao_proj, 1, GL_FALSE, glm::value_ptr(pl));
renderQuad();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
//-----------BLUR------------
blurShader->useShader();
glBindFramebuffer(GL_FRAMEBUFFER, blur_fbo);
glClear(GL_COLOR_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, ssao_texture);
renderQuad();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
//glLoadName(-1);
}
Here is the code for the renderQuad():
GLuint quadVAO = 0;
GLuint quadVBO;
void renderQuad()
{
if (quadVAO == 0)
{
GLfloat quadVertices[] = {
// Positions // Texture Coords
-1.0f, 1.0f, 0.0f, -1.0f, 1.0f,
-1.0f, -1.0f, 0.0f, -1.0f, -1.0f,
1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
1.0f, -1.0f, 0.0f, 1.0f, -1.0f,
};
// Setup plane VAO
glGenVertexArrays(1, &quadVAO);
glGenBuffers(1, &quadVBO);
glBindVertexArray(quadVAO);
glBindBuffer(GL_ARRAY_BUFFER, quadVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
}
glBindVertexArray(quadVAO);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);
}
My Main.draw():
void draw(){
glm::mat4 l(0.5, 0.0, 0.0, 0.0,
0.0, 0.5, 0.0, 0.0,
0.0, 0.0, 0.5, 0.0,
0.5, 0.5, 0.5, 1.0
);
//set up View Frustum
/*if (vfc == 1){
ExtractFrustum();
}
glm::vec3 cen;
float rad;*/
shader->useShader();
auto spotLight_Loc = glGetUniformLocation(shader->programHandle, "spotlightPosition");
glUniform4fv(spotLight_Loc, 1, glm::value_ptr(spot));
/*auto view_loc = glGetUniformLocation(shader->programHandle, "viewMatrix");
glUniformMatrix4fv(view_loc, 1, GL_FALSE, glm::value_ptr(item->modelMatrix));*/
auto tex_loc = glGetUniformLocation(shader->programHandle, "shadowMap");
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, zbufferTex);
glUniform1i(tex_loc, 1);
//----------SSAO------------
auto screenSize_loc = glGetUniformLocation(shader->programHandle, "screenSize");
glUniform2f(screenSize_loc, (float)width, (float)height);
auto aoTexture_loc = glGetUniformLocation(shader->programHandle, "gAOMap");
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, blur_texture);
glUniform1i(aoTexture_loc, 3);
//renderQuad();
//-------------------------
m_vl_pl_l_matrix = l*pl*vl*ball->modelMatrix;
auto mvpl_ball_loc = glGetUniformLocation(shader->programHandle, "mvlpllMatrix");
glUniformMatrix4fv(mvpl_ball_loc, 1, GL_FALSE, glm::value_ptr(m_vl_pl_l_matrix));
ball->draw(proj, view);
m_vl_pl_l_matrix = l*pl*vl*plane->modelMatrix;
auto mvpl_plane_loc = glGetUniformLocation(shader->programHandle, "mvlpllMatrix");
glUniformMatrix4fv(mvpl_plane_loc, 1, GL_FALSE, glm::value_ptr(m_vl_pl_l_matrix));
plane->draw(proj, view);
/*item->bSphere(cen, rad); //check view frustum
glm::vec4 tmp = glm::vec4(cen, 1);
tmp = item->modelMatrix * tmp;
if (vfc == 0 || SphereInFrustum(glm::vec3(tmp), rad)){*/
m_vl_pl_l_matrix = l*pl*vl*item->modelMatrix;
auto mvpl_item_loc = glGetUniformLocation(shader->programHandle, "mvlpllMatrix");
glUniformMatrix4fv(mvpl_item_loc, 1, GL_FALSE, glm::value_ptr(m_vl_pl_l_matrix));
item->draw(proj, view);
//}
if (transparent == 1){
auto transparent_loc = glGetUniformLocation(shader->programHandle, "transparent");
glUniform1i(transparent_loc, 1);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_CULL_FACE);
}
/*enemy->bSphere(cen, rad); //check view frustum
tmp = glm::vec4(cen, 1);
tmp = enemy->modelMatrix * tmp;
if (vfc == 0 || SphereInFrustum(glm::vec3(tmp), rad)){*/
m_vl_pl_l_matrix = l*pl*vl*enemy->modelMatrix;
auto mvpl_enemy_loc = glGetUniformLocation(shader->programHandle, "mvlpllMatrix");
glUniformMatrix4fv(mvpl_enemy_loc, 1, GL_FALSE, glm::value_ptr(m_vl_pl_l_matrix));
enemy->draw(proj, view);
//}
if (transparent == 1){
glDisable(GL_BLEND);
glEnable(GL_CULL_FACE);
}
glUseProgram(0);
}
The way I handle the geometry shader for my objects, I had to comment out the “normal”, if I don’t the whole scene turns into one ball in the center of the screen, the size of triple of the ball on the playing field.
void Mesh::depthProgramHandle(Shader* depthShader, bool isSSAO)
{
//glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
depthShader->useShader();
//texID = glGetUniformLocation(depthShader->programHandle, "texture_color");
glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
GLint positionIndex = glGetAttribLocation(depthShader->programHandle, "position");
glEnableVertexAttribArray(positionIndex);
glVertexAttribPointer(positionIndex, 3, GL_FLOAT, GL_FALSE, 0, 0);
if (isSSAO)
{
/*glBindBuffer(GL_ARRAY_BUFFER, normalsBuffer);
normalIndex = glGetAttribLocation(depthShader->programHandle, "normal");
if (normalIndex != -1){
glEnableVertexAttribArray(normalIndex);
glVertexAttribPointer(normalIndex, 3, GL_FLOAT, GL_FALSE, 0, 0);
}*/
glBindBuffer(GL_ARRAY_BUFFER, uvBuffer);
uvIndex = glGetAttribLocation(depthShader->programHandle, "texCoords");
if (uvIndex != -1){
glEnableVertexAttribArray(uvIndex);
glVertexAttribPointer(uvIndex, 2, GL_FLOAT, GL_FALSE, 0, 0);
}
}
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
As well as the object.draw() used in the ssaoExec():
void Mesh::draw()
{
glBindVertexArray(vao);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glDrawArrays(GL_TRIANGLES, 0, indices.size());
glBindVertexArray(0);
}
Shaders in the next post…