vtkEDLShading.cxx 25.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
/*=========================================================================

   Program: ParaView
   Module:    vtkEDLShading.cxx

   Copyright (c) 2005-2008 Sandia Corporation, Kitware Inc.
   All rights reserved.

   ParaView is a free software; you can redistribute it and/or modify it
   under the terms of the ParaView license version 1.2.

   See License_v1.2.txt for the full ParaView license.
   A copy of this license can be obtained by contacting
   Kitware Inc.
   28 Corporate Drive
   Clifton Park, NY 12065
   USA

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================*/
/*----------------------------------------------------------------------
Acknowledgement:
This algorithm is the result of joint work by Electricité de France,
CNRS, Collège de France and Université J. Fourier as part of the
Ph.D. thesis of Christian BOUCHENY.
------------------------------------------------------------------------*/

#include "vtkEDLShading.h"

#include "vtkCamera.h"
42
#include "vtkOpenGLFramebufferObject.h"
43 44 45
#include "vtkMath.h"
#include "vtkObjectFactory.h"
#include "vtkOpenGLError.h"
46
#include "vtkOpenGLRenderUtilities.h"
47 48
#include "vtkOpenGLRenderWindow.h"
#include "vtkOpenGLShaderCache.h"
49
#include "vtkOpenGLState.h"
50 51 52 53 54 55
#include "vtkPropCollection.h"
#include "vtkRenderState.h"
#include "vtkRenderer.h"
#include "vtkShaderProgram.h"
#include "vtkTextureObject.h"
#include "vtk_glew.h"
56
#include <cassert>
57 58 59 60 61 62 63 64 65 66 67
#include <sstream>
#include <string>


#include "vtkTextureObjectVS.h"
#include "vtkEDLShadeFS.h"
#include "vtkEDLComposeFS.h"
#include "vtkEDLBilateralFilterFS.h"

//#define VTK_EDL_SHADING_DEBUG

68 69 70 71
namespace
{
void annotate(const std::string &str)
{
72
  vtkOpenGLRenderUtilities::MarkDebugEvent(str);
73 74 75
}
}

76 77 78 79 80 81
vtkStandardNewMacro(vtkEDLShading);

// ----------------------------------------------------------------------------
vtkEDLShading::vtkEDLShading()
{

82 83 84
  this->ProjectionFBO = nullptr;
  this->ProjectionColorTexture = nullptr;
  this->ProjectionDepthTexture = nullptr;
85

86 87 88 89 90
  this->EDLHighFBO = nullptr;
  this->EDLHighShadeTexture = nullptr;
  this->EDLLowFBO = nullptr;
  this->EDLLowShadeTexture = nullptr;
  this->EDLLowBlurTexture = nullptr;
91 92 93 94

  this->EDLIsFiltered = true;
  // init neighbours in image space
  for (int c = 0; c < 8; c++)
95
  {
96
    float x, y;
97 98
    x = cos(2*vtkMath::Pi()*float(c)/8.);
    y = sin(2*vtkMath::Pi()*float(c)/8.);
99 100 101 102
    this->EDLNeighbours[c][0] = x / sqrt(x*x+y*y);
    this->EDLNeighbours[c][1] = y / sqrt(x*x+y*y);
    this->EDLNeighbours[c][2] = 0.;
    this->EDLNeighbours[c][3] = 0.;
103
  }
104
  this->EDLLowResFactor = 2;
Ken Martin's avatar
Ken Martin committed
105 106
  this->Zn = 0.1;
  this->Zf = 1.0;
107 108 109 110 111
}

// ----------------------------------------------------------------------------
vtkEDLShading::~vtkEDLShading()
{
112
  if (this->ProjectionFBO != nullptr)
113
  {
114 115
    vtkErrorMacro(<<"FrameBufferObject should have been deleted in "
      <<"ReleaseGraphicsResources().");
116
  }
117
  if (this->ProjectionColorTexture != nullptr)
118
  {
119 120
    vtkErrorMacro(<<"ColorTexture should have been deleted in "
      <<"ReleaseGraphicsResources().");
121
  }
122
  if (this->ProjectionDepthTexture != nullptr)
123
  {
124 125
    vtkErrorMacro(<<"DepthTexture should have been deleted in "
      <<"ReleaseGraphicsResources().");
126
  }
127
  if (this->EDLHighFBO != nullptr)
128
  {
129 130
    vtkErrorMacro(<<"FrameBufferObject should have been deleted in "
      <<"ReleaseGraphicsResources().");
131
  }
132
  if (this->EDLHighShadeTexture != nullptr)
133
  {
134 135
    vtkErrorMacro(<<"ColorTexture should have been deleted in "
      <<"ReleaseGraphicsResources().");
136
  }
137
  if (this->EDLLowFBO != nullptr)
138
  {
139 140
    vtkErrorMacro(<<"FrameBufferObject should have been deleted in "
      <<"ReleaseGraphicsResources().");
141
  }
142
  if (this->EDLLowShadeTexture != nullptr)
143
  {
144 145
    vtkErrorMacro(<<"ColorTexture should have been deleted in "
      <<"ReleaseGraphicsResources().");
146
  }
147
  if (this->EDLLowBlurTexture != nullptr)
148
  {
149 150
    vtkErrorMacro(<<"ColorTexture should have been deleted in "
      <<"ReleaseGraphicsResources().");
151
  }
152 153 154 155 156 157 158 159
}

