45 #include <ACG/GL/acg_glew.hh> 50 #include <ACG/GL/GLError.hh> 58 SSAOPlugin::SSAOPlugin() :
61 for (
unsigned int i = 0; i < 10; ++i)
64 for (
unsigned int i = 0; i < 6; ++i)
68 SSAOPlugin::~SSAOPlugin()
73 QString 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";
99 SSAOPlugin::ViewerResources::ViewerResources()
101 memset(
this, 0,
sizeof(ViewerResources));
104 void SSAOPlugin::initializePlugin()
106 memset(shaders_, 0,
sizeof(shaders_));
107 memset(programs_, 0,
sizeof(programs_));
111 generateSamplingKernel();
118 for (
unsigned int i = 0; i < numSamples_; ++i)
121 for (
int k = 0; k < 3; ++k)
123 unsigned int x = (rand()*rand()*rand()) & RAND_MAX;
124 r[k] = float(x) / float(RAND_MAX);
134 float d = float(i+1) / float(numSamples_);
136 if (d < 0.1f) d = 0.1f;
140 samplingKernel_[i] = r;
146 void SSAOPlugin::exit()
153 QString SSAOPlugin::rendererName() {
154 return QString(
"SSAO Renderer");
174 destroyResources(_viewerId);
193 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
194 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
196 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
197 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
205 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
206 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
208 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
209 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
210 glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, p->
glWidth_, p->
glHeight_, 0, GL_RGB, GL_FLOAT, 0);
216 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
217 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
219 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
220 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
221 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, p->
glWidth_, p->
glHeight_, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
225 for (
int i = 0; i < 2; ++i)
230 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
231 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
233 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
234 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
241 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
242 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
244 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
245 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
246 glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, p->
glWidth_, p->
glHeight_, 0, GL_RGB, GL_FLOAT, 0);
256 glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, p->
glWidth_, p->
glHeight_);
257 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
265 glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, p->
depthBufTex_, 0);
266 glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, p->
sceneNormalTex_, 0);
267 glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_TEXTURE_2D, p->
occlusionTex_, 0);
268 glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, p->
depthSSAORenderBuf_);
270 GLenum fboStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
271 if(fboStatus != GL_FRAMEBUFFER_COMPLETE_EXT)
272 printf(
"SSAO Plugin: ssaoFbo failed to initialize\n");
277 glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, p->
sceneBufTex_, 0);
285 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
287 glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, p->
depthSceneRenderBuf_);
290 glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, p->
depthSSAORenderBuf_);
292 fboStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
293 if(fboStatus != GL_FRAMEBUFFER_COMPLETE_EXT)
294 printf(
"SSAO Plugin: sceneFbo failed to initialize\n");
299 glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, p->
downsampledTex_, 0);
300 glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, p->
downsampledTmpTex_, 0);
303 fboStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
304 if(fboStatus != GL_FRAMEBUFFER_COMPLETE_EXT)
305 printf(
"SSAO Plugin: blurFbo failed to initialize\n");
313 const char* ShaderFiles[] = {
"SSAO/init_vertex.glsl",
314 "SSAO/fullscreen_vertex.glsl",
315 "SSAO/init_fragment.glsl",
316 "SSAO/downsampling_fragment.glsl",
317 "SSAO/blur_fragment.glsl",
318 "SSAO/ssao_fragment.glsl",
319 "SSAO/final_fragment.glsl",
320 "SSAO/final_MSAA_vertex.glsl",
321 "SSAO/final_MSAA_fragment.glsl"};
323 for (
int i = 0; i < 9; ++i)
325 QString shaderFile = OpenFlipper::Options::shaderDirStr() + QDir::separator() + QString(ShaderFiles[i]);
327 #ifdef SSAO_SHADER_DEBUG_MODE 330 if (shaders_[i])
continue;
340 log(
LOGERR, QString(ShaderFiles[i]) + QString(
" could not be loaded and compiled"));
346 for (
int i = 0; i < 6; ++i)
348 #ifndef SSAO_SHADER_DEBUG_MODE 360 pr->
attach(shaders_[2]);
break;
362 case PROG_DOWNSAMPLING:
364 pr->
attach(shaders_[3]);
break;
368 pr->
attach(shaders_[4]);
break;
372 pr->
attach(shaders_[5]);
break;
376 pr->
attach(shaders_[6]);
break;
378 case PROG_FINAL_MSAA:
380 pr->
attach(shaders_[8]);
break;
390 glGenTextures(1, &randomVecTex_);
393 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
394 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
396 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
397 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
400 for (
int i = 0; i < 16; ++i)
403 for (
int k = 0; k < 3; ++k)
404 x[k] =
float(rand()) / float(RAND_MAX);
406 float theta = x[0] * 6.2831853f;
407 float phi = x[1] * 6.2831853f;
408 randVecs[i][0] = sinf(phi);
409 randVecs[i][1] = cosf(phi);
410 randVecs[i][2] = sinf(theta);
411 randVecs[i][3] = cosf(theta);
413 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, 4, 4, 0, GL_RGBA, GL_FLOAT, randVecs);
425 for (
unsigned int i = 0; i <
sizeof(programs_) /
sizeof(programs_[0]); ++i)
427 delete programs_[i]; programs_[i] = 0;
430 for (
unsigned int i = 0; i <
sizeof(shaders_) /
sizeof(shaders_[0]); ++i)
436 if (randomVecTex_) glDeleteTextures(1, &randomVecTex_);
440 std::map<int, ViewerResources>::iterator resIt = viewerRes_.begin();
441 for (; resIt != viewerRes_.end(); ++resIt)
442 destroyResources(resIt->first);
482 glVertex2f(x0, y0-h);
483 glVertex2f(x0+w, y0-h);
484 glVertex2f(x0+w, y0);
499 void SSAOPlugin::gaussianBlurPass(
const ViewerResources* _pViewer,
const float* _texelSize,
500 GLenum _targetAttachement, GLuint _srcTexture)
503 const float gaussStDev = 1.0f;
507 float gaussKernel[5];
509 for (
int i = 0; i < 5; ++i)
512 gaussKernel[i] = powf(2.71828f, -
float(i*i)*(_texelSize[0]*_texelSize[0] + _texelSize[1]*_texelSize[1]) /
513 (gaussStDev*gaussStDev));
514 sum += gaussKernel[i];
517 for (
int i = 0; i < 5; ++i)
518 gaussKernel[i] /= sum;
523 programs_[PROG_BLUR]->setUniform(
"Tex", 0);
524 programs_[PROG_BLUR]->setUniform(
"TexelSize",
ACG::Vec2f(_texelSize));
525 programs_[PROG_BLUR]->setUniform(
"Kernel", gaussKernel, 5);
534 glPushAttrib(GL_ALL_ATTRIB_BITS);
538 int viewerId = _properties.
viewerId();
554 GLenum drawBuffers[] = {GL_COLOR_ATTACHMENT0_EXT,
555 GL_COLOR_ATTACHMENT1_EXT,
556 GL_COLOR_ATTACHMENT2_EXT,
557 GL_COLOR_ATTACHMENT3_EXT,
558 GL_COLOR_ATTACHMENT4_EXT,
559 GL_COLOR_ATTACHMENT5_EXT,
560 GL_COLOR_ATTACHMENT6_EXT};
563 const float maxDepth = 1000.0f;
565 GLint oldViewport[4];
566 glGetIntegerv(GL_VIEWPORT, oldViewport);
568 for (
int i = 0; i < 6; ++i)
574 float texelSize[4] = {1.0f / float(pViewer->
rtWidth_), 1.0f / float(pViewer->
rtHeight_), 0.0f, 0.0f};
597 glDepthMask(GL_TRUE);
598 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
600 drawScenePass(_glState, _properties, sceneGraphRoot);
602 ACG::GLState::unlockDepthFunc();
613 glDepthMask(GL_TRUE);
618 glClearColor(maxDepth, 0.0f, 0.0f, 0.0f);
619 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
622 glClearColor(0.5f, 0.5f, 0.0f, 0.0f);
623 glClear(GL_COLOR_BUFFER_BIT);
627 programs_[PROG_INIT]->use();
628 drawScenePass(_glState, _properties, sceneGraphRoot);
629 programs_[PROG_INIT]->disable();
636 texelSize[0] = 1.0f / float(pViewer->
rtWidth_);
637 texelSize[1] = 1.0f / float(pViewer->
rtHeight_);
639 programs_[PROG_SSAO]->use();
640 programs_[PROG_SSAO]->setUniform(
"TexelSize",
ACG::Vec2f(texelSize[0], texelSize[1]));
643 GLint location = programs_[PROG_SSAO]->getUniformLocation(
"Kernel");
644 glUniform3fv(location, 32, (GLfloat*)samplingKernel_);
647 programs_[PROG_SSAO]->setUniform(
"RandTex", 3);
648 programs_[PROG_SSAO]->setUniform(
"NormalTex", 2);
649 programs_[PROG_SSAO]->setUniform(
"SceneTex", 1);
650 programs_[PROG_SSAO]->setUniform(
"DepthTex", 0);
679 programs_[PROG_DOWNSAMPLING]->use();
680 programs_[PROG_DOWNSAMPLING]->setUniform(
"TexelSize",
ACG::Vec2f(texelSize));
685 programs_[PROG_DOWNSAMPLING]->setUniform(
"Tex", 0);
692 programs_[PROG_BLUR]->use();
693 programs_[PROG_BLUR]->setUniform(
"DepthTex", 1);
694 programs_[PROG_BLUR]->setUniform(
"EdgeBlur", _properties.
multisampling() ? 0.3f : 0.0f);
702 gaussianBlurPass(pViewer, texelSize, drawBuffers[1], pViewer->
downsampledTex_);
713 glViewport(oldViewport[0], oldViewport[1], oldViewport[2], oldViewport[3]);
unsigned int rtSceneWidth_
scene render target width
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 glWidth_
viewer window width
GLuint depthSSAORenderBuf_
depth renderbuffer for ssaoFbo
unsigned int rtWidth_
render target width
const GLenum & depthFunc() const
get glDepthFunc() that is supposed to be active
unsigned int rtDownWidth_
downsampled rt width
int viewport_width() const
get viewport width
static GLuint getFramebufferDraw()
get current draw framebuffer of a target
auto normalize() -> decltype(*this/=std::declval< VectorT< S, DIM >>().norm())
unsigned int rtDownHeight_
downsampled rt height
const Vec4f & clear_color() const
get background color
void disable()
Resets to standard rendering pipeline.
static void drawBuffers(GLsizei _n, const GLenum *_bufs)
replaces glDrawBuffers, supports locking
static void bindFramebuffer(GLenum _target, GLuint _framebuffer)
replaces glBindFramebuffer, supports locking
void compatibilityProfile(bool _enableCoreProfile)
Store opengl core profile setting.
void multisampling(bool _state)
set multisampling on/off
GLuint depthBufTex_
depth buffer render target
static void enable(GLenum _cap, bool _warnRemoved=true)
replaces glEnable, but supports locking
DrawMode DEFAULT
use the default (global) draw mode and not the node's own.
GLuint downsampledTex_
downsampled depth render target
unsigned int glHeight_
viewer window height
static void drawBuffer(GLenum _mode)
replaces glDrawBuffer, supports locking
GLuint downsampledTmpTex_
downsampled temp rt for intermediate results
void attach(PtrConstShader _shader)
Attaches a shader object to the program object.
void generateSamplingKernel()
computes a hemisphere sampling kernel in [0,1] range
void reloadResources(int _viewerId, unsigned int _sceneTexWidth, unsigned int _sceneTexHeight)
reload gl resources
void link()
Links the shader objects to the program.
int viewport_height() const
get viewport height
GLuint sceneBufTex_
standard scene without a render target
unsigned int rtSceneHeight_
scene render target height
void drawScenePass(ACG::GLState *_glState, Viewer::ViewerProperties &_properties, BaseNode *_sceneGraphRoot)
draw the current scene
void drawMode(ACG::SceneGraph::DrawModes::DrawMode _mode)
set draw mode (No test if this mode is available!)
GLuint depthSceneRenderBuf_
depth renderbuffer for sceneFbo
static void activeTexture(GLenum _texunit)
replaces glActiveTexture, no locking support
GLuint occlusionTex_
occlusion render target
void traverse_multipass(BaseNode *_node, Action &_action, const unsigned int &_pass)
static const unsigned int numSamples_
number of samples
unsigned int rtHeight_
render target height
bool checkExtensionSupported(const std::string &_extension)
GLSL::PtrFragmentShader loadFragmentShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new vertex shader.
static void disable(GLenum _cap, bool _warnRemoved=true)
replaces glDisable, but supports locking
void setUniform(const char *_name, GLint _value)
Set int uniform to specified value.
void use()
Enables the program object for using.
ACG::SceneGraph::BaseNode * getSceneGraphRootNode()
get scenegraph root node
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.
static void bindTexture(GLenum _target, GLuint _buffer)
replaces glBindTexture, supports locking
bool openGLVersion(const int _major, const int _minor, bool _verbose)