vtkOpenGLPolyDataMapper.cxx 119 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
/*=========================================================================

  Program:   Visualization Toolkit

  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.

=========================================================================*/
Ken Martin's avatar
Ken Martin committed
14
#include "vtkOpenGLPolyDataMapper.h"
15

16
#include "vtkCamera.h"
17
#include "vtkCellArray.h"
Ken Martin's avatar
Ken Martin committed
18
#include "vtkCellData.h"
19
20
21
22
#include "vtkCommand.h"
#include "vtkFloatArray.h"
#include "vtkHardwareSelector.h"
#include "vtkImageData.h"
23
#include "vtkInformation.h"
24
25
#include "vtkLight.h"
#include "vtkLightCollection.h"
26
#include "vtkLightingMapPass.h"
27
#include "vtkMath.h"
28
#include "vtkMatrix3x3.h"
29
#include "vtkMatrix4x4.h"
30
#include "vtkObjectFactory.h"
31
#include "vtkOpenGLActor.h"
Ken Martin's avatar
Ken Martin committed
32
#include "vtkOpenGLBufferObject.h"
33
#include "vtkOpenGLCamera.h"
Ken Martin's avatar
Ken Martin committed
34
35
36
#include "vtkOpenGLError.h"
#include "vtkOpenGLHelper.h"
#include "vtkOpenGLIndexBufferObject.h"
David C. Lonie's avatar
David C. Lonie committed
37
#include "vtkOpenGLRenderPass.h"
38
#include "vtkOpenGLRenderWindow.h"
Ken Martin's avatar
Ken Martin committed
39
#include "vtkOpenGLRenderer.h"
40
#include "vtkOpenGLResourceFreeCallback.h"
41
42
#include "vtkOpenGLShaderCache.h"
#include "vtkOpenGLTexture.h"
Ken Martin's avatar
Ken Martin committed
43
#include "vtkOpenGLVertexArrayObject.h"
Ken Martin's avatar
Ken Martin committed
44
#include "vtkOpenGLVertexBufferObject.h"
45
46
47
#include "vtkPointData.h"
#include "vtkPolyData.h"
#include "vtkProperty.h"
48
#include "vtkScalarsToColors.h"
49
#include "vtkShaderProgram.h"
50
#include "vtkTextureObject.h"
Ken Martin's avatar
Ken Martin committed
51
#include "vtkTransform.h"
52
#include "vtkUnsignedIntArray.h"
Ken Martin's avatar
Ken Martin committed
53
#include "vtkShadowMapPass.h"
Tim Thirion's avatar
Tim Thirion committed
54
#include "vtkValuePass.h"
55
#include "vtkValuePassHelper.h"
Ken Martin's avatar
Ken Martin committed
56

Ken Martin's avatar
Ken Martin committed
57
// Bring in our fragment lit shader symbols.
Ken Martin's avatar
Ken Martin committed
58
59
#include "vtkPolyDataVS.h"
#include "vtkPolyDataFS.h"
60
#include "vtkPolyDataWideLineGS.h"
61

Ken Martin's avatar
Ken Martin committed
62
#include <algorithm>
Ken Martin's avatar
Ken Martin committed
63
#include <sstream>
Ken Martin's avatar
Ken Martin committed
64

65

66
//-----------------------------------------------------------------------------
Ken Martin's avatar
Ken Martin committed
67
vtkStandardNewMacro(vtkOpenGLPolyDataMapper)
68
69

//-----------------------------------------------------------------------------
Ken Martin's avatar
Ken Martin committed
70
vtkOpenGLPolyDataMapper::vtkOpenGLPolyDataMapper()
Ken Martin's avatar
Ken Martin committed
71
  : UsingScalarColoring(false)
72
{
73
  this->InternalColorTexture = 0;
74
  this->PopulateSelectionSettings = 1;
75
  this->LastSelectionState = vtkHardwareSelector::MIN_KNOWN_PASS - 1;
76
  this->CurrentInput = 0;
77
78
  this->TempMatrix4 = vtkMatrix4x4::New();
  this->TempMatrix3 = vtkMatrix3x3::New();
79
  this->DrawingEdges = false;
Ken Martin's avatar
Ken Martin committed
80
  this->ForceTextureCoordinates = false;
81

Ken Martin's avatar
Ken Martin committed
82
83
  this->PrimitiveIDOffset = 0;

84
85
86
87
  this->CellScalarTexture = NULL;
  this->CellScalarBuffer = NULL;
  this->CellNormalTexture = NULL;
  this->CellNormalBuffer = NULL;
88

89
  this->HavePickScalars = false;
90
91
  this->HaveCellScalars = false;
  this->HaveCellNormals = false;
92
93
94
95
96

  this->PointIdArrayName = NULL;
  this->CellIdArrayName = NULL;
  this->ProcessIdArrayName = NULL;
  this->CompositeIdArrayName = NULL;
Ken Martin's avatar
Ken Martin committed
97
  this->VBO = vtkOpenGLVertexBufferObject::New();
98
99

  this->AppleBugPrimIDBuffer = 0;
100
  this->HaveAppleBug = false;
101
  this->HaveAppleBugForce = 0;
Dan Lipsa's avatar
Dan Lipsa committed
102
  this->LastBoundBO = NULL;
103
104
105
106

  this->VertexShaderCode = 0;
  this->FragmentShaderCode = 0;
  this->GeometryShaderCode = 0;
107

108
109
110
111
112
  for (int i = PrimitiveStart; i < PrimitiveEnd; i++)
  {
    this->LastLightComplexity[&this->Primitives[i]] = -1;
    this->Primitives[i].PrimitiveType = i;
  }
113

114
  this->TimerQuery = 0;
115
116
  this->ResourceCallback = new vtkOpenGLResourceFreeCallback<vtkOpenGLPolyDataMapper>(this,
    &vtkOpenGLPolyDataMapper::ReleaseGraphicsResources);
117
  this->ValuePassHelper = vtkSmartPointer<vtkValuePassHelper>::New();
118
}
119