// ----------------------------------------------------------------------------
void vtkEDLShading::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);

  os << indent << "DelegatePass:";
160
  if (this->DelegatePass != nullptr)
161
  {
162
    this->DelegatePass->PrintSelf(os, indent);
163
  }
164
  else
165
  {
166
    os << "(none)" << endl;
167
  }
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
}

// ----------------------------------------------------------------------------
// Description:
// Initialize framebuffers and associated texture objects,
// with link to render state s
void vtkEDLShading::EDLInitializeFramebuffers(vtkRenderState &s)
{
  vtkRenderer *r = s.GetRenderer();

  vtkOpenGLCheckErrorMacro("failed before Initialize");

  vtkOpenGLRenderWindow *renWin =
    vtkOpenGLRenderWindow::SafeDownCast(r->GetRenderWindow());

  //  PROJECTION FBO and TEXTURES
  //
185
  if (this->ProjectionFBO == nullptr)
186
  {
187
    this->ProjectionFBO = vtkOpenGLFramebufferObject::New();
188
    this->ProjectionFBO->SetContext(renWin);
189
  }
190
  s.SetFrameBuffer(this->ProjectionFBO);
191
  this->ProjectionFBO->SaveCurrentBindingsAndBuffers();
192 193
  this->ProjectionFBO->Bind();
  // Color texture
194
  if (this->ProjectionColorTexture == nullptr)
195
  {
196 197
    this->ProjectionColorTexture = vtkTextureObject::New();
    this->ProjectionColorTexture->SetContext(this->ProjectionFBO->GetContext());
198
  }
199 200 201 202
  if (this->ProjectionColorTexture->GetWidth() != static_cast<unsigned int>
    (this->W)
      || this->ProjectionColorTexture->GetHeight()
          != static_cast<unsigned int> (this->H))
203
  {
204
    this->ProjectionColorTexture->Create2D(this->W, this->H, 4, VTK_FLOAT, false);
205
  }
206
  // Depth texture
207
  if (this->ProjectionDepthTexture == nullptr)
208
  {
209 210
    this->ProjectionDepthTexture = vtkTextureObject::New();
    this->ProjectionDepthTexture->SetContext(this->ProjectionFBO->GetContext());
211
  }
212 213 214
  if (this->ProjectionDepthTexture->GetWidth() != static_cast<unsigned int> (this->W)
      || this->ProjectionDepthTexture->GetHeight()
          != static_cast<unsigned int> (this->H))
215
  {
216 217
    this->ProjectionDepthTexture->AllocateDepth(
      this->W, this->H, vtkTextureObject::Float32);
218
  }
219 220 221

  // Apply textures
  // to make things clear, we write all
222 223 224 225 226
  this->ProjectionFBO->AddColorAttachment(
    this->ProjectionFBO->GetBothMode(), 0, this->ProjectionColorTexture);
  this->ProjectionFBO->ActivateDrawBuffer(0);
  this->ProjectionFBO->AddDepthAttachment(
    this->ProjectionFBO->GetBothMode(), this->ProjectionDepthTexture);
227 228 229 230 231 232 233 234 235

  this->ProjectionDepthTexture->SetWrapS(vtkTextureObject::ClampToEdge);
  this->ProjectionDepthTexture->SetWrapT(vtkTextureObject::ClampToEdge);
  this->ProjectionDepthTexture->SetMinificationFilter(vtkTextureObject::Linear);
  this->ProjectionDepthTexture->SetLinearMagnification(true);
  this->ProjectionDepthTexture->Bind();
  this->ProjectionDepthTexture->SendParameters();

  this->ProjectionFBO->UnBind();
236
  this->ProjectionFBO->RestorePreviousBindingsAndBuffers();
237 238 239

  //  EDL-RES1 FBO and TEXTURE
  //
240
  if (this->EDLHighFBO == nullptr)
241
  {
242
    this->EDLHighFBO = vtkOpenGLFramebufferObject::New();
243
    this->EDLHighFBO->SetContext(renWin);
244
  }
245 246
  s.SetFrameBuffer(EDLHighFBO);
  // Color texture
247
  if (this->EDLHighShadeTexture == nullptr)
248
  {
249 250
    this->EDLHighShadeTexture = vtkTextureObject::New();
    this->EDLHighShadeTexture->SetContext(this->EDLHighFBO->GetContext());
251
  }
252 253 254
  if (this->EDLHighShadeTexture->GetWidth() != static_cast<unsigned int> (this->W)
      || this->EDLHighShadeTexture->GetHeight()
          != static_cast<unsigned int> (this->H))
255
  {
256
    this->EDLHighShadeTexture->Create2D(this->W, this->H, 4, VTK_FLOAT, false);
257
  }
258 259 260 261 262 263
  this->EDLHighFBO->SaveCurrentBindingsAndBuffers();
  this->EDLHighFBO->Bind();
  this->EDLHighFBO->AddColorAttachment(
    GL_DRAW_FRAMEBUFFER, 0, this->EDLHighShadeTexture);
  this->EDLHighFBO->ActivateDrawBuffer(0);
  this->EDLHighFBO->AddDepthAttachment(GL_DRAW_FRAMEBUFFER);
264
  this->EDLHighFBO->UnBind();
265
  this->EDLHighFBO->RestorePreviousBindingsAndBuffers();
266 267 268

  //  EDL-RES2 FBO and TEXTURE
  //
269
  if (this->EDLLowFBO == nullptr)
270
  {
271
    this->EDLLowFBO = vtkOpenGLFramebufferObject::New();
272
    this->EDLLowFBO->SetContext(renWin);
273
  }
274 275
  s.SetFrameBuffer(EDLLowFBO);
  // Color texture
276
  if (this->EDLLowShadeTexture == nullptr)
277
  {
278 279
    this->EDLLowShadeTexture = vtkTextureObject::New();
    this->EDLLowShadeTexture->SetContext(this->EDLLowFBO->GetContext());
280
  }
281 282 283
  if (this->EDLLowShadeTexture->GetWidth() != static_cast<unsigned int> (this->W
      / EDLLowResFactor) || this->EDLLowShadeTexture->GetHeight()
      != static_cast<unsigned int> (this->H / EDLLowResFactor))
284
  {
285 286
    this->EDLLowShadeTexture->Create2D(this->W / EDLLowResFactor,
        this->H / EDLLowResFactor, 4, VTK_FLOAT, false);
287
  }
288
  // Blur texture
289
  if (this->EDLLowBlurTexture == nullptr)
290
  {
291 292
    this->EDLLowBlurTexture = vtkTextureObject::New();
    this->EDLLowBlurTexture->SetContext(this->EDLLowFBO->GetContext());
293
  }
294 295 296
  if (this->EDLLowBlurTexture->GetWidth() != static_cast<unsigned int> (this->W
      / EDLLowResFactor) || this->EDLLowBlurTexture->GetHeight()
      != static_cast<unsigned int> (this->H / EDLLowResFactor))
297
  {
298 299
    this->EDLLowBlurTexture->Create2D(this->W / EDLLowResFactor, this->H / EDLLowResFactor,
        4, VTK_FLOAT, false);
300
  }
301 302 303 304 305 306
  this->EDLLowFBO->SaveCurrentBindingsAndBuffers();
  this->EDLLowFBO->Bind();
  this->EDLLowFBO->AddColorAttachment(
    GL_DRAW_FRAMEBUFFER, 0, this->EDLLowShadeTexture);
  this->EDLLowFBO->ActivateDrawBuffer(0);
  this->EDLLowFBO->AddDepthAttachment(GL_DRAW_FRAMEBUFFER);
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322

  this->EDLLowShadeTexture->SetWrapS(vtkTextureObject::ClampToEdge);
  this->EDLLowShadeTexture->SetWrapT(vtkTextureObject::ClampToEdge);
  this->EDLLowShadeTexture->SetMinificationFilter(vtkTextureObject::Linear);
  this->EDLLowShadeTexture->SetLinearMagnification(true);
  this->EDLLowShadeTexture->Bind();
  this->EDLLowShadeTexture->SendParameters();

  this->EDLLowBlurTexture->SetWrapS(vtkTextureObject::ClampToEdge);
  this->EDLLowBlurTexture->SetWrapT(vtkTextureObject::ClampToEdge);
  this->EDLLowBlurTexture->SetMinificationFilter(vtkTextureObject::Linear);
  this->EDLLowBlurTexture->SetLinearMagnification(true);
  this->EDLLowBlurTexture->Bind();
  this->EDLLowBlurTexture->SendParameters();

  this->EDLLowFBO->UnBind();
323
  this->EDLLowFBO->RestorePreviousBindingsAndBuffers();
324 325 326 327 328 329 330 331 332 333 334 335 336 337 338

  vtkOpenGLCheckErrorMacro("failed after Initialize");
}
// ----------------------------------------------------------------------------
// Description:
// Initialize shaders
//
void vtkEDLShading::EDLInitializeShaders(vtkOpenGLRenderWindow *renWin)
{
#ifdef VTK_EDL_SHADING_DEBUG
  cout << "EDL: INITIALIZE SHADERS" << endl;
#endif

  //  EDL SHADE
  //
339
  if (this->EDLShadeProgram.Program == nullptr)
340
  {
341 342 343 344 345
    this->EDLShadeProgram.Program =
      renWin->GetShaderCache()->ReadyShaderProgram(
        vtkTextureObjectVS,
        vtkEDLShadeFS,
        "");
346
  }
347 348 349

  //  EDL COMPOSE
  //
350
  if (this->EDLComposeProgram.Program == nullptr)
351
  {
352 353 354 355 356
    this->EDLComposeProgram.Program =
      renWin->GetShaderCache()->ReadyShaderProgram(
        vtkTextureObjectVS,
        vtkEDLComposeFS,
        "");
357
  }
358 359 360

  //  BILATERAL FILTER
  //
361
  if (this->BilateralProgram.Program == nullptr)
362
  {
363 364 365 366 367
    this->BilateralProgram.Program =
      renWin->GetShaderCache()->ReadyShaderProgram(
        vtkTextureObjectVS,
        vtkEDLBilateralFilterFS,
        "");
368
  }
369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399

#ifdef VTK_EDL_SHADING_DEBUG
  cout << "... done" << endl;
#endif
}

