vtkOpenGLRenderer.cxx 24.8 KB
Newer Older
1 2 3
/*=========================================================================

Program:   Visualization Toolkit
4
Module:    vtkOpenGLRenderer.cxx
5 6 7 8 9 10 11 12 13 14

Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
15
#include "vtkOpenGLRenderer.h"
16

Ken Martin's avatar
Ken Martin committed
17
#include "vtkOpenGLHelper.h"
18

19
#include "vtkCellArray.h"
20
#include "vtkDepthPeelingPass.h"
Ken Martin's avatar
Ken Martin committed
21
#include "vtkDualDepthPeelingPass.h"
22
#include "vtkFloatArray.h"
Ken Martin's avatar
Ken Martin committed
23
#include "vtkHardwareSelector.h"
24
#include "vtkHiddenLineRemovalPass.h"
25
#include "vtkLight.h"
26
#include "vtkLightCollection.h"
27
#include "vtkNew.h"
28
#include "vtkObjectFactory.h"
29
#include "vtkOpenGLCamera.h"
30
#include "vtkOpenGLError.h"
David C. Lonie's avatar
David C. Lonie committed
31
#include "vtkOpenGLFXAAFilter.h"
32
#include "vtkOpenGLRenderWindow.h"
33 34 35 36
#include "vtkPointData.h"
#include "vtkPoints.h"
#include "vtkPolyData.h"
#include "vtkPolyDataMapper2D.h"
37 38
#include "vtkRenderPass.h"
#include "vtkRenderState.h"
Ken Martin's avatar
Ken Martin committed
39 40
#include "vtkShadowMapBakerPass.h"
#include "vtkShadowMapPass.h"
41
#include "vtkTexture.h"
42
#include "vtkTextureObject.h"
43 44
#include "vtkTexturedActor2D.h"
#include "vtkTimerLog.h"
45
#include "vtkTranslucentPass.h"
46 47
#include "vtkTrivialProducer.h"
#include "vtkUnsignedCharArray.h"
48

David C. Lonie's avatar
David C. Lonie committed
49

Sean McBride's avatar
Sean McBride committed
50
#include <cmath>
51
#include <cassert>
52
#include <cstdlib>
53
#include <list>
54
#include <string>
55 56 57 58

class vtkGLPickInfo
{
public:
Ken Martin's avatar
Ken Martin committed
59 60
  unsigned int PickedId;
  unsigned int NumPicked;
61 62
  bool PerformedHardwarePick;
  std::map<unsigned int,float> PickValues;
63 64
};

65
vtkStandardNewMacro(vtkOpenGLRenderer);
66

67
vtkOpenGLRenderer::vtkOpenGLRenderer()
68 69 70 71 72 73
{
  this->PickInfo = new vtkGLPickInfo;
  this->PickInfo->PickedId = 0;
  this->PickInfo->NumPicked = 0;
  this->PickedZ = 0;

David C. Lonie's avatar
David C. Lonie committed
74
  this->FXAAFilter = 0;
75
  this->DepthPeelingPass = 0;
Ken Martin's avatar
Ken Martin committed
76
  this->ShadowMapPass = 0;
77 78 79
  this->DepthPeelingHigherLayer=0;

  this->BackgroundTexture = 0;
80 81
  this->HaveApplePrimitiveIdBugValue = false;
  this->HaveApplePrimitiveIdBugChecked = false;
82 83 84
}

// Ask lights to load themselves into graphics pipeline.
85
int vtkOpenGLRenderer::UpdateLights ()
86 87 88 89 90 91 92 93 94 95
{
  vtkOpenGLClearErrorMacro();

  vtkLight *light;
  float status;
  int count = 0;

  vtkCollectionSimpleIterator sit;
  for(this->Lights->InitTraversal(sit);
      (light = this->Lights->GetNextLight(sit)); )
96
  {
97 98
    status = light->GetSwitch();
    if (status > 0.0)
99
    {
100 101
      count++;
    }
102
  }
103 104

  if( !count )
105
  {
106 107
    vtkDebugMacro(<<"No lights are on, creating one.");
    this->CreateLight();
108
  }
109 110 111

  for(this->Lights->InitTraversal(sit);
      (light = this->Lights->GetNextLight(sit)); )
112
  {
113 114 115 116
    status = light->GetSwitch();

    // if the light is on then define it and bind it.
    if (status > 0.0)
117
    {
118 119
      light->Render(this,0);
    }
120
  }
121 122 123 124 125 126 127 128 129 130 131 132

  vtkOpenGLCheckErrorMacro("failed after UpdateLights");

  return count;
}

// ----------------------------------------------------------------------------
// Description:
// Is rendering at translucent geometry stage using depth peeling and
// rendering a layer other than the first one? (Boolean value)
// If so, the uniform variables UseTexture and Texture can be set.
// (Used by vtkOpenGLProperty or vtkOpenGLTexture)
133
int vtkOpenGLRenderer::GetDepthPeelingHigherLayer()
134 135 136 137 138 139
{
  return this->DepthPeelingHigherLayer;
}

// ----------------------------------------------------------------------------
// Concrete open gl render method.
140
void vtkOpenGLRenderer::DeviceRender(void)
141 142 143 144
{
  vtkTimerLog::MarkStartEvent("OpenGL Dev Render");

  if(this->Pass!=0)
145
  {
146 147 148 149
    vtkRenderState s(this);
    s.SetPropArrayAndCount(this->PropArray, this->PropArrayCount);
    s.SetFrameBuffer(0);
    this->Pass->Render(&s);
150
  }
151
  else
152
  {
153 154 155 156 157 158 159 160 161 162 163 164 165
    // Do not remove this MakeCurrent! Due to Start / End methods on
    // some objects which get executed during a pipeline update,
    // other windows might get rendered since the last time
    // a MakeCurrent was called.
    this->RenderWindow->MakeCurrent();
    vtkOpenGLClearErrorMacro();

    this->UpdateCamera();
    this->UpdateLightGeometry();
    this->UpdateLights();
    this->UpdateGeometry();

    vtkOpenGLCheckErrorMacro("failed after DeviceRender");
166
  }
167 168 169 170

  vtkTimerLog::MarkEndEvent("OpenGL Dev Render");
}

Ken Martin's avatar
Ken Martin committed
171 172 173 174 175 176 177 178 179
// Ask actors to render themselves. As a side effect will cause
// visualization network to update.
int vtkOpenGLRenderer::UpdateGeometry()
{
  int        i;

  this->NumberOfPropsRendered = 0;

  if ( this->PropArrayCount == 0 )
180
  {
Ken Martin's avatar
Ken Martin committed
181
    return 0;
182
  }
Ken Martin's avatar
Ken Martin committed
183 184

  if (this->Selector)
185
  {
Ken Martin's avatar
Ken Martin committed
186 187 188 189 190 191 192 193
    // When selector is present, we are performing a selection,
    // so do the selection rendering pass instead of the normal passes.
    // Delegate the rendering of the props to the selector itself.
    this->NumberOfPropsRendered = this->Selector->Render(this,
      this->PropArray, this->PropArrayCount);
    this->RenderTime.Modified();
    vtkDebugMacro("Rendered " << this->NumberOfPropsRendered << " actors" );
    return this->NumberOfPropsRendered;
194
  }
Ken Martin's avatar
Ken Martin committed
195 196 197 198

  // if we are suing shadows then let the renderpasses handle it
  // for opaque and translucent
  if (this->UseShadows)
199
  {
Ken Martin's avatar
Ken Martin committed
200
    if (!this->ShadowMapPass)
201
    {
Ken Martin's avatar
Ken Martin committed
202
      this->ShadowMapPass = vtkShadowMapPass::New();
203
    }
Ken Martin's avatar
Ken Martin committed
204 205 206 207 208
    vtkRenderState s(this);
    s.SetPropArrayAndCount(this->PropArray, this->PropArrayCount);
    //s.SetFrameBuffer(0);
    this->ShadowMapPass->GetShadowMapBakerPass()->Render(&s);
    this->ShadowMapPass->Render(&s);
209
  }
Ken Martin's avatar
Ken Martin committed
210
  else
211
  {
212 213
    // Opaque geometry first:
    this->DeviceRenderOpaqueGeometry();
Ken Martin's avatar
Ken Martin committed
214 215 216 217 218 219

    // do the render library specific stuff about translucent polygonal geometry.
    // As it can be expensive, do a quick check if we can skip this step
    int hasTranslucentPolygonalGeometry=0;
    for ( i = 0; !hasTranslucentPolygonalGeometry && i < this->PropArrayCount;
          i++ )
220
    {
Ken Martin's avatar
Ken Martin committed
221 222
      hasTranslucentPolygonalGeometry=
        this->PropArray[i]->HasTranslucentPolygonalGeometry();
223
    }
Ken Martin's avatar
Ken Martin committed
224
    if(hasTranslucentPolygonalGeometry)
225
    {
Ken Martin's avatar
Ken Martin committed
226 227
      this->DeviceRenderTranslucentPolygonalGeometry();
    }
228
  }
Ken Martin's avatar
Ken Martin committed
229

David C. Lonie's avatar
David C. Lonie committed
230 231 232
  // Apply FXAA before volumes and overlays. Volumes don't need AA, and overlays
  // are usually things like text, which are already antialiased.
  if (this->UseFXAA)
233
  {
David C. Lonie's avatar
David C. Lonie committed
234
    if (!this->FXAAFilter)
235
    {
David C. Lonie's avatar
David C. Lonie committed
236
      this->FXAAFilter = vtkOpenGLFXAAFilter::New();
237
    }
238
    if (this->FXAAOptions)
239
    {
240
      this->FXAAFilter->UpdateConfiguration(this->FXAAOptions);
241
    }
David C. Lonie's avatar
David C. Lonie committed
242 243

    this->FXAAFilter->Execute(this);
244
  }
David C. Lonie's avatar
David C. Lonie committed
245

Ken Martin's avatar
Ken Martin committed
246 247 248
  // loop through props and give them a chance to
  // render themselves as volumetric geometry.
  for ( i = 0; i < this->PropArrayCount; i++ )
249
  {
Ken Martin's avatar
Ken Martin committed
250 251
    this->NumberOfPropsRendered +=
      this->PropArray[i]->RenderVolumetricGeometry(this);
252
  }
Ken Martin's avatar
Ken Martin committed
253 254 255 256

  // loop through props and give them a chance to
  // render themselves as an overlay (or underlay)
  for ( i = 0; i < this->PropArrayCount; i++ )
257
  {
Ken Martin's avatar
Ken Martin committed
258 259
    this->NumberOfPropsRendered +=
      this->PropArray[i]->RenderOverlay(this);
260
  }
Ken Martin's avatar
Ken Martin committed
261 262 263 264 265 266 267 268 269

  this->RenderTime.Modified();

  vtkDebugMacro( << "Rendered " <<
                    this->NumberOfPropsRendered << " actors" );

  return  this->NumberOfPropsRendered;
}

270 271 272 273 274 275 276 277 278 279
// ----------------------------------------------------------------------------
void vtkOpenGLRenderer::DeviceRenderOpaqueGeometry()
{
  // Do we need hidden line removal?
  bool useHLR =
      this->UseHiddenLineRemoval &&
      vtkHiddenLineRemovalPass::WireframePropsExist(this->PropArray,
                                                    this->PropArrayCount);

  if (useHLR)
280
  {
281 282 283 284 285 286
    vtkNew<vtkHiddenLineRemovalPass> hlrPass;
    vtkRenderState s(this);
    s.SetPropArrayAndCount(this->PropArray, this->PropArrayCount);
    s.SetFrameBuffer(0);
    hlrPass->Render(&s);
    this->NumberOfPropsRendered += hlrPass->GetNumberOfRenderedProps();
287
  }
288
  else
289
  {
290
    this->Superclass::DeviceRenderOpaqueGeometry();
291
  }
292 293
}

294 295 296 297 298 299
// ----------------------------------------------------------------------------
// Description:
// Render translucent polygonal geometry. Default implementation just call
// UpdateTranslucentPolygonalGeometry().
// Subclasses of vtkRenderer that can deal with depth peeling must
// override this method.
300
void vtkOpenGLRenderer::DeviceRenderTranslucentPolygonalGeometry()
301 302 303
{
  vtkOpenGLClearErrorMacro();

304 305
  vtkOpenGLRenderWindow *context
    = vtkOpenGLRenderWindow::SafeDownCast(this->RenderWindow);
Ken Martin's avatar
Ken Martin committed
306

307
  if(this->UseDepthPeeling && !context)
308
  {
309 310
    vtkErrorMacro("OpenGL render window is required.")
    return;
311
  }
312

313
  if(!this->UseDepthPeeling)
314
  {
315 316
    // just alpha blending
    this->UpdateTranslucentPolygonalGeometry();
317
  }
Ken Martin's avatar
Ken Martin committed
318
  else   // depth peeling.
319
  {
320
    if (!this->DepthPeelingPass)
321
    {
David C. Lonie's avatar
David C. Lonie committed
322 323 324 325 326
      // Dual depth peeling requires:
      // - float textures (ARB_texture_float)
      // - RG textures (ARB_texture_rg)
      // - MAX blending (not available in ES2, but added in ES3).
      bool dualDepthPeelingSupported = false;
Ken Martin's avatar
Ken Martin committed
327
#if GL_ES_VERSION_3_0 == 1
David C. Lonie's avatar
David C. Lonie committed
328 329
      // ES3 is supported:
      dualDepthPeelingSupported = true;
Ken Martin's avatar
Ken Martin committed
330 331 332
#else
      dualDepthPeelingSupported = context->GetContextSupportsOpenGL32() ||
          (GLEW_ARB_texture_float && GLEW_ARB_texture_rg);
David C. Lonie's avatar
David C. Lonie committed
333
#endif
334 335 336 337 338 339

      // There's a bug on current mesa master that prevents dual depth peeling
      // from functioning properly, something in the texture sampler is causing
      // all lookups to return NaN. See discussion on
      // https://bugs.freedesktop.org/show_bug.cgi?id=94955
      // We'll always fallback to regular depth peeling until this is fixed.
340 341
      // Only disable for mesa + llvmpipe/SWR, since those are the drivers that
      // seem to be affected by this.
342 343
      std::string glVersion =
          reinterpret_cast<const char *>(glGetString(GL_VERSION));
344
      if (glVersion.find("Mesa") != std::string::npos)
345
      {
346 347 348 349
        std::string glRenderer =
            reinterpret_cast<const char *>(glGetString(GL_RENDERER));
        if (glRenderer.find("llvmpipe") != std::string::npos ||
            glRenderer.find("SWR") != std::string::npos)
350
        {
351 352 353 354
          vtkDebugMacro("Disabling dual depth peeling -- mesa bug detected. "
                        "GL_VERSION = '" << glVersion << "'; "
                        "GL_RENDERER = '" << glRenderer << "'.");
          dualDepthPeelingSupported = false;
355
        }
356
      }
357

358 359 360
      // The old implemention can be force by defining the environment var
      // "VTK_USE_LEGACY_DEPTH_PEELING":
      if (dualDepthPeelingSupported)
361
      {
362 363
        const char *forceLegacy = getenv("VTK_USE_LEGACY_DEPTH_PEELING");
        if (forceLegacy)
364
        {
365 366 367 368
          vtkDebugMacro("Disabling dual depth peeling -- "
                        "VTK_USE_LEGACY_DEPTH_PEELING defined in environment.");
          dualDepthPeelingSupported = false;
        }
369
      }
370

David C. Lonie's avatar
David C. Lonie committed
371
      if (dualDepthPeelingSupported)
372
      {
David C. Lonie's avatar
David C. Lonie committed
373
        vtkDebugMacro("Using dual depth peeling.");
David C. Lonie's avatar
David C. Lonie committed
374
        this->DepthPeelingPass = vtkDualDepthPeelingPass::New();
375
      }
David C. Lonie's avatar
David C. Lonie committed
376
      else
377
      {
David C. Lonie's avatar
David C. Lonie committed
378 379
        vtkDebugMacro("Using standard depth peeling (dual depth peeling not "
                      "supported by the graphics card/driver).");
David C. Lonie's avatar
David C. Lonie committed
380
        this->DepthPeelingPass = vtkDepthPeelingPass::New();
381
      }
382 383 384
      vtkTranslucentPass *tp = vtkTranslucentPass::New();
      this->DepthPeelingPass->SetTranslucentPass(tp);
      tp->Delete();
385
    }
386 387 388 389 390
    this->DepthPeelingPass->SetMaximumNumberOfPeels(this->MaximumNumberOfPeels);
    this->DepthPeelingPass->SetOcclusionRatio(this->OcclusionRatio);
    vtkRenderState s(this);
    s.SetPropArrayAndCount(this->PropArray, this->PropArrayCount);
    s.SetFrameBuffer(0);
391
    this->LastRenderingUsedDepthPeeling=1;
392
    this->DepthPeelingPass->Render(&s);
393
  }
394 395 396 397

  vtkOpenGLCheckErrorMacro("failed after DeviceRenderTranslucentPolygonalGeometry");
}

Ken Martin's avatar
Ken Martin committed
398

399
// ----------------------------------------------------------------------------
400
void vtkOpenGLRenderer::PrintSelf(ostream& os, vtkIndent indent)
401 402 403 404 405 406 407 408 409
{
  this->Superclass::PrintSelf(os,indent);

  os << indent << "PickedId" << this->PickInfo->PickedId<< "\n";
  os << indent << "NumPicked" << this->PickInfo->NumPicked<< "\n";
  os << indent << "PickedZ " << this->PickedZ << "\n";
}


410
void vtkOpenGLRenderer::Clear(void)
411 412 413 414 415 416
{
  vtkOpenGLClearErrorMacro();

  GLbitfield  clear_mask = 0;

  if (! this->Transparent())
417
  {
418
    if (this->IsPicking)
419
    {
420
      glClearColor(0.0,0.0,0.0,0.0);
421
    }
422
    else
423
    {
424 425 426 427
      glClearColor( static_cast<GLclampf>(this->Background[0]),
                    static_cast<GLclampf>(this->Background[1]),
                    static_cast<GLclampf>(this->Background[2]),
                    static_cast<GLclampf>(0.0));
428
    }
429 430
    clear_mask |= GL_COLOR_BUFFER_BIT;
  }
431

Ken Martin's avatar
Ken Martin committed
432
  if (!this->GetPreserveDepthBuffer())
433
  {
Ken Martin's avatar
Ken Martin committed
434
#if GL_ES_VERSION_3_0 == 1
Ken Martin's avatar
Ken Martin committed
435 436
    glClearDepthf(static_cast<GLclampf>(1.0));
#else
437
    glClearDepth(static_cast<GLclampf>(1.0));
Ken Martin's avatar
Ken Martin committed
438
#endif
Ken Martin's avatar
Ken Martin committed
439
    clear_mask |= GL_DEPTH_BUFFER_BIT;
440
    glDepthMask(GL_TRUE);
441
  }
Ken Martin's avatar
Ken Martin committed
442

443
  vtkDebugMacro(<< "glClear\n");
Ken Martin's avatar
Ken Martin committed
444
  glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
445 446 447
  glClear(clear_mask);

  // If gradient background is turned on, draw it now.
448
  if (!this->IsPicking && !this->Transparent() &&
449
      (this->GradientBackground || this->TexturedBackground))
450
  {
Ken Martin's avatar
Ken Martin committed
451 452 453 454
    int size[2];
    size[0] = this->GetSize()[0];
    size[1] = this->GetSize()[1];

455 456
    double tile_viewport[4];
    this->GetRenderWindow()->GetTileViewport(tile_viewport);
Ken Martin's avatar
Ken Martin committed
457

458
    vtkNew<vtkTexturedActor2D> actor;
Ken Martin's avatar
Ken Martin committed
459 460 461 462 463 464 465 466
    vtkNew<vtkPolyDataMapper2D> mapper;
    vtkNew<vtkPolyData> polydata;
    vtkNew<vtkPoints> points;
    points->SetNumberOfPoints(4);
    points->SetPoint(0, 0, 0, 0);
    points->SetPoint(1, size[0], 0, 0);
    points->SetPoint(2, size[0], size[1], 0);
    points->SetPoint(3, 0, size[1], 0);
467
    polydata->SetPoints(points.Get());
Ken Martin's avatar
Ken Martin committed
468 469 470 471 472 473

    vtkNew<vtkCellArray> tris;
    tris->InsertNextCell(3);
    tris->InsertCellPoint(0);
    tris->InsertCellPoint(1);
    tris->InsertCellPoint(2);
Ken Martin's avatar
Ken Martin committed
474
    tris->InsertNextCell(3);
Ken Martin's avatar
Ken Martin committed
475 476 477 478 479 480 481 482 483 484 485 486 487
    tris->InsertCellPoint(0);
    tris->InsertCellPoint(2);
    tris->InsertCellPoint(3);
    polydata->SetPolys(tris.Get());

    vtkNew<vtkTrivialProducer> prod;
    prod->SetOutput(polydata.Get());

    // Set some properties.
    mapper->SetInputConnection(prod->GetOutputPort());
    actor->SetMapper(mapper.Get());

    if(this->TexturedBackground && this->BackgroundTexture)
488
    {
489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505
      this->BackgroundTexture->InterpolateOn();
      actor->SetTexture(this->BackgroundTexture);

      vtkNew<vtkFloatArray> tcoords;
      float tmp[2];
      tmp[0] = 0;
      tmp[1] = 0;
      tcoords->SetNumberOfComponents(2);
      tcoords->SetNumberOfTuples(4);
      tcoords->SetTuple(0,tmp);
      tmp[0] = 1.0;
      tcoords->SetTuple(1,tmp);
      tmp[1] = 1.0;
      tcoords->SetTuple(2,tmp);
      tmp[0] = 0.0;
      tcoords->SetTuple(3,tmp);
      polydata->GetPointData()->SetTCoords(tcoords.Get());
506
    }
507
    else // gradient
508
    {
509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524
      vtkNew<vtkUnsignedCharArray> colors;
      float tmp[4];
      tmp[0] = this->Background[0]*255;
      tmp[1] = this->Background[1]*255;
      tmp[2] = this->Background[2]*255;
      tmp[3] = 255;
      colors->SetNumberOfComponents(4);
      colors->SetNumberOfTuples(4);
      colors->SetTuple(0,tmp);
      colors->SetTuple(1,tmp);
      tmp[0] = this->Background2[0]*255;
      tmp[1] = this->Background2[1]*255;
      tmp[2] = this->Background2[2]*255;
      colors->SetTuple(2,tmp);
      colors->SetTuple(3,tmp);
      polydata->GetPointData()->SetScalars(colors.Get());
525
    }
526

527 528
    glDisable(GL_DEPTH_TEST);
    actor->RenderOverlay(this);
529
  }
530

531
  glEnable(GL_DEPTH_TEST);
Ken Martin's avatar
Ken Martin committed
532

533 534 535
  vtkOpenGLCheckErrorMacro("failed after Clear");
}

536
void vtkOpenGLRenderer::StartPick(unsigned int vtkNotUsed(pickFromSize))
537 538 539
{
  vtkOpenGLClearErrorMacro();

540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578
  /*
  int size[2];
  size[0] = this->GetSize()[0];
  size[1] = this->GetSize()[1];

  // Create the FBO
  glGenFramebuffers(1, &this->PickInfo->PickingFBO);
  glBindFramebuffer(GL_FRAMEBUFFER, this->PickInfo->PickingFBO);

  // Create the texture object for the primitive information buffer
  glGenTextures(1, &this->PickInfo->PickingTexture);
  glBindTexture(GL_TEXTURE_2D, this->PickInfo->PickingTexture);
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32UI, size[0], size[1],
              0, GL_RGB_INTEGER, GL_UNSIGNED_INT, NULL);
  glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
              this->PickInfo->PickingTexture, 0);

  // Create the texture object for the depth buffer
  glGenTextures(1, &this->PickInfo->DepthTexture);
  glBindTexture(GL_TEXTURE_2D, this->PickInfo->DepthTexture);
  glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, size[0], size[1],
              0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
  glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D,
              this->PickInfo->DepthTexture, 0);

  // Disable reading to avoid problems with older GPUs
  glReadBuffer(GL_NONE);

  // Verify that the FBO is correct
  GLenum Status = glCheckFramebufferStatus(GL_FRAMEBUFFER);

  if (Status != GL_FRAMEBUFFER_COMPLETE)
    {
    printf("FB error, status: 0x%x\n", Status);
    return;
    }

  glBindFramebuffer(GL_DRAW_FRAMEBUFFER, this->PickInfo->PickingFBO);
  */