120
//-----------------------------------------------------------------------------
Ken Martin's avatar
Ken Martin committed
121
vtkOpenGLPolyDataMapper::~vtkOpenGLPolyDataMapper()
122
{
123
  if (this->ResourceCallback)
124
  {
125
126
127
    this->ResourceCallback->Release();
    delete this->ResourceCallback;
    this->ResourceCallback = NULL;
128
  }
129
  if (this->InternalColorTexture)
130
  { // Resources released previously.
131
132
    this->InternalColorTexture->Delete();
    this->InternalColorTexture = 0;
133
  }
134
135
  this->TempMatrix3->Delete();
  this->TempMatrix4->Delete();
136
137

  if (this->CellScalarTexture)
138
  { // Resources released previously.
139
140
    this->CellScalarTexture->Delete();
    this->CellScalarTexture = 0;
141
  }
142
  if (this->CellScalarBuffer)
143
  { // Resources released previously.
Ken Martin's avatar
Ken Martin committed
144
    this->CellScalarBuffer->Delete();
145
    this->CellScalarBuffer = 0;
146
  }
147
148

  if (this->CellNormalTexture)
149
  { // Resources released previously.
150
151
    this->CellNormalTexture->Delete();
    this->CellNormalTexture = 0;
152
  }
153
  if (this->CellNormalBuffer)
154
  { // Resources released previously.
Ken Martin's avatar
Ken Martin committed
155
    this->CellNormalBuffer->Delete();
156
    this->CellNormalBuffer = 0;
157
  }
158
159
160
161
162

  this->SetPointIdArrayName(NULL);
  this->SetCellIdArrayName(NULL);
  this->SetProcessIdArrayName(NULL);
  this->SetCompositeIdArrayName(NULL);
Ken Martin's avatar
Ken Martin committed
163
164
  this->VBO->Delete();
  this->VBO = 0;
165
166

  if (this->AppleBugPrimIDBuffer)
167
  {
168
    this->AppleBugPrimIDBuffer->Delete();
169
  }
170
171
172
173

  this->SetVertexShaderCode(0);
  this->SetFragmentShaderCode(0);
  this->SetGeometryShaderCode(0);
174
175
176
}

//-----------------------------------------------------------------------------
Ken Martin's avatar
Ken Martin committed
177
void vtkOpenGLPolyDataMapper::ReleaseGraphicsResources(vtkWindow* win)
178
{
179
  if (!this->ResourceCallback->IsReleasing())
180
  {
181
182
    this->ResourceCallback->Release();
    return;
183
  }
184

Ken Martin's avatar
Ken Martin committed
185
  this->VBO->ReleaseGraphicsResources();
186
187
188
189
  for (int i = PrimitiveStart; i < PrimitiveEnd; i++)
  {
    this->Primitives[i].ReleaseGraphicsResources(win);
  }
190

191
  if (this->InternalColorTexture)
192
  {
193
    this->InternalColorTexture->ReleaseGraphicsResources(win);
194
  }
195
  if (this->CellScalarTexture)
196
  {
197
    this->CellScalarTexture->ReleaseGraphicsResources(win);
198
  }
199
  if (this->CellScalarBuffer)
200
  {
201
    this->CellScalarBuffer->ReleaseGraphicsResources();
202
  }
203
  if (this->CellNormalTexture)
204
  {
205
    this->CellNormalTexture->ReleaseGraphicsResources(win);
206
  }
207
  if (this->CellNormalBuffer)
208
  {
209
    this->CellNormalBuffer->ReleaseGraphicsResources();
210
  }
211
212
213

  this->ValuePassHelper->ReleaseGraphicsResources(win);

214
  if (this->AppleBugPrimIDBuffer)
215
  {
216
    this->AppleBugPrimIDBuffer->ReleaseGraphicsResources();
217
  }
218
  if (this->TimerQuery)
219
  {
Ken Martin's avatar
Ken Martin committed
220
#if GL_ES_VERSION_3_0 != 1
221
    glDeleteQueries(1, &this->TimerQuery);
222
#endif
223
    this->TimerQuery = 0;
224
  }
225
226
  this->VBOBuildString = "";
  this->IBOBuildString = "";
227
  this->Modified();
228
229
}