// ----------------------------------------------------------------------------
// Description:
// Render EDL in full resolution
//
bool vtkEDLShading::EDLShadeHigh(
  vtkRenderState &s,
  vtkOpenGLRenderWindow *renWin)
{
  //  VARIABLES
  //
  float d = 1.0;
  float F_scale = 5.0;
  float SX = 1. / float(this->W);
  float SY = 1. / float(this->H);
  float L[3] =
    { 0., 0., -1. };

  // ACTIVATE SHADER
  //
  renWin->GetShaderCache()->ReadyShaderProgram(this->EDLShadeProgram.Program);

  // ACTIVATE FBO
  //
  s.SetFrameBuffer(this->EDLHighFBO);
  this->EDLHighShadeTexture->Activate();
400 401 402 403 404
  this->EDLHighFBO->SaveCurrentBindingsAndBuffers();
  this->EDLHighFBO->AddColorAttachment(
    GL_DRAW_FRAMEBUFFER, 0, this->EDLHighShadeTexture);
  this->EDLHighFBO->ActivateDrawBuffer(0);
  this->EDLHighFBO->Start(this->W, this->H);
405 406 407 408 409 410 411 412 413 414 415 416 417

  // DEPTH TEXTURE PARAMETERS
  this->ProjectionDepthTexture->Activate();
  vtkShaderProgram *prog = this->EDLShadeProgram.Program;

  // shader parameters
  prog->SetUniformi("s2_depth", this->ProjectionDepthTexture->GetTextureUnit());
  prog->SetUniformf("d", d);
  prog->SetUniformf("F_scale", F_scale);
  prog->SetUniformf("SX", SX);
  prog->SetUniformf("SY", SY);
  prog->SetUniform3f("L", L);
  prog->SetUniform4fv("N", 8, this->EDLNeighbours);
Ken Martin's avatar
Ken Martin committed
418 419
  prog->SetUniformf("Znear", this->Zn);
  prog->SetUniformf("Zfar", this->Zf);
420 421 422 423

  // compute the scene bounding box, and set the scene size to the diagonal of it.
  double bb[6];
  vtkMath::UninitializeBounds(bb);
424
  bool boundsSet = false;
425
  for(int i=0; i<s.GetPropArrayCount(); i++)
426
  {
427
    const double* bounds = s.GetPropArray()[i]->GetBounds();
428
    if (bounds)
429
    {
430
      if(!boundsSet)
431
      {
432 433 434 435 436 437 438
        bb[0] = bounds[0];
        bb[1] = bounds[1];
        bb[2] = bounds[2];
        bb[3] = bounds[3];
        bb[4] = bounds[4];
        bb[5] = bounds[5];
        boundsSet = true;
439
      }
440
      else
441
      {
442 443 444 445 446 447
        bb[0] = (bb[0] < bounds[0] ? bb[0] : bounds[0]);
        bb[1] = (bb[1] > bounds[1] ? bb[1] : bounds[1]);
        bb[2] = (bb[2] < bounds[2] ? bb[2] : bounds[2]);
        bb[3] = (bb[3] > bounds[3] ? bb[3] : bounds[3]);
        bb[4] = (bb[4] < bounds[4] ? bb[4] : bounds[4]);
        bb[5] = (bb[5] > bounds[5] ? bb[5] : bounds[5]);
448 449
      }
    }
450
  }
451 452 453 454 455 456 457 458 459 460 461 462 463
  float diag = (bb[1]-bb[0])*(bb[1]-bb[0]) + (bb[3]-bb[2])*(bb[3]-bb[2])
               + (bb[5]-bb[4])*(bb[5]-bb[4]);
  diag = sqrt(diag);
  prog->SetUniformf("SceneSize", diag);

  // RENDER AND FREE ALL
  this->EDLHighFBO->RenderQuad(0, this->W - 1, 0, this->H - 1,
    prog, this->EDLShadeProgram.VAO);

  //
  this->ProjectionDepthTexture->Deactivate();
  this->EDLHighShadeTexture->Deactivate();
  this->EDLHighFBO->UnBind();
464
  this->EDLHighFBO->RestorePreviousBindingsAndBuffers();
465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491

  return true; // succeeded
}

