NorMIT-nav  16.5
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 #ifdef __APPLE__
57 #include <OpenGL/glu.h>
58 #include "X11/Xlib.h"
59 //#include "/usr/include/X11/Xlib.h"
60 #else
61 #define GL_GLEXT_PROTOTYPES
62 #include <GL/glu.h>
63 #include <GL/glext.h>
64 #endif
65 
66 #ifdef WIN32
67 #include <windows.h>
68 #include <GL/glext.h>
69 #endif
70 
71 #include "cxGPUImageBuffer.h"
72 #include "cxTypeConversions.h"
73 #include "cxGLHelpers.h"
74 
75 //---------------------------------------------------------
76 namespace cx
77 {
78 //---------------------------------------------------------
79 
80 vtkStandardNewMacro(TextureSlicePainter);
81 
83  mWindow(0.0),
84  mLevel(0.0),
85  mLLR(0.0),
86  mAlpha(1.0)
87 {
88  mIndex = index;
89 }
90 
92  mWindow(0.0),
93  mLevel(0.0),
94  mLLR(0.0),
95  mAlpha(1.0)
96 {
97  mIndex = -1;
98 }
99 
101 {
102 
103 }
104 
106 {
107  mVolumeBuffer = buffer;
108 }
109 
111 {
112  mLutBuffer = buffer;
113 }
114 
115 void SingleVolumePainterHelper::SetColorAttribute(float window, float level, float llr,float alpha)
116 {
117  mWindow = window;
118  mLevel = level;
119  mLLR = llr;
120  mAlpha = alpha;
121 }
122 
124 {
125  if (mVolumeBuffer)
126  mVolumeBuffer->allocate();
127  if (mLutBuffer)
128  mLutBuffer->allocate();
129 }
130 
131 void SingleVolumePainterHelper::setUniformiArray(vtkUniformVariables* uniforms, QString name, int val)
132 {
133  QString fullName = QString("%1[%2]").arg(name).arg(mIndex);
134  uniforms->SetUniformi(cstring_cast(fullName), 1, &val);
135 }
136 
137 void SingleVolumePainterHelper::setUniformfArray(vtkUniformVariables* uniforms, QString name, float val)
138 {
139  QString fullName = QString("%1[%2]").arg(name).arg(mIndex);
140  uniforms->SetUniformf(cstring_cast(fullName), 1, &val);
141 }
142 
143 void SingleVolumePainterHelper::eachRenderInternal(vtkSmartPointer<vtkShaderProgram2> shader)
144 {
145  if (!mVolumeBuffer)
146  return;
147 
148  mVolumeBuffer->bind(mIndex);
149 
150  int texture = 2*mIndex; //texture unit 1
151  int lut = 2*mIndex+1; //texture unit 1
152 
153  int lutsize = 0;
154  if (mLutBuffer)
155  {
156  mLutBuffer->bind(mIndex);
157  lutsize = mLutBuffer->getLutSize();
158  }
159 
160  vtkUniformVariables* uniforms = shader->GetUniformVariables();
161  this->setUniformiArray(uniforms, "texture", texture);
162  this->setUniformiArray(uniforms, "lut", lut);
163  this->setUniformiArray(uniforms, "lutsize", lutsize);
164  this->setUniformfArray(uniforms, "llr", mLLR);
165  this->setUniformfArray(uniforms, "level", mLevel);
166  this->setUniformfArray(uniforms, "window", mWindow);
167  this->setUniformfArray(uniforms, "alpha", mAlpha);
168 
169  report_gl_error();
170 }
171 
172 //---------------------------------------------------------
174  hasLoadedExtensions(false)
175 {
176 }
177 
179 {
180  mShaderPath = path;
181 }
182 
183 QString TextureSlicePainter::loadShaderFile()
184 {
185  QString filepath = mShaderPath + "/cxOverlay2D_frag.glsl";
186  QFile fp(filepath);
187  if (fp.exists())
188  {
189  fp.open(QFile::ReadOnly);
190  QTextStream shaderfile(&fp);
191  return shaderfile.readAll();
192  }
193  else
194  {
195  std::cout << "TextureSlicer can't read shaderfile [" << fp.fileName() << "]" << std::endl;
196  }
197  return "";
198 }
199 
201 {
202  if (this->LastContext)
203  {
204  this->ReleaseGraphicsResources(this->LastWindow);
205  }
206 }
207 
209 {
210  if (this->Shader != 0)
211  {
212  this->Shader->ReleaseGraphicsResources();
213  this->Shader = 0;
214  }
215 
216  this->ClearGraphicsResources(); //the shader
217  this->LastContext = 0;
218  this->Superclass::ReleaseGraphicsResources(win);
219 }
220 
221 void TextureSlicePainter::PrepareForRendering(vtkRenderer* renderer, vtkActor* actor)
222 {
223  report_gl_error();
224  if (!CanRender(renderer, actor))
225  {
226  this->ClearGraphicsResources();
227  this->LastContext = 0;
228  this->Superclass::PrepareForRendering(renderer, actor);
229  return;
230  }
231 
232  GLint oldTextureUnit;
233  glGetIntegerv(GL_ACTIVE_TEXTURE, &oldTextureUnit);
234 
235  vtkRenderWindow* renWin = renderer->GetRenderWindow();
236  if (this->LastContext != renWin)
237  {
238  this->ClearGraphicsResources();
239  hasLoadedExtensions = false; // force re-check
240  }
241  this->LastContext = renWin;
242 
243  vtkOpenGLRenderWindow *context = vtkOpenGLRenderWindow::SafeDownCast(renWin);
244  if (!hasLoadedExtensions)
245  {
246  if (!this->LoadRequiredExtensions(context->GetExtensionManager()))
247  {
248  return;
249  }
250  hasLoadedExtensions = true;
251  }
252 
253  for (unsigned i = 0; i < this->mElement.size(); ++i)
254  this->mElement[i].initializeRendering();
255 
256  if (!this->Shader)
257  {
258  report_gl_error();
259  QString shaderSource = this->loadShaderFile();
260  shaderSource = this->replaceShaderSourceMacros(shaderSource);
261 // int layers = this->mElement.size();
262 // shaderSource = shaderSource.replace("${LAYERS}", QString("%1").arg(layers));
263 
264  this->buildProgram(shaderSource, context);
265  }
266 
267  glPixelStorei(GL_PACK_ALIGNMENT, 1);
268  glPixelStorei(GL_PACK_ROW_LENGTH, 0);
269  glPixelStorei(GL_PACK_SKIP_ROWS, 0);
270  glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
271 
272  this->Superclass::PrepareForRendering(renderer, actor);
273  report_gl_error();
274  glActiveTexture(oldTextureUnit);
275 }
276 
277 QString TextureSlicePainter::replaceShaderSourceMacros(QString shaderSource)
278 {
279  // set constant layers
280  int layers = this->mElement.size();
281  shaderSource = shaderSource.replace("${LAYERS}", QString("%1").arg(layers));
282 
283  // fill function vec4 sampleLut(in int index, in float idx)
284  QString element = "\tif (index==%1) return texture1D(lut[%1], idx);\n";
285  QString sampleLutContent;
286  for (unsigned i=0; i<layers; ++i)
287  sampleLutContent += element.arg(i);
288  shaderSource = shaderSource.replace("${SAMPLE_LUT_CONTENT}", sampleLutContent);
289 
290  return shaderSource;
291 }
292 
293 
294 void TextureSlicePainter::RenderInternal(vtkRenderer* renderer, vtkActor* actor, unsigned long typeflags,
295  bool forceCompileOnly)
296 {
297  if (!CanRender(renderer, actor))
298  {
299  return;
300  }
301 
302  GLint oldTextureUnit;
303  glGetIntegerv(GL_ACTIVE_TEXTURE, &oldTextureUnit);
304 
305  int layers = this->mElement.size();
306  this->Shader->GetUniformVariables()->SetUniformi("layers", 1, &layers);
307 
308  for (unsigned i = 0; i < this->mElement.size(); ++i)
309  {
310  this->mElement[i].eachRenderInternal(this->Shader);
311  }
312 
313  this->Shader->Use();
314 
315  if (!this->Shader->IsValid())
316  {
317  vtkErrorMacro(<<" validation of the program failed: "<< this->Shader->GetLastValidateLog());
318  }
319 
320  this->Superclass::RenderInternal(renderer, actor, typeflags, forceCompileOnly);
321 
322  this->Shader->Restore();
323  report_gl_error();
324  glActiveTexture(oldTextureUnit);
325 }
326 
327 bool TextureSlicePainter::CanRender(vtkRenderer*, vtkActor*)
328 {
329  return !this->mElement.empty();
330 }
331 
332 bool TextureSlicePainter::LoadRequiredExtension(vtkOpenGLExtensionManager* mgr, QString id)
333 {
334  bool loaded = mgr->LoadSupportedExtension(cstring_cast(id));
335  if (!loaded)
336  std::cout << "TextureSlicePainter Error: GL extension " + id + " not found" << std::endl;
337  return loaded;
338 }
339 
340 bool TextureSlicePainter::LoadRequiredExtensions(vtkOpenGLExtensionManager* mgr)
341 {
342  return (LoadRequiredExtension(mgr, "GL_VERSION_2_0")
343  && LoadRequiredExtension(mgr, "GL_VERSION_1_5")
344  && LoadRequiredExtension(mgr, "GL_ARB_vertex_buffer_object"));
345 }
346 
348 {
349  this->safeIndex(index).SetBuffer(buffer);
350 }
351 
353 {
354  this->safeIndex(index).SetBuffer(buffer);
355 }
356 
357 void TextureSlicePainter::SetColorAttribute(int index, float window, float level, float llr,float alpha)
358 {
359  this->safeIndex(index).SetColorAttribute(window, level, llr, alpha);
360 }
361 
363 {
364 }
365 
366 void TextureSlicePainter::PrintSelf(ostream& os, vtkIndent indent)
367 {
368 }
369 
370 SingleVolumePainterHelper& TextureSlicePainter::safeIndex(int index)
371 {
372  if ((int)mElement.size() <= index)
373  {
374  mElement.resize(index+1);
375  mElement[index] = SingleVolumePainterHelper(index);
376  }
377  return mElement[index];
378 }
379 
380 void TextureSlicePainter::buildProgram(QString shaderSource, vtkOpenGLRenderWindow* renderWindow)
381 {
382  vtkShaderProgram2Ptr pgm = vtkShaderProgram2Ptr::New();
383  pgm->SetContext(renderWindow);
384 
385  vtkShader2Ptr s2 = vtkShader2Ptr::New();
386  s2->SetType(VTK_SHADER_TYPE_FRAGMENT);
387  s2->SetSourceCode(cstring_cast(shaderSource));
388  s2->SetContext(pgm->GetContext());
389  pgm->GetShaders()->AddItem(s2);
390  report_gl_error();
391  pgm->Build();
392 
393  if (pgm->GetLastBuildStatus() != VTK_SHADER_PROGRAM2_LINK_SUCCEEDED)
394  {
395  vtkErrorMacro("Pass Two failed.");
396  abort();
397  }
398 
399  this->Shader = pgm;
400 }
401 
403 {
404  if (this->Shader != 0)
405  {
406  this->Shader->ReleaseGraphicsResources();
407  this->Shader = 0;
408  }
409 }
410 
411 
412 //---------------------------------------------------------
413 }//end namespace
414 //---------------------------------------------------------
415 
416 #endif //CX_VTK_OPENGL2
417 //#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