579 580 581 582 583 584 585

  // Do not remove this MakeCurrent! Due to Start / End methods on
  // some objects which get executed during a pipeline update,
  // other windows might get rendered since the last time
  // a MakeCurrent was called.
  this->RenderWindow->MakeCurrent();
  this->RenderWindow->IsPickingOn();
586
  this->IsPicking = 1;
587 588 589 590 591
  this->PickInfo->PerformedHardwarePick = false;
  this->PickInfo->PickValues.clear();
  this->PickInfo->NumPicked = 0;
  this->PickInfo->PickedId = 0;

592
  this->Clear();
593 594 595 596

  vtkOpenGLCheckErrorMacro("failed after StartPick");
}

597
void vtkOpenGLRenderer::ReleaseGraphicsResources(vtkWindow *w)
598 599
{
  if (w && this->Pass)
600
  {
601
    this->Pass->ReleaseGraphicsResources(w);
602
  }
David C. Lonie's avatar
David C. Lonie committed
603
  if (this->FXAAFilter)
604
  {
David C. Lonie's avatar
David C. Lonie committed
605
    this->FXAAFilter->ReleaseGraphicsResources();
606
  }
607
  if (w && this->DepthPeelingPass)
608
  {
609
    this->DepthPeelingPass->ReleaseGraphicsResources(w);
610
  }
Ken Martin's avatar
Ken Martin committed
611
  if (w && this->ShadowMapPass)
612
  {
Ken Martin's avatar
Ken Martin committed
613
    this->ShadowMapPass->ReleaseGraphicsResources(w);
614
  }
615
  this->Superclass::ReleaseGraphicsResources(w);
616 617
}

