Fraxinus  17.12
An IGT application
cxShaderCallback.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 #include "cxShaderCallback.h"
34 
35 #include <vtkShaderProgram.h>
36 #include <vtkShader.h>
37 #include <vtkOpenGLHelper.h>
38 #include <vtkOpenGLVertexArrayObject.h>
39 #include <vtkOpenGLBufferObject.h>
40 #include <vtkTextureObject.h>
41 #include <vtkOpenGLIndexBufferObject.h>
42 #include <vtkOpenGLRenderWindow.h>
43 
44 #include "cxGLHelpers.h"
45 #include "cxLogger.h"
46 #include "GL/glew.h"
47 
48 #ifdef __APPLE__
49 #include <glu.h>
50 #else
51 #include <GL/glu.h>
52 #endif
53 
54 #include "cxOpenGLShaders.h"
55 
56 namespace cx
57 {
58 
59 
61 {
62 }
63 
65 {
66 }
67 
69 {
70  return new ShaderCallback;
71 }
72 
73 void ShaderCallback::printDebugInfo(vtkOpenGLHelper *OpenGLHelper)
74 {
75  if(!OpenGLHelper)
76  {
77  return;
78  }
79 
80  vtkShaderProgram *program = OpenGLHelper->Program;
81  std::cout << "Program is compiled? " << program->GetCompiled() << std::endl;
82  std::cout << "Program is bound? " << program->isBound() << std::endl;
83  std::cout << "IBO index count " << OpenGLHelper->IBO->IndexCount << std::endl;
84  std::string vertexshader = program->GetVertexShader()->GetSource();
85  std::cout << "Vertexshader:\n " << vertexshader << std::endl;
86  std::string fragmentshader = program->GetFragmentShader()->GetSource();
87  std::cout << "Fragmentshader:\n " << fragmentshader << std::endl;
89 }
90 
91 void ShaderCallback::Execute(vtkObject *, unsigned long eventId, void *cbo)
92 {
94 
95  vtkOpenGLHelper *OpenGLHelper = reinterpret_cast<vtkOpenGLHelper*>(cbo);
96 
97  if(!OpenGLHelper || !OpenGLHelper->VAO || !OpenGLHelper->Program)
98  {
99  return;
100  }
101 
102 
103  if(eventId == vtkCommand::UpdateShaderEvent)
104  {
105  report_gl_error();
106 
107 
108  int textures_to_add = this->getNumberOfUploadedTextures();
109 
110  //Bind fragmentshader output variable
111  // (glsl: vec4)
112  if(textures_to_add != 0)
113  {
114  this->bindFSOutputVariable(OpenGLHelper->Program);
115  }
116 
117  report_gl_error();
118 
119  //Bind VAO (Vertext Array Object - aka saved input to the vertex shader)
120  OpenGLHelper->VAO->Bind();
121  report_gl_error();
122 
123  for(int i=0; i< textures_to_add; ++i)
124  {
125  ShaderItemPtr shaderItem = mShaderItems.at(i);
126  // texture coordinates (glsl: vec3)
127  vtkOpenGLBufferObjectPtr texture_coordinates = shaderItem->mTextureCoordinates;
128 
129  if(texture_coordinates)
130  {
131  if(!texture_coordinates->Bind())
132  {
133  CX_LOG_WARNING() << "Could not bind texture coordinates";
134  }
135 
136  this->addArrayToAttributeArray(OpenGLHelper->Program, texture_coordinates, VS_In_Vec3_TextureCoordinate, i);
137  }
138  else
139  {
140  CX_LOG_WARNING() << "NO TEXTURE COORDINATES!";
141  }
142 
143  report_gl_error();
144 
145  // 3D texture pointer (glsl: sampler3D)
146  vtkTextureObjectPtr texture = shaderItem->mTexture;
147 
148  if(texture)
149  {
150  texture->Activate();
151  this->addUniformiArray(OpenGLHelper->Program, getVectorNameFromName(FS_Uniform_3DTexture_Volume, i), texture->GetTextureUnit());
152  }
153  else
154  {
155  CX_LOG_WARNING() << "NO 3D TEXTURE!";
156  }
157 
158  report_gl_error();
159 
160  // 1D texture pointer (glsl: sampler1D)
161  vtkTextureObjectPtr lut = shaderItem->mLUT;
162 
163  if(lut)
164  {
165  lut->Activate();
166  this->addUniformiArray(OpenGLHelper->Program, getVectorNameFromName(FS_Uniform_1DTexture_LUT, i), lut->GetTextureUnit());
167  }
168  else
169  {
170  CX_LOG_WARNING() << "NO 1D TEXTURE!";
171  }
172 
173  report_gl_error();
174 
175  this->addUniformfArray(OpenGLHelper->Program, getVectorNameFromName(FS_Uniform_Window,i), shaderItem->mWindow);
176  this->addUniformfArray(OpenGLHelper->Program, getVectorNameFromName(FS_Uniform_Level,i), shaderItem->mLevel);
177  this->addUniformfArray(OpenGLHelper->Program, getVectorNameFromName(FS_Uniform_LLR,i), shaderItem->mLLR);
178  this->addUniformfArray(OpenGLHelper->Program, getVectorNameFromName(FS_Uniform_Alpha,i), shaderItem->mAlpha);
179  }
180  }
181 
182  report_gl_error();
183 
184 }
185 
187 {
188  ShaderItemPtr item;
189 
190  for(int i=0; i<mShaderItems.size(); ++i)
191  {
192  item = mShaderItems.at(i);
193 
194  if(item->mTextureUid == image_uid)
195  {
196  return item;
197  }
198  }
199 
200  CX_LOG_ERROR() << "COULD NOT FIND THE SHADERITEM";
201  return item;
202 }
203 
205 {
206  return mShaderItems.size();
207 }
208 
210 {
211  mShaderItems.push_back(item);
212 }
213 
215 {
216  mShaderItems.clear();
217 }
218 
227 void ShaderCallback::addArrayToAttributeArray(vtkShaderProgram *program, vtkOpenGLBufferObjectPtr buffer, std::string name, int vector_index)
228 {
229  //--------
230  //This is information about how the texture coordinates are uploaded.
231  int offset = 0;
232  int vec_size = 3;
233  size_t stride = sizeof(float)*vec_size; //is this correct? was *3;
234  int elementType = GL_FLOAT; //VTK_FLOAT
235  bool normalize = false;
236 
237  //CX_LOG_DEBUG() << "Adding attribute called: " << name << " to vector_index: " << vector_index;
238  //--------
239 
240  const GLchar *namePtr = static_cast<const GLchar *>(name.c_str());
241  GLint start_of_vector_index = glGetAttribLocation(program->GetHandle(), namePtr);
242  report_gl_error();
243 
244 
245  if(start_of_vector_index != -1)
246  {
247  GLint position_in_vector_index = start_of_vector_index + vector_index;
248  buffer->Bind();
249 
250  glEnableVertexAttribArray(position_in_vector_index);
251 
252  glVertexAttribPointer(position_in_vector_index,
253  vec_size,
254  elementType,
255  normalize,
256  static_cast<GLsizei>(stride),
257  ((char *)NULL + (offset))
258  );
259  report_gl_error();
260  }
261  else
262  {
263  CX_LOG_ERROR() << "Error setting attribute " << name << " with vector_index " << vector_index;
264  }
265 
266 }
267 
268 void ShaderCallback::addUniformiArray(vtkShaderProgram *program, std::string name, int value)
269 {
270  //Note: Set uniform will fail if the uniform is not present OR active (used inside the program).
271  report_gl_error();
272 
273  //CX_LOG_DEBUG() << "Adding uniform called: " << name << " with value " << value;
274  if(!program->SetUniform1iv(name.c_str(), 1, &value))
275  {
276  CX_LOG_ERROR() << "Could not set uniform named " << name;
277  }
278 
279  report_gl_error();
280 }
281 
282 void ShaderCallback::addUniformfArray(vtkShaderProgram *program, std::string name, float value)
283 {
284  //Note: Set uniform will fail if the uniform is not present OR active (used inside the program).
285  report_gl_error();
286 
287  //CX_LOG_DEBUG() << "Adding uniform called: " << name << " with value " << value;
288  if(!program->SetUniform1fv(name.c_str(), 1, &value))
289  {
290  CX_LOG_ERROR() << "Could not set uniform named " << name;
291  }
292 
293  report_gl_error();
294 }
295 
296 void ShaderCallback::bindFSOutputVariable(vtkShaderProgram *program)
297 {
298  GLint color_frag_out_index = glGetFragDataLocation(program->GetHandle(), FS_Out_Vec4_Color.c_str());
299 
300  if(color_frag_out_index != -1)
301  {
302  glBindFragDataLocation(program->GetHandle(), color_frag_out_index, FS_Out_Vec4_Color.c_str()); //setting output of fragment shader
303  //CX_LOG_DEBUG() << "Binding fragmentshader output to " << FS_Out_Vec4_Color << " at index "<< color_frag_out_index;
304  }
305  else
306  {
307  CX_LOG_ERROR() << "Could not find glGetFragDataLocation for " << FS_Out_Vec4_Color;
308  }
309 }
310 
311 std::string ShaderCallback::getVectorNameFromName(std::string name, int index_of_vector) const
312 {
313  QString fullName = QString("%1[%2]").arg(QString(name.c_str())).arg(index_of_vector);
314  return fullName.toStdString();
315 }
316 
317 }//namespace cx
318 
vtkSmartPointer< class vtkTextureObject > vtkTextureObjectPtr
virtual void Execute(vtkObject *, unsigned long eventId, void *cbo)
vtkSmartPointer< class vtkOpenGLBufferObject > vtkOpenGLBufferObjectPtr
The ShaderCallback class is used to update information sent to our custom OpenGL shaders.
#define CX_LOG_ERROR
Definition: cxLogger.h:120
int getNumberOfUploadedTextures() const
boost::shared_ptr< ShaderItem > ShaderItemPtr
static ShaderCallback * New()
#define CX_LOG_WARNING
Definition: cxLogger.h:119
void add(ShaderItemPtr item)
ShaderItemPtr getShaderItem(QString image_uid) const
#define report_gl_error()
Definition: cxGLHelpers.h:49
Namespace for all CustusX production code.