// ----------------------------------------------------------------------------
// Description:
// Render EDL in low resolution
//
bool vtkEDLShading::EDLShadeLow(
  vtkRenderState &s,
  vtkOpenGLRenderWindow *renWin)
{
  //  VARIABLES
  //
  float d = 2.0;
  float F_scale = 5.0;
  float SX = 1. / float(this->W / this->EDLLowResFactor);
  float SY = 1. / float(this->H / this->EDLLowResFactor);
  float L[3] =
    { 0., 0., -1. };

  // ACTIVATE FBO
  //
  s.SetFrameBuffer(this->EDLLowFBO);
  this->EDLLowShadeTexture->Activate();
  this->EDLLowShadeTexture->SetLinearMagnification(true);
  this->EDLLowShadeTexture->SendParameters();
492 493 494 495
  this->EDLLowFBO->SaveCurrentBindingsAndBuffers();
  this->EDLLowFBO->AddColorAttachment(
    GL_DRAW_FRAMEBUFFER, 0, this->EDLLowShadeTexture);
  this->EDLLowFBO->ActivateDrawBuffer(0);
496
  this->EDLLowFBO->Start(this->W / this->EDLLowResFactor,
497
    this->H / this->EDLLowResFactor);
498 499 500 501 502 503 504 505 506 507 508 509 510 511 512

  // ACTIVATE SHADER
  //
  renWin->GetShaderCache()->ReadyShaderProgram(this->EDLShadeProgram.Program);
  // DEPTH TEXTURE PARAMETERS
  vtkShaderProgram *prog = this->EDLShadeProgram.Program;
  this->ProjectionDepthTexture->Activate();
  // shader parameters
  prog->SetUniformi("s2_depth", this->ProjectionDepthTexture->GetTextureUnit());
  prog->SetUniformf("d", d);
  prog->SetUniformf("F_scale", F_scale);
  prog->SetUniformf("SX", SX);
  prog->SetUniformf("SY", SY);
  prog->SetUniform3f("L", L);
  prog->SetUniform4fv("N", 8, this->EDLNeighbours); // USELESS, ALREADY DEFINED IN FULL RES
Ken Martin's avatar
Ken Martin committed
513 514
  prog->SetUniformf("Znear", this->Zn);
  prog->SetUniformf("Zfar", this->Zf);
515 516 517 518 519 520 521 522 523 524

  // RENDER AND FREE ALL
  //
  this->EDLLowFBO->RenderQuad(0, this->W / this->EDLLowResFactor - 1,
    0, this->H / this->EDLLowResFactor - 1,
    prog, this->EDLShadeProgram.VAO);

  this->ProjectionDepthTexture->Deactivate();
  this->EDLLowShadeTexture->Deactivate();
  this->EDLLowFBO->UnBind();
525
  this->EDLLowFBO->RestorePreviousBindingsAndBuffers();
526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550

  return true; // succeeded
}