230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
void vtkOpenGLPolyDataMapper::AddShaderReplacement(
    vtkShader::Type shaderType, // vertex, fragment, etc
    std::string originalValue,
    bool replaceFirst,  // do this replacement before the default
    std::string replacementValue,
    bool replaceAll)
{
  vtkOpenGLPolyDataMapper::ReplacementSpec spec;
  spec.ShaderType = shaderType;
  spec.OriginalValue = originalValue;
  spec.ReplaceFirst = replaceFirst;

  vtkOpenGLPolyDataMapper::ReplacementValue values;
  values.Replacement = replacementValue;
  values.ReplaceAll = replaceAll;

  this->UserShaderReplacements[spec] = values;
}

void vtkOpenGLPolyDataMapper::ClearShaderReplacement(
    vtkShader::Type shaderType, // vertex, fragment, etc
    std::string originalValue,
    bool replaceFirst)
{
  vtkOpenGLPolyDataMapper::ReplacementSpec spec;
  spec.ShaderType = shaderType;
  spec.OriginalValue = originalValue;
  spec.ReplaceFirst = replaceFirst;

  typedef std::map<const vtkOpenGLPolyDataMapper::ReplacementSpec,
Ken Martin's avatar
Ken Martin committed
260
    vtkOpenGLPolyDataMapper::ReplacementValue>::iterator RIter;
261
262
  RIter found = this->UserShaderReplacements.find(spec);
  if (found == this->UserShaderReplacements.end())
263
  {
264
    this->UserShaderReplacements.erase(found);
265
  }
266
267
}

268
//-----------------------------------------------------------------------------
269
270
271
void vtkOpenGLPolyDataMapper::BuildShaders(
    std::map<vtkShader::Type, vtkShader *> shaders,
    vtkRenderer *ren, vtkActor *actor)
272
{
273
  this->GetShaderTemplate(shaders, ren, actor);
274
275
276
277
278
279
280

  typedef std::map<const vtkOpenGLPolyDataMapper::ReplacementSpec,
    vtkOpenGLPolyDataMapper::ReplacementValue>::const_iterator RIter;

  // user specified pre replacements
  for (RIter i = this->UserShaderReplacements.begin();
    i != this->UserShaderReplacements.end(); i++)
281
  {
282
    if (i->first.ReplaceFirst)
283
    {
284
285
286
287
288
289
290
      std::string ssrc = shaders[i->first.ShaderType]->GetSource();
      vtkShaderProgram::Substitute(ssrc,
        i->first.OriginalValue,
        i->second.Replacement,
        i->second.ReplaceAll);
      shaders[i->first.ShaderType]->SetSource(ssrc);
    }
291
  }
292

293
  this->ReplaceShaderValues(shaders, ren, actor);
294
295
296
297

  // user specified post replacements
  for (RIter i = this->UserShaderReplacements.begin();
    i != this->UserShaderReplacements.end(); i++)
298
  {
299
    if (!i->first.ReplaceFirst)
300
    {
301
302
303
304
305
306
307
      std::string ssrc = shaders[i->first.ShaderType]->GetSource();
      vtkShaderProgram::Substitute(ssrc,
        i->first.OriginalValue,
        i->second.Replacement,
        i->second.ReplaceAll);
      shaders[i->first.ShaderType]->SetSource(ssrc);
    }
308
  }
309
310
}

311
//-----------------------------------------------------------------------------
312
313
314
bool vtkOpenGLPolyDataMapper::HaveWideLines(
  vtkRenderer *ren,
  vtkActor *actor)
315
{
316
317
  if (this->GetOpenGLMode(actor->GetProperty()->GetRepresentation(),
      this->LastBoundBO->PrimitiveType) == GL_LINES
318
319
      && actor->GetProperty()->GetLineWidth() > 1.0
      && vtkOpenGLRenderWindow::GetContextSupportsOpenGL32())
320
  {
321
322
323
324
    // we have wide lines, but the OpenGL implementation may
    // actually support them, check the range to see if we
      // really need have to implement our own wide lines
    vtkOpenGLRenderWindow *renWin = vtkOpenGLRenderWindow::SafeDownCast(ren->GetRenderWindow());
Ken Martin's avatar
Ken Martin committed
325
    return actor->GetProperty()->GetRenderLinesAsTubes() || !(renWin &&
326
      renWin->GetMaximumHardwareLineWidth() >= actor->GetProperty()->GetLineWidth());
327
  }
328
329
330
  return false;
}

