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