1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4 
5   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
6   All rights reserved.
7   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
8 
9      This software is distributed WITHOUT ANY WARRANTY; without even
10      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11      PURPOSE.  See the above copyright notice for more information.
12 
13 =========================================================================*/
14 /**
15  * @class   vtkShaderProgram
16  * @brief   a glsl shader program
17  *
18  * This class contains the vertex, fragment, geometry shaders that combine to make a shader program
19 */
20 
21 #ifndef vtkShaderProgram_h
22 #define vtkShaderProgram_h
23 
24 #include "vtkRenderingOpenGL2Module.h" // for export macro
25 #include "vtkObject.h"
26 
27 #include <string> // For member variables.
28 #include <map>    // For member variables.
29 
30 class vtkMatrix3x3;
31 class vtkMatrix4x4;
32 class vtkTransformFeedback;
33 class vtkShader;
34 class VertexArrayObject;
35 class vtkWindow;
36 
37 /**
38  * @brief The ShaderProgram uses one or more Shader objects.
39  *
40  * This class creates a Vertex or Fragment shader, that can be attached to a
41  * ShaderProgram in order to render geometry etc.
42  */
43 
44 class VTKRENDERINGOPENGL2_EXPORT vtkShaderProgram : public vtkObject
45 {
46 public:
47   static vtkShaderProgram *New();
48   vtkTypeMacro(vtkShaderProgram, vtkObject);
49   void PrintSelf(ostream& os, vtkIndent indent) override;
50 
51   //@{
52   /**
53    * Get the vertex shader for this program
54    */
55   vtkGetObjectMacro(VertexShader, vtkShader);
56   void SetVertexShader(vtkShader*);
57   //@}
58 
59   //@{
60   /**
61    * Get the fragment shader for this program
62    */
63   vtkGetObjectMacro(FragmentShader, vtkShader);
64   void SetFragmentShader(vtkShader*);
65   //@}
66 
67   //@{
68   /**
69    * Get the geometry shader for this program
70    */
71   vtkGetObjectMacro(GeometryShader, vtkShader);
72   void SetGeometryShader(vtkShader*);
73   //@}
74 
75   //@{
76   /**
77    * Get/Set a TransformFeedbackCapture object on this shader program.
78    */
79   vtkGetObjectMacro(TransformFeedback, vtkTransformFeedback);
80   void SetTransformFeedback(vtkTransformFeedback *tfc);
81   //@}
82 
83   //@{
84   /**
85    * Set/Get flag for if this program is compiled
86    */
87   vtkGetMacro(Compiled, bool);
88   vtkSetMacro(Compiled, bool);
89   vtkBooleanMacro(Compiled, bool);
90   //@}
91 
92   /**
93    * Set/Get the md5 hash of this program
94    */
GetMD5Hash()95   std::string GetMD5Hash() const { return this->MD5Hash; }
SetMD5Hash(const std::string & hash)96   void SetMD5Hash(const std::string &hash) { this->MD5Hash = hash; }
97 
98 
99   /** Options for attribute normalization. */
100   enum NormalizeOption {
101     /// The values range across the limits of the numeric type.
102     /// This option instructs the rendering engine to normalize them to
103     /// the range [0.0, 1.0] for unsigned types, and [-1.0, 1.0] for signed
104     /// types.
105     /// For example, unsigned char values will be mapped so that 0 = 0.0,
106     /// and 255 = 1.0.
107     /// The resulting floating point numbers will be passed into
108     /// the shader program.
109     Normalize,
110     /// The values should be used as-is. Do not perform any normalization.
111     NoNormalize
112   };
113 
114 
115   /**
116    * Check if the program is currently bound, or not.
117    * @return True if the program is bound, false otherwise.
118    */
isBound()119   bool isBound() const { return this->Bound; }
120 
121   /**
122    * release any graphics resources this class is using.
123    */
124   void ReleaseGraphicsResources(vtkWindow *win);
125 
126   /** Get the handle of the shader program. */
GetHandle()127   int GetHandle() const { return Handle; }
128 
129   /** Get the error message (empty if none) for the shader program. */
GetError()130   std::string GetError() const { return Error; }
131 
132   /**
133    * Enable the named attribute array. Return false if the attribute array is
134    * not contained in the linked shader program.
135    */
136   bool EnableAttributeArray(const char *name);
137 
138   /**
139    * Disable the named attribute array. Return false if the attribute array is
140    * not contained in the linked shader program.
141    */
142   bool DisableAttributeArray(const char *name);
143 
144   /**
145    * Use the named attribute array with the bound BufferObject.
146    * @param name of the attribute (as seen in the shader program).
147    * @param offset into the bound BufferObject.
148    * @param stride The stride of the element access (i.e. the size of each
149    * element in the currently bound BufferObject). 0 may be used to indicate
150    * tightly packed data.
151    * @param elementType Tag identifying the memory representation of the
152    * element.
153    * @param elementTupleSize The number of elements per vertex (e.g. a 3D
154    * position attribute would be 3).
155    * @param normalize Indicates the range used by the attribute data.
156    * See NormalizeOption for more information.
157    * @return false if the attribute array does not exist.
158    */
159   bool UseAttributeArray(const char *name, int offset, size_t stride,
160                          int elementType, int elementTupleSize,
161                          NormalizeOption normalize);
162 
163   /**
164    * Upload the supplied array of tightly packed values to the named attribute.
165    * BufferObject attributes should be preferred and this may be removed in
166    * future.
167    *
168    * @param name Attribute name
169    * @param array Container of data. See note.
170    * @param tupleSize The number of elements per vertex, e.g. a 3D coordinate
171    * array will have a tuple size of 3.
172    * @param  normalize Indicates the range used by the attribute data.
173    * See NormalizeOption for more information.
174    *
175    * @note The T type must have tightly packed values of
176    * T::value_type accessible by reference via T::operator[].
177    * Additionally, the standard size() and empty() methods must be implemented.
178    * The std::vector classes is an example of such a container.
179    */
180   template <class T>
181   bool SetAttributeArray(const char *name, const T &array,
182                          int tupleSize, NormalizeOption normalize);
183 
184   /** Set the @p name uniform value to int @p v. */
185   bool SetUniformi(const char *name, int v);
186   bool SetUniformf(const char *name, float v);
187   bool SetUniform2i(const char *name, const int v[2]);
188   bool SetUniform2f(const char *name, const float v[2]);
189   bool SetUniform3f(const char *name, const float v[3]);
190   bool SetUniform3f(const char *name, const double v[3]);
191   bool SetUniform4f(const char *name, const float v[4]);
192   bool SetUniform3uc(const char *name, const unsigned char v[3]); // maybe remove
193   bool SetUniform4uc(const char *name, const unsigned char v[4]); // maybe remove
194   bool SetUniformMatrix(const char *name, vtkMatrix3x3 *v);
195   bool SetUniformMatrix(const char *name, vtkMatrix4x4 *v);
196   bool SetUniformMatrix3x3(const char *name, float *v);
197   bool SetUniformMatrix4x4(const char *name, float *v);
198 
199   /** Set the @p name uniform array to @p f with @p count elements */
200   bool SetUniform1iv(const char *name, const int count, const int *f);
201   bool SetUniform1fv(const char *name, const int count, const float *f);
202   bool SetUniform2fv(const char *name, const int count, const float (*f)[2]);
203   bool SetUniform3fv(const char *name, const int count, const float (*f)[3]);
204   bool SetUniform4fv(const char *name, const int count, const float (*f)[4]);
205   bool SetUniformMatrix4x4v(const char *name, const int count, float *v);
206 
207   // How many outputs does this program produce
208   // only valid for OpenGL 3.2 or later
209   vtkSetMacro(NumberOfOutputs,unsigned int);
210 
211   /**
212    * perform in place string substitutions, indicate if a substitution was done
213    * this is useful for building up shader strings which typically involve
214    * lots of string substitutions.
215    *
216    * \param[in] shader  The source shader object to perform substitutions on
217    * \param[in] search  The string to search for
218    * \param[in] replace The string replacement
219    * \param[in] all     Whether to replace all matches or just the first one
220    * \return    A boolean indicating whether the replacement was successful
221    */
222   static bool Substitute(
223     std::string &source,
224     const std::string &search,
225     const std::string &replace,
226     bool all = true);
227 
228   /**
229    * Perform in-place string substitutions on the shader source string and
230    * indicate if one or all substitutions were done. This is useful for building
231    * up shader strings which typically involve a lot of string substitutions.
232    *
233    * \param[in] shader  The source shader object to perform substitutions on
234    * \param[in] search  The string to search for
235    * \param[in] replace The string replacement
236    * \param[in] all     Whether to replace all matches or just the first one
237    * \return    A boolean indicating whether the replacement was successful
238    */
239   static bool Substitute(
240     vtkShader* shader,
241     const std::string &search,
242     const std::string &replace,
243     bool all = true);
244 
245   /**
246    * methods to inquire as to what uniforms/attributes are used by
247    * this shader.  This can save some compute time if the uniforms
248    * or attributes are expensive to compute
249    */
250   bool IsUniformUsed(const char *);
251 
252   /**
253    * Return true if the compiled and linked shader has an attribute matching @a
254    * name.
255    */
256   bool IsAttributeUsed(const char *name);
257 
258   // maps of std::string are super slow when calling find
259   // with a string literal or const char * as find
260   // forces construction/copy/destruction of a
261   // std::string copy of the const char *
262   // In spite of the doubters this can really be a
263   // huge CPU hog.
264   struct cmp_str
265   {
operatorcmp_str266      bool operator()(const char *a, const char *b) const
267      {
268         return strcmp(a, b) < 0;
269      }
270   };
271 
272   //@{
273   /**
274    * When developing shaders, it's often convenient to tweak the shader and
275    * re-render incrementally. This provides a mechanism to do the same. To debug
276    * any shader program, set `FileNamePrefixForDebugging` to a file path e.g.
277    * `/tmp/myshaders`. Subsequently, when `Bind()` is called on the shader
278    * program, it will check for files named `<FileNamePrefixForDebugging>VS.glsl`,
279    * `<FileNamePrefixForDebugging>GS.glsl` and `<FileNamePrefixForDebugging>FS.glsl` for
280    * vertex shader, geometry shader and fragment shader codes respectively. If
281    * a file doesn't exist, then it dumps out the current code to that file.
282    * If the file exists, then the shader is recompiled to use the contents of that file.
283    * Thus, after the files have been dumped in the first render, you can open the files
284    * in a text editor and update as needed. On following render, the modified
285    * contexts from the file will be used.
286    *
287    * This is only intended for debugging during development and should not be
288    * used in production.
289    */
290   vtkSetStringMacro(FileNamePrefixForDebugging);
291   vtkGetStringMacro(FileNamePrefixForDebugging);
292   //@}
293 
294   //@{
295   /**
296    * Set/Get times that can be used to track when a set of
297    * uniforms was last updated. This can be used to reduce
298    * redundent SetUniformCalls
299    */
300   enum UniformGroups {
301     CameraGroup,
302     LightingGroup,
303     UserGroup, // always will be last
304   };
305   void SetUniformGroupUpdateTime(int, vtkMTimeType tm);
306   vtkMTimeType GetUniformGroupUpdateTime(int);
307   //@}
308 
309   // returns the location for a uniform or attribute in
310   // this program. Is cached for performance.
311   int FindUniform(const char *name);
312   int FindAttributeArray(const char *name);
313 
314 protected:
315   vtkShaderProgram();
316   ~vtkShaderProgram() override;
317 
318   /***************************************************************
319    * The following functions are only for use by the shader cache
320    * which is why they are protected and that class is a friend
321    * you need to use the shader cache to compile/link/bind your shader
322    * do not try to do it yourself as it will screw up the cache
323    ***************************************************************/
324    friend class vtkOpenGLShaderCache;
325 
326     /**
327    * Attach the supplied shader to this program.
328    * @note A maximum of one Vertex shader and one Fragment shader can be
329    * attached to a shader program.
330    * @return true on success.
331    */
332   bool AttachShader(const vtkShader *shader);
333 
334   /** Detach the supplied shader from this program.
335    * @note A maximum of one Vertex shader and one Fragment shader can be
336    * attached to a shader program.
337    * @return true on success.
338    */
339   bool DetachShader(const vtkShader *shader);
340 
341   /**
342    * Compile this shader program and attached shaders
343    */
344   virtual int CompileShader();
345 
346   /**
347    * Attempt to link the shader program.
348    * @return false on failure. Query error to get the reason.
349    * @note The shaders attached to the program must have been compiled.
350    */
351   bool Link();
352 
353   /**
354    * Bind the program in order to use it. If the program has not been linked
355    * then link() will be called.
356    */
357   bool Bind();
358 
359   /** Releases the shader program from the current context. */
360   void Release();
361 
362   /************* end **************************************/
363 
364   vtkShader *VertexShader;
365   vtkShader *FragmentShader;
366   vtkShader *GeometryShader;
367   vtkTransformFeedback *TransformFeedback;
368 
369   // hash of the shader program
370   std::string MD5Hash;
371 
372   bool SetAttributeArrayInternal(const char *name, void *buffer,
373                                  int type, int tupleSize,
374                                  NormalizeOption normalize);
375   int Handle;
376   int VertexShaderHandle;
377   int FragmentShaderHandle;
378   int GeometryShaderHandle;
379 
380   bool Linked;
381   bool Bound;
382   bool Compiled;
383 
384   // for glsl 1.5 or later, how many outputs
385   // does this shader create
386   // they will be bound in order to
387   // fragOutput0 fragOutput1 etc...
388   unsigned int NumberOfOutputs;
389 
390   std::string Error;
391 
392   // since we are using const char * arrays we have to
393   // free our memory :-)
394   void ClearMaps();
395   std::map<const char *, int, cmp_str> AttributeLocs;
396   std::map<const char *, int, cmp_str> UniformLocs;
397 
398   std::map<int, vtkMTimeType> UniformGroupMTimes;
399 
400   friend class VertexArrayObject;
401 
402 private:
403   vtkShaderProgram(const vtkShaderProgram&) = delete;
404   void operator=(const vtkShaderProgram&) = delete;
405 
406   char* FileNamePrefixForDebugging;
407 };
408 
409 
410 #endif
411