1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkOrderIndependentTranslucentPass.cxx
5
6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7 All rights reserved.
8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9
10 This software is distributed WITHOUT ANY WARRANTY; without even
11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12 PURPOSE. See the above copyright notice for more information.
13
14 =========================================================================*/
15
16 #include "vtkOrderIndependentTranslucentPass.h"
17 #include "vtkOpenGLFramebufferObject.h"
18 #include "vtkInformation.h"
19 #include "vtkObjectFactory.h"
20 #include "vtkOpenGLActor.h"
21 #include "vtkOpenGLError.h"
22 #include "vtkOpenGLQuadHelper.h"
23 #include "vtkOpenGLRenderWindow.h"
24 #include "vtkOpenGLRenderer.h"
25 #include "vtkOpenGLShaderCache.h"
26 #include "vtkOpenGLState.h"
27 #include "vtkProp.h"
28 #include "vtkRenderState.h"
29 #include "vtkRenderer.h"
30 #include "vtkShaderProgram.h"
31 #include "vtkTextureObject.h"
32 #include <cassert>
33 #include <list>
34
35 #include "vtkRenderStepsPass.h"
36
37 #include "vtkOpenGLHelper.h"
38
39 // the 2D blending shaders we use
40 #include "vtkOrderIndependentTranslucentPassFinalFS.h"
41
42 vtkStandardNewMacro(vtkOrderIndependentTranslucentPass);
43 vtkCxxSetObjectMacro(vtkOrderIndependentTranslucentPass,TranslucentPass,vtkRenderPass);
44
45 // ----------------------------------------------------------------------------
vtkOrderIndependentTranslucentPass()46 vtkOrderIndependentTranslucentPass::vtkOrderIndependentTranslucentPass() :
47 Framebuffer(nullptr), State(nullptr)
48 {
49 this->TranslucentPass=nullptr;
50
51 this->FinalBlend = nullptr;
52
53 this->TranslucentZTexture = vtkTextureObject::New();
54
55 this->TranslucentRGBATexture = vtkTextureObject::New();
56 this->TranslucentRTexture = vtkTextureObject::New();
57
58 this->ViewportX = 0;
59 this->ViewportY = 0;
60 this->ViewportWidth = 100;
61 this->ViewportHeight = 100;
62 }
63
64 // ----------------------------------------------------------------------------
~vtkOrderIndependentTranslucentPass()65 vtkOrderIndependentTranslucentPass::~vtkOrderIndependentTranslucentPass()
66 {
67 if(this->TranslucentPass!=nullptr)
68 {
69 this->TranslucentPass->Delete();
70 }
71 if (this->TranslucentZTexture)
72 {
73 this->TranslucentZTexture->UnRegister(this);
74 this->TranslucentZTexture = nullptr;
75 }
76 if (this->TranslucentRGBATexture)
77 {
78 this->TranslucentRGBATexture->UnRegister(this);
79 this->TranslucentRGBATexture = nullptr;
80 }
81 if (this->TranslucentRTexture)
82 {
83 this->TranslucentRTexture->UnRegister(this);
84 this->TranslucentRTexture = nullptr;
85 }
86 if (this->Framebuffer)
87 {
88 this->Framebuffer->UnRegister(this);
89 this->Framebuffer = nullptr;
90 }
91 }
92
93 //-----------------------------------------------------------------------------
94 // Description:
95 // Destructor. Delete SourceCode if any.
ReleaseGraphicsResources(vtkWindow * w)96 void vtkOrderIndependentTranslucentPass::ReleaseGraphicsResources(vtkWindow *w)
97 {
98 assert("pre: w_exists" && w!=nullptr);
99
100 if (this->FinalBlend !=nullptr)
101 {
102 delete this->FinalBlend;
103 this->FinalBlend = nullptr;
104 }
105 if(this->TranslucentPass)
106 {
107 this->TranslucentPass->ReleaseGraphicsResources(w);
108 }
109 if (this->TranslucentZTexture)
110 {
111 this->TranslucentZTexture->ReleaseGraphicsResources(w);
112 }
113 if (this->TranslucentRGBATexture)
114 {
115 this->TranslucentRGBATexture->ReleaseGraphicsResources(w);
116 }
117 if (this->TranslucentRTexture)
118 {
119 this->TranslucentRTexture->ReleaseGraphicsResources(w);
120 }
121 if (this->Framebuffer)
122 {
123 this->Framebuffer->ReleaseGraphicsResources(w);
124 this->Framebuffer->UnRegister(this);
125 this->Framebuffer = nullptr;
126 }
127
128 }
129
130 // ----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)131 void vtkOrderIndependentTranslucentPass::PrintSelf(ostream& os, vtkIndent indent)
132 {
133 this->Superclass::PrintSelf(os,indent);
134
135 os << indent << "TranslucentPass:";
136 if(this->TranslucentPass!=nullptr)
137 {
138 this->TranslucentPass->PrintSelf(os,indent);
139 }
140 else
141 {
142 os << "(none)" <<endl;
143 }
144 }
145
BlendFinalPeel(vtkOpenGLRenderWindow * renWin)146 void vtkOrderIndependentTranslucentPass::BlendFinalPeel(vtkOpenGLRenderWindow *renWin)
147 {
148 if (!this->FinalBlend)
149 {
150 this->FinalBlend = new vtkOpenGLQuadHelper(renWin,
151 nullptr,
152 vtkOrderIndependentTranslucentPassFinalFS,
153 "");
154 }
155 else
156 {
157 renWin->GetShaderCache()->ReadyShaderProgram(
158 this->FinalBlend->Program);
159 }
160
161 if (this->FinalBlend->Program)
162 {
163 this->TranslucentRGBATexture->Activate();
164 this->TranslucentRTexture->Activate();
165
166 this->FinalBlend->Program->SetUniformi(
167 "translucentRGBATexture",
168 this->TranslucentRGBATexture->GetTextureUnit());
169 this->FinalBlend->Program->SetUniformi(
170 "translucentRTexture",
171 this->TranslucentRTexture->GetTextureUnit());
172
173 this->FinalBlend->Render();
174 }
175 }
176
177
178 // ----------------------------------------------------------------------------
179 // Description:
180 // Perform rendering according to a render state \p s.
181 // \pre s_exists: s!=0
Render(const vtkRenderState * s)182 void vtkOrderIndependentTranslucentPass::Render(const vtkRenderState *s)
183 {
184 assert("pre: s_exists" && s!=nullptr);
185
186 this->NumberOfRenderedProps=0;
187
188 if(this->TranslucentPass==nullptr)
189 {
190 vtkWarningMacro(<<"No TranslucentPass delegate set. Nothing can be rendered.");
191 return;
192 }
193
194 // Any prop to render?
195 bool hasTranslucentPolygonalGeometry=false;
196 int i=0;
197 while(!hasTranslucentPolygonalGeometry && i<s->GetPropArrayCount())
198 {
199 hasTranslucentPolygonalGeometry=
200 s->GetPropArray()[i]->HasTranslucentPolygonalGeometry()==1;
201 ++i;
202 }
203 if(!hasTranslucentPolygonalGeometry)
204 {
205 return; // nothing to render.
206 }
207
208 vtkOpenGLRenderWindow *renWin
209 = vtkOpenGLRenderWindow::SafeDownCast(s->GetRenderer()->GetRenderWindow());
210 this->State = renWin->GetState();
211
212 vtkRenderer *r=s->GetRenderer();
213 if(s->GetFrameBuffer()==nullptr)
214 {
215 // get the viewport dimensions
216 r->GetTiledSizeAndOrigin(&this->ViewportWidth,&this->ViewportHeight,
217 &this->ViewportX,&this->ViewportY);
218 }
219 else
220 {
221 int size[2];
222 s->GetWindowSize(size);
223 this->ViewportWidth=size[0];
224 this->ViewportHeight=size[1];
225 this->ViewportX=0;
226 this->ViewportY=0;
227 }
228
229 // create textures we need if not done already
230 if (this->TranslucentRGBATexture->GetHandle() == 0)
231 {
232 this->TranslucentRGBATexture->SetInternalFormat(GL_RGBA16F);
233 this->TranslucentRGBATexture->SetFormat(GL_RGBA);
234 this->TranslucentRGBATexture->SetDataType(GL_HALF_FLOAT);
235 this->TranslucentRGBATexture->SetContext(renWin);
236 this->TranslucentRGBATexture->Allocate2D(
237 this->ViewportWidth, this->ViewportHeight, 4, VTK_FLOAT);
238
239 this->TranslucentRTexture->SetInternalFormat(GL_R16F);
240 this->TranslucentRTexture->SetFormat(GL_RED);
241 this->TranslucentRTexture->SetDataType(GL_HALF_FLOAT);
242 this->TranslucentRTexture->SetContext(renWin);
243 this->TranslucentRTexture->Allocate2D(
244 this->ViewportWidth, this->ViewportHeight, 1, VTK_FLOAT);
245
246 // what depth format should we use?
247 this->TranslucentZTexture->SetContext(renWin);
248 int dbits =renWin->GetDepthBufferSize();
249 if (dbits == 32)
250 {
251 this->TranslucentZTexture->AllocateDepth(
252 this->ViewportWidth, this->ViewportHeight, vtkTextureObject::Float32);
253 }
254 else
255 {
256 this->TranslucentZTexture->AllocateDepth(
257 this->ViewportWidth, this->ViewportHeight, vtkTextureObject::Fixed24);
258 }
259 this->TranslucentZTexture->SetWrapS(vtkTextureObject::ClampToEdge);
260 this->TranslucentZTexture->SetWrapT(vtkTextureObject::ClampToEdge);
261 }
262 else
263 {
264 // make sure texture sizes are up to date
265 this->TranslucentRGBATexture->Resize(
266 this->ViewportWidth, this->ViewportHeight);
267 this->TranslucentRTexture->Resize(
268 this->ViewportWidth, this->ViewportHeight);
269 this->TranslucentZTexture->Resize(
270 this->ViewportWidth, this->ViewportHeight);
271 }
272
273 // create framebuffer if not done already
274 if (!this->Framebuffer)
275 {
276 this->Framebuffer = vtkOpenGLFramebufferObject::New();
277 this->Framebuffer->SetContext(renWin);
278 this->Framebuffer->SaveCurrentBindingsAndBuffers();
279 this->Framebuffer->Bind();
280 this->Framebuffer->AddDepthAttachment(
281 this->Framebuffer->GetBothMode(), this->TranslucentZTexture);
282 this->Framebuffer->AddColorAttachment(
283 this->Framebuffer->GetBothMode(), 0,
284 this->TranslucentRGBATexture);
285 this->Framebuffer->AddColorAttachment(
286 this->Framebuffer->GetDrawMode(), 1,
287 this->TranslucentRTexture);
288 this->Framebuffer->RestorePreviousBindingsAndBuffers();
289 }
290
291 this->State->vtkglViewport(0, 0,
292 this->ViewportWidth, this->ViewportHeight);
293 bool saveScissorTestState = this->State->GetEnumState(GL_SCISSOR_TEST);
294 this->State->vtkglDisable(GL_SCISSOR_TEST);
295
296 // bind the draw mode but leave read as the previous FO
297 this->Framebuffer->SaveCurrentBindingsAndBuffers();
298 this->Framebuffer->Bind(this->Framebuffer->GetDrawMode());
299 this->Framebuffer->ActivateDrawBuffers(2);
300
301 #ifdef GL_MULTISAMPLE
302 bool multiSampleStatus = this->State->GetEnumState(GL_MULTISAMPLE);
303 this->State->vtkglDisable(GL_MULTISAMPLE);
304 #endif
305
306 this->State->vtkglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
307 this->State->vtkglClearColor(0.0,0.0,0.0,1.0);
308 this->State->vtkglDepthMask(GL_TRUE);
309 this->State->vtkglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
310
311 #if defined(__APPLE__)
312 this->State->vtkglColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
313 // apple fails if not the upper left corenr of the window
314 // blit on apple is fubar, so rerender opaque
315 // to get a good depth buffer
316 r->DeviceRenderOpaqueGeometry();
317 this->State->vtkglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
318 #else
319 // blit read buffer depth to FO depth texture
320 glBlitFramebuffer(
321 this->ViewportX, this->ViewportY,
322 this->ViewportX + this->ViewportWidth,
323 this->ViewportY + this->ViewportHeight,
324 0, 0, this->ViewportWidth, this->ViewportHeight,
325 GL_DEPTH_BUFFER_BIT,
326 GL_NEAREST);
327 #endif
328
329
330 // now bind both read and draw
331 this->Framebuffer->Bind();
332
333 // Setup property keys for actors:
334 this->PreRender(s);
335
336 // Enable the depth buffer (otherwise it's disabled for translucent geometry)
337 assert("Render state valid." && s);
338
339 this->State->vtkglEnable(GL_DEPTH_TEST);
340 this->State->vtkglEnable(GL_BLEND);
341
342 // basic gist is we accumulate color into RGB
343 // We compute final opacity into A
344 // We store accumulated opacity into R of the
345 // R texture.
346 this->State->vtkglBlendFuncSeparate(
347 GL_ONE,
348 GL_ONE,
349 GL_ZERO,
350 GL_ONE_MINUS_SRC_ALPHA
351 );
352
353 // render the translucent data into the FO
354 this->TranslucentPass->Render(s);
355
356 // back to the original FO
357 this->Framebuffer->RestorePreviousBindingsAndBuffers();
358
359 this->State->vtkglBlendFuncSeparate(
360 GL_ONE_MINUS_SRC_ALPHA,
361 GL_SRC_ALPHA,
362 GL_ONE_MINUS_SRC_ALPHA,
363 GL_SRC_ALPHA
364 );
365
366 // Restore the original viewport and scissor test settings
367 this->State->vtkglViewport(this->ViewportX, this->ViewportY,
368 this->ViewportWidth, this->ViewportHeight);
369 if (saveScissorTestState)
370 {
371 this->State->vtkglEnable(GL_SCISSOR_TEST);
372 }
373 else
374 {
375 this->State->vtkglDisable(GL_SCISSOR_TEST);
376 }
377
378 // do not write zvalues on final blend
379 this->State->vtkglDepthMask(GL_FALSE);
380 this->State->vtkglDepthFunc( GL_ALWAYS );
381 this->BlendFinalPeel(renWin);
382
383 // unload the textures
384 this->TranslucentRGBATexture->Deactivate();
385 this->TranslucentRTexture->Deactivate();
386 this->TranslucentZTexture->Deactivate();
387
388 this->State->vtkglDepthFunc( GL_LEQUAL );
389
390 #ifdef GL_MULTISAMPLE
391 if(multiSampleStatus)
392 {
393 this->State->vtkglEnable(GL_MULTISAMPLE);
394 }
395 #endif
396
397 // Restore blending parameters:
398 this->State->vtkglBlendFuncSeparate(
399 GL_SRC_ALPHA,
400 GL_ONE_MINUS_SRC_ALPHA,
401 GL_ONE,
402 GL_ONE_MINUS_SRC_ALPHA
403 );
404
405 this->PostRender(s);
406
407 this->NumberOfRenderedProps = this->TranslucentPass->GetNumberOfRenderedProps();
408
409 vtkOpenGLCheckErrorMacro("failed after Render");
410 }
411
412 //------------------------------------------------------------------------------
PostReplaceShaderValues(std::string &,std::string &,std::string & fragmentShader,vtkAbstractMapper *,vtkProp *)413 bool vtkOrderIndependentTranslucentPass::PostReplaceShaderValues(std::string &,
414 std::string &,
415 std::string &fragmentShader,
416 vtkAbstractMapper *,
417 vtkProp *)
418 {
419 vtkShaderProgram::Substitute(
420 fragmentShader, "//VTK::DepthPeeling::Impl",
421 " gl_FragData[0] = vec4(gl_FragData[0].rgb*gl_FragData[0].a, gl_FragData[0].a);\n"
422 " gl_FragData[1].r = gl_FragData[0].a;\n"
423 );
424
425 return true;
426 }
427