// ----------------------------------------------------------------------------
// Description:
// Bilateral Filter low resolution shaded image
//
bool vtkEDLShading::EDLBlurLow(vtkRenderState &s,
  vtkOpenGLRenderWindow *renWin)
{
  // shader parameters
  float SX = 1. / float(this->W / this->EDLLowResFactor);
  float SY = 1. / float(this->H / this->EDLLowResFactor);
  int EDL_Bilateral_N = 5;
  float EDL_Bilateral_Sigma = 2.5;

  // ACTIVATE SHADER
  //
  renWin->GetShaderCache()->ReadyShaderProgram(this->BilateralProgram.Program);

  // ACTIVATE FBO
  //
  s.SetFrameBuffer(this->EDLLowFBO);
  this->EDLLowBlurTexture->Activate();
551 552 553 554 555
  this->EDLLowFBO->SaveCurrentBindingsAndBuffers();
  this->EDLLowFBO->AddColorAttachment(
    GL_DRAW_FRAMEBUFFER, 0, this->EDLLowBlurTexture);
  this->EDLLowFBO->ActivateDrawBuffer(0);
  this->EDLLowFBO->Start(this->W / EDLLowResFactor, this->H / EDLLowResFactor);
556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581

  // DEPTH TEXTURE PARAMETERS
  vtkShaderProgram *prog = this->BilateralProgram.Program;

  // DEPTH TEXTURE PARAMETERS
  this->EDLLowShadeTexture->Activate();
  this->ProjectionDepthTexture->Activate();

  // shader parameters
  prog->SetUniformi("s2_I", this->EDLLowShadeTexture->GetTextureUnit());
  prog->SetUniformi("s2_D", this->ProjectionDepthTexture->GetTextureUnit());
  prog->SetUniformf("SX", SX);
  prog->SetUniformf("SY", SY);
  prog->SetUniformi("N", EDL_Bilateral_N);
  prog->SetUniformf("sigma", EDL_Bilateral_Sigma);

  this->EDLLowFBO->RenderQuad(
    0, this->W / this->EDLLowResFactor - 1,
    0, this->H / this->EDLLowResFactor - 1,
    prog, this->BilateralProgram.VAO);

  this->EDLLowBlurTexture->Deactivate();
  this->EDLLowShadeTexture->Deactivate();
  this->ProjectionDepthTexture->Deactivate();

  this->EDLLowFBO->UnBind();
582
  this->EDLLowFBO->RestorePreviousBindingsAndBuffers();
583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598

  return EDLIsFiltered;
}