331
//-----------------------------------------------------------------------------
Bill Lorensen's avatar
Bill Lorensen committed
332
vtkMTimeType vtkOpenGLPolyDataMapper::GetRenderPassStageMTime(vtkActor *actor)
333
334
{
  vtkInformation *info = actor->GetPropertyKeys();
Bill Lorensen's avatar
Bill Lorensen committed
335
  vtkMTimeType renderPassMTime = 0;
336
337
338

  int curRenderPasses = 0;
  if (info && info->Has(vtkOpenGLRenderPass::RenderPasses()))
339
  {
340
    curRenderPasses = info->Length(vtkOpenGLRenderPass::RenderPasses());
341
  }
342
343
344

  int lastRenderPasses = 0;
  if (this->LastRenderPassInfo->Has(vtkOpenGLRenderPass::RenderPasses()))
345
  {
346
347
    lastRenderPasses =
        this->LastRenderPassInfo->Length(vtkOpenGLRenderPass::RenderPasses());
348
  }
349
350
351

  // Determine the last time a render pass changed stages:
  if (curRenderPasses != lastRenderPasses)
352
  {
353
354
355
    // Number of passes changed, definitely need to update.
    // Fake the time to force an update:
    renderPassMTime = VTK_UNSIGNED_LONG_MAX;
356
  }
357
  else
358
  {
359
360
    // Compare the current to the previous render passes:
    for (int i = 0; i < curRenderPasses; ++i)
361
    {
362
363
364
365
366
      vtkObjectBase *curRP = info->Get(vtkOpenGLRenderPass::RenderPasses(), i);
      vtkObjectBase *lastRP =
          this->LastRenderPassInfo->Get(vtkOpenGLRenderPass::RenderPasses(), i);

      if (curRP != lastRP)
367
      {
368
369
370
        // Render passes have changed. Force update:
        renderPassMTime = VTK_UNSIGNED_LONG_MAX;
        break;
371
      }
372
      else
373
      {
374
375
376
377
378
        // Render passes have not changed -- check MTime.
        vtkOpenGLRenderPass *rp = static_cast<vtkOpenGLRenderPass*>(curRP);
        renderPassMTime = std::max(renderPassMTime, rp->GetShaderStageMTime());
      }
    }
379
  }
380
381
382

  // Cache the current set of render passes for next time:
  if (info)
383
  {
384
385
    this->LastRenderPassInfo->CopyEntry(info,
                                        vtkOpenGLRenderPass::RenderPasses());
386
  }
387
  else
388
  {
389
    this->LastRenderPassInfo->Clear();
390
  }
391
392
393
394

  return renderPassMTime;
}

395
396
397
398
399
400
401
402
403
404
//-----------------------------------------------------------------------------
bool vtkOpenGLPolyDataMapper::HaveTextures(vtkActor *actor)
{
  return (this->GetNumberOfTextures(actor) > 0);
}

//-----------------------------------------------------------------------------
unsigned int vtkOpenGLPolyDataMapper::GetNumberOfTextures(vtkActor *actor)
{
  unsigned int res = 0;
405
  if (this->ColorTextureMap)
406
  {
407
    res++;
408
  }
409
  if (actor->GetTexture())
410
  {
411
    res++;
412
  }
413
414
415
416
417
418
419
420
421
422
  res += actor->GetProperty()->GetNumberOfTextures();
  return res;
}

//-----------------------------------------------------------------------------
std::vector<vtkTexture *> vtkOpenGLPolyDataMapper::GetTextures(vtkActor *actor)
{
  std::vector<vtkTexture *> res;

  if (this->ColorTextureMap)
423
  {
424
    res.push_back(this->InternalColorTexture);
425
  }
426
  if (actor->GetTexture())
427
  {
428
    res.push_back(actor->GetTexture());
429
  }
430
  for (int i = 0; i < actor->GetProperty()->GetNumberOfTextures(); i++)
431
  {
432
    res.push_back(actor->GetProperty()->GetTexture(i));
433
  }
434
435
436
437
438
439
440
441
442
443
444
  return res;
}

//-----------------------------------------------------------------------------
bool vtkOpenGLPolyDataMapper::HaveTCoords(vtkPolyData *poly)
{
  return (this->ColorCoordinates ||
          poly->GetPointData()->GetTCoords() ||
          this->ForceTextureCoordinates);
}

445
//-----------------------------------------------------------------------------
446
void vtkOpenGLPolyDataMapper::GetShaderTemplate(
447
    std::map<vtkShader::Type, vtkShader *> shaders,
448
    vtkRenderer *ren, vtkActor *actor)
449
{
450
  if (this->VertexShaderCode && strcmp(this->VertexShaderCode,"") != 0)
451
  {
452
    shaders[vtkShader::Vertex]->SetSource(this->VertexShaderCode);
453
  }
454
  else
455
  {
456
    shaders[vtkShader::Vertex]->SetSource(vtkPolyDataVS);
457
  }
458
459

  if (this->FragmentShaderCode && strcmp(this->FragmentShaderCode,"") != 0)
460
  {
461
    shaders[vtkShader::Fragment]->SetSource(this->FragmentShaderCode);
462
  }
463
  else
464
  {
465
    shaders[vtkShader::Fragment]->SetSource(vtkPolyDataFS);
466
  }
467
468

  if (this->GeometryShaderCode && strcmp(this->GeometryShaderCode,"") != 0)
469
  {
470
    shaders[vtkShader::Geometry]->SetSource(this->GeometryShaderCode);
471
  }
472
  else
473
  {
474
    if (this->HaveWideLines(ren, actor))
475
    {
476
      shaders[vtkShader::Geometry]->SetSource(vtkPolyDataWideLineGS);
477
    }
478
    else
479
    {
480
      shaders[vtkShader::Geometry]->SetSource("");
481
    }
482
  }
483
}
484

