51 #include <ACG/GL/acg_glew.hh> 56 #include <ACG/GL/GLError.hh> 64 SSAOPlugin::SSAOPlugin() :
67 for (
unsigned int i = 0; i < 10; ++i)
70 for (
unsigned int i = 0; i < 6; ++i)
74 SSAOPlugin::~SSAOPlugin()
79 QString SSAOPlugin::checkOpenGL()
82 return QString(
"Insufficient OpenGL Version! OpenGL 3.2 or higher required");
86 missing +=
"GL_ARB_vertex_buffer_object extension missing\n";
90 missing +=
"GL_ARB_vertex_program extension missing\n";
94 missing +=
"GL_ARB_texture_float extension missing\n";
97 missing +=
"GL_EXT_framebuffer_object extension missing\n";
103 SSAOPlugin::ViewerResources::ViewerResources()
105 memset(
this, 0,
sizeof(ViewerResources));
108 void SSAOPlugin::initializePlugin()
110 memset(shaders_, 0,
sizeof(shaders_));
111 memset(programs_, 0,
sizeof(programs_));
115 generateSamplingKernel();
122 for (
unsigned int i = 0; i < numSamples_; ++i)
125 for (
int k = 0; k < 3; ++k)
127 unsigned int x = (rand()*rand()*rand()) & RAND_MAX;
128 r[k] = float(x) / float(RAND_MAX);
138 float d = float(i+1) / float(numSamples_);
140 if (d < 0.1f) d = 0.1f;
144 samplingKernel_[i] = r;
150 void SSAOPlugin::exit()
157 QString SSAOPlugin::rendererName() {
158 return QString(
"SSAO Renderer");
178 destroyResources(_viewerId);
197 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
198 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
200 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
201 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
209 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
210 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
212 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
213 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
214 glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, p->
glWidth_, p->
glHeight_, 0, GL_RGB, GL_FLOAT, 0);
220 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
221 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
223 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
224 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
225 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, p->
glWidth_, p->
glHeight_, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
229 for (
int i = 0; i < 2; ++i)
234 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
235 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
237 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
238 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
245 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
246 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
248 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
249 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
250 glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, p->
glWidth_, p->
glHeight_, 0, GL_RGB, GL_FLOAT, 0);
260 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, p->
glWidth_, p->
glHeight_);
261 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
264 glGenFramebuffersEXT(1, &p->
ssaoFbo_);
269 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, p->
depthBufTex_, 0);
270 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, p->
sceneNormalTex_, 0);
271 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_TEXTURE_2D, p->
occlusionTex_, 0);
272 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, p->
depthSSAORenderBuf_);
274 GLenum fboStatus = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
275 if(fboStatus != GL_FRAMEBUFFER_COMPLETE_EXT)
276 printf(
"SSAO Plugin: ssaoFbo failed to initialize\n");
281 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, p->
sceneBufTex_, 0);
289 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
291 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, p->
depthSceneRenderBuf_);
294 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, p->
depthSSAORenderBuf_);
296 fboStatus = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
297 if(fboStatus != GL_FRAMEBUFFER_COMPLETE_EXT)
298 printf(
"SSAO Plugin: sceneFbo failed to initialize\n");
301 glGenFramebuffersEXT(1, &p->
blurFbo_);
303 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, p->
downsampledTex_, 0);
304 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, p->
downsampledTmpTex_, 0);
307 fboStatus = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
308 if(fboStatus != GL_FRAMEBUFFER_COMPLETE_EXT)
309 printf(
"SSAO Plugin: blurFbo failed to initialize\n");
317 const char* ShaderFiles[] = {
"SSAO/init_vertex.glsl",
318 "SSAO/fullscreen_vertex.glsl",
319 "SSAO/init_fragment.glsl",
320 "SSAO/downsampling_fragment.glsl",
321 "SSAO/blur_fragment.glsl",
322 "SSAO/ssao_fragment.glsl",
323 "SSAO/final_fragment.glsl",
324 "SSAO/final_MSAA_vertex.glsl",
325 "SSAO/final_MSAA_fragment.glsl"};
327 for (
int i = 0; i < 9; ++i)
329 QString shaderFile = OpenFlipper::Options::shaderDirStr() + QDir::separator() + QString(ShaderFiles[i]);
331 #ifdef SSAO_SHADER_DEBUG_MODE 334 if (shaders_[i])
continue;
344 log(
LOGERR, QString(ShaderFiles[i]) + QString(
" could not be loaded and compiled"));
350 for (
int i = 0; i < 6; ++i)
352 #ifndef SSAO_SHADER_DEBUG_MODE 364 pr->
attach(shaders_[2]);
break;
366 case PROG_DOWNSAMPLING:
368 pr->
attach(shaders_[3]);
break;
372 pr->
attach(shaders_[4]);
break;
376 pr->
attach(shaders_[5]);
break;
380 pr->
attach(shaders_[6]);
break;
382 case PROG_FINAL_MSAA:
384 pr->
attach(shaders_[8]);
break;
394 glGenTextures(1, &randomVecTex_);
397 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
398 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
400 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
401 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
404 for (
int i = 0; i < 16; ++i)
407 for (
int k = 0; k < 3; ++k)
408 x[k] =
float(rand()) / float(RAND_MAX);
410 float theta = x[0] * 6.2831853f;
411 float phi = x[1] * 6.2831853f;
412 randVecs[i][0] = sinf(phi);
413 randVecs[i][1] = cosf(phi);
414 randVecs[i][2] = sinf(theta);
415 randVecs[i][3] = cosf(theta);
417 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, 4, 4, 0, GL_RGBA, GL_FLOAT, randVecs);
429 for (
unsigned int i = 0; i <
sizeof(programs_) /
sizeof(programs_[0]); ++i)
431 delete programs_[i]; programs_[i] = 0;
434 for (
unsigned int i = 0; i <
sizeof(shaders_) /
sizeof(shaders_[0]); ++i)
440 if (randomVecTex_) glDeleteTextures(1, &randomVecTex_);
444 std::map<int, ViewerResources>::iterator resIt = viewerRes_.begin();
445 for (; resIt != viewerRes_.end(); ++resIt)
446 destroyResources(resIt->first);
486 glVertex2f(x0, y0-h);
487 glVertex2f(x0+w, y0-h);
488 glVertex2f(x0+w, y0);
503 void SSAOPlugin::gaussianBlurPass(
const ViewerResources* _pViewer,
const float* _texelSize,
504 GLenum _targetAttachement, GLuint _srcTexture)
507 const float gaussStDev = 1.0f;
511 float gaussKernel[5];
513 for (
int i = 0; i < 5; ++i)
516 gaussKernel[i] = powf(2.71828f, -
float(i*i)*(_texelSize[0]*_texelSize[0] + _texelSize[1]*_texelSize[1]) /
517 (gaussStDev*gaussStDev));
518 sum += gaussKernel[i];
521 for (
int i = 0; i < 5; ++i)
522 gaussKernel[i] /= sum;
527 programs_[PROG_BLUR]->setUniform(
"Tex", 0);
528 programs_[PROG_BLUR]->setUniform(
"TexelSize",
ACG::Vec2f(_texelSize));
529 programs_[PROG_BLUR]->setUniform(
"Kernel", gaussKernel, 5);
538 glPushAttrib(GL_ALL_ATTRIB_BITS);
542 int viewerId = _properties.
viewerId();
558 GLenum drawBuffers[] = {GL_COLOR_ATTACHMENT0_EXT,
559 GL_COLOR_ATTACHMENT1_EXT,
560 GL_COLOR_ATTACHMENT2_EXT,
561 GL_COLOR_ATTACHMENT3_EXT,
562 GL_COLOR_ATTACHMENT4_EXT,
563 GL_COLOR_ATTACHMENT5_EXT,
564 GL_COLOR_ATTACHMENT6_EXT};
567 const float maxDepth = 1000.0f;
569 GLint oldViewport[4];
570 glGetIntegerv(GL_VIEWPORT, oldViewport);
572 for (
int i = 0; i < 6; ++i)
578 float texelSize[4] = {1.0f / float(pViewer->
rtWidth_), 1.0f / float(pViewer->
rtHeight_), 0.0f, 0.0f};
601 glDepthMask(GL_TRUE);
602 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
604 drawScenePass(_glState, _properties, sceneGraphRoot);
606 ACG::GLState::unlockDepthFunc();
617 glDepthMask(GL_TRUE);
622 glClearColor(maxDepth, 0.0f, 0.0f, 0.0f);
623 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
626 glClearColor(0.5f, 0.5f, 0.0f, 0.0f);
627 glClear(GL_COLOR_BUFFER_BIT);
631 programs_[PROG_INIT]->use();
632 drawScenePass(_glState, _properties, sceneGraphRoot);
633 programs_[PROG_INIT]->disable();
640 texelSize[0] = 1.0f / float(pViewer->
rtWidth_);
641 texelSize[1] = 1.0f / float(pViewer->
rtHeight_);
643 programs_[PROG_SSAO]->use();
644 programs_[PROG_SSAO]->setUniform(
"TexelSize",
ACG::Vec2f(texelSize[0], texelSize[1]));
647 GLint location = programs_[PROG_SSAO]->getUniformLocation(
"Kernel");
648 glUniform3fv(location, 32, (GLfloat*)samplingKernel_);
651 programs_[PROG_SSAO]->setUniform(
"RandTex", 3);
652 programs_[PROG_SSAO]->setUniform(
"NormalTex", 2);
653 programs_[PROG_SSAO]->setUniform(
"SceneTex", 1);
654 programs_[PROG_SSAO]->setUniform(
"DepthTex", 0);
683 programs_[PROG_DOWNSAMPLING]->use();
684 programs_[PROG_DOWNSAMPLING]->setUniform(
"TexelSize",
ACG::Vec2f(texelSize));
689 programs_[PROG_DOWNSAMPLING]->setUniform(
"Tex", 0);
696 programs_[PROG_BLUR]->use();
697 programs_[PROG_BLUR]->setUniform(
"DepthTex", 1);
698 programs_[PROG_BLUR]->setUniform(
"EdgeBlur", _properties.
multisampling() ? 0.3f : 0.0f);
706 gaussianBlurPass(pViewer, texelSize, drawBuffers[1], pViewer->
downsampledTex_);
717 glViewport(oldViewport[0], oldViewport[1], oldViewport[2], oldViewport[3]);
743 #if QT_VERSION < 0x050000 static void enable(GLenum _cap)
replaces glEnable, but supports locking
void attach(PtrConstShader _shader)
Attaches a shader object to the program object.
GLSL::PtrFragmentShader loadFragmentShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new vertex shader.
const Vec4f & clear_color() const
get background color
unsigned int rtDownWidth_
downsampled rt width
DrawMode DEFAULT
use the default (global) draw mode and not the node's own.
unsigned int glHeight_
viewer window height
void traverse_multipass(BaseNode *_node, Action &_action, const unsigned int &_pass)
void link()
Links the shader objects to the program.
unsigned int rtWidth_
render target width
int viewport_width() const
get viewport width
static GLuint getFramebufferDraw()
get current draw framebuffer of a target
GLuint depthSceneRenderBuf_
depth renderbuffer for sceneFbo
unsigned int glWidth_
viewer window width
static void bindFramebuffer(GLenum _target, GLuint _framebuffer)
replaces glBindFramebuffer, supports locking
void use()
Enables the program object for using.
GLuint downsampledTmpTex_
downsampled temp rt for intermediate results
GLuint depthSSAORenderBuf_
depth renderbuffer for ssaoFbo
bool openGLVersion(const int _major, const int _minor)
unsigned int rtSceneWidth_
scene render target width
const GLenum & depthFunc() const
get glDepthFunc() that is supposed to be active
void multisampling(bool _state)
set multisampling on/off
void drawScenePass(ACG::GLState *_glState, Viewer::ViewerProperties &_properties, BaseNode *_sceneGraphRoot)
draw the current scene
void reloadResources(int _viewerId, unsigned int _sceneTexWidth, unsigned int _sceneTexHeight)
reload gl resources
void setUniform(const char *_name, GLint _value)
Set int uniform to specified value.
static void drawBuffers(GLsizei _n, const GLenum *_bufs)
replaces glDrawBuffers, supports locking
GLuint occlusionTex_
occlusion render target
GLuint sceneBufTex_
standard scene without a render target
static void activeTexture(GLenum _texunit)
replaces glActiveTexture, no locking support
int viewerId()
Get the id of the viewer this viewerproperties belongs to.
static void disable(GLenum _cap)
replaces glDisable, but supports locking
auto normalize() -> decltype(*this/=std::declval< VectorT< S, DIM >>().norm())
unsigned int rtDownHeight_
downsampled rt height
void generateSamplingKernel()
computes a hemisphere sampling kernel in [0,1] range
void drawMode(ACG::SceneGraph::DrawModes::DrawMode _mode)
set draw mode (No test if this mode is available!)
GLSL::PtrVertexShader loadVertexShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new vertex shader.
void destroyResources()
free all gl resources
unsigned int rtHeight_
render target height
GLuint depthBufTex_
depth buffer render target
static void bindTexture(GLenum _target, GLuint _buffer)
replaces glBindTexture, supports locking
bool checkExtensionSupported(const std::string &_extension)
int viewport_height() const
get viewport height
ACG::SceneGraph::BaseNode * getSceneGraphRootNode()
get scenegraph root node
static void drawBuffer(GLenum _mode)
replaces glDrawBuffer, supports locking
unsigned int rtSceneHeight_
scene render target height
GLuint downsampledTex_
downsampled depth render target
void disable()
Resets to standard rendering pipeline.
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)
static const unsigned int numSamples_
number of samples