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