618
void vtkOpenGLRenderer::UpdatePickId()
619
{
620
  this->CurrentPickId++;
621 622 623
}


624
void vtkOpenGLRenderer::DevicePickRender()
625 626 627 628 629 630 631 632
{
  // Do not remove this MakeCurrent! Due to Start / End methods on
  // some objects which get executed during a pipeline update,
  // other windows might get rendered since the last time
  // a MakeCurrent was called.
  this->RenderWindow->MakeCurrent();
  vtkOpenGLClearErrorMacro();

Ken Martin's avatar
Ken Martin committed
633
#if GL_ES_VERSION_3_0 != 1
634 635 636 637 638 639
  bool msaaWasEnabled = false;
  if (this->RenderWindow->GetMultiSamples() > 0 && glIsEnabled(GL_MULTISAMPLE))
  {
    glDisable(GL_MULTISAMPLE);
    msaaWasEnabled = true;
  }
Ken Martin's avatar
Ken Martin committed
640
#endif
641

642 643 644 645 646 647
  this->UpdateCamera();
  this->UpdateLightGeometry();
  this->UpdateLights();

  this->PickGeometry();

648 649
  this->PickInfo->PerformedHardwarePick = true;

Ken Martin's avatar
Ken Martin committed
650
#if GL_ES_VERSION_3_0 != 1
651 652 653 654
  if (msaaWasEnabled)
  {
    glEnable(GL_MULTISAMPLE);
  }
Ken Martin's avatar
Ken Martin committed
655 656
#endif

657 658 659 660
  vtkOpenGLCheckErrorMacro("failed after DevicePickRender");
}


