Developer Documentation
Loading...
Searching...
No Matches
ClassicDepthPeeling_glew.cc
1/*===========================================================================*\
2* *
3* OpenFlipper *
4 * Copyright (c) 2001-2015, RWTH-Aachen University *
5 * Department of Computer Graphics and Multimedia *
6 * All rights reserved. *
7 * www.openflipper.org *
8 * *
9 *---------------------------------------------------------------------------*
10 * This file is part of OpenFlipper. *
11 *---------------------------------------------------------------------------*
12 * *
13 * Redistribution and use in source and binary forms, with or without *
14 * modification, are permitted provided that the following conditions *
15 * are met: *
16 * *
17 * 1. Redistributions of source code must retain the above copyright notice, *
18 * this list of conditions and the following disclaimer. *
19 * *
20 * 2. Redistributions in binary form must reproduce the above copyright *
21 * notice, this list of conditions and the following disclaimer in the *
22 * documentation and/or other materials provided with the distribution. *
23 * *
24 * 3. Neither the name of the copyright holder nor the names of its *
25 * contributors may be used to endorse or promote products derived from *
26 * this software without specific prior written permission. *
27 * *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39* *
40\*===========================================================================*/
41
42
43#include <ACG/GL/acg_glew.hh>
44#include "ClassicDepthPeeling.hh"
45
46#include <ACG/GL/GLError.hh>
49
51 // called in constructor and resizeEvent()
52
54
55 ViewerResources* p = &viewerRes_[_viewerId];
56
57 if (!p->glWidth_ || !p->glHeight_) return;
58
59 destroyResources(_viewerId);
60
61 // dual depth peeling rt's
62 glGenTextures(7, p->blendDualPeelTexID_);
63 GLint DualPeelIntFmt[] = {GL_RG32F, GL_RG32F, // depth0, depth1
64 GL_RGBA, GL_RGBA, // front blender0, ..._1
65 GL_RGBA, GL_RGBA, // back_temp_tex0, ..._1,
66 GL_RGB}; // back_blender
67
68 for (int i = 0; i < 7; ++i)
69 {
70 GLint fmt = GL_RGB; // fmt for depth textures
71
72 if (i >= 2) fmt = GL_RGBA; // fmt for front_blender01 and back_temp01
73 if (i == 6) fmt = GL_RGB; // fmt for back_blender
74
75 ACG::GLState::bindTexture(GL_TEXTURE_RECTANGLE_EXT, p->blendDualPeelTexID_[i]);
76 // texture access: clamped
77 glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_S, GL_CLAMP);
78 glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_T, GL_CLAMP);
79 // filter: none
80 glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
81 glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
82
83 glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, DualPeelIntFmt[i], p->glWidth_, p->glHeight_, 0, fmt, GL_FLOAT, 0);
84
85
86
87
89 }
90
91 p->rtWidth_ = p->glWidth_;
92 p->rtHeight_ = p->glHeight_;
93
94 // dual depth peeling fbo's
95 glGenFramebuffers(1, &p->blendDualPeelFbo_);
96 {
97 // layer_peel fbo
99
100 // color_attachment order:
101 // depth0, front_blend0, back_temp0, depth1, front_blend1, back_temp1, back_blender_tex_id
102
103 for (int i = 0; i < 6; ++i)
104 {
105 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i,
106 GL_TEXTURE_RECTANGLE_EXT, p->blendDualPeelTexID_[i < 3 ? 2*i : 2*(i-3) +1], 0);
107 }
108
109 // back_blender_tex_id
110 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT6, GL_TEXTURE_RECTANGLE_EXT,
111 p->blendDualPeelTexID_[6], 0);
112 }
113
114 ACG::GLState::bindFramebuffer(GL_FRAMEBUFFER, 0);
115
116
117 // load shaders
118
119 const char* ShaderFiles[] = {"Blending/dual_peeling_init_vertex.glsl",
120 "Blending/dual_peeling_init_fragment.glsl",
121 "Blending/dual_peeling_blend_vertex.glsl",
122 "Blending/dual_peeling_blend_fragment.glsl",
123 "Blending/dual_peeling_final_vertex.glsl",
124 "Blending/dual_peeling_final_fragment.glsl"};
125
126 for (int i = 0; i < 6; ++i)
127 {
128 QString shaderFile = OpenFlipper::Options::shaderDirStr() + QDir::separator() + QString(ShaderFiles[i]);
129
130 if (blendShaders_[i]) continue;
131
132 if (i & 1) // alternating vertex/fragment shader
133 blendShaders_[i] = GLSL::loadFragmentShader(shaderFile.toUtf8());
134 else
135 blendShaders_[i] = GLSL::loadVertexShader(shaderFile.toUtf8());
136
137 if (!blendShaders_[i]) {
138 log(LOGERR, QString(ShaderFiles[i]) + QString(" could not be loaded and compiled"));
139 return;
140 }
141 }
142
143 // dual depth peeling programs
144
145 if (!blendDualPeelProg_[0])
146 {
147 for (int i = 0; i < 4; ++i)
148 {
149 if (i != 1)
151 }
152
153 // init shaders
157
158 // blend shaders
162
163 // final shaders
167 }
168
169 if (!blendQueryID_)
170 glGenQueries(1, &blendQueryID_);
171
173}
174
176{
177 ViewerResources* p = &viewerRes_[_viewerId];
178
179 if (p->blendDualPeelFbo_) glDeleteFramebuffers(1, &p->blendDualPeelFbo_);
180 p->blendDualPeelFbo_ = 0;
181
182 if (p->blendDualPeelTexID_[0]) glDeleteTextures(7, p->blendDualPeelTexID_);
183 memset(p->blendDualPeelTexID_, 0, sizeof(p->blendDualPeelTexID_));
184}
185
187 // called in destructor and reloadBlendingTech()
188
189 if (blendQueryID_)
190 glDeleteQueries(1, &blendQueryID_);
191 blendQueryID_ = 0;
192
193 for (int i = 0; i < 4; ++i)
194 {
195 delete blendDualPeelProg_[i]; blendDualPeelProg_[i] = 0;
196 }
197
198 for (unsigned int i = 0; i < sizeof(blendShaders_) / sizeof(blendShaders_[0]); ++i)
199 {
200 delete blendShaders_[i];
201 blendShaders_[i] = 0;
202 }
203
204 for (unsigned int i = 0; i < sizeof(peelShaders_) / sizeof(peelShaders_[0]); ++i)
205 {
206 delete peelShaders_[i]; peelShaders_[i] = 0;
207 }
208
209 for (unsigned int i = 0; i < sizeof(peelProgs_) / sizeof(peelProgs_[0]); ++i)
210 {
211 delete peelProgs_[i]; peelProgs_[i] = 0;
212 }
213
214 // free all viewer specific resources
215 std::map<int, ViewerResources>::iterator resIt = viewerRes_.begin();
216 for (; resIt != viewerRes_.end(); ++resIt)
217 destroyResources(resIt->first);
218}
219
220void DepthPeelingPlugin::render(ACG::GLState* _glState, Viewer::ViewerProperties& _properties)
221{
222 glStateTmp_ = _glState;
223
224 glPushAttrib(GL_ALL_ATTRIB_BITS);
225
226 const GLuint targetFbo = ACG::GLState::getFramebufferDraw();
227
228 int viewerId = _properties.viewerId();
229
230 ViewerResources* pViewer = &viewerRes_[viewerId];
231 pViewer->glWidth_ = _glState->viewport_width();
232 pViewer->glHeight_ = _glState->viewport_height();
233
234 if (pViewer->glWidth_ != pViewer->rtWidth_ || pViewer->glHeight_ != pViewer->rtHeight_)
235 reloadResources(viewerId);
236
237// updatePeelingShaderSet(viewerId, _properties.drawMode());
240
242
243
244 ACG::GLState::disable(GL_CULL_FACE);
245 ACG::GLState::disable(GL_LIGHTING);
246 ACG::GLState::disable(GL_NORMALIZE);
247
248 ACG::GLState::lockDepthFunc();
249 ACG::GLState::lockState(GL_CULL_FACE);
250 ACG::GLState::lockState(GL_LIGHTING);
251 ACG::GLState::lockState(GL_NORMALIZE);
252
253 // from nvidia demo code:
254 // needed some minor adjustments
255
256 GLenum drawBuffers[] = {GL_COLOR_ATTACHMENT0_EXT,
257 GL_COLOR_ATTACHMENT1_EXT,
258 GL_COLOR_ATTACHMENT2_EXT,
259 GL_COLOR_ATTACHMENT3_EXT,
260 GL_COLOR_ATTACHMENT4_EXT,
261 GL_COLOR_ATTACHMENT5_EXT,
262 GL_COLOR_ATTACHMENT6_EXT};
263
264 // the farthest depth value possible in the depth buffer
265 const float maxDepth = 1.0f;
266
267 ACG::GLState::disable(GL_DEPTH_TEST);
268 ACG::GLState::enable(GL_BLEND);
269
270 ACG::GLState::lockState(GL_DEPTH_TEST);
271 ACG::GLState::lockState(GL_BLEND);
272
273
274
275 /* FIXED: VIEWPORT BUG
276
277 log-window causes viewport shift by 16 units upward in window's y axis
278 therefore the scene gets rendered only in the upper part of the viewport:
279 -> glViewport(0, 16, glWidht, glHeight_)
280
281 glHeight_() is NOT the height of the back buffer (i.e. glViewer window),
282 but the height of scene target view
283 -> glHeight_() is 16 units less than the back buffer
284
285 -> all render targets are 16 units less in height than back buffer
286
287 since the scene has to use the full render targets size,
288 use glViewport(0, 0, glWidth_, glHeight_) for all offscreen rendering
289
290 in the final pass, shift the viewport up by 16 units and use the shift amount
291 in the shader (uniform g_Offset), to finally get the correct sampling coordinates
292
293
294 note: shift amount is not hardcoded, but fetched from glGetIntegerv(GL_VIEWPORT)
295 */
296
297
298 GLint old_viewport[4];
299 glGetIntegerv(GL_VIEWPORT, old_viewport);
300 glViewport(0, 0, pViewer->glWidth_, pViewer->glHeight_);
301
302 for (int i = 0; i < 6; ++i)
303 {
304 ACG::GLState::activeTexture(GL_TEXTURE0 + i);
305 ACG::GLState::bindTexture(GL_TEXTURE_RECTANGLE_EXT, 0);
306 }
307
308
309 // ---------------------------------------------------------------------
310 // 1. Initialize Min-Max Depth Buffer
311 // ---------------------------------------------------------------------
312
313 ACG::GLState::bindFramebuffer(GL_FRAMEBUFFER_EXT, pViewer->blendDualPeelFbo_);
314
315 // Render targets 1 and 2 store the front and back colors
316 // Clear to 0.0 and use MAX blending to filter written color
317 // At most one front color and one back color can be written every pass
318 ACG::GLState::drawBuffers(2, &drawBuffers[1]);
319 glClearColor(0, 0, 0, 0);
320 glClear(GL_COLOR_BUFFER_BIT);
321
322 // Render target 0 stores (-minDepth, maxDepth, alphaMultiplier)
323 ACG::GLState::drawBuffer(drawBuffers[0]);
324 glClearColor(-maxDepth, -maxDepth, 0, 0);
325 glClear(GL_COLOR_BUFFER_BIT);
326 ACG::GLState::blendEquation(GL_MAX_EXT);
328
331 drawScenePass(_glState, _properties.drawMode(), sceneGraphRoot);
333
334
335
336 int currId = 0;
337
338 // ---------------------------------------------------------------------
339 // 2. Dual Depth Peeling + Blending
340 // ---------------------------------------------------------------------
341
342 // Since we cannot blend the back colors in the geometry passes,
343 // we use another render target to do the alpha blending
344 //glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, g_dualBackBlenderFboId);
345 ACG::GLState::drawBuffer(drawBuffers[6]);
346 glClearColor(_glState->clear_color()[0], _glState->clear_color()[1], _glState->clear_color()[2], 0);
347
348 glClear(GL_COLOR_BUFFER_BIT);
349
350 // Geometry layers are peeled until the sample query returns 0
351 GLuint sampleCount = 1;
352 for (int pass = 1; sampleCount; ++pass)
353 {
354 currId = pass % 2;
355 int prevId = 1 - currId;
356 int bufId = currId * 3;
357
358 ACG::GLState::drawBuffers(2, &drawBuffers[bufId+1]);
359 glClearColor(0, 0, 0, 0);
360 glClear(GL_COLOR_BUFFER_BIT);
361
362 ACG::GLState::drawBuffer(drawBuffers[bufId+0]);
363 glClearColor(-maxDepth, -maxDepth, 0, 0);
364 glClear(GL_COLOR_BUFFER_BIT);
365
366 // Render target 0: RG32F MAX blending
367 // Render target 1: RGBA MAX blending
368 // Render target 2: RGBA MAX blending
369 ACG::GLState::drawBuffers(3, &drawBuffers[bufId+0]);
371 ACG::GLState::blendEquation(GL_MAX_EXT);
373
374 ACG::GLState::activeTexture(GL_TEXTURE5); // front_blender_tex base_offset: 2
375 ACG::GLState::bindTexture(GL_TEXTURE_RECTANGLE_EXT, pViewer->blendDualPeelTexID_[2 + prevId]);
376
377 ACG::GLState::activeTexture(GL_TEXTURE4); // depth_tex base_offset: 0
378 ACG::GLState::bindTexture(GL_TEXTURE_RECTANGLE_EXT, pViewer->blendDualPeelTexID_[0 + prevId]);
379
380
381 // scene geometry peeling pass
382 // note that the peel shader is set right before rendering in the traverser, based on a node's drawmode
383 ACG::GLState::activeTexture(GL_TEXTURE0);
384
385 ACG::GLState::shadeModel(GL_SMOOTH); // flat shading is emulated in Geometry Shader, which only works with interpolated vertex shader output
387 drawScenePeelPass(_glState, _properties.drawMode(), sceneGraphRoot, pass);
389
390
391 // Full screen pass to alpha-blend the back color
392 ACG::GLState::drawBuffer(drawBuffers[6]);
393
395 ACG::GLState::blendEquation(GL_FUNC_ADD);
397 ACG::GLState::blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
398
399 // start samples counter query
400 glBeginQuery(GL_SAMPLES_PASSED_ARB, blendQueryID_);
401
403 blendDualPeelProg_[2]->setUniform("TempTex", 4);
404
405 ACG::GLState::activeTexture(GL_TEXTURE4); // back_temp_tex base_offset: 4
406 ACG::GLState::bindTexture(GL_TEXTURE_RECTANGLE_EXT, pViewer->blendDualPeelTexID_[4 + currId]);
407
408 drawQuadProj(); // full screen quad, already projected
409
410 glEndQuery(GL_SAMPLES_PASSED_ARB);
411 glGetQueryObjectuiv(blendQueryID_, GL_QUERY_RESULT_ARB, &sampleCount);
412 }
413
415
417 ACG::GLState::disable(GL_BLEND);
418
419
420
421 // ---------------------------------------------------------------------
422 // 3. Final Pass
423 // operates on screen pixels only
424 // ---------------------------------------------------------------------
425
426 // enable back buffer
427 ACG::GLState::bindFramebuffer(GL_FRAMEBUFFER_EXT, targetFbo);
428 if(targetFbo == 0) //if the default fbo is bound use GL_BACK
430 else //if no default FBO is bound (e.g. with QOpenGLWindow use color attachment0 since only color attachment and none are allowed)
431 ACG::GLState::drawBuffer(GL_COLOR_ATTACHMENT0);
432
433 // program id 3
435 blendDualPeelProg_[3]->setUniform("FrontBlenderTex", 4);
436 blendDualPeelProg_[3]->setUniform("BackBlenderTex", 5);
437
438 // bugfix for multiple viewports:
439 // gl_FragCoord represents the screen space coordinate of a pixel into the back buffer
440 // this has to be back-shifted by the upper left viewport coordinate to get correct texture coordinates
441 blendDualPeelProg_[3]->setUniform("ViewportOffset", ACG::Vec2f(old_viewport[0], old_viewport[1]));
442
443 ACG::GLState::activeTexture(GL_TEXTURE5); // back_blender: offset 6
444 ACG::GLState::bindTexture(GL_TEXTURE_RECTANGLE_EXT, pViewer->blendDualPeelTexID_[6]);
445
446
447 ACG::GLState::activeTexture(GL_TEXTURE4); // front_blender_tex base_offset: 2
448 ACG::GLState::bindTexture(GL_TEXTURE_RECTANGLE_EXT, pViewer->blendDualPeelTexID_[2 + currId]);
449
450
451 glViewport(old_viewport[0], old_viewport[1], old_viewport[2], old_viewport[3]);
452 drawQuadProj(-1.0f, 1.0f, 2.0f, 2.0f);
453
454
456
457
458
460
461
462 // unlock states
463 ACG::GLState::unlockDepthFunc();
464 ACG::GLState::unlockState(GL_CULL_FACE);
465 ACG::GLState::unlockState(GL_LIGHTING);
466 ACG::GLState::unlockState(GL_NORMALIZE);
467
468 ACG::GLState::unlockState(GL_DEPTH_TEST);
470
471
472 glPopAttrib();
473}
@ LOGERR
static void unlockState(GLenum _cap)
unlocks a specific cap state
Definition GLState.cc:1552
static void lockProgram()
lock the program
Definition GLState.hh:654
static void enable(GLenum _cap, bool _warnRemoved=true)
replaces glEnable, but supports locking
Definition GLState.cc:1507
static void bindTexture(GLenum _target, GLuint _buffer)
replaces glBindTexture, supports locking
Definition GLState.cc:1911
static void unlockShadeModel()
unlock shade model
Definition GLState.hh:385
int viewport_width() const
get viewport width
Definition GLState.hh:847
static void syncFromGL()
synchronize this class with the OpenGL state machine
Definition GLState.cc:1244
static void lockBlendEquation()
lock blend equation
Definition GLState.hh:344
static void drawBuffers(GLsizei _n, const GLenum *_bufs)
replaces glDrawBuffers, supports locking
Definition GLState.cc:2091
static void blendEquation(GLenum _mode)
replaces glBlendEquation, supports locking
Definition GLState.cc:1672
static void blendFunc(GLenum _sfactor, GLenum _dfactor)
replaces glBlendFunc, supports locking
Definition GLState.hh:307
static void activeTexture(GLenum _texunit)
replaces glActiveTexture, no locking support
Definition GLState.cc:1900
static void disable(GLenum _cap, bool _warnRemoved=true)
replaces glDisable, but supports locking
Definition GLState.cc:1527
const Vec4f & clear_color() const
get background color
Definition GLState.hh:946
int viewport_height() const
get viewport height
Definition GLState.hh:849
static void lockShadeModel()
lock shade model
Definition GLState.hh:383
static void shadeModel(GLenum _mode)
replaces glShadeModel, supports locking
Definition GLState.cc:1729
static void unlockProgram()
unlock the program
Definition GLState.hh:656
static GLuint getFramebufferDraw()
get current draw framebuffer of a target
Definition GLState.cc:2117
const GLenum & depthFunc() const
get glDepthFunc() that is supposed to be active
Definition GLState.cc:941
static void drawBuffer(GLenum _mode)
replaces glDrawBuffer, supports locking
Definition GLState.cc:2076
static void unlockBlendEquation()
unlock blend equation
Definition GLState.hh:346
static void bindFramebuffer(GLenum _target, GLuint _framebuffer)
replaces glBindFramebuffer, supports locking
Definition GLState.cc:2132
static void lockState(GLenum _cap)
locks a specific cap state, such that enable() or disable() has no effect
Definition GLState.cc:1547
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)
GLSL::Program * peelProgs_[PEEL_NUM_COMBINATIONS]
generates shader programs
void destroyResources()
free all gl resources
void updatePeelingShaderSet()
regenerates peeling shaders based on light nodes in scenegraph
GLSL::Shader * blendShaders_[8]
shader resources
ACG::GLState * glStateTmp_
current glState ptr for hiddenline rendering
GLSL::Program * blendDualPeelProg_[4]
depth peeling programs
void drawScenePass(ACG::GLState *_glState, ACG::SceneGraph::DrawModes::DrawMode _drawMode, BaseNode *_sceneGraphRoot)
draw the current scene
void reloadResources(int _viewerId)
reload gl resources
GLSL::Shader * peelShaders_[PEEL_NUM_COMBINATIONS *3]
generated shader set
GLuint blendQueryID_
fragment query
GLSL program class.
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.
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 glCheckErrors()
Definition GLError.hh:96
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.
ACG::SceneGraph::BaseNode * getSceneGraphRootNode()
get scenegraph root node
unsigned int glWidth_
viewer window width
unsigned int rtWidth_
render target width
GLuint blendDualPeelTexID_[7]
render target textures: {depth0, depth1, front_blend0, front_blend1, back_temp0, back_temp1,...
unsigned int glHeight_
viewer window height
unsigned int rtHeight_
render target height