CustusX  2023.01.05-dev+develop.0da12
An IGT application
vtkfixture.cpp
Go to the documentation of this file.
1 #include "vtkfixture.h"
2 
3 //VTK
4 #include <vtkCubeSource.h>
5 #include <vtkOpenGLPolyDataMapper.h>
6 #include <vtkActor.h>
7 #include <vtkRenderer.h>
8 #include <vtkProperty.h>
9 #include <vtkCamera.h>
10 #include <vtkOpenGLRenderWindow.h>
11 #include <vtkRenderWindowInteractor.h>
12 #include <vtkNew.h>
13 #include <vtkTextureObject.h>
14 #include <vtkOpenGLVertexArrayObject.h>
15 #include <vtkOpenGLProperty.h>
16 #include <vtkOpenGLBufferObject.h>
17 
18 #include "cxGLHelpers.h"
19 
20 #include "texture.h"
21 #include "shadercallback.h"
22 
24 {
25 
26 }
27 
28 void vtkfixture::printActiveVertexAndFragmentShader(vtkSmartPointer<vtkOpenGLPolyDataMapper> mapper)
29 {
30  char *vertexShader = mapper->GetVertexShaderCode();
31  if(vertexShader)
32  {
33  std::cout << "VERTEX SHADER:" << std::endl;
34  std::cout << vertexShader << std::endl;
35  }
36 
37  char *fragmentShader = mapper->GetFragmentShaderCode();
38  if(fragmentShader)
39  {
40  std::cout << "FRAGMENT SHADER:" << std::endl;
41  std::cout << fragmentShader << std::endl;
42  }
43 }
44 
45 void vtkfixture::printOpenGLVersion()
46 {
47  const GLubyte* version = glGetString(GL_VERSION);
48  std::cout << "OpenGL version " << version << std::endl;
49 }
50 
51 
52 void vtkfixture::printVtkOpenGLRenderWindowInfo(vtkSmartPointer<vtkOpenGLRenderWindow> opengl_renderwindow)
53 {
54  std::cout << "context support for open gl core 3.2: " << vtkOpenGLRenderWindow::GetContextSupportsOpenGL32() << std::endl;
55  std::cout << "context was created at: " << opengl_renderwindow->GetContextCreationTime() << std::endl;
57 }
58 
59 vtkSmartPointer<vtkTextureObject> vtkfixture::createTextureObject(unsigned int width, unsigned int height, unsigned int depth, int dataType, int numComps, void *data, vtkSmartPointer<vtkOpenGLRenderWindow> opengl_renderwindow)
60 {
61  vtkNew<vtkTextureObject> texture_object;
62  texture_object->SetContext(opengl_renderwindow);
63 
64  if(!texture_object->Create3DFromRaw(width, height, depth, numComps, dataType, data))
65  std::cout << "---------------------------------------- > Error creating 3D texture" << std::endl;
66 
67  //6403 == GL_RED 0x1903
68  //6407 == GL_RGB 0x1907
69  //6408 == GL_RGBA 0x1908
70  std::cout << texture_object->GetFormat(dataType, numComps, true) << std::endl;
71 
72  texture_object->Activate();
73 
74  texture_object->SetWrapS(vtkTextureObject::ClampToEdge);
75  texture_object->SetWrapT(vtkTextureObject::ClampToEdge);
76  texture_object->SetWrapR(vtkTextureObject::ClampToEdge);
77  texture_object->SetMagnificationFilter(vtkTextureObject::Linear);
78  texture_object->SetMinificationFilter(vtkTextureObject::Linear);
79  texture_object->SendParameters();
80 
81  std::cout << "Texture unit: " << texture_object->GetTextureUnit() << std::endl;
82  texture_object->PrintSelf(std::cout, vtkIndent(4));
83 
85 
86  return texture_object.Get();
87 }
88 
89 vtkSmartPointer<vtkOpenGLBufferObject> vtkfixture::allocateAndUploadArrayBuffer(int numberOfLines, int numberOfComponentsLine, const GLfloat *data)
90 {
91  vtkNew<vtkOpenGLBufferObject> buffer_object;
92  std::cout << "ALLOCATING BUFFER" << std::endl;
93  buffer_object->GenerateBuffer(vtkOpenGLBufferObject::ArrayBuffer);
94  if(!buffer_object->Bind())
95  std::cout << "buffer object not bind" << std::endl;
97 
98  std::cout << "UPLOADING" << std::endl;
99  if(!buffer_object->Upload(
100  data,
101  numberOfLines*numberOfComponentsLine, //how many floats to upload! (aka number of floats in the vector)
102  vtkOpenGLBufferObject::ArrayBuffer
103  ))
104  {
105  vtkGenericWarningMacro(<< "Error uploading buffer object data.");
106  }
107  report_gl_error();
108 
109  return buffer_object.Get();
110 }
111 
113 {
114  // --------------------------------------------------------------------------------
115 
116  //===========
117  // Create mesh
118  //===========
119  vtkSmartPointer<vtkCubeSource> cube = vtkSmartPointer<vtkCubeSource>::New();
120 
121  // --------------------------------------------------------------------------------
122 
123  //===========
124  // Create mapper
125  //===========
126  // The mapper is responsible for pushing the geometry into the graphics library.
127  // It may also do color mapping, if scalars or other attributes are defined.
128  vtkSmartPointer<vtkOpenGLPolyDataMapper> mapper = vtkSmartPointer<vtkOpenGLPolyDataMapper>::New();
129  mapper->SetInputConnection(cube->GetOutputPort());
130 
131  // --------------------------------------------------------------------------------
132 
133  //===========
134  // Modify vertex shader declarations
135  //===========
136  mapper->AddShaderReplacement(
137  vtkShader::Vertex,
138  "//VTK::PositionVC::Dec", // replace the normal block
139  true, // before the standard replacements
140  "//VTK::PositionVC::Dec\n" // we still want the default
141  "attribute vec3 COLOR_VSIN;\n"
142  "attribute vec3 TEXTURE_COORDINATE_VSIN;\n"
143  "varying vec3 COLOR_VSOUT;\n"
144  "varying vec3 TEXTURE_COORDINATE_VSOUT;\n",
145  false // only do it once
146  );
147 
148  //===========
149  // Modify vertex shader implementations
150  //===========
151  mapper->AddShaderReplacement(
152  vtkShader::Vertex,
153  "//VTK::PositionVC::Impl", // replace the normal block
154  true, // before the standard replacements
155  "//VTK::PositionVC::Impl\n" // we still want the default
156  "COLOR_VSOUT = COLOR_VSIN;\n"
157  "TEXTURE_COORDINATE_VSOUT = TEXTURE_COORDINATE_VSIN;\n",
158  false // only do it once
159  );
160 
161  // --------------------------------------------------------------------------------
162 
163  //===========
164  // Replace the fragment shader
165  //===========
166  std::string fragment_shader =
167  "//VTK::System::Dec\n" // always start with this line
168  "//VTK::Output::Dec\n" // always have this line in your FS
169  "in vec3 COLOR_VSOUT;\n"
170  "in vec3 TEXTURE_COORDINATE_VSOUT;\n"
171  "uniform sampler3D my_texture_1;\n"
172  "uniform sampler3D my_texture_2;\n"
173  "out vec4 color;\n"
174  "void main () {\n"
175  " vec4 color_1 = texture(my_texture_1, TEXTURE_COORDINATE_VSOUT);\n"
176  " vec4 color_2 = texture(my_texture_2, TEXTURE_COORDINATE_VSOUT);\n"
177  " color = vec4(color_1.xy, color_2.zw);\n"
178  "}\n";
179  mapper->SetFragmentShaderCode(fragment_shader.c_str());
180  //printActiveVertexAndFragmentShader(mapper);
181 
182  // --------------------------------------------------------------------------------
183 
184  //===========
185  // Create an actor for the mesh
186  //===========
187  // The actor is a grouping mechanism: besides the geometry (mapper), it
188  // also has a property, transformation matrix, and/or texture map.
189  // Here we set its color and rotate it around the X and Y axes.
190  vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
191  actor->SetMapper(mapper);
192  //actor->GetProperty()->SetColor(1.0000, 0.3882, 0.2784);
193  actor->RotateX(30.0);
194  actor->RotateY(-45.0);
195 
196  // --------------------------------------------------------------------------------
197 
198  //===========
199  // Create the renderer
200  //===========
201  // The renderer generates the image
202  // which is then displayed on the render window.
203  // It can be thought of as a scene to which the actor is added
204  vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
205  renderer->AddActor(actor);
206  renderer->SetBackground(0.1, 0.2, 0.4);
207  // Zoom in a little by accessing the camera and invoking its "Zoom" method.
208  renderer->ResetCamera();
209  renderer->GetActiveCamera()->Zoom(1.5);
210 
211  // --------------------------------------------------------------------------------
212 
213  //===========
214  // Create the render window
215  //===========
216  // The render window is the actual GUI window
217  // that appears on the computer screen
218  vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
219  renderWindow->SetSize(200, 200);
220  renderWindow->AddRenderer(renderer);
221 
222  // --------------------------------------------------------------------------------
223 
224  //===========
225  // Create the opengl context
226  //===========
227  // We call Render to create the OpenGL context as it will
228  // be needed by the texture object
229  //http://www.vtk.org/gitweb?p=VTK.git;a=blob;f=Rendering/OpenGL2/Testing/Cxx/TestCubeMap.cxx
230  renderWindow->Render();
231 
232  // --------------------------------------------------------------------------------
233 
234  //===========
235  // Init GLEW
236  //===========
237  GLenum err = glewInit();
238  if (GLEW_OK != err)
239  {
240  // Problem: glewInit failed, something is seriously wrong.
241  fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
242  }
243  fprintf(stdout, "Status: Using GLEW %s\n", glewGetString(GLEW_VERSION));
244  report_gl_error();
245 
246  printOpenGLVersion();
247 
248  // --------------------------------------------------------------------------------
249 
250  //===========
251  // Allocate buffer and upload color data to opengl
252  //===========
253  //Only need to allocate and upload once
254  int my_numberOfColors = numberOfColors;
255  int my_numberOfComponentsPerColor = numberOfComponentsPerColor;
256  const GLfloat *my_color_data = color_data;
257  vtkSmartPointer<vtkOpenGLBufferObject> color_buffer_object = allocateAndUploadArrayBuffer(my_numberOfColors, my_numberOfComponentsPerColor, my_color_data);
258 
259  // --------------------------------------------------------------------------------
260 
261  //===========
262  // Allocate buffer and upload texture coordinate data to opengl
263  //===========
264  //Only need to allocate and upload once
265  int my_numberOfTextureCoordinates = numberOfTextureCoordinates;
266  int my_numberOfComponentsPerTexture = numberOfComponentsPerTexture;
267  const GLfloat *my_texture_data = texture_data;
268  vtkSmartPointer<vtkOpenGLBufferObject> texture_buffer_object = allocateAndUploadArrayBuffer(my_numberOfTextureCoordinates, my_numberOfComponentsPerTexture, my_texture_data);
269 
270  // --------------------------------------------------------------------------------
271 
272  //===========
273  // Get OpenGLRenderWindow to be able to make its context current
274  //===========
275  vtkSmartPointer<vtkOpenGLRenderWindow> opengl_renderwindow = vtkOpenGLRenderWindow::SafeDownCast(renderWindow.Get());
276  if(!opengl_renderwindow)
277  std::cout << "not opengl_renderwindow" << std::endl;
278  else
279  {
280  printVtkOpenGLRenderWindowInfo(opengl_renderwindow);
281  }
282  //opengl_renderwindow->MakeCurrent(); //set current context
283 
284  // --------------------------------------------------------------------------------
285 
286  //===========
287  // Create 3D texture objects
288  //===========
289  std::cout << "ALLOCATING AND UPLOADING TEXTURE OBJECT" << std::endl;
290  unsigned int width = 4;
291  unsigned int height = 4;
292  unsigned int depth = 4;
293 
294  int numComps = 3;
295  int dataType = VTK_FLOAT;
296  void *data1 = (void*)color_data; //numComps=3, dataType = VTK_FLOAT //4*4*4*3 = 192 < 243 (see shadercallback.h) (WORKS!!!)
297  vtkSmartPointer<vtkTextureObject> texture_object_1 = createTextureObject(width, height, depth, dataType, numComps, data1, opengl_renderwindow);
298 
299  numComps = 4;
300  dataType = VTK_UNSIGNED_CHAR;
301  void *data2 = generateTexture<unsigned char>(width, height, depth, 200, 140, 0, 200); //numComps=4, dataType=VTK_UNSIGNED_CHAR (WORKS!!!)
302  //void *data2 = generateTexture<float>(width, height, depth, 0.5f, 0.1f, 0.2f, 1.0f); //numComps=4, dataType=VTK_FLOAT (WORKS!!!)
303  vtkSmartPointer<vtkTextureObject> texture_object_2 = createTextureObject(width, height, depth, dataType, numComps, data2, opengl_renderwindow);
304 
305  // --------------------------------------------------------------------------------
306 
307  //===========
308  // Setup a callback to change some uniforms and attributes
309  //===========
310  vtkSmartPointer<ShaderCallback> callback = vtkSmartPointer<ShaderCallback>::New();
311  callback->mRenderWindow = opengl_renderwindow; //used to set current context
312  //callback->mCube = cube; // not used
313  callback->mColorBufferObject = color_buffer_object; //used to set in/attribute COLOR_VSIN in vertex shader
314  callback->mTextureBufferObject = texture_buffer_object; //used to set in/attribute TEXTURE_COORDINATE_VSIN in vertex shader
315  callback->mTextureObject1 = texture_object_1; //used to set sampler in frament shader
316  callback->mTextureObject2 = texture_object_2; //used to set sampler in frament shader
317 
318  mapper->AddObserver(vtkCommand::UpdateShaderEvent,callback);
319 
320  // --------------------------------------------------------------------------------
321 
322  //===========
323  // Setup a render window interactor
324  //===========
325  // The render window interactor captures mouse events
326  // and will perform appropriate camera or actor manipulation
327  // depending on the nature of the events.
328  vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
329  renderWindowInteractor->SetRenderWindow(renderWindow);
330 
331  // --------------------------------------------------------------------------------
332 
333  //===========
334  // Render
335  //===========
336  // This starts the event loop and as a side effect causes an initial render.
337  renderWindowInteractor->Start();
338 
339  // --------------------------------------------------------------------------------
340 
341  //===========
342  // Clean up
343  //===========
344  renderer->ReleaseGraphicsResources(renderWindow);
345 
346  //TODO:
347  //delete texture coordinate buffer
348  //delete color buffer
349  //delete texture object1
350  //delete texture object2
351 
352  // --------------------------------------------------------------------------------
353 }
354 
vtkSmartPointer< class vtkTextureObject > createTextureObject(unsigned int width, unsigned int height, unsigned int depth, int dataType, int numComps, void *data, vtkSmartPointer< class vtkOpenGLRenderWindow > opengl_renderwindow)
Definition: vtkfixture.cpp:59
void createVTKWindowWithCylinderSourceWith3DTexture()
Definition: vtkfixture.cpp:112
vtkSmartPointer< class vtkOpenGLBufferObject > allocateAndUploadArrayBuffer(int my_numberOfTextureCoordinates, int numberOfComponentsPerTexture, const GLfloat *texture_data)
Definition: vtkfixture.cpp:89
#define report_gl_error()
Definition: cxGLHelpers.h:28