// ----------------------------------------------------------------------------
// Description:
// Compose color and shaded images
//
bool vtkEDLShading::EDLCompose(const vtkRenderState *,
  vtkOpenGLRenderWindow *renWin)
{
  //  this->EDLIsFiltered = true;

  // ACTIVATE SHADER
  //
  renWin->GetShaderCache()->ReadyShaderProgram(this->EDLComposeProgram.Program);
599 600
  vtkOpenGLState *ostate = renWin->GetState();

601 602 603 604 605 606 607 608 609 610 611
  // DEPTH TEXTURE PARAMETERS
  vtkShaderProgram *prog = this->EDLComposeProgram.Program;

  //  EDL shaded texture - full res
  this->EDLHighShadeTexture->Activate();
  prog->SetUniformi("s2_S1", this->EDLHighShadeTexture->GetTextureUnit());

  //  EDL shaded texture - low res
  //this->EDLLowBlurTexture->SetLinearMagnification(true);
  //this->EDLLowBlurTexture->SendParameters();
  if (this->EDLIsFiltered)
612
  {
613 614
    this->EDLLowBlurTexture->Activate();
    prog->SetUniformi("s2_S2", this->EDLLowBlurTexture->GetTextureUnit());
615
  }
616
  else
617
  {
618 619
    this->EDLLowShadeTexture->Activate();
    prog->SetUniformi("s2_S2", this->EDLLowShadeTexture->GetTextureUnit());
620
  }
621 622 623 624 625 626 627 628

  //  initial color texture
  this->ProjectionColorTexture->Activate();
  prog->SetUniformi("s2_C", this->ProjectionColorTexture->GetTextureUnit());

  //  DRAW CONTEXT - prepare blitting
  //
  // Prepare blitting
629 630 631
  ostate->vtkglClearColor(1., 1., 1., 1.);
  ostate->vtkglClearDepth(1.0);
  ostate->vtkglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
632
  // IMPORTANT since we enable depth writing hereafter
633 634
  ostate->vtkglDisable(GL_BLEND);
  ostate->vtkglEnable(GL_DEPTH_TEST);
635
  // IMPORTANT : so that depth information is propagated
636
  ostate->vtkglDisable(GL_SCISSOR_TEST);
637

638 639 640 641 642 643 644 645 646
  int blitSize[2] = { this->W - 1 - 2 * this->ExtraPixels,
                      this->H - 1 - 2 * this->ExtraPixels };

  this->EDLHighShadeTexture->CopyToFrameBuffer(
      this->ExtraPixels,  this->ExtraPixels,
      blitSize[0], blitSize[1],
      this->Origin[0], this->Origin[1],
      this->Origin[0] + blitSize[0], this->Origin[1] + blitSize[1],
      prog, this->EDLComposeProgram.VAO);
647 648 649 650

  //  FREE ALL
  //
  if (this->EDLIsFiltered)
651
  {
652
    this->EDLLowBlurTexture->Deactivate();
653
  }
654
  else
655
  {
656
    this->EDLLowShadeTexture->Deactivate();
657
  }
658 659 660 661 662 663 664 665 666 667 668 669
  this->EDLHighShadeTexture->Deactivate();
  this->ProjectionColorTexture->Deactivate();

  return true;
}

