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
15 #include "vtkOpenGLFluidMapper.h"
16 #include "vtkOpenGLHelper.h"
17
18 #include "vtkCommand.h"
19 #include "vtkExecutive.h"
20 #include "vtkMath.h"
21 #include "vtkMatrix3x3.h"
22 #include "vtkMatrix4x4.h"
23 #include "vtkObjectFactory.h"
24 #include "vtkOpenGLActor.h"
25 #include "vtkOpenGLCamera.h"
26 #include "vtkOpenGLFramebufferObject.h"
27 #include "vtkOpenGLIndexBufferObject.h"
28 #include "vtkOpenGLQuadHelper.h"
29 #include "vtkOpenGLRenderWindow.h"
30 #include "vtkOpenGLRenderer.h"
31 #include "vtkOpenGLShaderCache.h"
32 #include "vtkOpenGLState.h"
33 #include "vtkOpenGLTexture.h"
34 #include "vtkOpenGLVertexArrayObject.h"
35 #include "vtkOpenGLVertexBufferObject.h"
36 #include "vtkOpenGLVertexBufferObjectGroup.h"
37 #include "vtkPBRPrefilterTexture.h"
38 #include "vtkPointData.h"
39 #include "vtkPolyData.h"
40 #include "vtkProperty.h"
41 #include "vtkShaderProgram.h"
42 #include "vtkTextureObject.h"
43 #include "vtkVolumeProperty.h"
44
45 #include "vtkFluidMapperDepthFilterBiGaussFS.h"
46 #include "vtkFluidMapperDepthFilterNarrowRangeFS.h"
47 #include "vtkFluidMapperFS.h"
48 #include "vtkFluidMapperFinalFS.h"
49 #include "vtkFluidMapperGS.h"
50 #include "vtkFluidMapperSurfaceNormalFS.h"
51 #include "vtkFluidMapperThicknessAndVolumeColorFilterFS.h"
52 #include "vtkFluidMapperVS.h"
53
54 #include "vtk_glew.h"
55
56 #include <cassert>
57 #include <sstream>
58
59 //------------------------------------------------------------------------------
60 vtkStandardNewMacro(vtkOpenGLFluidMapper);
61
62 //------------------------------------------------------------------------------
vtkOpenGLFluidMapper()63 vtkOpenGLFluidMapper::vtkOpenGLFluidMapper()
64 : VBOs(vtkOpenGLVertexBufferObjectGroup::New())
65 , TempMatrix4(vtkMatrix4x4::New())
66 {
67 for (int i = 0; i < NumTexBuffers; ++i)
68 {
69 this->TexBuffer[i] = vtkTextureObject::New();
70 }
71 for (int i = 0; i < NumOptionalTexBuffers; ++i)
72 {
73 this->OptionalTexBuffer[i] = vtkTextureObject::New();
74 }
75 this->CamDCVC = vtkMatrix4x4::New();
76 this->CamInvertedNorms = vtkMatrix3x3::New();
77 }
78
79 //------------------------------------------------------------------------------
~vtkOpenGLFluidMapper()80 vtkOpenGLFluidMapper::~vtkOpenGLFluidMapper()
81 {
82 this->TempMatrix4->Delete();
83 this->VBOs->Delete();
84 for (int i = 0; i < NumTexBuffers; ++i)
85 {
86 this->TexBuffer[i]->Delete();
87 }
88 for (int i = 0; i < NumOptionalTexBuffers; ++i)
89 {
90 this->OptionalTexBuffer[i]->Delete();
91 }
92 this->CamDCVC->Delete();
93 this->CamInvertedNorms->Delete();
94 }
95
96 //------------------------------------------------------------------------------
SetInputData(vtkPolyData * input)97 void vtkOpenGLFluidMapper::SetInputData(vtkPolyData* input)
98 {
99 this->SetInputDataInternal(0, input);
100 }
101
102 //------------------------------------------------------------------------------
103 // Specify the input data or filter.
GetInput()104 vtkPolyData* vtkOpenGLFluidMapper::GetInput()
105 {
106 return vtkPolyData::SafeDownCast(this->GetExecutive()->GetInputData(0, 0));
107 }
108
109 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)110 void vtkOpenGLFluidMapper::PrintSelf(ostream& os, vtkIndent indent)
111 {
112 this->Superclass::PrintSelf(os, indent);
113 os << indent << "Particle radius: " << this->ParticleRadius << "\n";
114 }
115
116 //------------------------------------------------------------------------------
UpdateDepthThicknessColorShaders(vtkOpenGLHelper & glHelper,vtkRenderer * renderer,vtkVolume * actor)117 void vtkOpenGLFluidMapper::UpdateDepthThicknessColorShaders(
118 vtkOpenGLHelper& glHelper, vtkRenderer* renderer, vtkVolume* actor)
119 {
120 const auto renderWindow = vtkOpenGLRenderWindow::SafeDownCast(renderer->GetRenderWindow());
121
122 glHelper.VAO->Bind();
123
124 // Has something changed that would require us to recreate the shader?
125 if (!glHelper.Program)
126 {
127 // Build the shader source code
128 std::map<vtkShader::Type, vtkShader*> shaders;
129
130 vtkShader* vertexShader = vtkShader::New();
131 vertexShader->SetType(vtkShader::Vertex);
132 vertexShader->SetSource(vtkFluidMapperVS);
133 shaders[vtkShader::Vertex] = vertexShader;
134
135 vtkShader* geomShader = vtkShader::New();
136 geomShader->SetType(vtkShader::Geometry);
137 geomShader->SetSource(vtkFluidMapperGS);
138 shaders[vtkShader::Geometry] = geomShader;
139
140 vtkShader* fragmentShader = vtkShader::New();
141 fragmentShader->SetType(vtkShader::Fragment);
142 fragmentShader->SetSource(vtkFluidMapperFS);
143 shaders[vtkShader::Fragment] = fragmentShader;
144
145 // Compile and bind the program if needed
146 vtkShaderProgram* newProgram = renderWindow->GetShaderCache()->ReadyShaderProgram(shaders);
147
148 // Done with you, now you're thrown away
149 fragmentShader->Delete();
150 geomShader->Delete();
151 vertexShader->Delete();
152
153 // If the shader changed, reinitialize the VAO
154 if (newProgram != glHelper.Program)
155 {
156 glHelper.Program = newProgram;
157 // reset the VAO as the shader has changed
158 glHelper.VAO->ReleaseGraphicsResources();
159 }
160 glHelper.ShaderSourceTime.Modified();
161 }
162 else
163 {
164 renderWindow->GetShaderCache()->ReadyShaderProgram(glHelper.Program);
165 }
166
167 if (glHelper.Program)
168 {
169 this->SetDepthThicknessColorShaderParameters(glHelper, renderer, actor);
170
171 // Allow the program to set what it wants
172 this->InvokeEvent(vtkCommand::UpdateShaderEvent, glHelper.Program);
173 }
174 }
175
176 //------------------------------------------------------------------------------
SetDepthThicknessColorShaderParameters(vtkOpenGLHelper & glHelper,vtkRenderer * ren,vtkVolume * actor)177 void vtkOpenGLFluidMapper::SetDepthThicknessColorShaderParameters(
178 vtkOpenGLHelper& glHelper, vtkRenderer* ren, vtkVolume* actor)
179 {
180 if (glHelper.IBO->IndexCount &&
181 (this->VBOs->GetMTime() > glHelper.AttributeUpdateTime ||
182 glHelper.ShaderSourceTime > glHelper.AttributeUpdateTime))
183 {
184 glHelper.VAO->Bind();
185 this->VBOs->AddAllAttributesToVAO(glHelper.Program, glHelper.VAO);
186 glHelper.AttributeUpdateTime.Modified();
187 }
188
189 const auto program = glHelper.Program;
190
191 program->SetUniformi("outputEyeZ", this->InDepthPass);
192 if (!this->InDepthPass)
193 {
194 // based on clipping range
195 program->SetUniformf("minThickness", ren->GetActiveCamera()->GetClippingRange()[1] * 1.0e-9);
196 }
197 if (this->HasVertexColor)
198 {
199 program->SetUniformi("hasVertexColor", this->HasVertexColor);
200 }
201
202 // Set texture and particle radius
203 program->SetUniformi("opaqueZTexture", this->TexBuffer[OpaqueZ]->GetTextureUnit());
204 program->SetUniformf("particleRadius", this->ParticleRadius);
205
206 // Set camera
207 if (program->IsUniformUsed("VCDCMatrix"))
208 {
209 program->SetUniformMatrix("VCDCMatrix", this->CamVCDC);
210 }
211
212 if (program->IsUniformUsed("MCVCMatrix"))
213 {
214 if (!actor->GetIsIdentity())
215 {
216 vtkMatrix4x4* mcwc;
217 vtkMatrix3x3* anorms;
218 ((vtkOpenGLActor*)actor)->GetKeyMatrices(mcwc, anorms);
219 vtkMatrix4x4::Multiply4x4(mcwc, this->CamWCVC, this->TempMatrix4);
220 program->SetUniformMatrix("MCVCMatrix", this->TempMatrix4);
221 }
222 else
223 {
224 program->SetUniformMatrix("MCVCMatrix", this->CamWCVC);
225 }
226 }
227 if (program->IsUniformUsed("cameraParallel"))
228 {
229 glHelper.Program->SetUniformi("cameraParallel", this->CamParallelProjection);
230 }
231 }
232
SetupBuffers(vtkOpenGLRenderWindow * const renderWindow)233 void vtkOpenGLFluidMapper::SetupBuffers(vtkOpenGLRenderWindow* const renderWindow)
234 {
235 // create textures we need if not done already
236 if (this->TexBuffer[0]->GetHandle() == 0)
237 {
238 for (int i = 0; i < NumTexBuffers; ++i)
239 {
240 this->TexBuffer[i]->SetContext(renderWindow);
241 switch (i)
242 {
243 case OpaqueZ:
244 case FluidZ:
245 this->TexBuffer[i]->AllocateDepth(static_cast<unsigned int>(this->ViewportWidth),
246 static_cast<unsigned int>(this->ViewportHeight), vtkTextureObject::Float32);
247 break;
248 case FluidEyeZ:
249 case SmoothedFluidEyeZ:
250 case FluidThickness:
251 case SmoothedFluidThickness:
252 this->TexBuffer[i]->SetInternalFormat(GL_R32F);
253 this->TexBuffer[i]->SetFormat(GL_RED);
254 this->TexBuffer[i]->Allocate2D(static_cast<unsigned int>(this->ViewportWidth),
255 static_cast<unsigned int>(this->ViewportHeight), 1, VTK_FLOAT);
256 break;
257 case FluidNormal:
258 this->TexBuffer[i]->Allocate2D(static_cast<unsigned int>(this->ViewportWidth),
259 static_cast<unsigned int>(this->ViewportHeight), 3, VTK_FLOAT);
260 break;
261 case OpaqueRGBA:
262 this->TexBuffer[i]->Allocate2D(static_cast<unsigned int>(this->ViewportWidth),
263 static_cast<unsigned int>(this->ViewportHeight), 4, VTK_UNSIGNED_CHAR);
264 break;
265 default:;
266 }
267
268 this->TexBuffer[i]->SetMinificationFilter(vtkTextureObject::Nearest);
269 this->TexBuffer[i]->SetMagnificationFilter(vtkTextureObject::Nearest);
270 this->TexBuffer[i]->SetWrapS(vtkTextureObject::ClampToEdge);
271 this->TexBuffer[i]->SetWrapT(vtkTextureObject::ClampToEdge);
272 }
273 }
274 else
275 {
276 // make sure we handle size changes
277 for (int i = 0; i < NumTexBuffers; ++i)
278 {
279 this->TexBuffer[i]->Resize(static_cast<unsigned int>(this->ViewportWidth),
280 static_cast<unsigned int>(this->ViewportHeight));
281 }
282 }
283
284 // Allocate additional 2 texture bufferes for color data
285 if (this->HasVertexColor)
286 {
287 if (this->OptionalTexBuffer[0]->GetHandle() == 0)
288 {
289 for (int i = 0; i < NumOptionalTexBuffers; ++i)
290 {
291 this->OptionalTexBuffer[i]->SetContext(renderWindow);
292 this->OptionalTexBuffer[i]->Allocate2D(static_cast<unsigned int>(this->ViewportWidth),
293 static_cast<unsigned int>(this->ViewportHeight), 3, VTK_FLOAT);
294 this->OptionalTexBuffer[i]->SetMinificationFilter(vtkTextureObject::Nearest);
295 this->OptionalTexBuffer[i]->SetMagnificationFilter(vtkTextureObject::Nearest);
296 this->OptionalTexBuffer[i]->SetWrapS(vtkTextureObject::ClampToEdge);
297 this->OptionalTexBuffer[i]->SetWrapT(vtkTextureObject::ClampToEdge);
298 }
299 }
300 else
301 {
302 // make sure we handle size changes
303 for (int i = 0; i < NumOptionalTexBuffers; ++i)
304 {
305 this->OptionalTexBuffer[i]->Resize(static_cast<unsigned int>(this->ViewportWidth),
306 static_cast<unsigned int>(this->ViewportHeight));
307 }
308 }
309 }
310
311 // copy the opaque buffers into textures
312 this->TexBuffer[OpaqueZ]->CopyFromFrameBuffer(this->ViewportX, this->ViewportY, this->ViewportX,
313 this->ViewportY, this->ViewportWidth, this->ViewportHeight);
314 this->TexBuffer[OpaqueRGBA]->CopyFromFrameBuffer(this->ViewportX, this->ViewportY,
315 this->ViewportX, this->ViewportY, this->ViewportWidth, this->ViewportHeight);
316
317 if (!this->FBFluidEyeZ)
318 {
319 this->FBFluidEyeZ = vtkOpenGLFramebufferObject::New();
320 this->FBFluidEyeZ->SetContext(renderWindow);
321 this->FBFluidEyeZ->AddDepthAttachment(this->TexBuffer[FluidZ]); // Must have a depth buffer
322 }
323
324 if (!this->FBThickness)
325 {
326 this->FBThickness = vtkOpenGLFramebufferObject::New();
327 this->FBThickness->SetContext(renderWindow);
328 this->FBThickness->AddDepthAttachment(this->TexBuffer[FluidZ]); // Must have a depth buffer
329 }
330
331 if (!this->FBFilterThickness)
332 {
333 this->FBFilterThickness = vtkOpenGLFramebufferObject::New();
334 this->FBFilterThickness->SetContext(renderWindow);
335 // Color attachment will be dynamically added later
336 }
337
338 if (!this->FBFilterDepth)
339 {
340 this->FBFilterDepth = vtkOpenGLFramebufferObject::New();
341 this->FBFilterDepth->SetContext(renderWindow);
342 // Color attachment will be dynamically added later
343 }
344
345 if (!this->FBCompNormal)
346 {
347 this->FBCompNormal = vtkOpenGLFramebufferObject::New();
348 this->FBCompNormal->SetContext(renderWindow);
349 this->FBCompNormal->AddColorAttachment(0, this->TexBuffer[FluidNormal]);
350 }
351 }
352
353 //------------------------------------------------------------------------------
Render(vtkRenderer * renderer,vtkVolume * vol)354 void vtkOpenGLFluidMapper::Render(vtkRenderer* renderer, vtkVolume* vol)
355 {
356 // make sure we have data
357 vtkPolyData* input = vtkPolyData::SafeDownCast(GetInputDataObject(0, 0));
358 if (input == nullptr || input->GetPoints() == nullptr)
359 {
360 return;
361 }
362
363 // check to see if we are using vertex coloring
364 int cellFlag = 0;
365 vtkDataArray* scalars = vtkOpenGLFluidMapper::GetScalars(
366 input, this->ScalarMode, this->ArrayAccessMode, this->ArrayId, this->ArrayName, cellFlag);
367
368 this->HasVertexColor = false;
369 if (scalars && cellFlag == 0 && scalars->GetNumberOfComponents() == 3 && this->ScalarVisibility)
370 {
371 this->HasVertexColor = true;
372 }
373
374 // Get the viewport dimensions
375 renderer->GetTiledSizeAndOrigin(
376 &this->ViewportWidth, &this->ViewportHeight, &this->ViewportX, &this->ViewportY);
377
378 // Get the camera parameters
379 const auto cam = static_cast<vtkOpenGLCamera*>(renderer->GetActiveCamera());
380 vtkMatrix3x3* tmpNormMat;
381 cam->GetKeyMatrices(renderer, this->CamWCVC, tmpNormMat, this->CamVCDC, this->CamWCDC);
382 this->CamDCVC->DeepCopy(this->CamVCDC);
383 this->CamDCVC->Invert();
384 this->CamInvertedNorms->DeepCopy(tmpNormMat);
385 this->CamInvertedNorms->Invert();
386 this->CamParallelProjection = cam->GetParallelProjection();
387
388 // Prepare the texture and frame buffers
389 const auto renderWindow = vtkOpenGLRenderWindow::SafeDownCast(renderer->GetRenderWindow());
390 this->SetupBuffers(renderWindow);
391
392 const auto glState = renderWindow->GetState();
393 glState->vtkglViewport(0, 0, this->ViewportWidth, this->ViewportHeight);
394 bool saveScissorTestState = glState->GetEnumState(GL_SCISSOR_TEST);
395 #ifdef GL_MULTISAMPLE
396 glState->vtkglDisable(GL_MULTISAMPLE);
397 #endif
398
399 double* crange = cam->GetClippingRange();
400
401 // Generate depth
402 {
403 // Attach texture every time, since it will be swapped out during smoothing
404 this->FBFluidEyeZ->SetContext(renderWindow);
405 glState->PushFramebufferBindings();
406 this->FBFluidEyeZ->Bind();
407 this->FBFluidEyeZ->AddColorAttachment(0U, this->TexBuffer[FluidEyeZ]);
408 this->FBFluidEyeZ->ActivateDrawBuffers(1);
409 this->FBFluidEyeZ->CheckFrameBufferStatus(GL_FRAMEBUFFER);
410 glState->vtkglDisable(GL_SCISSOR_TEST);
411 glState->vtkglClearDepth(1.0);
412 glState->vtkglColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE);
413 // Set a clear color value to be slightly past the far clipping plane
414 glState->vtkglClearColor(-1.1 * crange[1], 0.0, 0.0, 0.0);
415 glState->vtkglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
416
417 // Render the spheres to get the eye coordinate z values
418 this->TexBuffer[OpaqueZ]->Activate();
419 glState->vtkglDepthMask(GL_TRUE);
420 glState->vtkglEnable(GL_DEPTH_TEST);
421 glState->vtkglDepthFunc(GL_LEQUAL);
422 this->InDepthPass = true;
423 this->RenderParticles(renderer, vol);
424 this->InDepthPass = false;
425 this->TexBuffer[OpaqueZ]->Deactivate();
426 this->FBFluidEyeZ->DeactivateDrawBuffers();
427 this->FBFluidEyeZ->RemoveColorAttachment(0U);
428 glState->PopFramebufferBindings();
429 }
430
431 // Generate thickness and color (if applicable)
432 {
433 // Attache texture every time, since it will be swapped out during smoothing
434 this->FBThickness->SetContext(renderWindow);
435 glState->PushFramebufferBindings();
436 this->FBThickness->Bind();
437 this->FBThickness->AddColorAttachment(0U, this->TexBuffer[FluidThickness]);
438 this->FBThickness->ActivateDrawBuffers(1);
439 this->FBThickness->CheckFrameBufferStatus(GL_FRAMEBUFFER);
440 if (this->HasVertexColor)
441 {
442 this->FBThickness->AddColorAttachment(1, this->OptionalTexBuffer[Color]);
443 this->FBThickness->ActivateDrawBuffers(2);
444 this->FBThickness->CheckFrameBufferStatus(GL_FRAMEBUFFER);
445 }
446 glState->vtkglDisable(GL_SCISSOR_TEST);
447 glState->vtkglClearDepth(1.0);
448 glState->vtkglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
449 glState->vtkglClearColor(0.0, 0.0, 0.0, 0.0);
450 glState->vtkglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
451
452 vtkOpenGLState::ScopedglBlendFuncSeparate bf(glState);
453 glState->vtkglBlendFuncSeparate(GL_ONE, GL_ONE, GL_ONE, GL_ONE);
454
455 this->TexBuffer[OpaqueZ]->Activate();
456 glState->vtkglDepthMask(GL_FALSE);
457 glState->vtkglDisable(GL_DEPTH_TEST);
458 glState->vtkglDepthFunc(GL_ALWAYS);
459 this->RenderParticles(renderer, vol);
460 this->TexBuffer[OpaqueZ]->Deactivate();
461 this->FBThickness->DeactivateDrawBuffers();
462 if (this->HasVertexColor)
463 {
464 this->FBThickness->RemoveColorAttachment(1U);
465 }
466 this->FBThickness->RemoveColorAttachment(0U);
467 glState->PopFramebufferBindings();
468 }
469
470 // Filter fluid thickness and color (if applicable)
471 if (true)
472 {
473 if (!this->QuadThicknessFilter)
474 {
475 this->QuadThicknessFilter = new vtkOpenGLQuadHelper(
476 renderWindow, nullptr, vtkFluidMapperThicknessAndVolumeColorFilterFS, "");
477 }
478 else
479 {
480 renderWindow->GetShaderCache()->ReadyShaderProgram(this->QuadThicknessFilter->Program);
481 }
482 const auto program = this->QuadThicknessFilter->Program;
483 assert(program);
484
485 // Attache texture every time, since it will be swapped out during smoothing
486 this->FBFilterThickness->SetContext(renderWindow);
487 glState->PushFramebufferBindings();
488
489 for (uint32_t iter = 0; iter < this->ThicknessAndVolumeColorFilterIterations; ++iter)
490 {
491 this->FBFilterThickness->Bind();
492 this->FBFilterThickness->AddColorAttachment(0U, this->TexBuffer[SmoothedFluidThickness]);
493 this->FBFilterThickness->ActivateDrawBuffers(1);
494 this->FBFilterThickness->CheckFrameBufferStatus(GL_FRAMEBUFFER);
495 glState->vtkglClearDepth(1.0);
496 glState->vtkglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
497 glState->vtkglClearColor(0.0, 0.0, 0.0, 0.0);
498 glState->vtkglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
499 if (this->HasVertexColor)
500 {
501 this->FBFilterThickness->AddColorAttachment(1, this->OptionalTexBuffer[SmoothedColor]);
502 this->FBFilterThickness->ActivateDrawBuffers(2);
503 this->OptionalTexBuffer[Color]->Activate();
504 program->SetUniformi("hasVertexColor", this->HasVertexColor);
505 program->SetUniformi("fluidColorTexture", this->OptionalTexBuffer[Color]->GetTextureUnit());
506 }
507
508 this->TexBuffer[FluidThickness]->Activate();
509 program->SetUniformi(
510 "fluidThicknessTexture", this->TexBuffer[FluidThickness]->GetTextureUnit());
511
512 program->SetUniformi("viewportHeight", this->ViewportHeight);
513 program->SetUniformi("viewportWidth", this->ViewportWidth);
514 program->SetUniformi(
515 "filterRadius", static_cast<int>(this->ThicknessAndVolumeColorFilterRadius));
516
517 this->QuadThicknessFilter->Render();
518 this->TexBuffer[FluidThickness]->Deactivate();
519 this->FBFilterThickness->DeactivateDrawBuffers();
520 this->FBFilterThickness->RemoveColorAttachment(0U);
521
522 std::swap(this->TexBuffer[FluidThickness], this->TexBuffer[SmoothedFluidThickness]);
523 if (this->HasVertexColor)
524 {
525 this->OptionalTexBuffer[Color]->Deactivate();
526 std::swap(this->OptionalTexBuffer[Color], this->OptionalTexBuffer[SmoothedColor]);
527 }
528 }
529 glState->PopFramebufferBindings();
530 }
531
532 if (true)
533 {
534 // Filter depth surface
535 if (DisplayMode != UnfilteredOpaqueSurface && DisplayMode != UnfilteredSurfaceNormal)
536 {
537 if (!this->QuadFluidDepthFilter[SurfaceFilterMethod])
538 {
539 switch (this->SurfaceFilterMethod)
540 {
541 case BilateralGaussian:
542 this->QuadFluidDepthFilter[SurfaceFilterMethod] = new vtkOpenGLQuadHelper(
543 renderWindow, nullptr, vtkFluidMapperDepthFilterBiGaussFS, "");
544 break;
545 case NarrowRange:
546 this->QuadFluidDepthFilter[SurfaceFilterMethod] = new vtkOpenGLQuadHelper(
547 renderWindow, nullptr, vtkFluidMapperDepthFilterNarrowRangeFS, "");
548 break;
549 // New filter method is added here
550 default:
551 vtkErrorMacro("Invalid filter method");
552 }
553 }
554 else
555 {
556 renderWindow->GetShaderCache()->ReadyShaderProgram(
557 this->QuadFluidDepthFilter[SurfaceFilterMethod]->Program);
558 }
559
560 const auto program = this->QuadFluidDepthFilter[SurfaceFilterMethod]->Program;
561 assert(program);
562 this->FBFilterDepth->SetContext(renderWindow);
563 glState->PushFramebufferBindings();
564
565 program->SetUniformi("viewportHeight", this->ViewportHeight);
566 program->SetUniformi("viewportWidth", this->ViewportWidth);
567 program->SetUniformi("filterRadius", static_cast<int>(this->SurfaceFilterRadius));
568 program->SetUniformf("particleRadius", this->ParticleRadius);
569 program->SetUniformf("farZValue", -crange[1]);
570
571 for (uint32_t iter = 0; iter < this->SurfaceFilterIterations; ++iter)
572 {
573 this->FBFilterDepth->Bind();
574 this->FBFilterDepth->AddColorAttachment(
575 0U, this->TexBuffer[SmoothedFluidEyeZ]); // Replace color attachement
576 this->FBFilterDepth->ActivateDrawBuffers(1);
577 this->FBFilterDepth->CheckFrameBufferStatus(GL_FRAMEBUFFER);
578 glState->vtkglClearDepth(1.0);
579 glState->vtkglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
580 glState->vtkglClearColor(0.0, 0.0, 0.0, 0.0);
581 glState->vtkglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
582
583 switch (SurfaceFilterMethod)
584 {
585 case BilateralGaussian:
586 program->SetUniformf("sigmaDepth", this->BiGaussFilterSigmaDepth);
587 break;
588 case NarrowRange:
589 program->SetUniformf("lambda", this->NRFilterLambda);
590 program->SetUniformf("mu", this->NRFilterMu);
591 break;
592 // New filter method is added here
593 default:
594 vtkErrorMacro("Invalid filter method");
595 }
596
597 glState->vtkglEnable(GL_DEPTH_TEST);
598 this->TexBuffer[FluidEyeZ]->Activate();
599 program->SetUniformi("fluidZTexture", this->TexBuffer[FluidEyeZ]->GetTextureUnit());
600
601 this->QuadFluidDepthFilter[SurfaceFilterMethod]->Render();
602 this->TexBuffer[FluidEyeZ]->Deactivate();
603 this->FBFilterDepth->DeactivateDrawBuffers();
604 this->FBFilterDepth->RemoveColorAttachment(0);
605
606 // Swap the filtered buffers
607 std::swap(this->TexBuffer[FluidEyeZ], this->TexBuffer[SmoothedFluidEyeZ]);
608 }
609
610 glState->PopFramebufferBindings();
611 }
612 }
613
614 // Compute normal for the filtered depth surface
615 if (true)
616 {
617 if (!this->QuadFluidNormal)
618 {
619 this->QuadFluidNormal =
620 new vtkOpenGLQuadHelper(renderWindow, nullptr, vtkFluidMapperSurfaceNormalFS, "");
621 }
622 else
623 {
624 renderWindow->GetShaderCache()->ReadyShaderProgram(this->QuadFluidNormal->Program);
625 }
626
627 const auto program = this->QuadFluidNormal->Program;
628 assert(program);
629
630 this->FBCompNormal->SetContext(renderWindow);
631 glState->PushFramebufferBindings();
632 this->FBCompNormal->Bind();
633 this->FBCompNormal->AddColorAttachment(0, this->TexBuffer[FluidNormal]);
634 this->FBCompNormal->ActivateDrawBuffers(1);
635 this->FBCompNormal->CheckFrameBufferStatus(GL_FRAMEBUFFER);
636
637 this->TexBuffer[FluidEyeZ]->Activate();
638 program->SetUniformi("fluidZTexture", this->TexBuffer[FluidEyeZ]->GetTextureUnit());
639
640 program->SetUniformi("viewportHeight", this->ViewportHeight);
641 program->SetUniformi("viewportWidth", this->ViewportWidth);
642 program->SetUniformMatrix("DCVCMatrix", this->CamDCVC);
643 program->SetUniformMatrix("VCDCMatrix", this->CamVCDC);
644
645 glState->vtkglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
646 glState->vtkglDepthMask(GL_FALSE);
647 glState->vtkglDisable(GL_DEPTH_TEST);
648 glState->vtkglDepthFunc(GL_ALWAYS);
649 glState->vtkglClearColor(0.0, 0.0, 0.0, 0.0);
650 glState->vtkglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
651
652 this->QuadFluidNormal->Render();
653 this->TexBuffer[FluidEyeZ]->Deactivate();
654 this->FBCompNormal->DeactivateDrawBuffers();
655 glState->PopFramebufferBindings();
656 }
657
658 vtkOpenGLRenderer* oren = static_cast<vtkOpenGLRenderer*>(renderer);
659
660 // Restore the original viewport properties
661 glState->vtkglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
662 glState->vtkglViewport(
663 this->ViewportX, this->ViewportY, this->ViewportWidth, this->ViewportHeight);
664 saveScissorTestState ? glState->vtkglEnable(GL_SCISSOR_TEST)
665 : glState->vtkglDisable(GL_SCISSOR_TEST);
666
667 {
668 bool useIBL = oren->GetUseImageBasedLighting() && oren->GetEnvironmentTexture();
669
670 // Final blend, render everything
671 if (!this->QuadFinalBlend)
672 {
673 std::ostringstream toString;
674
675 // todo this needs to be done when the lighting code changes
676 // if the light complexity changed then update the shader code
677 std::string fssource = vtkFluidMapperFinalFS;
678 vtkShaderProgram::Substitute(fssource, "//VTK::Light::Dec", oren->GetLightingUniforms());
679 switch (oren->GetLightingComplexity())
680 {
681 // no lighting
682 case 0:
683 vtkShaderProgram::Substitute(fssource, "//VTK::Light::Impl",
684 " accumulatedLightSpecularColor = vec3(1.0,1.0,1.0);", false);
685 break;
686
687 // headlight
688 case 1:
689 vtkShaderProgram::Substitute(fssource, "//VTK::Light::Impl",
690 " float df = max(0.0,N.z);\n"
691 " float sf = pow(df, fluidShininess);\n"
692 " accumulatedLightDiffuseColor = df * lightColor0;\n"
693 " accumulatedLightSpecularColor = sf * lightColor0;\n"
694 " //VTK::Light::Impl\n",
695 false);
696 break;
697 case 2:
698 toString << " float df;\n"
699 " float sf;\n";
700 for (int i = 0; i < oren->GetLightingCount(); ++i)
701 {
702 toString << " df = max(0.0, dot(N, -lightDirectionVC" << i
703 << "));\n"
704 " accumulatedLightDiffuseColor += (df * lightColor"
705 << i << ");\n"
706 << " sf = sign(df)*pow(max(0.0, dot( reflect(lightDirectionVC" << i
707 << " , N), normalize(-position))), fluidShininess);\n"
708 " accumulatedLightSpecularColor += (sf * lightColor"
709 << i << ");\n";
710 }
711 vtkShaderProgram::Substitute(fssource, "//VTK::Light::Impl", toString.str(), false);
712 break;
713 case 3:
714 toString << " vec3 vertLightDirectionVC;\n"
715 " float attenuation;\n"
716 " float df;\n"
717 " float sf;\n";
718 for (int i = 0; i < oren->GetLightingCount(); ++i)
719 {
720 toString << " attenuation = 1.0;\n"
721 " if (lightPositional"
722 << i
723 << " == 0) {\n"
724 " vertLightDirectionVC = lightDirectionVC"
725 << i
726 << "; }\n"
727 " else {\n"
728 " vertLightDirectionVC = position - lightPositionVC"
729 << i
730 << ";\n"
731 " float distanceVC = length(vertLightDirectionVC);\n"
732 " vertLightDirectionVC = "
733 "normalize(vertLightDirectionVC);\n"
734 " attenuation = 1.0 /\n"
735 " (lightAttenuation"
736 << i
737 << ".x\n"
738 " + lightAttenuation"
739 << i
740 << ".y * distanceVC\n"
741 " + lightAttenuation"
742 << i
743 << ".z * distanceVC * distanceVC);\n"
744 " // per OpenGL standard cone angle is 90 or less for a "
745 "spot light\n"
746 " if (lightConeAngle"
747 << i
748 << " <= 90.0) {\n"
749 " float coneDot = dot(vertLightDirectionVC, "
750 "lightDirectionVC"
751 << i
752 << ");\n"
753 " // if inside the cone\n"
754 " if (coneDot >= cos(radians(lightConeAngle"
755 << i
756 << "))) {\n"
757 " attenuation = attenuation * pow(coneDot, "
758 "lightExponent"
759 << i
760 << "); }\n"
761 " else {\n"
762 " attenuation = 0.0; }\n"
763 " }\n"
764 " }\n"
765 << " df = max(0.0,attenuation*dot(N, "
766 "-vertLightDirectionVC));\n"
767 " accumulatedLightDiffuseColor += (df * lightColor"
768 << i << ");\n"
769 << " sf = sign(df)*attenuation*pow( max(0.0, dot( "
770 "reflect(vertLightDirectionVC, N), normalize(-position))), "
771 "fluidShininess);\n"
772 " accumulatedLightSpecularColor += (sf * lightColor"
773 << i << ");\n";
774 }
775
776 vtkShaderProgram::Substitute(fssource, "//VTK::Light::Impl", toString.str(), false);
777 break;
778 }
779
780 if (useIBL)
781 {
782 vtkShaderProgram::Substitute(fssource, "//VTK::UseIBL::Dec", "#define UseIBL", false);
783 }
784
785 this->QuadFinalBlend = new vtkOpenGLQuadHelper(renderWindow, nullptr, fssource.c_str(), "");
786 }
787 else
788 {
789 renderWindow->GetShaderCache()->ReadyShaderProgram(this->QuadFinalBlend->Program);
790 }
791
792 const auto program = this->QuadFinalBlend->Program;
793 assert(program);
794
795 oren->UpdateLightingUniforms(program);
796
797 // Add IBL textures
798 if (useIBL)
799 {
800 program->SetUniformi("prefilterTex", oren->GetEnvMapPrefiltered()->GetTextureUnit());
801 program->SetUniformMatrix("invNormalMatrix", this->CamInvertedNorms);
802 }
803
804 this->TexBuffer[FluidEyeZ]->Activate();
805 program->SetUniformi("fluidZTexture", this->TexBuffer[FluidEyeZ]->GetTextureUnit());
806
807 this->TexBuffer[FluidThickness]->Activate();
808 program->SetUniformi(
809 "fluidThicknessTexture", this->TexBuffer[FluidThickness]->GetTextureUnit());
810
811 this->TexBuffer[FluidNormal]->Activate();
812 program->SetUniformi("fluidNormalTexture", this->TexBuffer[FluidNormal]->GetTextureUnit());
813
814 this->TexBuffer[OpaqueRGBA]->Activate();
815 program->SetUniformi("opaqueRGBATexture", this->TexBuffer[OpaqueRGBA]->GetTextureUnit());
816
817 if (this->HasVertexColor)
818 {
819 this->OptionalTexBuffer[Color]->Activate();
820 program->SetUniformi("fluidColorTexture", this->OptionalTexBuffer[Color]->GetTextureUnit());
821 program->SetUniformi("hasVertexColor", this->HasVertexColor);
822 program->SetUniformf("vertexColorPower", this->ParticleColorPower);
823 program->SetUniformf("vertexColorScale", this->ParticleColorScale);
824 }
825
826 program->SetUniformMatrix("DCVCMatrix", this->CamDCVC);
827 program->SetUniformMatrix("VCDCMatrix", this->CamVCDC);
828 if (this->QuadFinalBlend->Program->IsUniformUsed("MCVCMatrix"))
829 {
830 if (!vol->GetIsIdentity())
831 {
832 vtkMatrix4x4* mcwc;
833 vtkMatrix3x3* anorms;
834 ((vtkOpenGLActor*)vol)->GetKeyMatrices(mcwc, anorms);
835 vtkMatrix4x4::Multiply4x4(mcwc, this->CamWCVC, this->TempMatrix4);
836 this->QuadFinalBlend->Program->SetUniformMatrix("MCVCMatrix", this->TempMatrix4);
837 }
838 else
839 {
840 this->QuadFinalBlend->Program->SetUniformMatrix("MCVCMatrix", this->CamWCVC);
841 }
842 }
843
844 program->SetUniformi("displayModeOpaqueSurface",
845 this->DisplayMode == UnfilteredOpaqueSurface || this->DisplayMode == FilteredOpaqueSurface);
846 program->SetUniformi("displayModeSurfaceNormal",
847 this->DisplayMode == UnfilteredSurfaceNormal || this->DisplayMode == FilteredSurfaceNormal);
848 program->SetUniformf("attenuationScale", this->AttenuationScale);
849 program->SetUniformf("additionalReflection", this->AdditionalReflection);
850 program->SetUniformf("refractiveIndex", this->RefractiveIndex);
851 program->SetUniformf("refractionScale", this->RefractionScale);
852 program->SetUniform3f("fluidOpaqueColor", this->OpaqueColor);
853 program->SetUniform3f("fluidAttenuationColor", this->AttenuationColor);
854 program->SetUniformf("farZValue", -crange[1]);
855 program->SetUniformf("ambientValue", vol->GetProperty()->GetAmbient());
856 glState->vtkglEnable(GL_DEPTH_TEST);
857 glState->vtkglDepthMask(GL_TRUE);
858 glState->vtkglDepthFunc(GL_ALWAYS);
859
860 this->QuadFinalBlend->Render();
861
862 this->TexBuffer[OpaqueZ]->Deactivate();
863 this->TexBuffer[OpaqueRGBA]->Deactivate();
864 this->TexBuffer[FluidEyeZ]->Deactivate();
865 this->TexBuffer[FluidThickness]->Deactivate();
866 this->TexBuffer[FluidNormal]->Deactivate();
867 if (this->HasVertexColor)
868 {
869 this->OptionalTexBuffer[Color]->Deactivate();
870 }
871
872 glState->vtkglDepthFunc(GL_LEQUAL);
873 }
874 }
875
876 //------------------------------------------------------------------------------
RenderParticles(vtkRenderer * renderer,vtkVolume * vol)877 void vtkOpenGLFluidMapper::RenderParticles(vtkRenderer* renderer, vtkVolume* vol)
878 {
879 vtkPolyData* input = vtkPolyData::SafeDownCast(GetInputDataObject(0, 0));
880 if (input == nullptr || input->GetPoints() == nullptr)
881 {
882 return;
883 }
884
885 if (this->VBOBuildTime < input->GetPoints()->GetMTime())
886 {
887 this->VBOs->CacheDataArray("vertexMC", input->GetPoints()->GetData(), renderer, VTK_FLOAT);
888
889 if (this->HasVertexColor)
890 {
891 int cellFlag = 0;
892 vtkDataArray* scalars = vtkOpenGLFluidMapper::GetScalars(
893 input, this->ScalarMode, this->ArrayAccessMode, this->ArrayId, this->ArrayName, cellFlag);
894 this->VBOs->CacheDataArray("vertexColor", scalars, renderer, VTK_FLOAT);
895 }
896 this->VBOs->BuildAllVBOs(renderer);
897
898 vtkIdType numPts = input->GetPoints()->GetNumberOfPoints();
899 this->GLHelperDepthThickness.IBO->IndexCount = static_cast<size_t>(numPts);
900 this->VBOBuildTime.Modified();
901 }
902
903 // draw polygons
904 int numVerts = this->VBOs->GetNumberOfTuples("vertexMC");
905 if (numVerts)
906 {
907 // First we do the triangles, update the shader, set uniforms, etc.
908 this->UpdateDepthThicknessColorShaders(this->GLHelperDepthThickness, renderer, vol);
909 glDrawArrays(GL_POINTS, 0, static_cast<GLsizei>(numVerts));
910 }
911 }
912
913 //------------------------------------------------------------------------------
914 // Description:
915 // Destructor. Delete SourceCode if any.
ReleaseGraphicsResources(vtkWindow * w)916 void vtkOpenGLFluidMapper::ReleaseGraphicsResources(vtkWindow* w)
917 {
918 if (this->FBFluidEyeZ != nullptr)
919 {
920 this->FBFluidEyeZ->ReleaseGraphicsResources(w);
921 this->FBFluidEyeZ->UnRegister(this);
922 this->FBFluidEyeZ = nullptr;
923 }
924 if (this->FBThickness != nullptr)
925 {
926 this->FBThickness->ReleaseGraphicsResources(w);
927 this->FBThickness->UnRegister(this);
928 this->FBThickness = nullptr;
929 }
930 if (this->FBFilterThickness != nullptr)
931 {
932 this->FBFilterThickness->ReleaseGraphicsResources(w);
933 this->FBFilterThickness->UnRegister(this);
934 this->FBFilterThickness = nullptr;
935 }
936 if (this->FBCompNormal != nullptr)
937 {
938 this->FBCompNormal->ReleaseGraphicsResources(w);
939 this->FBCompNormal->UnRegister(this);
940 this->FBCompNormal = nullptr;
941 }
942 if (this->FBFilterDepth != nullptr)
943 {
944 this->FBFilterDepth->ReleaseGraphicsResources(w);
945 this->FBFilterDepth->UnRegister(this);
946 this->FBFilterDepth = nullptr;
947 }
948
949 if (this->QuadThicknessFilter != nullptr)
950 {
951 delete this->QuadThicknessFilter;
952 this->QuadThicknessFilter = nullptr;
953 }
954 if (this->QuadFluidNormal != nullptr)
955 {
956 delete this->QuadFluidNormal;
957 this->QuadFluidNormal = nullptr;
958 }
959 if (this->QuadFinalBlend != nullptr)
960 {
961 delete this->QuadFinalBlend;
962 this->QuadFinalBlend = nullptr;
963 }
964 for (int i = 0; i < this->NumFilterMethods; ++i)
965 {
966 if (this->QuadFluidDepthFilter[i] != nullptr)
967 {
968 delete this->QuadFluidDepthFilter[i];
969 this->QuadFluidDepthFilter[i] = nullptr;
970 }
971 }
972
973 this->VBOs->ReleaseGraphicsResources(w);
974
975 for (int i = 0; i < NumTexBuffers; ++i)
976 {
977 this->TexBuffer[i]->ReleaseGraphicsResources(w);
978 }
979 for (int i = 0; i < NumOptionalTexBuffers; ++i)
980 {
981 this->OptionalTexBuffer[i]->ReleaseGraphicsResources(w);
982 }
983
984 this->GLHelperDepthThickness.ReleaseGraphicsResources(w);
985
986 this->Modified();
987 }
988