661
void vtkOpenGLRenderer::DonePick()
662
{
663
  if (this->PickInfo->PerformedHardwarePick)
664
  {
665 666 667 668 669
    unsigned char *pixBuffer = this->GetRenderWindow()->GetPixelData(
      this->PickX1, this->PickY1, this->PickX2, this->PickY2, 0);
  //    (this->GetRenderWindow()->GetSwapBuffers() == 1) ? 0 : 1);

    // for debugging save out the image
670 671 672 673
    // FILE * pFile;
    // pFile = fopen ("myfile.ppm", "wb");
    // fwrite (pixBuffer , sizeof(unsigned char), 3*((int)this->PickY2-(int)this->PickY1+1)*((int)this->PickX2-(int)this->PickX1+1), pFile);
    // fclose (pFile);
674 675 676 677 678 679 680 681 682 683

    float *depthBuffer = this->GetRenderWindow()->GetZbufferData(
      this->PickX1, this->PickY1, this->PickX2, this->PickY2);

    // read the color and z buffer values for the region
    // to see what hits we have
    this->PickInfo->PickValues.clear();
    unsigned char *pb = pixBuffer;
    float *dbPtr = depthBuffer;
    for (int y = this->PickY1; y <= this->PickY2; y++)
684
    {
685
      for (int x = this->PickX1; x <= this->PickX2; x++)
686
      {
687 688 689 690 691 692 693 694 695 696 697
        unsigned char rgb[3];
        rgb[0] = *pb++;
        rgb[1] = *pb++;
        rgb[2] = *pb++;
        int val = 0;
        val |= rgb[2];
        val = val << 8;
        val |= rgb[1];
        val = val << 8;
        val |= rgb[0];
        if (val > 0)
698
        {
699
          if (this->PickInfo->PickValues.find(val) == this->PickInfo->PickValues.end())
700
          {
701
            this->PickInfo->PickValues.insert(std::pair<unsigned int,float>(val,*dbPtr));
702 703
          }
        }
704
        dbPtr++;
705
      }
706
    }
707

Ken Martin's avatar
Ken Martin committed
708
    this->PickInfo->NumPicked = (unsigned int)this->PickInfo->PickValues.size();
709

710 711 712 713 714
    this->PickInfo->PickedId = 0;
    std::map<unsigned int,float>::const_iterator dvItr =
      this->PickInfo->PickValues.begin();
    this->PickedZ = 1.0;
    for ( ; dvItr != this->PickInfo->PickValues.end(); dvItr++)
715
    {
716
      if(dvItr->second < this->PickedZ)
717
      {
718 719
        this->PickedZ = dvItr->second;
        this->PickInfo->PickedId = dvItr->first - 1;
720
      }
721
    }
722
  }
723

724 725
  // Restore the default framebuffer
  //glBindFramebuffer(GL_FRAMEBUFFER, 0);
726 727

  this->RenderWindow->IsPickingOff();
728
  this->IsPicking = 0;
729 730
}