// ----------------------------------------------------------------------------
// Description:
// Perform rendering according to a render state \p s.
// \pre s_exists: s!=0
void vtkEDLShading::Render(const vtkRenderState *s)
{
670
  assert("pre: s_exists" && s!=nullptr);
671
  annotate("Start vtkEDLShading::Render");
672 673 674 675 676 677

  this->NumberOfRenderedProps = 0;
  vtkRenderer *r = s->GetRenderer();
  vtkOpenGLRenderWindow *renWin =
    vtkOpenGLRenderWindow::SafeDownCast(r->GetRenderWindow());

678
  if (this->DelegatePass != nullptr)
679
  {
680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698

    //////////////////////////////////////////////////////
    //
    //  2. DEFINE SIZE and ACCORDING RENDER STATE
    //
    this->ReadWindowSize(s);
    // this->extraPixels = 20; Obsolete
    this->ExtraPixels = 0; // extra pixels to zero in the new system
    this->W = this->Width + 2* this ->ExtraPixels;
    this->H=this->Height+2*this->ExtraPixels;
    vtkRenderState s2(r);
    s2.SetPropArrayAndCount(s->GetPropArray(),s->GetPropArrayCount());

    //////////////////////////////////////////////////////
    //
    // 3. INITIALIZE FBOs and SHADERS
    //
    //  FBOs
    //
699
    annotate("Start vtkEDLShading Initialization");
700 701 702 703
    this->EDLInitializeFramebuffers(s2);
    //  Shaders
    //
    this->EDLInitializeShaders(renWin);
704
    annotate("End vtkEDLShading Initialization");
705

706 707 708
    if (this->EDLShadeProgram.Program == nullptr ||
        this->EDLComposeProgram.Program == nullptr ||
        this->BilateralProgram.Program == nullptr)
709 710 711 712
    {
      return;
    }

713 714 715 716 717 718 719 720 721 722
    //////////////////////////////////////////////////////
    //
    // 4. DELEGATE RENDER IN PROJECTION FBO
    //
    //
    double znear,zfar;
    r->GetActiveCamera()->GetClippingRange(znear,zfar);
    this->Zf = zfar;
    this->Zn = znear;
    //cout << " -- ZNEAR/ZFAR : " << Zn << " || " << Zf << endl;
723
    this->ProjectionFBO->SaveCurrentBindingsAndBuffers();
724
    this->ProjectionFBO->Bind();
725
    annotate("Start vtkEDLShading::RenderDelegate");
726 727 728
    this->RenderDelegate(s,this->Width,this->Height,
         this->W,this->H,this->ProjectionFBO,
         this->ProjectionColorTexture,this->ProjectionDepthTexture);
729
    annotate("End vtkEDLShading::RenderDelegate");
730 731 732 733 734 735 736 737 738 739

    this->ProjectionFBO->UnBind();

    //system("PAUSE");

    //////////////////////////////////////////////////////
    //
    // 5. EDL SHADING PASS - FULL RESOLUTION
    //
#if EDL_HIGH_RESOLUTION_ON
740
    annotate("Start vtkEDLShading::ShadeHigh");
741
    if(! this->EDLShadeHigh(s2,renWin) )
742
    {
743
      this->ProjectionFBO->RestorePreviousBindingsAndBuffers();
744
    }
745
    annotate("End vtkEDLShading::ShadeHigh");
746 747 748 749 750 751 752
#endif // EDL_HIGH_RESOLUTION_ON

    //////////////////////////////////////////////////////
    //
    // 6. EDL SHADING PASS - LOW RESOLUTION + blur pass
    //
#if EDL_LOW_RESOLUTION_ON
753
    annotate("Start vtkEDLShading::ShadeLow");
754
    if(! this->EDLShadeLow(s2, renWin) )
755
    {
756
      this->ProjectionFBO->RestorePreviousBindingsAndBuffers();
757
    }
758
    annotate("End vtkEDLShading::ShadeLow");
759
    if (this->EDLIsFiltered)
760
    {
761
      annotate("Start vtkEDLShading::BlurLow");
762
      this->EDLBlurLow(s2, renWin);
763
      annotate("End vtkEDLShading::BlurLow");
764
    }
765 766 767 768 769 770
#endif // EDL_LOW_RESOLUTION_ON

    //////////////////////////////////////////////////////
    //
    // 7. COMPOSITING PASS (in original framebuffer)
    //
771
    if(s->GetFrameBuffer() != nullptr)
772
    {
773
      vtkOpenGLFramebufferObject::SafeDownCast(s->GetFrameBuffer())->Bind();
774
    }
775
    this->ProjectionFBO->RestorePreviousBindingsAndBuffers();
776

777
    annotate("Start vtkEDLShading::Compose");
778
    if( ! this->EDLCompose(s, renWin))
779
    {
780 781
      return;
    }
782
    annotate("End vtkEDLShading::Compose");
783
  }
784
  else
785
  {
786
    vtkWarningMacro(<<" no delegate.");
787
  }
788 789

  annotate("END vtkEDLShading::Render");
790 791 792 793 794 795 796 797 798
}

