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