Fraxinus  16.5.0-fx-rc1
An IGT application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
cxTextureSlicePainter.cpp
Go to the documentation of this file.
1 /*=========================================================================
2 This file is part of CustusX, an Image Guided Therapy Application.
3 
4 Copyright (c) 2008-2014, SINTEF Department of Medical Technology
5 All rights reserved.
6 
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9 
10 1. Redistributions of source code must retain the above copyright notice,
11  this list of conditions and the following disclaimer.
12 
13 2. Redistributions in binary form must reproduce the above copyright notice,
14  this list of conditions and the following disclaimer in the documentation
15  and/or other materials provided with the distribution.
16 
17 3. Neither the name of the copyright holder nor the names of its contributors
18  may be used to endorse or promote products derived from this software
19  without specific prior written permission.
20 
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 =========================================================================*/
32 
33 
34 /*
35  * vmTextureSlicePainter.cpp
36  *
37  * Created on: Oct 13, 2009
38  * Author: petterw
39  */
40 
41 #include "cxTextureSlicePainter.h"
42 
43 //#ifndef WIN32
44 //#ifndef CX_VTK_OPENGL2
45 #if !defined(CX_VTK_OPENGL2) && !defined(WIN32)
46 #include <QtCore>
47 #include <vtkOpenGLExtensionManager.h>
48 #include <vtkRenderer.h>
49 #include <vtkShaderProgram2.h>
50 #include <vtkShader2.h>
51 #include <vtkShader2Collection.h>
52 #include <vtkUniformVariables.h>
53 #include <vtkObjectFactory.h>
54 #include <vtkOpenGLRenderWindow.h>
55 
56 
57 #ifdef __APPLE__
58 #include <OpenGL/glu.h>
59 #include "X11/Xlib.h"
60 //#include "/usr/include/X11/Xlib.h"
61 #else
62 #include <GL/glu.h>
63 #endif
64 
65 #ifdef WIN32
66 #include <windows.h>
67 #include <GL/glext.h>
68 #endif
69 
70 #include "cxGPUImageBuffer.h"
71 #include "cxTypeConversions.h"
72 #include "cxGLHelpers.h"
73 
74 //---------------------------------------------------------
75 namespace cx
76 {
77 //---------------------------------------------------------
78 
79 vtkStandardNewMacro(TextureSlicePainter);
80 
82  mWindow(0.0),
83  mLevel(0.0),
84  mLLR(0.0),
85  mAlpha(1.0)
86 {
87  mIndex = index;
88 }
89 
91  mWindow(0.0),
92  mLevel(0.0),
93  mLLR(0.0),
94  mAlpha(1.0)
95 {
96  mIndex = -1;
97 }
98 
100 {
101 
102 }
103 
105 {
106  mVolumeBuffer = buffer;
107 }
108 
110 {
111  mLutBuffer = buffer;
112 }
113 
114 void SingleVolumePainterHelper::SetColorAttribute(float window, float level, float llr,float alpha)
115 {
116  mWindow = window;
117  mLevel = level;
118  mLLR = llr;
119  mAlpha = alpha;
120 }
121 
123 {
124  if (mVolumeBuffer)
125  mVolumeBuffer->allocate();
126  if (mLutBuffer)
127  mLutBuffer->allocate();
128 }
129 
130 void SingleVolumePainterHelper::setUniformiArray(vtkUniformVariables* uniforms, QString name, int val)
131 {
132  QString fullName = QString("%1[%2]").arg(name).arg(mIndex);
133  uniforms->SetUniformi(cstring_cast(fullName), 1, &val);
134 }
135 
136 void SingleVolumePainterHelper::setUniformfArray(vtkUniformVariables* uniforms, QString name, float val)
137 {
138  QString fullName = QString("%1[%2]").arg(name).arg(mIndex);
139  uniforms->SetUniformf(cstring_cast(fullName), 1, &val);
140 }
141 
142 void SingleVolumePainterHelper::eachRenderInternal(vtkSmartPointer<vtkShaderProgram2> shader)
143 {
144  if (!mVolumeBuffer)
145  return;
146 
147  mVolumeBuffer->bind(mIndex);
148 
149  int texture = 2*mIndex; //texture unit 1
150  int lut = 2*mIndex+1; //texture unit 1
151 
152  int lutsize = 0;
153  if (mLutBuffer)
154  {
155  mLutBuffer->bind(mIndex);
156  lutsize = mLutBuffer->getLutSize();
157  }
158 
159  vtkUniformVariables* uniforms = shader->GetUniformVariables();
160  this->setUniformiArray(uniforms, "texture", texture);
161  this->setUniformiArray(uniforms, "lut", lut);
162  this->setUniformiArray(uniforms, "lutsize", lutsize);
163  this->setUniformfArray(uniforms, "llr", mLLR);
164  this->setUniformfArray(uniforms, "level", mLevel);
165  this->setUniformfArray(uniforms, "window", mWindow);
166  this->setUniformfArray(uniforms, "alpha", mAlpha);
167 
168  report_gl_error();
169 }
170 
171 //---------------------------------------------------------
173  hasLoadedExtensions(false)
174 {
175 }
176 
178 {
179  mShaderPath = path;
180 }
181 
182 QString TextureSlicePainter::loadShaderFile()
183 {
184  QString filepath = mShaderPath + "/cxOverlay2D_frag.glsl";
185  QFile fp(filepath);
186  if (fp.exists())
187  {
188  fp.open(QFile::ReadOnly);
189  QTextStream shaderfile(&fp);
190  return shaderfile.readAll();
191  }
192  else
193  {
194  std::cout << "TextureSlicer can't read shaderfile [" << fp.fileName() << "]" << std::endl;
195  }
196  return "";
197 }
198 
200 {
201  if (this->LastContext)
202  {
203  this->ReleaseGraphicsResources(this->LastWindow);
204  }
205 }
206 
208 {
209  if (this->Shader != 0)
210  {
211  this->Shader->ReleaseGraphicsResources();
212  this->Shader = 0;
213  }
214 
215  this->ClearGraphicsResources(); //the shader
216  this->LastContext = 0;
217  this->Superclass::ReleaseGraphicsResources(win);
218 }
219 
220 void TextureSlicePainter::PrepareForRendering(vtkRenderer* renderer, vtkActor* actor)
221 {
222  report_gl_error();
223  if (!CanRender(renderer, actor))
224  {
225  this->ClearGraphicsResources();
226  this->LastContext = 0;
227  this->Superclass::PrepareForRendering(renderer, actor);
228  return;
229  }
230 
231  GLint oldTextureUnit;
232  glGetIntegerv(GL_ACTIVE_TEXTURE, &oldTextureUnit);
233 
234  vtkRenderWindow* renWin = renderer->GetRenderWindow();
235  if (this->LastContext != renWin)
236  {
237  this->ClearGraphicsResources();
238  hasLoadedExtensions = false; // force re-check
239  }
240  this->LastContext = renWin;
241 
242  vtkOpenGLRenderWindow *context = vtkOpenGLRenderWindow::SafeDownCast(renWin);
243  if (!hasLoadedExtensions)
244  {
245  if (!this->LoadRequiredExtensions(context->GetExtensionManager()))
246  {
247  return;
248  }
249  hasLoadedExtensions = true;
250  }
251 
252  for (unsigned i = 0; i < this->mElement.size(); ++i)
253  this->mElement[i].initializeRendering();
254 
255  if (!this->Shader)
256  {
257  report_gl_error();
258  QString shaderSource = this->loadShaderFile();
259  shaderSource = this->replaceShaderSourceMacros(shaderSource);
260 // int layers = this->mElement.size();
261 // shaderSource = shaderSource.replace("${LAYERS}", QString("%1").arg(layers));
262 
263  this->buildProgram(shaderSource, context);
264  }
265 
266  glPixelStorei(GL_PACK_ALIGNMENT, 1);
267  glPixelStorei(GL_PACK_ROW_LENGTH, 0);
268  glPixelStorei(GL_PACK_SKIP_ROWS, 0);
269  glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
270 
271  this->Superclass::PrepareForRendering(renderer, actor);
272  report_gl_error();
273  glActiveTexture(oldTextureUnit);
274 }
275 
276 QString TextureSlicePainter::replaceShaderSourceMacros(QString shaderSource)
277 {
278  // set constant layers
279  int layers = this->mElement.size();
280  shaderSource = shaderSource.replace("${LAYERS}", QString("%1").arg(layers));
281 
282  // fill function vec4 sampleLut(in int index, in float idx)
283  QString element = "\tif (index==%1) return texture1D(lut[%1], idx);\n";
284  QString sampleLutContent;
285  for (unsigned i=0; i<layers; ++i)
286  sampleLutContent += element.arg(i);
287  shaderSource = shaderSource.replace("${SAMPLE_LUT_CONTENT}", sampleLutContent);
288 
289  return shaderSource;
290 }
291 
292 
293 void TextureSlicePainter::RenderInternal(vtkRenderer* renderer, vtkActor* actor, unsigned long typeflags,
294  bool forceCompileOnly)
295 {
296  if (!CanRender(renderer, actor))
297  {
298  return;
299  }
300 
301  GLint oldTextureUnit;
302  glGetIntegerv(GL_ACTIVE_TEXTURE, &oldTextureUnit);
303 
304  int layers = this->mElement.size();
305  this->Shader->GetUniformVariables()->SetUniformi("layers", 1, &layers);
306 
307  for (unsigned i = 0; i < this->mElement.size(); ++i)
308  {
309  this->mElement[i].eachRenderInternal(this->Shader);
310  }
311 
312  this->Shader->Use();
313 
314  if (!this->Shader->IsValid())
315  {
316  vtkErrorMacro(<<" validation of the program failed: "<< this->Shader->GetLastValidateLog());
317  }
318 
319  this->Superclass::RenderInternal(renderer, actor, typeflags, forceCompileOnly);
320 
321  this->Shader->Restore();
322  report_gl_error();
323  glActiveTexture(oldTextureUnit);
324 }
325 
326 bool TextureSlicePainter::CanRender(vtkRenderer*, vtkActor*)
327 {
328  return !this->mElement.empty();
329 }
330 
331 bool TextureSlicePainter::LoadRequiredExtension(vtkOpenGLExtensionManager* mgr, QString id)
332 {
333  bool loaded = mgr->LoadSupportedExtension(cstring_cast(id));
334  if (!loaded)
335  std::cout << "TextureSlicePainter Error: GL extension " + id + " not found" << std::endl;
336  return loaded;
337 }
338 
339 bool TextureSlicePainter::LoadRequiredExtensions(vtkOpenGLExtensionManager* mgr)
340 {
341  return (LoadRequiredExtension(mgr, "GL_VERSION_2_0")
342  && LoadRequiredExtension(mgr, "GL_VERSION_1_5")
343  && LoadRequiredExtension(mgr, "GL_ARB_vertex_buffer_object"));
344 }
345 
347 {
348  this->safeIndex(index).SetBuffer(buffer);
349 }
350 
352 {
353  this->safeIndex(index).SetBuffer(buffer);
354 }
355 
356 void TextureSlicePainter::SetColorAttribute(int index, float window, float level, float llr,float alpha)
357 {
358  this->safeIndex(index).SetColorAttribute(window, level, llr, alpha);
359 }
360 
362 {
363 }
364 
365 void TextureSlicePainter::PrintSelf(ostream& os, vtkIndent indent)
366 {
367 }
368 
369 SingleVolumePainterHelper& TextureSlicePainter::safeIndex(int index)
370 {
371  if ((int)mElement.size() <= index)
372  {
373  mElement.resize(index+1);
374  mElement[index] = SingleVolumePainterHelper(index);
375  }
376  return mElement[index];
377 }
378 
379 void TextureSlicePainter::buildProgram(QString shaderSource, vtkOpenGLRenderWindow* renderWindow)
380 {
381  vtkShaderProgram2Ptr pgm = vtkShaderProgram2Ptr::New();
382  pgm->SetContext(renderWindow);
383 
384  vtkShader2Ptr s2 = vtkShader2Ptr::New();
385  s2->SetType(VTK_SHADER_TYPE_FRAGMENT);
386  s2->SetSourceCode(cstring_cast(shaderSource));
387  s2->SetContext(pgm->GetContext());
388  pgm->GetShaders()->AddItem(s2);
389  report_gl_error();
390  pgm->Build();
391 
392  if (pgm->GetLastBuildStatus() != VTK_SHADER_PROGRAM2_LINK_SUCCEEDED)
393  {
394  vtkErrorMacro("Pass Two failed.");
395  abort();
396  }
397 
398  this->Shader = pgm;
399 }
400 
402 {
403  if (this->Shader != 0)
404  {
405  this->Shader->ReleaseGraphicsResources();
406  this->Shader = 0;
407  }
408 }
409 
410 
411 //---------------------------------------------------------
412 }//end namespace
413 //---------------------------------------------------------
414 
415 #endif //CX_VTK_OPENGL2
416 //#endif //WIN32
vtkSmartPointer< class vtkShaderProgram2 > vtkShaderProgram2Ptr
bool CanRender(vtkRenderer *, vtkActor *)
void PrintSelf(ostream &os, vtkIndent indent)
void SetLutBuffer(int index, GPUImageLutBufferPtr buffer)
void setUniformiArray(vtkUniformVariables *uniforms, QString name, int val)
void eachRenderInternal(vtkSmartPointer< vtkShaderProgram2 > shader)
void SetColorAttribute(float window, float level, float llr, float alpha)
cstring_cast_Placeholder cstring_cast(const T &val)
void releaseGraphicsResources(int index)
virtual void PrepareForRendering(vtkRenderer *, vtkActor *)
static bool LoadRequiredExtension(vtkOpenGLExtensionManager *mgr, QString id)
vtkStandardNewMacro(TextureSlicePainter)
static bool LoadRequiredExtensions(vtkOpenGLExtensionManager *mgr)
void SetVolumeBuffer(int index, GPUImageDataBufferPtr buffer)
void setUniformfArray(vtkUniformVariables *uniforms, QString name, float val)
boost::shared_ptr< class GPUImageDataBuffer > GPUImageDataBufferPtr
void RenderInternal(vtkRenderer *renderer, vtkActor *actor, unsigned long typeflags, bool forceCompileOnly)
boost::shared_ptr< class GPUImageLutBuffer > GPUImageLutBufferPtr
vtkSmartPointer< class vtkShader2 > vtkShader2Ptr
void SetBuffer(GPUImageDataBufferPtr buffer)
void SetColorAttribute(int index, float window, float level, float llr, float alpha)
virtual void ReleaseGraphicsResources(vtkWindow *)
#define report_gl_error()
Definition: cxGLHelpers.h:50