731
double vtkOpenGLRenderer::GetPickedZ()
732 733 734 735
{
  return this->PickedZ;
}

736
unsigned int vtkOpenGLRenderer::GetPickedId()
737 738 739 740
{
  return static_cast<unsigned int>(this->PickInfo->PickedId);
}

741
vtkOpenGLRenderer::~vtkOpenGLRenderer()
742 743 744
{
  delete this->PickInfo;

Ken Martin's avatar
Ken Martin committed
745
  if(this->Pass != NULL)
746
  {
747
    this->Pass->UnRegister(this);
Ken Martin's avatar
Ken Martin committed
748
    this->Pass = NULL;
749
  }
Ken Martin's avatar
Ken Martin committed
750

David C. Lonie's avatar
David C. Lonie committed
751
  if (this->FXAAFilter)
752
  {
David C. Lonie's avatar
David C. Lonie committed
753 754
    this->FXAAFilter->Delete();
    this->FXAAFilter = 0;
755
  }
David C. Lonie's avatar
David C. Lonie committed
756

Ken Martin's avatar
Ken Martin committed
757
  if (this->ShadowMapPass)
758
  {
Ken Martin's avatar
Ken Martin committed
759 760
    this->ShadowMapPass->Delete();
    this->ShadowMapPass = 0;
761
  }
Ken Martin's avatar
Ken Martin committed
762

763
  if (this->DepthPeelingPass)
764
  {
765 766
    this->DepthPeelingPass->Delete();
    this->DepthPeelingPass = 0;
767
  }
768 769
}

