45#include <ACG/GL/acg_glew.hh>
50#include <ACG/GL/GLError.hh>
58SSAOPlugin::SSAOPlugin() :
61 for (
unsigned int i = 0; i < 10; ++i)
64 for (
unsigned int i = 0; i < 6; ++i)
68SSAOPlugin::~SSAOPlugin()
73QString SSAOPlugin::checkOpenGL()
76 return QString(
"SSAO rendering-plugin is not yet compatible with Core Profile contexts.");
78 return QString(
"Insufficient OpenGL Version! OpenGL 3.2 or higher required");
82 missing +=
"GL_ARB_vertex_buffer_object extension missing\n";
86 missing +=
"GL_ARB_vertex_program extension missing\n";
90 missing +=
"GL_ARB_texture_float extension missing\n";
93 missing +=
"GL_EXT_framebuffer_object extension missing\n";
99void SSAOPlugin::initializePlugin()
116 for (
int k = 0; k < 3; ++k)
118 unsigned int x = (rand()*rand()*rand()) & RAND_MAX;
119 r[k] = float(x) / float(RAND_MAX);
131 if (d < 0.1f) d = 0.1f;
141void SSAOPlugin::exit()
148QString SSAOPlugin::rendererName() {
149 return QString(
"SSAO Renderer");
188 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
189 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
191 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
192 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
200 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
201 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
203 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
204 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
205 glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, p->
glWidth_, p->
glHeight_, 0, GL_RGB, GL_FLOAT, 0);
211 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
212 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
214 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
215 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
216 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, p->
glWidth_, p->
glHeight_, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
220 for (
int i = 0; i < 2; ++i)
225 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
226 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
228 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
229 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
236 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
237 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
239 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
240 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
241 glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, p->
glWidth_, p->
glHeight_, 0, GL_RGB, GL_FLOAT, 0);
251 glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, p->
glWidth_, p->
glHeight_);
252 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
260 glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, p->
depthBufTex_, 0);
261 glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, p->
sceneNormalTex_, 0);
262 glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_TEXTURE_2D, p->
occlusionTex_, 0);
263 glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, p->
depthSSAORenderBuf_);
265 GLenum fboStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
266 if(fboStatus != GL_FRAMEBUFFER_COMPLETE_EXT)
267 printf(
"SSAO Plugin: ssaoFbo failed to initialize\n");
272 glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, p->
sceneBufTex_, 0);
280 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
282 glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, p->
depthSceneRenderBuf_);
285 glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, p->
depthSSAORenderBuf_);
287 fboStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
288 if(fboStatus != GL_FRAMEBUFFER_COMPLETE_EXT)
289 printf(
"SSAO Plugin: sceneFbo failed to initialize\n");
294 glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, p->
downsampledTex_, 0);
295 glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, p->
downsampledTmpTex_, 0);
298 fboStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
299 if(fboStatus != GL_FRAMEBUFFER_COMPLETE_EXT)
300 printf(
"SSAO Plugin: blurFbo failed to initialize\n");
308 const char* ShaderFiles[] = {
"SSAO/init_vertex.glsl",
309 "SSAO/fullscreen_vertex.glsl",
310 "SSAO/init_fragment.glsl",
311 "SSAO/downsampling_fragment.glsl",
312 "SSAO/blur_fragment.glsl",
313 "SSAO/ssao_fragment.glsl",
314 "SSAO/final_fragment.glsl",
315 "SSAO/final_MSAA_vertex.glsl",
316 "SSAO/final_MSAA_fragment.glsl"};
318 for (
int i = 0; i < 9; ++i)
320 QString shaderFile = OpenFlipper::Options::shaderDirStr() + QDir::separator() + QString(ShaderFiles[i]);
322#ifdef SSAO_SHADER_DEBUG_MODE
335 log(
LOGERR, QString(ShaderFiles[i]) + QString(
" could not be loaded and compiled"));
341 for (
int i = 0; i < 6; ++i)
343#ifndef SSAO_SHADER_DEBUG_MODE
357 case PROG_DOWNSAMPLING:
373 case PROG_FINAL_MSAA:
388 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
389 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
391 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
392 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
395 for (
int i = 0; i < 16; ++i)
398 for (
int k = 0; k < 3; ++k)
399 x[k] =
float(rand()) / float(RAND_MAX);
401 float theta = x[0] * 6.2831853f;
402 float phi = x[1] * 6.2831853f;
403 randVecs[i][0] = sinf(phi);
404 randVecs[i][1] = cosf(phi);
405 randVecs[i][2] = sinf(theta);
406 randVecs[i][3] = cosf(theta);
408 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, 4, 4, 0, GL_RGBA, GL_FLOAT, randVecs);
435 std::map<int, ViewerResources>::iterator resIt = viewerRes_.begin();
436 for (; resIt != viewerRes_.end(); ++resIt)
477 glVertex2f(x0, y0-h);
478 glVertex2f(x0+w, y0-h);
479 glVertex2f(x0+w, y0);
494void SSAOPlugin::gaussianBlurPass(
const ViewerResources* _pViewer,
const float* _texelSize,
495 GLenum _targetAttachement, GLuint _srcTexture)
498 const float gaussStDev = 1.0f;
502 float gaussKernel[5];
504 for (
int i = 0; i < 5; ++i)
507 gaussKernel[i] = powf(2.71828f, -
float(i*i)*(_texelSize[0]*_texelSize[0] + _texelSize[1]*_texelSize[1]) /
508 (gaussStDev*gaussStDev));
509 sum += gaussKernel[i];
512 for (
int i = 0; i < 5; ++i)
513 gaussKernel[i] /= sum;
529 glPushAttrib(GL_ALL_ATTRIB_BITS);
535 ViewerResources* pViewer = &viewerRes_[
viewerId];
541 if ((pViewer->glWidth_ * 2 != pViewer->rtSceneWidth_) || (pViewer->glHeight_ * 2 != pViewer->rtSceneHeight_))
542 reloadResources(viewerId, pViewer->glWidth_ * 2, pViewer->glHeight_ * 2);
544 else if ((pViewer->glWidth_ != pViewer->rtSceneWidth_) || (pViewer->glHeight_ != pViewer->rtSceneHeight_))
549 GLenum drawBuffers[] = {GL_COLOR_ATTACHMENT0_EXT,
550 GL_COLOR_ATTACHMENT1_EXT,
551 GL_COLOR_ATTACHMENT2_EXT,
552 GL_COLOR_ATTACHMENT3_EXT,
553 GL_COLOR_ATTACHMENT4_EXT,
554 GL_COLOR_ATTACHMENT5_EXT,
555 GL_COLOR_ATTACHMENT6_EXT};
558 const float maxDepth = 1000.0f;
560 GLint oldViewport[4];
561 glGetIntegerv(GL_VIEWPORT, oldViewport);
563 for (
int i = 0; i < 6; ++i)
569 float texelSize[4] = {1.0f / float(pViewer->rtWidth_), 1.0f / float(pViewer->rtHeight_), 0.0f, 0.0f};
574 glViewport(0, 0, pViewer->rtSceneWidth_, pViewer->rtSceneHeight_);
592 glDepthMask(GL_TRUE);
593 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
597 ACG::GLState::unlockDepthFunc();
600 if (pViewer->rtSceneWidth_ != pViewer->glWidth_ || pViewer->rtSceneHeight_ != pViewer->glHeight_)
601 glViewport(0, 0, pViewer->glWidth_, pViewer->glHeight_);
608 glDepthMask(GL_TRUE);
613 glClearColor(maxDepth, 0.0f, 0.0f, 0.0f);
614 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
617 glClearColor(0.5f, 0.5f, 0.0f, 0.0f);
618 glClear(GL_COLOR_BUFFER_BIT);
631 texelSize[0] = 1.0f / float(pViewer->rtWidth_);
632 texelSize[1] = 1.0f / float(pViewer->rtHeight_);
667 glViewport(0, 0, pViewer->rtDownWidth_, pViewer->rtDownHeight_);
694 texelSize[0] = 1.0f / float(pViewer->rtDownWidth_);
697 gaussianBlurPass(pViewer, texelSize, drawBuffers[1], pViewer->downsampledTex_);
701 texelSize[1] = 1.0f / float(pViewer->rtDownHeight_);
703 gaussianBlurPass(pViewer, texelSize, drawBuffers[0], pViewer->downsampledTmpTex_);
708 glViewport(oldViewport[0], oldViewport[1], oldViewport[2], oldViewport[3]);
723 finalProg->
setUniform(
"SceneTexelSize",
ACG::Vec2f(1.0f /
float(pViewer->rtSceneWidth_), 1.0f /
float(pViewer->rtSceneHeight_)));
static void enable(GLenum _cap, bool _warnRemoved=true)
replaces glEnable, but supports locking
static void bindTexture(GLenum _target, GLuint _buffer)
replaces glBindTexture, supports locking
int viewport_width() const
get viewport width
static void drawBuffers(GLsizei _n, const GLenum *_bufs)
replaces glDrawBuffers, supports locking
static void activeTexture(GLenum _texunit)
replaces glActiveTexture, no locking support
static void disable(GLenum _cap, bool _warnRemoved=true)
replaces glDisable, but supports locking
const Vec4f & clear_color() const
get background color
int viewport_height() const
get viewport height
static GLuint getFramebufferDraw()
get current draw framebuffer of a target
const GLenum & depthFunc() const
get glDepthFunc() that is supposed to be active
static void drawBuffer(GLenum _mode)
replaces glDrawBuffer, supports locking
static void bindFramebuffer(GLenum _target, GLuint _framebuffer)
replaces glBindFramebuffer, supports locking
int getUniformLocation(const char *_name)
Get location of the specified uniform.
void disable()
Resets to standard rendering pipeline.
void link()
Links the shader objects to the program.
void use()
Enables the program object for using.
void setUniform(const char *_name, GLint _value)
Set int uniform to specified value.
void attach(PtrConstShader _shader)
Attaches a shader object to the program object.
auto normalize() -> decltype(*this/=std::declval< VectorT< S, DIM > >().norm())
static const unsigned int numSamples_
number of samples
GLuint randomVecTex_
random vector table for sample offset rotation
void drawScenePass(ACG::GLState *_glState, Viewer::ViewerProperties &_properties, BaseNode *_sceneGraphRoot)
draw the current scene
void destroyResources()
free all gl resources
void reloadResources(int _viewerId, unsigned int _sceneTexWidth, unsigned int _sceneTexHeight)
reload gl resources
ACG::Vec3f samplingKernel_[128]
ssao sampling kernel
GLSL::Shader * shaders_[10]
shader resources
void generateSamplingKernel()
computes a hemisphere sampling kernel in [0,1] range
GLSL::Program * programs_[6]
shader programs
void drawQuadProj(float _x0=-1.0f, float _y0=1.0f, float _w=2.0f, float _h=2.0f)
draw a quad in projection space (only positions)
int viewerId()
Get the id of the viewer this viewerproperties belongs to.
void drawMode(ACG::SceneGraph::DrawModes::DrawMode _mode)
set draw mode (No test if this mode is available!)
void multisampling(bool _state)
set multisampling on/off
DrawMode DEFAULT
use the default (global) draw mode and not the node's own.
void traverse_multipass(BaseNode *_node, Action &_action, const unsigned int &_pass)
bool checkExtensionSupported(const std::string &_extension)
bool openGLVersion(const int _major, const int _minor, bool _verbose)
bool compatibilityProfile()
get opengl core profile setting
GLSL::PtrFragmentShader loadFragmentShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new vertex shader.
GLSL::PtrVertexShader loadVertexShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new vertex shader.
int viewerId()
Return unique viewer id.
ACG::SceneGraph::BaseNode * getSceneGraphRootNode()
get scenegraph root node
GLuint depthSceneRenderBuf_
depth renderbuffer for sceneFbo
GLuint depthBufTex_
depth buffer render target
unsigned int rtHeight_
render target height
GLuint downsampledTex_
downsampled depth render target
unsigned int rtDownWidth_
downsampled rt width
unsigned int rtSceneWidth_
scene render target width
unsigned int rtDownHeight_
downsampled rt height
unsigned int rtSceneHeight_
scene render target height
GLuint downsampledTmpTex_
downsampled temp rt for intermediate results
GLuint occlusionTex_
occlusion render target
GLuint depthSSAORenderBuf_
depth renderbuffer for ssaoFbo
GLuint sceneBufTex_
standard scene without a render target
unsigned int glWidth_
viewer window width
unsigned int glHeight_
viewer window height
unsigned int rtWidth_
render target width