David C. Lonie's avatar
David C. Lonie committed
485
486
487
488
489
490
491
492
493
494
495
//------------------------------------------------------------------------------
void vtkOpenGLPolyDataMapper::ReplaceShaderRenderPass(
    std::map<vtkShader::Type, vtkShader *> shaders, vtkRenderer *,
    vtkActor *act)
{
  std::string VSSource = shaders[vtkShader::Vertex]->GetSource();
  std::string GSSource = shaders[vtkShader::Geometry]->GetSource();
  std::string FSSource = shaders[vtkShader::Fragment]->GetSource();

  vtkInformation *info = act->GetPropertyKeys();
  if (info && info->Has(vtkOpenGLRenderPass::RenderPasses()))
496
  {
David C. Lonie's avatar
David C. Lonie committed
497
498
    int numRenderPasses = info->Length(vtkOpenGLRenderPass::RenderPasses());
    for (int i = 0; i < numRenderPasses; ++i)
499
    {
David C. Lonie's avatar
David C. Lonie committed
500
501
502
      vtkObjectBase *rpBase = info->Get(vtkOpenGLRenderPass::RenderPasses(), i);
      vtkOpenGLRenderPass *rp = static_cast<vtkOpenGLRenderPass*>(rpBase);
      if (!rp->ReplaceShaderValues(VSSource, GSSource, FSSource, this, act))
503
      {
David C. Lonie's avatar
David C. Lonie committed
504
505
506
507
        vtkErrorMacro("vtkOpenGLRenderPass::ReplaceShaderValues failed for "
                      << rp->GetClassName());
      }
    }
508
  }
David C. Lonie's avatar
David C. Lonie committed
509
510
511
512
513
514
515

  shaders[vtkShader::Vertex]->SetSource(VSSource);
  shaders[vtkShader::Geometry]->SetSource(GSSource);
  shaders[vtkShader::Fragment]->SetSource(FSSource);
}

//------------------------------------------------------------------------------
516
517
518
void vtkOpenGLPolyDataMapper::ReplaceShaderColor(
  std::map<vtkShader::Type, vtkShader *> shaders,
  vtkRenderer *, vtkActor *actor)