770 771 772
bool vtkOpenGLRenderer::HaveApplePrimitiveIdBug()
{
  if (this->HaveApplePrimitiveIdBugChecked)
773
  {
774
    return this->HaveApplePrimitiveIdBugValue;
775
  }
776 777

#ifdef __APPLE__
778
  // Known working Apple+AMD systems:
779
  // OpenGL vendor string:  ATI Technologies Inc.
780
  // OpenGL version string:   4.1 ATI-1.38.3
781 782
  // OpenGL version string:   4.1 ATI-1.40.15
  // OpenGL renderer string:    AMD Radeon R9 M370X OpenGL Engine
783

784 785 786
  // OpenGL version string:   4.1 ATI-1.40.16
  // OpenGL renderer string:    AMD Radeon HD - FirePro D500 OpenGL Engine
  // OpenGL renderer string:    AMD Radeon HD 5770 OpenGL Engine
787
  // OpenGL renderer string:    AMD Radeon R9 M395 OpenGL Engine
788

789 790 791 792 793
  // OpenGL vendor string:  ATI Technologies Inc.
  // OpenGL renderer string:  ATI Radeon HD 5770 OpenGL Engine
  // OpenGL version string:  4.1 ATI-1.42.6

  // Known buggy Apple+AMD systems:
794 795 796 797
  // OpenGL vendor string:  ATI Technologies Inc.
  // OpenGL version string:   3.3 ATI-10.0.40
  // OpenGL renderer string:    ATI Radeon HD 2600 PRO OpenGL Engine

798 799 800 801
  // OpenGL vendor string:  ATI Technologies Inc.
  // OpenGL renderer string:  AMD Radeon HD - FirePro D300 OpenGL Engine
  // OpenGL version string:  4.1 ATI-1.24.39

802 803 804 805
  std::string vendor = (const char *)glGetString(GL_VENDOR);
  if (vendor.find("ATI") != std::string::npos ||
      vendor.find("AMD") != std::string::npos ||
      vendor.find("amd") != std::string::npos)
806
  {
807 808 809 810 811 812
    // assume we have the bug
    this->HaveApplePrimitiveIdBugValue = true;

    // but exclude systems we know do not have it
    std::string renderer = (const char *)glGetString(GL_RENDERER);
    std::string version = (const char *)glGetString(GL_VERSION);
813 814 815 816
    int minorVersion = 0;
    int patchVersion = 0;
    // try to extract some minor version numbers
    if (version.find("4.1 ATI-1.") == 0)
817
    {
818 819
      std::string minorVer = version.substr(strlen("4.1 ATI-1."),std::string::npos);
      if (minorVer.find(".") == 2)
820
      {
821 822
        minorVersion = atoi(minorVer.substr(0,2).c_str());
        patchVersion = atoi(minorVer.substr(3,std::string::npos).c_str());
823
      }
824
    }
825
    if (
826 827
        ((version.find("4.1 ATI-1.38.3") != std::string::npos ||
          version.find("4.1 ATI-1.40.15") != std::string::npos) &&
828
          (renderer.find("AMD Radeon R9 M370X OpenGL Engine") != std::string::npos)) ||
829 830 831
          // assume anything with 1.40.16 or later is good?
          minorVersion > 40 ||
          (minorVersion == 40 && patchVersion >= 16)
832
         )
833
    {
834 835
      this->HaveApplePrimitiveIdBugValue = false;
    }
836
  }
837 838 839 840 841 842 843 844
#else
  this->HaveApplePrimitiveIdBugValue = false;
#endif

  this->HaveApplePrimitiveIdBugChecked = true;
  return this->HaveApplePrimitiveIdBugValue;
}

845
unsigned int vtkOpenGLRenderer::GetNumPickedIds()
846 847 848 849
{
  return static_cast<unsigned int>(this->PickInfo->NumPicked);
}

850
int vtkOpenGLRenderer::GetPickedIds(unsigned int atMost,
851 852
                                    unsigned int *callerBuffer)
{
853
  if (this->PickInfo->PickValues.empty())
854
  {
855
    return 0;
856
  }