// --------------------------------------------------------------------------
// Description:
// Release graphics resources and ask components to release their own
// resources.
// \pre w_exists: w!=0
void vtkEDLShading::ReleaseGraphicsResources(vtkWindow *w)
{
799
  assert("pre: w_exists" && w!=nullptr);
800 801 802 803 804 805 806 807

  //  SHADERS
  this->EDLShadeProgram.ReleaseGraphicsResources(w);
  this->EDLComposeProgram.ReleaseGraphicsResources(w);
  this->BilateralProgram.ReleaseGraphicsResources(w);

  // FBOs and TOs
  //
808
  if (this->ProjectionFBO != nullptr)
809
  {
810
    this->ProjectionFBO->Delete();
811
    this->ProjectionFBO = nullptr;
812
  }
813
  if (this->ProjectionColorTexture != nullptr)
814
  {
815
    this->ProjectionColorTexture->Delete();
816
    this->ProjectionColorTexture = nullptr;
817
  }
818
  if (this->ProjectionDepthTexture != nullptr)
819
  {
820
    this->ProjectionDepthTexture->Delete();
821
    this->ProjectionDepthTexture = nullptr;
822
  }
823
  if (this->EDLHighFBO != nullptr)
824
  {
825
    this->EDLHighFBO->Delete();
826
    this->EDLHighFBO = nullptr;
827
  }
828
  if (this->EDLHighShadeTexture != nullptr)
829
  {
830
    this->EDLHighShadeTexture->Delete();
831
    this->EDLHighShadeTexture = nullptr;
832
  }
833
  if (this->EDLLowFBO != nullptr)
834
  {
835
    this->EDLLowFBO->Delete();
836
    this->EDLLowFBO = nullptr;
837
  }
838
  if (this->EDLLowShadeTexture != nullptr)
839
  {
840
    this->EDLLowShadeTexture->Delete();
841
    this->EDLLowShadeTexture = nullptr;
842
  }
843
  if (this->EDLLowBlurTexture != nullptr)
844
  {
845
    this->EDLLowBlurTexture->Delete();
846
    this->EDLLowBlurTexture = nullptr;
847
  }
848 849 850

  this->Superclass::ReleaseGraphicsResources(w);
}