519
{
520
  std::string VSSource = shaders[vtkShader::Vertex]->GetSource();
521
  std::string GSSource = shaders[vtkShader::Geometry]->GetSource();
522
523
  std::string FSSource = shaders[vtkShader::Fragment]->GetSource();

524
  // create the material/color property declarations, and VS implementation
525
526
527
528
529
530
  // these are always defined
  std::string colorDec =
    "uniform float opacityUniform; // the fragment opacity\n"
    "uniform vec3 ambientColorUniform; // intensity weighted color\n"
    "uniform vec3 diffuseColorUniform; // intensity weighted color\n";
  // add some if we have a backface property
531
  if (actor->GetBackfaceProperty() && !this->DrawingEdges)
532
  {
533
534
535
536
    colorDec +=
      "uniform float opacityUniformBF; // the fragment opacity\n"
      "uniform vec3 ambientColorUniformBF; // intensity weighted color\n"
      "uniform vec3 diffuseColorUniformBF; // intensity weighted color\n";
537
  }
538
  // add more for specular
539
  if (this->LastLightComplexity[this->LastBoundBO])
540
  {
541
542
543
544
    colorDec +=
      "uniform vec3 specularColorUniform; // intensity weighted color\n"
      "uniform float specularPowerUniform;\n";
    if (actor->GetBackfaceProperty())
545
    {
546
547
548
549
      colorDec +=
        "uniform vec3 specularColorUniformBF; // intensity weighted color\n"
        "uniform float specularPowerUniformBF;\n";
    }
550
  }
551
  // add scalar vertex coloring
552
  if (this->VBO->ColorComponents != 0 && !this->DrawingEdges)
553
  {
554
    colorDec += "varying vec4 vertexColorVSOutput;\n";
Ken Martin's avatar
Ken Martin committed
555
    vtkShaderProgram::Substitute(VSSource,"//VTK::Color::Dec",
Ken Martin's avatar
Ken Martin committed
556
                        "attribute vec4 scalarColor;\n"
557
                        "varying vec4 vertexColorVSOutput;");
Ken Martin's avatar
Ken Martin committed
558
    vtkShaderProgram::Substitute(VSSource,"//VTK::Color::Impl",
559
560
561
562
563
564
565
566
                        "vertexColorVSOutput =  scalarColor;");
    vtkShaderProgram::Substitute(GSSource,
      "//VTK::Color::Dec",
      "in vec4 vertexColorVSOutput[];\n"
      "out vec4 vertexColorGSOutput;");
    vtkShaderProgram::Substitute(GSSource,
      "//VTK::Color::Impl",
      "vertexColorGSOutput = vertexColorVSOutput[i];");
567
  }
Ken Martin's avatar
Ken Martin committed
568
  if (this->HaveCellScalars && !this->HavePickScalars && !this->DrawingEdges)
569
  {
570
    colorDec += "uniform samplerBuffer textureC;\n";
571
  }
572

Ken Martin's avatar
Ken Martin committed
573
  vtkShaderProgram::Substitute(FSSource,"//VTK::Color::Dec", colorDec);
574
575
576
577
578

  // now handle the more complex fragment shader implementation
  // the following are always defined variables.  We start
  // by assiging a default value from the uniform
  std::string colorImpl =
579
    "  vec3 ambientColor;\n"
580
581
    "  vec3 diffuseColor;\n"
    "  float opacity;\n";
582
583

  if (this->ValuePassHelper->GetRenderingMode() == vtkValuePass::FLOATING_POINT)
584
  {
585
    this->ValuePassHelper->UpdateShaders(VSSource, FSSource, colorImpl);
586
  }
587

588
  if (this->LastLightComplexity[this->LastBoundBO])
589
  {
590
591
592
    colorImpl +=
      "  vec3 specularColor;\n"
      "  float specularPower;\n";
593
  }
594
  if (actor->GetBackfaceProperty() && !this->DrawingEdges)
595
  {
596
    if (this->LastLightComplexity[this->LastBoundBO])
597
    {
598
599
600
601
602
603
604
605
606
607
608
609
610
      colorImpl +=
        "  if (int(gl_FrontFacing) == 0) {\n"
        "    ambientColor = ambientColorUniformBF;\n"
        "    diffuseColor = diffuseColorUniformBF;\n"
        "    specularColor = specularColorUniformBF;\n"
        "    specularPower = specularPowerUniformBF;\n"
        "    opacity = opacityUniformBF; }\n"
        "  else {\n"
        "    ambientColor = ambientColorUniform;\n"
        "    diffuseColor = diffuseColorUniform;\n"
        "    specularColor = specularColorUniform;\n"
        "    specularPower = specularPowerUniform;\n"
        "    opacity = opacityUniform; }\n";
611
    }
612
    else
613
    {
614
615
616
617
618
619
620
621
622
623
      colorImpl +=
        "  if (int(gl_FrontFacing) == 0) {\n"
        "    ambientColor = ambientColorUniformBF;\n"
        "    diffuseColor = diffuseColorUniformBF;\n"
        "    opacity = opacityUniformBF; }\n"
        "  else {\n"
        "    ambientColor = ambientColorUniform;\n"
        "    diffuseColor = diffuseColorUniform;\n"
        "    opacity = opacityUniform; }\n";
    }
624
  }
625
  else
626
  {
627
    colorImpl +=
Ken Martin's avatar
Ken Martin committed
628
629
630
      "  ambientColor = ambientColorUniform;\n"
      "  diffuseColor = diffuseColorUniform;\n"
      "  opacity = opacityUniform;\n";
631
    if (this->LastLightComplexity[this->LastBoundBO])
632
    {
633
      colorImpl +=
Ken Martin's avatar
Ken Martin committed
634
635
        "  specularColor = specularColorUniform;\n"
        "  specularPower = specularPowerUniform;\n";
636
    }
637
  }
638
639

  // now handle scalar coloring
640
  if (this->VBO->ColorComponents != 0 && !this->DrawingEdges)
641
  {
Ken Martin's avatar
Ken Martin committed
642
    if (this->ScalarMaterialMode == VTK_MATERIALMODE_AMBIENT ||
Ken Martin's avatar
Ken Martin committed
643
644
        (this->ScalarMaterialMode == VTK_MATERIALMODE_DEFAULT &&
          actor->GetProperty()->GetAmbient() > actor->GetProperty()->GetDiffuse()))
645
    {
646
647
648
649
      vtkShaderProgram::Substitute(FSSource,"//VTK::Color::Impl",
        colorImpl +
        "  ambientColor = vertexColorVSOutput.rgb;\n"
        "  opacity = opacity*vertexColorVSOutput.a;");
650
    }
Ken Martin's avatar
Ken Martin committed
651
    else if (this->ScalarMaterialMode == VTK_MATERIALMODE_DIFFUSE ||
Ken Martin's avatar
Ken Martin committed
652
653
        (this->ScalarMaterialMode == VTK_MATERIALMODE_DEFAULT &&
          actor->GetProperty()->GetAmbient() <= actor->GetProperty()->GetDiffuse()))
654
    {
Ken Martin's avatar
Ken Martin committed
655
      vtkShaderProgram::Substitute(FSSource,"//VTK::Color::Impl", colorImpl +
656
657
        "  diffuseColor = vertexColorVSOutput.rgb;\n"
        "  opacity = opacity*vertexColorVSOutput.a;");
658
    }
Ken Martin's avatar
Ken Martin committed
659
    else
660
    {
Ken Martin's avatar
Ken Martin committed
661
      vtkShaderProgram::Substitute(FSSource,"//VTK::Color::Impl", colorImpl +
662
663
664
        "  diffuseColor = vertexColorVSOutput.rgb;\n"
        "  ambientColor = vertexColorVSOutput.rgb;\n"
        "  opacity = opacity*vertexColorVSOutput.a;");
Ken Martin's avatar
Ken Martin committed
665
    }
666
  }
Ken Martin's avatar
Ken Martin committed
667
  else
668
  {
Ken Martin's avatar
Ken Martin committed
669
    // are we doing scalar coloring by texture?
670
671
672
    if (this->InterpolateScalarsBeforeMapping &&
        this->ColorCoordinates &&
        !this->DrawingEdges)
673
    {
Ken Martin's avatar
Ken Martin committed
674
675
676
      if (this->ScalarMaterialMode == VTK_MATERIALMODE_AMBIENT ||
          (this->ScalarMaterialMode == VTK_MATERIALMODE_DEFAULT &&
            actor->GetProperty()->GetAmbient() > actor->GetProperty()->GetDiffuse()))
677
      {
Ken Martin's avatar
Ken Martin committed
678
        vtkShaderProgram::Substitute(FSSource,
679
          "//VTK::Color::Impl", colorImpl +
680
          "  vec4 texColor = texture2D(texture_0, tcoordVCVSOutput.st);\n"
681
682
          "  ambientColor = texColor.rgb;\n"
          "  opacity = opacity*texColor.a;");
683
      }
Ken Martin's avatar
Ken Martin committed
684
685
686
      else if (this->ScalarMaterialMode == VTK_MATERIALMODE_DIFFUSE ||
          (this->ScalarMaterialMode == VTK_MATERIALMODE_DEFAULT &&
           actor->GetProperty()->GetAmbient() <= actor->GetProperty()->GetDiffuse()))
687
      {
Ken Martin's avatar
Ken Martin committed
688
        vtkShaderProgram::Substitute(FSSource,
689
          "//VTK::Color::Impl", colorImpl +
690
          "  vec4 texColor = texture2D(texture_0, tcoordVCVSOutput.st);\n"
691
692
          "  diffuseColor = texColor.rgb;\n"
          "  opacity = opacity*texColor.a;");
693
      }
Ken Martin's avatar
Ken Martin committed
694
      else
695
      {
Ken Martin's avatar
Ken Martin committed
696
        vtkShaderProgram::Substitute(FSSource,
697
          "//VTK::Color::Impl", colorImpl +
698
          "vec4 texColor = texture2D(texture_0, tcoordVCVSOutput.st);\n"
699
700
701
          "  ambientColor = texColor.rgb;\n"
          "  diffuseColor = texColor.rgb;\n"
          "  opacity = opacity*texColor.a;");
Ken Martin's avatar
Ken Martin committed
702
      }
703
    }
Ken Martin's avatar
Ken Martin committed
704
    else
705
    {
Ken Martin's avatar
Ken Martin committed
706
      if (this->HaveCellScalars && !this->DrawingEdges)
707
      {
708
709
710
        if (this->ScalarMaterialMode == VTK_MATERIALMODE_AMBIENT ||
            (this->ScalarMaterialMode == VTK_MATERIALMODE_DEFAULT &&
              actor->GetProperty()->GetAmbient() > actor->GetProperty()->GetDiffuse()))
711
        {
Ken Martin's avatar
Ken Martin committed
712
          vtkShaderProgram::Substitute(FSSource,
713
714
715
            "//VTK::Color::Impl", colorImpl +
            "  vec4 texColor = texelFetchBuffer(textureC, gl_PrimitiveID + PrimitiveIDOffset);\n"
            "  ambientColor = texColor.rgb;\n"
716
717
            "  opacity = opacity*texColor.a;"
            );
718
        }
719
720
721
        else if (this->ScalarMaterialMode == VTK_MATERIALMODE_DIFFUSE ||
            (this->ScalarMaterialMode == VTK_MATERIALMODE_DEFAULT &&
             actor->GetProperty()->GetAmbient() <= actor->GetProperty()->GetDiffuse()))
722
        {
Ken Martin's avatar
Ken Martin committed
723
          vtkShaderProgram::Substitute(FSSource,
724
725
726
            "//VTK::Color::Impl", colorImpl +
           "  vec4 texColor = texelFetchBuffer(textureC, gl_PrimitiveID + PrimitiveIDOffset);\n"
            "  diffuseColor = texColor.rgb;\n"
727
            "  opacity = opacity*texColor.a;"
728
            //  "  diffuseColor = vec3((gl_PrimitiveID%256)/255.0,((gl_PrimitiveID/256)%256)/255.0,1.0);\n"
729
            );
730
        }
731
        else
732
        {
Ken Martin's avatar
Ken Martin committed
733
          vtkShaderProgram::Substitute(FSSource,
734
735
736
737
            "//VTK::Color::Impl", colorImpl +
            "vec4 texColor = texelFetchBuffer(textureC, gl_PrimitiveID + PrimitiveIDOffset);\n"
            "  ambientColor = texColor.rgb;\n"
            "  diffuseColor = texColor.rgb;\n"
738
739
            "  opacity = opacity*texColor.a;"
            );
740
        }
Ken Martin's avatar
Ken Martin committed
741
      }
742
      vtkShaderProgram::Substitute(FSSource,"//VTK::Color::Impl", colorImpl);
Ken Martin's avatar
Ken Martin committed
743
    }
744
  }
745
746

  shaders[vtkShader::Vertex]->SetSource(VSSource);
747
  shaders[vtkShader::Geometry]->SetSource(GSSource);
748
  shaders[vtkShader::Fragment]->SetSource(FSSource);
749
750
}

