1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4 
5   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
6   All rights reserved.
7   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
8 
9      This software is distributed WITHOUT ANY WARRANTY; without even
10      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11      PURPOSE.  See the above copyright notice for more information.
12 
13 =========================================================================*/
14 #include "vtkOpenGLGlyph3DHelper.h"
15 
16 #include "vtkOpenGLHelper.h"
17 
18 #include "vtkBitArray.h"
19 #include "vtkCamera.h"
20 #include "vtkDataObject.h"
21 #include "vtkHardwareSelector.h"
22 #include "vtkMath.h"
23 #include "vtkMatrix3x3.h"
24 #include "vtkMatrix4x4.h"
25 #include "vtkNew.h"
26 #include "vtkObjectFactory.h"
27 #include "vtkOpenGLActor.h"
28 #include "vtkOpenGLBufferObject.h"
29 #include "vtkOpenGLCamera.h"
30 #include "vtkOpenGLError.h"
31 #include "vtkOpenGLIndexBufferObject.h"
32 #include "vtkOpenGLInstanceCulling.h"
33 #include "vtkOpenGLRenderWindow.h"
34 #include "vtkOpenGLRenderer.h"
35 #include "vtkOpenGLResourceFreeCallback.h"
36 #include "vtkOpenGLShaderCache.h"
37 #include "vtkOpenGLState.h"
38 #include "vtkOpenGLVertexArrayObject.h"
39 #include "vtkOpenGLVertexBufferObject.h"
40 #include "vtkOpenGLVertexBufferObjectGroup.h"
41 #include "vtkPolyData.h"
42 #include "vtkProperty.h"
43 #include "vtkShader.h"
44 #include "vtkShaderProgram.h"
45 #include "vtkTransform.h"
46 #include "vtkTransformFeedback.h"
47 
48 #include "vtkGlyph3DVS.h"
49 
50 #include <algorithm>
51 #include <numeric>
52 
53 //------------------------------------------------------------------------------
54 vtkStandardNewMacro(vtkOpenGLGlyph3DHelper);
55 
56 //------------------------------------------------------------------------------
vtkOpenGLGlyph3DHelper()57 vtkOpenGLGlyph3DHelper::vtkOpenGLGlyph3DHelper()
58 {
59   this->UsingInstancing = false;
60   this->PopulateSelectionSettings = 0;
61 
62   // Shift and Scale are not used in this mapper producing errors when the Shift Scale
63   // feature was enabled by the superclass.
64   // GCMCMatrix could be modified accordingly but Shift and Scale coefficients are
65   // computed with the glyph source and not the point cloud.
66   // Disabling it for now.
67   this->SetVBOShiftScaleMethod(vtkOpenGLVertexBufferObject::DISABLE_SHIFT_SCALE);
68 }
69 
70 //------------------------------------------------------------------------------
71 // Description:
72 // Release any graphics resources that are being consumed by this mapper.
ReleaseGraphicsResources(vtkWindow * window)73 void vtkOpenGLGlyph3DHelper::ReleaseGraphicsResources(vtkWindow* window)
74 {
75   this->InstanceBuffersBuildTime = vtkTimeStamp();
76   this->NormalMatrixBuffer->ReleaseGraphicsResources();
77   this->MatrixBuffer->ReleaseGraphicsResources();
78   this->ColorBuffer->ReleaseGraphicsResources();
79   this->Superclass::ReleaseGraphicsResources(window);
80 }
81 
82 //------------------------------------------------------------------------------
GetShaderTemplate(std::map<vtkShader::Type,vtkShader * > shaders,vtkRenderer * ren,vtkActor * actor)83 void vtkOpenGLGlyph3DHelper::GetShaderTemplate(
84   std::map<vtkShader::Type, vtkShader*> shaders, vtkRenderer* ren, vtkActor* actor)
85 {
86   this->Superclass::GetShaderTemplate(shaders, ren, actor);
87 
88   shaders[vtkShader::Vertex]->SetSource(vtkGlyph3DVS);
89 }
90 
ReplaceShaderPositionVC(std::map<vtkShader::Type,vtkShader * > shaders,vtkRenderer * ren,vtkActor * actor)91 void vtkOpenGLGlyph3DHelper::ReplaceShaderPositionVC(
92   std::map<vtkShader::Type, vtkShader*> shaders, vtkRenderer* ren, vtkActor* actor)
93 {
94   std::string VSSource = shaders[vtkShader::Vertex]->GetSource();
95 
96   if (this->PrimitiveInfo[this->LastBoundBO].LastLightComplexity > 0)
97   {
98     // we use vertex instead of vertexMC
99     vtkShaderProgram::Substitute(VSSource, "//VTK::PositionVC::Impl",
100       "vertexVCVSOutput = MCVCMatrix * vertex;\n"
101       "  gl_Position = MCDCMatrix * vertex;\n");
102   }
103   else
104   {
105     vtkShaderProgram::Substitute(
106       VSSource, "//VTK::PositionVC::Impl", "gl_Position = MCDCMatrix * vertex;\n");
107   }
108 
109   shaders[vtkShader::Vertex]->SetSource(VSSource);
110 
111   this->Superclass::ReplaceShaderPositionVC(shaders, ren, actor);
112 }
113 
ReplaceShaderColor(std::map<vtkShader::Type,vtkShader * > shaders,vtkRenderer * ren,vtkActor * actor)114 void vtkOpenGLGlyph3DHelper::ReplaceShaderColor(
115   std::map<vtkShader::Type, vtkShader*> shaders, vtkRenderer* ren, vtkActor* actor)
116 {
117   std::string VSSource = shaders[vtkShader::Vertex]->GetSource();
118   std::string FSSource = shaders[vtkShader::Fragment]->GetSource();
119   std::string GSSource = shaders[vtkShader::Geometry]->GetSource();
120 
121   // deal with color
122   if (this->UsingInstancing)
123   {
124     vtkShaderProgram::Substitute(VSSource, "//VTK::Color::Dec",
125       "in vec4 glyphColor;\n"
126       "out vec4 vertexColorVSOutput;");
127     vtkShaderProgram::Substitute(GSSource, "//VTK::Color::Dec",
128       "in vec4 vertexColorVSOutput[];\n"
129       "out vec4 vertexColorGSOutput;");
130     vtkShaderProgram::Substitute(
131       GSSource, "//VTK::Color::Impl", "vertexColorGSOutput = vertexColorVSOutput[i];");
132     vtkShaderProgram::Substitute(
133       VSSource, "//VTK::Color::Impl", "vertexColorVSOutput =  glyphColor;");
134     vtkShaderProgram::Substitute(FSSource, "//VTK::Color::Dec",
135       "in vec4 vertexColorVSOutput;\n"
136       "//VTK::Color::Dec",
137       false);
138   }
139   else
140   {
141     vtkShaderProgram::Substitute(VSSource, "//VTK::Color::Dec", "");
142     vtkShaderProgram::Substitute(FSSource, "//VTK::Color::Dec",
143       "uniform vec4 glyphColor;\n"
144       "//VTK::Color::Dec",
145       false);
146     vtkShaderProgram::Substitute(FSSource, "//VTK::Color::Impl",
147       "vec4 vertexColorVSOutput = glyphColor;\n"
148       "//VTK::Color::Impl",
149       false);
150   }
151 
152   // now handle scalar coloring
153   if (!this->DrawingVertices)
154   {
155     vtkShaderProgram::Substitute(FSSource, "//VTK::Color::Impl",
156       "//VTK::Color::Impl\n"
157       "  diffuseColor = diffuseIntensity * vertexColorVSOutput.rgb;\n"
158       "  ambientColor = ambientIntensity * vertexColorVSOutput.rgb;\n"
159       "  opacity = opacity * vertexColorVSOutput.a;");
160   }
161 
162   if (this->UsingInstancing)
163   {
164     vtkShaderProgram::Substitute(VSSource, "//VTK::Glyph::Dec", "in mat4 GCMCMatrix;");
165   }
166   else
167   {
168     vtkShaderProgram::Substitute(VSSource, "//VTK::Glyph::Dec", "uniform mat4 GCMCMatrix;");
169   }
170   vtkShaderProgram::Substitute(
171     VSSource, "//VTK::Glyph::Impl", "vec4 vertex = GCMCMatrix * vertexMC;\n");
172 
173   shaders[vtkShader::Vertex]->SetSource(VSSource);
174   shaders[vtkShader::Fragment]->SetSource(FSSource);
175   shaders[vtkShader::Geometry]->SetSource(GSSource);
176 
177   this->Superclass::ReplaceShaderColor(shaders, ren, actor);
178 }
179 
ReplaceShaderNormal(std::map<vtkShader::Type,vtkShader * > shaders,vtkRenderer * ren,vtkActor * actor)180 void vtkOpenGLGlyph3DHelper::ReplaceShaderNormal(
181   std::map<vtkShader::Type, vtkShader*> shaders, vtkRenderer* ren, vtkActor* actor)
182 {
183   std::string VSSource = shaders[vtkShader::Vertex]->GetSource();
184   std::string FSSource = shaders[vtkShader::Fragment]->GetSource();
185 
186   // new code for normal matrix if we have normals
187   if (this->VBOs->GetNumberOfComponents("normalMC") == 3)
188   {
189     if (this->UsingInstancing)
190     {
191       vtkShaderProgram::Substitute(VSSource, "//VTK::Normal::Dec",
192         "uniform mat3 normalMatrix;\n"
193         "in vec3 normalMC;\n"
194         "in mat3 glyphNormalMatrix;\n"
195         "out vec3 normalVCVSOutput;");
196     }
197     else
198     {
199       vtkShaderProgram::Substitute(VSSource, "//VTK::Normal::Dec",
200         "uniform mat3 normalMatrix;\n"
201         "in vec3 normalMC;\n"
202         "uniform mat3 glyphNormalMatrix;\n"
203         "out vec3 normalVCVSOutput;");
204     }
205     vtkShaderProgram::Substitute(VSSource, "//VTK::Normal::Impl",
206       "normalVCVSOutput = normalMatrix * glyphNormalMatrix * normalMC;");
207   }
208 
209   shaders[vtkShader::Vertex]->SetSource(VSSource);
210   shaders[vtkShader::Fragment]->SetSource(FSSource);
211 
212   this->Superclass::ReplaceShaderNormal(shaders, ren, actor);
213 }
214 
ReplaceShaderClip(std::map<vtkShader::Type,vtkShader * > shaders,vtkRenderer * ren,vtkActor * actor)215 void vtkOpenGLGlyph3DHelper::ReplaceShaderClip(
216   std::map<vtkShader::Type, vtkShader*> shaders, vtkRenderer* ren, vtkActor* actor)
217 {
218   std::string VSSource = shaders[vtkShader::Vertex]->GetSource();
219 
220   // override one part of the clipping code
221   if (this->GetNumberOfClippingPlanes())
222   {
223     // add all the clipping planes
224     int numClipPlanes = this->GetNumberOfClippingPlanes();
225     if (numClipPlanes > 6)
226     {
227       vtkErrorMacro("OpenGL has a limit of 6 clipping planes");
228     }
229 
230     vtkShaderProgram::Substitute(VSSource, "//VTK::Clip::Impl",
231       "for (int planeNum = 0; planeNum < numClipPlanes; planeNum++)\n"
232       "    {\n"
233       "    clipDistancesVSOutput[planeNum] = dot(clipPlanes[planeNum], vertex);\n"
234       "    }\n");
235   }
236 
237   shaders[vtkShader::Vertex]->SetSource(VSSource);
238 
239   this->Superclass::ReplaceShaderClip(shaders, ren, actor);
240 }
241 
ReplaceShaderPicking(std::map<vtkShader::Type,vtkShader * > shaders,vtkRenderer *,vtkActor *)242 void vtkOpenGLGlyph3DHelper::ReplaceShaderPicking(
243   std::map<vtkShader::Type, vtkShader*> shaders, vtkRenderer*, vtkActor*)
244 {
245   std::string FSSource = shaders[vtkShader::Fragment]->GetSource();
246 
247   if (this->LastSelectionState >= vtkHardwareSelector::MIN_KNOWN_PASS)
248   {
249     vtkShaderProgram::Substitute(FSSource, "//VTK::Picking::Dec", "uniform vec3 mapperIndex;");
250     vtkShaderProgram::Substitute(
251       FSSource, "//VTK::Picking::Impl", "  gl_FragData[0] = vec4(mapperIndex,1.0);\n");
252   }
253   shaders[vtkShader::Fragment]->SetSource(FSSource);
254 }
255 
GlyphRender(vtkRenderer * ren,vtkActor * actor,vtkIdType numPts,std::vector<unsigned char> & colors,std::vector<float> & matrices,std::vector<float> & normalMatrices,std::vector<vtkIdType> & pickIds,vtkMTimeType pointMTime,bool culling)256 void vtkOpenGLGlyph3DHelper::GlyphRender(vtkRenderer* ren, vtkActor* actor, vtkIdType numPts,
257   std::vector<unsigned char>& colors, std::vector<float>& matrices,
258   std::vector<float>& normalMatrices, std::vector<vtkIdType>& pickIds, vtkMTimeType pointMTime,
259   bool culling)
260 {
261   this->ResourceCallback->RegisterGraphicsResources(
262     static_cast<vtkOpenGLRenderWindow*>(ren->GetRenderWindow()));
263 
264   this->UsingInstancing = false;
265 
266   vtkHardwareSelector* selector = ren->GetSelector();
267 
268   if (!selector && GLEW_ARB_instanced_arrays)
269   {
270     // if there is no triangle, culling is useless.
271     // GLEW_ARB_gpu_shader5 is needed by the culling shader.
272 #ifndef GL_ES_VERSION_3_0
273     if (this->CurrentInput->GetNumberOfPolys() <= 0 || !GLEW_ARB_gpu_shader5 ||
274       !GLEW_ARB_transform_feedback3)
275     {
276       culling = false;
277     }
278 #else
279     // disable culling on OpenGL ES
280     culling = false;
281 #endif
282 
283     this->GlyphRenderInstances(
284       ren, actor, numPts, colors, matrices, normalMatrices, pointMTime, culling);
285     return;
286   }
287 
288   bool selecting_points =
289     selector && (selector->GetFieldAssociation() == vtkDataObject::FIELD_ASSOCIATION_POINTS);
290 
291   int representation = actor->GetProperty()->GetRepresentation();
292 
293   this->RenderPieceStart(ren, actor);
294 
295   vtkOpenGLRenderWindow* renWin = static_cast<vtkOpenGLRenderWindow*>(ren->GetRenderWindow());
296   vtkOpenGLState* ostate = renWin->GetState();
297 
298   if (selecting_points)
299   {
300     ostate->vtkglPointSize(6.0);
301     representation = GL_POINTS;
302   }
303 
304   bool draw_surface_with_edges =
305     (actor->GetProperty()->GetEdgeVisibility() && representation == VTK_SURFACE) && !selector;
306   int numVerts = this->VBOs->GetNumberOfTuples("vertexMC");
307   for (int i = PrimitiveStart;
308        i < (draw_surface_with_edges ? PrimitiveEnd : PrimitiveTriStrips + 1); i++)
309   {
310     this->DrawingVertices = (i > PrimitiveTriStrips ? true : false);
311     if (this->Primitives[i].IBO->IndexCount)
312     {
313       this->UpdateShaders(this->Primitives[i], ren, actor);
314       GLenum mode = this->GetOpenGLMode(representation, i);
315       this->Primitives[i].IBO->Bind();
316       for (vtkIdType inPtId = 0; inPtId < numPts; inPtId++)
317       {
318         // handle the middle
319         vtkShaderProgram* program = this->Primitives[i].Program;
320 
321         if (!program)
322         {
323           return;
324         }
325 
326         // Apply the extra transform
327         program->SetUniformMatrix4x4("GCMCMatrix", &(matrices[inPtId * 16]));
328 
329         // for lit shaders set normal matrix
330         if (this->PrimitiveInfo[this->LastBoundBO].LastLightComplexity > 0 &&
331           this->VBOs->GetNumberOfComponents("normalMC") == 3 && !this->UsingInstancing)
332         {
333           program->SetUniformMatrix3x3("glyphNormalMatrix", &(normalMatrices[inPtId * 9]));
334         }
335 
336         program->SetUniform4uc("glyphColor", &(colors[inPtId * 4]));
337 
338         if (selector)
339         {
340           if (selector->GetCurrentPass() == vtkHardwareSelector::POINT_ID_LOW24 ||
341             selector->GetCurrentPass() == vtkHardwareSelector::POINT_ID_HIGH24 ||
342             selector->GetCurrentPass() == vtkHardwareSelector::CELL_ID_LOW24 ||
343             selector->GetCurrentPass() == vtkHardwareSelector::CELL_ID_HIGH24)
344           {
345             selector->SetPropColorValue(pickIds[inPtId]);
346           }
347           program->SetUniform3f("mapperIndex", selector->GetPropColorValue());
348         }
349 
350         glDrawRangeElements(mode, 0, static_cast<GLuint>(numVerts - 1),
351           static_cast<GLsizei>(this->Primitives[i].IBO->IndexCount), GL_UNSIGNED_INT, nullptr);
352       }
353       this->Primitives[i].IBO->Release();
354     }
355   }
356   this->RenderPieceFinish(ren, actor);
357 }
358 
359 //------------------------------------------------------------------------------
SetMapperShaderParameters(vtkOpenGLHelper & cellBO,vtkRenderer * ren,vtkActor * actor)360 void vtkOpenGLGlyph3DHelper::SetMapperShaderParameters(
361   vtkOpenGLHelper& cellBO, vtkRenderer* ren, vtkActor* actor)
362 {
363   this->Superclass::SetMapperShaderParameters(cellBO, ren, actor);
364 
365   vtkHardwareSelector* selector = ren->GetSelector();
366   if (selector)
367   {
368     cellBO.Program->SetUniform3f("mapperIndex", selector->GetPropColorValue());
369   }
370 }
371 
GlyphRenderInstances(vtkRenderer * ren,vtkActor * actor,vtkIdType numPts,std::vector<unsigned char> & colors,std::vector<float> & matrices,std::vector<float> & normalMatrices,vtkMTimeType pointMTime,bool culling)372 void vtkOpenGLGlyph3DHelper::GlyphRenderInstances(vtkRenderer* ren, vtkActor* actor,
373   vtkIdType numPts, std::vector<unsigned char>& colors, std::vector<float>& matrices,
374   std::vector<float>& normalMatrices, vtkMTimeType pointMTime, bool culling)
375 {
376   this->UsingInstancing = true;
377   this->RenderPieceStart(ren, actor);
378   int representation = actor->GetProperty()->GetRepresentation();
379 
380   bool withNormals = (this->VBOs->GetNumberOfComponents("normalMC") == 3);
381 
382   // update the VBOs if needed
383   if (pointMTime > this->InstanceBuffersBuildTime.GetMTime())
384   {
385     this->MatrixBuffer->Upload(matrices, vtkOpenGLBufferObject::ArrayBuffer);
386 
387     if (withNormals)
388     {
389       this->NormalMatrixBuffer->Upload(normalMatrices, vtkOpenGLBufferObject::ArrayBuffer);
390     }
391 
392     this->ColorBuffer->Upload(colors, vtkOpenGLBufferObject::ArrayBuffer);
393     this->InstanceBuffersBuildTime.Modified();
394   }
395 
396   bool draw_surface_with_edges =
397     (actor->GetProperty()->GetEdgeVisibility() && representation == VTK_SURFACE);
398   for (int i = PrimitiveStart;
399        i < (draw_surface_with_edges ? PrimitiveEnd : PrimitiveTriStrips + 1); i++)
400   {
401     this->DrawingVertices = (i > PrimitiveTriStrips ? true : false);
402     if (this->Primitives[i].IBO->IndexCount)
403     {
404       GLenum mode = this->GetOpenGLMode(representation, i);
405 
406       // culling
407       if (culling)
408       {
409         this->BuildCullingShaders(ren, actor, numPts, withNormals);
410         if (!this->InstanceCulling->GetHelper().Program)
411         {
412           return;
413         }
414 
415         this->InstanceCulling->RunCullingShaders(
416           numPts, this->MatrixBuffer, this->ColorBuffer, this->NormalMatrixBuffer);
417 
418         // draw each LOD
419 
420         this->UpdateShaders(this->Primitives[i], ren, actor);
421         if (!this->Primitives[i].Program)
422         {
423           return;
424         }
425 
426         size_t stride = (withNormals ? 29 : 20) * sizeof(float);
427 
428         this->Primitives[i].VAO->Bind();
429 
430         for (vtkIdType j = 0; j < this->InstanceCulling->GetNumberOfLOD(); j++)
431         {
432           if (this->InstanceCulling->GetLOD(j).NumberOfInstances == 0)
433             continue;
434 
435           // add VBO of current instance in VAO
436           if (!this->Primitives[i].VAO->AddAttributeArray(this->Primitives[i].Program,
437                 this->InstanceCulling->GetLOD(j).PositionVBO, "vertexMC", 0, 4 * sizeof(float),
438                 VTK_FLOAT, 4, false))
439           {
440             vtkErrorMacro("Error setting 'vertexMC' in shader VAO.");
441           }
442 
443           if (withNormals)
444           {
445             if (!this->Primitives[i].VAO->AddAttributeArray(this->Primitives[i].Program,
446                   this->InstanceCulling->GetLOD(j).NormalVBO, "normalMC", 0, 3 * sizeof(float),
447                   VTK_FLOAT, 3, false))
448             {
449               vtkErrorMacro("Error setting 'normalMC' in shader VAO.");
450             }
451           }
452 
453           // add instances attributes based on transform feedback buffers
454           if (!this->Primitives[i].VAO->AddAttributeArrayWithDivisor(this->Primitives[i].Program,
455                 this->InstanceCulling->GetLODBuffer(j), "glyphColor", 16 * sizeof(float), stride,
456                 VTK_FLOAT, 4, false, 1, false))
457           {
458             vtkErrorMacro("Error setting 'diffuse color' in shader VAO.");
459           }
460 
461           if (!this->Primitives[i].VAO->AddAttributeMatrixWithDivisor(this->Primitives[i].Program,
462                 this->InstanceCulling->GetLODBuffer(j), "GCMCMatrix", 0, stride, VTK_FLOAT, 4,
463                 false, 1, 4 * sizeof(float)))
464           {
465             vtkErrorMacro("Error setting 'GCMCMatrix' in shader VAO.");
466           }
467 
468           if (withNormals)
469           {
470             if (!this->Primitives[i].VAO->AddAttributeMatrixWithDivisor(this->Primitives[i].Program,
471                   this->InstanceCulling->GetLODBuffer(j), "glyphNormalMatrix", 20 * sizeof(float),
472                   stride, VTK_FLOAT, 3, false, 1, 3 * sizeof(float)))
473             {
474               vtkErrorMacro("Error setting 'glyphNormalMatrix' in shader VAO.");
475             }
476           }
477 
478           if (this->InstanceCulling->GetLOD(j).IBO->IndexCount > 0)
479           {
480             this->InstanceCulling->GetLOD(j).IBO->Bind();
481 
482 #ifdef GL_ES_VERSION_3_0
483             glDrawElementsInstanced(mode,
484               static_cast<GLsizei>(this->InstanceCulling->GetLOD(j).IBO->IndexCount),
485               GL_UNSIGNED_INT, nullptr, this->InstanceCulling->GetLOD(j).NumberOfInstances);
486 #else
487             glDrawElementsInstancedARB(mode,
488               static_cast<GLsizei>(this->InstanceCulling->GetLOD(j).IBO->IndexCount),
489               GL_UNSIGNED_INT, nullptr, this->InstanceCulling->GetLOD(j).NumberOfInstances);
490 #endif
491             this->InstanceCulling->GetLOD(j).IBO->Release();
492           }
493           else
494           {
495 #ifdef GL_ES_VERSION_3_0
496             glDrawArraysInstanced(
497               GL_POINTS, 0, 1, this->InstanceCulling->GetLOD(j).NumberOfInstances);
498 #else
499             glDrawArraysInstancedARB(
500               GL_POINTS, 0, 1, this->InstanceCulling->GetLOD(j).NumberOfInstances);
501 #endif
502           }
503         }
504       }
505       else
506       {
507         this->UpdateShaders(this->Primitives[i], ren, actor);
508         if (!this->Primitives[i].Program)
509         {
510           return;
511         }
512 
513         // do the superclass and then reset a couple values
514         if ((this->InstanceBuffersBuildTime > this->InstanceBuffersLoadTime ||
515               this->Primitives[i].ShaderSourceTime > this->InstanceBuffersLoadTime))
516         {
517           this->Primitives[i].VAO->Bind();
518 
519           this->MatrixBuffer->Bind();
520           if (!this->Primitives[i].VAO->AddAttributeMatrixWithDivisor(this->Primitives[i].Program,
521                 this->MatrixBuffer, "GCMCMatrix", 0, 16 * sizeof(float), VTK_FLOAT, 4, false, 1,
522                 4 * sizeof(float)))
523           {
524             vtkErrorMacro("Error setting 'GCMCMatrix' in shader VAO.");
525           }
526           this->MatrixBuffer->Release();
527 
528           if (withNormals && this->Primitives[i].Program->IsAttributeUsed("glyphNormalMatrix"))
529           {
530             this->NormalMatrixBuffer->Bind();
531             if (!this->Primitives[i].VAO->AddAttributeMatrixWithDivisor(this->Primitives[i].Program,
532                   this->NormalMatrixBuffer, "glyphNormalMatrix", 0, 9 * sizeof(float), VTK_FLOAT, 3,
533                   false, 1, 3 * sizeof(float)))
534             {
535               vtkErrorMacro("Error setting 'glyphNormalMatrix' in shader VAO.");
536             }
537             this->NormalMatrixBuffer->Release();
538           }
539 
540           if (this->Primitives[i].Program->IsAttributeUsed("glyphColor"))
541           {
542             this->ColorBuffer->Bind();
543             if (!this->Primitives[i].VAO->AddAttributeArrayWithDivisor(this->Primitives[i].Program,
544                   this->ColorBuffer, "glyphColor", 0, 4 * sizeof(unsigned char), VTK_UNSIGNED_CHAR,
545                   4, true, 1, false))
546             {
547               vtkErrorMacro("Error setting 'diffuse color' in shader VAO.");
548             }
549             this->ColorBuffer->Release();
550           }
551           this->InstanceBuffersLoadTime.Modified();
552         }
553 
554         this->Primitives[i].IBO->Bind();
555 
556 #ifdef GL_ES_VERSION_3_0
557         glDrawElementsInstanced(mode, static_cast<GLsizei>(this->Primitives[i].IBO->IndexCount),
558           GL_UNSIGNED_INT, nullptr, numPts);
559 #else
560         glDrawElementsInstancedARB(mode, static_cast<GLsizei>(this->Primitives[i].IBO->IndexCount),
561           GL_UNSIGNED_INT, nullptr, numPts);
562 #endif
563 
564         this->Primitives[i].IBO->Release();
565       }
566     }
567   }
568 
569   vtkOpenGLCheckErrorMacro("failed after Render");
570   this->RenderPieceFinish(ren, actor);
571 }
572 
573 //------------------------------------------------------------------------------
BuildCullingShaders(vtkRenderer * ren,vtkActor * actor,vtkIdType numPts,bool withNormals)574 void vtkOpenGLGlyph3DHelper::BuildCullingShaders(
575   vtkRenderer* ren, vtkActor* actor, vtkIdType numPts, bool withNormals)
576 {
577   vtkOpenGLRenderWindow* renWin = vtkOpenGLRenderWindow::SafeDownCast(ren->GetRenderWindow());
578 
579   if (!this->InstanceCulling->GetHelper().Program)
580   {
581     this->InstanceCulling->InitLOD(this->CurrentInput);
582 
583     for (auto& lod : this->LODs)
584     {
585       this->InstanceCulling->AddLOD(lod.first, lod.second);
586     }
587   }
588 
589   this->InstanceCulling->BuildCullingShaders(renWin->GetShaderCache(), numPts, withNormals);
590 
591   if (this->InstanceCulling->GetHelper().Program)
592   {
593     this->SetCameraShaderParameters(this->InstanceCulling->GetHelper(), ren, actor);
594 
595     double* bounds = this->CurrentInput->GetBounds();
596     float BBoxSize[4] = { static_cast<float>(bounds[1] - bounds[0]),
597       static_cast<float>(bounds[3] - bounds[2]), static_cast<float>(bounds[5] - bounds[4]), 0.f };
598 
599     this->InstanceCulling->GetHelper().Program->SetUniform4f("BBoxSize", BBoxSize);
600   }
601 }
602 
603 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)604 void vtkOpenGLGlyph3DHelper::PrintSelf(ostream& os, vtkIndent indent)
605 {
606   this->Superclass::PrintSelf(os, indent);
607 }
608 
609 //------------------------------------------------------------------------------
SetLODs(std::vector<std::pair<float,float>> & lods)610 void vtkOpenGLGlyph3DHelper::SetLODs(std::vector<std::pair<float, float>>& lods)
611 {
612   this->LODs = lods;
613 }
614 
615 //------------------------------------------------------------------------------
SetLODColoring(bool val)616 void vtkOpenGLGlyph3DHelper::SetLODColoring(bool val)
617 {
618   this->InstanceCulling->SetColorLOD(val);
619 }
620