751
752
void vtkOpenGLPolyDataMapper::ReplaceShaderLight(
  std::map<vtkShader::Type, vtkShader *> shaders,
Ken Martin's avatar
Ken Martin committed
753
  vtkRenderer *, vtkActor *actor)
754
{
755
756
  std::string FSSource = shaders[vtkShader::Fragment]->GetSource();

757
  // check for normal rendering
Ken Martin's avatar
Ken Martin committed
758
  vtkInformation *info = actor->GetPropertyKeys();
759
  if (info && info->Has(vtkLightingMapPass::RENDER_NORMALS()))
760
  {
761
762
763
764
765
766
      vtkShaderProgram::Substitute(FSSource,"//VTK::Light::Impl",
        "  vec3 n = (normalVCVSOutput + 1.0) * 0.5;\n"
        "  gl_FragData[0] = vec4(n.x, n.y, n.z, 1.0);"
      );
      shaders[vtkShader::Fragment]->SetSource(FSSource);
      return;
767
  }
768
769

  // check for shadow maps
Ken Martin's avatar
Ken Martin committed
770
  std::string shadowFactor = "";
Ken Martin's avatar
Ken Martin committed
771
  if (info && info->Has(vtkShadowMapPass::ShadowMapPass()))
772
  {
Ken Martin's avatar
Ken Martin committed
773
774
775
    vtkShadowMapPass *smp = vtkShadowMapPass::SafeDownCast(
      info->Get(vtkShadowMapPass::ShadowMapPass()));
    if (smp)
776
    {
Ken Martin's avatar
Ken Martin committed
777
778
779
780
781
      vtkShaderProgram::Substitute(FSSource,"//VTK::Light::Dec",
        smp->GetFragmentDeclaration(), false);
      vtkShaderProgram::Substitute(FSSource,"//VTK::Light::Impl",
        smp->GetFragmentImplementation(), false);
      shadowFactor = "*factors[lightNum]";
Ken Martin's avatar
Ken Martin committed
782
    }
783
  }
Ken Martin's avatar
Ken Martin committed
784

785
786
  // If rendering, set diffuse and specular colors to pure white
  if (info && info->Has(vtkLightingMapPass::RENDER_LUMINANCE()))
787
  {
788
789
790
791
792
793
      vtkShaderProgram::Substitute(FSSource, "//VTK::Light::Impl",
        "  diffuseColor = vec3(1, 1, 1);\n"
        "  specularColor = vec3(1, 1, 1);\n"
        "  //VTK::Light::Impl\n",
        false
      );
794
  }
795

Tim Thirion's avatar
Tim Thirion committed
796
797
  int lastLightComplexity = this->LastLightComplexity[this->LastBoundBO];
  if (info && info->Has(vtkValuePass::RENDER_VALUES()))
798
  {
799
800
    // Although vtkValuePass::FLOATING_POINT does not require this, it is for
    // simplicity left unchanged (only required when using INVERTIBLE_LUT mode).
Tim Thirion's avatar
Tim Thirion committed
801
    lastLightComplexity = 0;
802
  }
Tim Thirion's avatar
Tim Thirion committed
803
804

  switch (lastLightComplexity)
805
  {
Tim Thirion's avatar
Tim Thirion committed
806
    case 0: // no lighting or RENDER_VALUES
807
808
809
810
      vtkShaderProgram::Substitute(FSSource, "//VTK::Light::Impl",
        "  gl_FragData[0] = vec4(ambientColor + diffuseColor, opacity);\n"
        "  //VTK::Light::Impl\n",
        false
811
812
813
814
        );
      break;

    case 1:  // headlight
815
816
      vtkShaderProgram::Substitute(FSSource, "//VTK::Light::Impl",
        "  float df = max(0.0, normalVCVSOutput.z);\n"
817
818
819
        "  float sf = pow(df, specularPower);\n"
        "  vec3 diffuse = df * diffuseColor;\n"
        "  vec3 specular = sf * specularColor;\n"
820
821
822
823
        "  gl_FragData[0] = vec4(ambientColor + diffuse + specular, opacity);\n"
        "  //VTK::Light::Impl\n",
        false
      );
824
      break;