You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
402 lines
14 KiB
C++
402 lines
14 KiB
C++
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
|
|
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
|
|
All rights reserved.
|
|
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
|
|
|
|
This software is distributed WITHOUT ANY WARRANTY; without even
|
|
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
PURPOSE. See the above copyright notice for more information.
|
|
|
|
=========================================================================*/
|
|
/**
|
|
* @class vtkShaderProgram
|
|
* @brief a glsl shader program
|
|
*
|
|
* This class contains the vertex, fragment, geometry shaders that combine to make a shader program
|
|
*/
|
|
|
|
#ifndef vtkShaderProgram_h
|
|
#define vtkShaderProgram_h
|
|
|
|
#include "vtkObject.h"
|
|
#include "vtkRenderingOpenGL2Module.h" // for export macro
|
|
|
|
#include <map> // For member variables.
|
|
#include <string> // For member variables.
|
|
|
|
class vtkMatrix3x3;
|
|
class vtkMatrix4x4;
|
|
class vtkTransformFeedback;
|
|
class vtkShader;
|
|
class VertexArrayObject;
|
|
class vtkWindow;
|
|
|
|
/**
|
|
* @brief The ShaderProgram uses one or more Shader objects.
|
|
*
|
|
* This class creates a Vertex or Fragment shader, that can be attached to a
|
|
* ShaderProgram in order to render geometry etc.
|
|
*/
|
|
|
|
class VTKRENDERINGOPENGL2_EXPORT vtkShaderProgram : public vtkObject
|
|
{
|
|
public:
|
|
static vtkShaderProgram* New();
|
|
vtkTypeMacro(vtkShaderProgram, vtkObject);
|
|
void PrintSelf(ostream& os, vtkIndent indent) override;
|
|
|
|
//@{
|
|
/**
|
|
* Get the vertex shader for this program
|
|
*/
|
|
vtkGetObjectMacro(VertexShader, vtkShader);
|
|
void SetVertexShader(vtkShader*);
|
|
//@}
|
|
|
|
//@{
|
|
/**
|
|
* Get the fragment shader for this program
|
|
*/
|
|
vtkGetObjectMacro(FragmentShader, vtkShader);
|
|
void SetFragmentShader(vtkShader*);
|
|
//@}
|
|
|
|
//@{
|
|
/**
|
|
* Get the geometry shader for this program
|
|
*/
|
|
vtkGetObjectMacro(GeometryShader, vtkShader);
|
|
void SetGeometryShader(vtkShader*);
|
|
//@}
|
|
|
|
//@{
|
|
/**
|
|
* Get/Set a TransformFeedbackCapture object on this shader program.
|
|
*/
|
|
vtkGetObjectMacro(TransformFeedback, vtkTransformFeedback);
|
|
void SetTransformFeedback(vtkTransformFeedback* tfc);
|
|
//@}
|
|
|
|
//@{
|
|
/**
|
|
* Set/Get flag for if this program is compiled
|
|
*/
|
|
vtkGetMacro(Compiled, bool);
|
|
vtkSetMacro(Compiled, bool);
|
|
vtkBooleanMacro(Compiled, bool);
|
|
//@}
|
|
|
|
/**
|
|
* Set/Get the md5 hash of this program
|
|
*/
|
|
std::string GetMD5Hash() const { return this->MD5Hash; }
|
|
void SetMD5Hash(const std::string& hash) { this->MD5Hash = hash; }
|
|
|
|
/** Options for attribute normalization. */
|
|
enum NormalizeOption
|
|
{
|
|
/// The values range across the limits of the numeric type.
|
|
/// This option instructs the rendering engine to normalize them to
|
|
/// the range [0.0, 1.0] for unsigned types, and [-1.0, 1.0] for signed
|
|
/// types.
|
|
/// For example, unsigned char values will be mapped so that 0 = 0.0,
|
|
/// and 255 = 1.0.
|
|
/// The resulting floating point numbers will be passed into
|
|
/// the shader program.
|
|
Normalize,
|
|
/// The values should be used as-is. Do not perform any normalization.
|
|
NoNormalize
|
|
};
|
|
|
|
/**
|
|
* Check if the program is currently bound, or not.
|
|
* @return True if the program is bound, false otherwise.
|
|
*/
|
|
bool isBound() const { return this->Bound; }
|
|
|
|
/**
|
|
* release any graphics resources this class is using.
|
|
*/
|
|
void ReleaseGraphicsResources(vtkWindow* win);
|
|
|
|
/** Get the handle of the shader program. */
|
|
int GetHandle() const { return Handle; }
|
|
|
|
/** Get the error message (empty if none) for the shader program. */
|
|
std::string GetError() const { return Error; }
|
|
|
|
/**
|
|
* Enable the named attribute array. Return false if the attribute array is
|
|
* not contained in the linked shader program.
|
|
*/
|
|
bool EnableAttributeArray(const char* name);
|
|
|
|
/**
|
|
* Disable the named attribute array. Return false if the attribute array is
|
|
* not contained in the linked shader program.
|
|
*/
|
|
bool DisableAttributeArray(const char* name);
|
|
|
|
/**
|
|
* Use the named attribute array with the bound BufferObject.
|
|
* @param name of the attribute (as seen in the shader program).
|
|
* @param offset into the bound BufferObject.
|
|
* @param stride The stride of the element access (i.e. the size of each
|
|
* element in the currently bound BufferObject). 0 may be used to indicate
|
|
* tightly packed data.
|
|
* @param elementType Tag identifying the memory representation of the
|
|
* element.
|
|
* @param elementTupleSize The number of elements per vertex (e.g. a 3D
|
|
* position attribute would be 3).
|
|
* @param normalize Indicates the range used by the attribute data.
|
|
* See NormalizeOption for more information.
|
|
* @return false if the attribute array does not exist.
|
|
*/
|
|
bool UseAttributeArray(const char* name, int offset, size_t stride, int elementType,
|
|
int elementTupleSize, NormalizeOption normalize);
|
|
|
|
/**
|
|
* Upload the supplied array of tightly packed values to the named attribute.
|
|
* BufferObject attributes should be preferred and this may be removed in
|
|
* future.
|
|
*
|
|
* @param name Attribute name
|
|
* @param array Container of data. See note.
|
|
* @param tupleSize The number of elements per vertex, e.g. a 3D coordinate
|
|
* array will have a tuple size of 3.
|
|
* @param normalize Indicates the range used by the attribute data.
|
|
* See NormalizeOption for more information.
|
|
*
|
|
* @note The T type must have tightly packed values of
|
|
* T::value_type accessible by reference via T::operator[].
|
|
* Additionally, the standard size() and empty() methods must be implemented.
|
|
* The std::vector classes is an example of such a container.
|
|
*/
|
|
template <class T>
|
|
bool SetAttributeArray(
|
|
const char* name, const T& array, int tupleSize, NormalizeOption normalize);
|
|
|
|
/** Set the @p name uniform value to int @p v. */
|
|
bool SetUniformi(const char* name, int v);
|
|
bool SetUniformf(const char* name, float v);
|
|
bool SetUniform2i(const char* name, const int v[2]);
|
|
bool SetUniform2f(const char* name, const float v[2]);
|
|
bool SetUniform3f(const char* name, const float v[3]);
|
|
bool SetUniform3f(const char* name, const double v[3]);
|
|
bool SetUniform4f(const char* name, const float v[4]);
|
|
bool SetUniform3uc(const char* name, const unsigned char v[3]); // maybe remove
|
|
bool SetUniform4uc(const char* name, const unsigned char v[4]); // maybe remove
|
|
bool SetUniformMatrix(const char* name, vtkMatrix3x3* v);
|
|
bool SetUniformMatrix(const char* name, vtkMatrix4x4* v);
|
|
bool SetUniformMatrix3x3(const char* name, float* v);
|
|
bool SetUniformMatrix4x4(const char* name, float* v);
|
|
|
|
/** Set the @p name uniform array to @p f with @p count elements */
|
|
bool SetUniform1iv(const char* name, const int count, const int* f);
|
|
bool SetUniform1fv(const char* name, const int count, const float* f);
|
|
bool SetUniform2fv(const char* name, const int count, const float* f);
|
|
bool SetUniform2fv(const char* name, const int count, const float (*f)[2]);
|
|
bool SetUniform3fv(const char* name, const int count, const float* f);
|
|
bool SetUniform3fv(const char* name, const int count, const float (*f)[3]);
|
|
bool SetUniform4fv(const char* name, const int count, const float* f);
|
|
bool SetUniform4fv(const char* name, const int count, const float (*f)[4]);
|
|
bool SetUniformMatrix4x4v(const char* name, const int count, float* v);
|
|
|
|
// How many outputs does this program produce
|
|
// only valid for OpenGL 3.2 or later
|
|
vtkSetMacro(NumberOfOutputs, unsigned int);
|
|
|
|
/**
|
|
* perform in place string substitutions, indicate if a substitution was done
|
|
* this is useful for building up shader strings which typically involve
|
|
* lots of string substitutions.
|
|
*
|
|
* \param[in] shader The source shader object to perform substitutions on
|
|
* \param[in] search The string to search for
|
|
* \param[in] replace The string replacement
|
|
* \param[in] all Whether to replace all matches or just the first one
|
|
* \return A boolean indicating whether the replacement was successful
|
|
*/
|
|
static bool Substitute(
|
|
std::string& source, const std::string& search, const std::string& replace, bool all = true);
|
|
|
|
/**
|
|
* Perform in-place string substitutions on the shader source string and
|
|
* indicate if one or all substitutions were done. This is useful for building
|
|
* up shader strings which typically involve a lot of string substitutions.
|
|
*
|
|
* \param[in] shader The source shader object to perform substitutions on
|
|
* \param[in] search The string to search for
|
|
* \param[in] replace The string replacement
|
|
* \param[in] all Whether to replace all matches or just the first one
|
|
* \return A boolean indicating whether the replacement was successful
|
|
*/
|
|
static bool Substitute(
|
|
vtkShader* shader, const std::string& search, const std::string& replace, bool all = true);
|
|
|
|
/**
|
|
* methods to inquire as to what uniforms/attributes are used by
|
|
* this shader. This can save some compute time if the uniforms
|
|
* or attributes are expensive to compute
|
|
*/
|
|
bool IsUniformUsed(const char*);
|
|
|
|
/**
|
|
* Return true if the compiled and linked shader has an attribute matching @a
|
|
* name.
|
|
*/
|
|
bool IsAttributeUsed(const char* name);
|
|
|
|
// maps of std::string are super slow when calling find
|
|
// with a string literal or const char * as find
|
|
// forces construction/copy/destruction of a
|
|
// std::string copy of the const char *
|
|
// In spite of the doubters this can really be a
|
|
// huge CPU hog.
|
|
struct cmp_str
|
|
{
|
|
bool operator()(const char* a, const char* b) const { return strcmp(a, b) < 0; }
|
|
};
|
|
|
|
//@{
|
|
/**
|
|
* When developing shaders, it's often convenient to tweak the shader and
|
|
* re-render incrementally. This provides a mechanism to do the same. To debug
|
|
* any shader program, set `FileNamePrefixForDebugging` to a file path e.g.
|
|
* `/tmp/myshaders`. Subsequently, when `Bind()` is called on the shader
|
|
* program, it will check for files named `<FileNamePrefixForDebugging>VS.glsl`,
|
|
* `<FileNamePrefixForDebugging>GS.glsl` and `<FileNamePrefixForDebugging>FS.glsl` for
|
|
* vertex shader, geometry shader and fragment shader codes respectively. If
|
|
* a file doesn't exist, then it dumps out the current code to that file.
|
|
* If the file exists, then the shader is recompiled to use the contents of that file.
|
|
* Thus, after the files have been dumped in the first render, you can open the files
|
|
* in a text editor and update as needed. On following render, the modified
|
|
* contexts from the file will be used.
|
|
*
|
|
* This is only intended for debugging during development and should not be
|
|
* used in production.
|
|
*/
|
|
vtkSetStringMacro(FileNamePrefixForDebugging);
|
|
vtkGetStringMacro(FileNamePrefixForDebugging);
|
|
//@}
|
|
|
|
//@{
|
|
/**
|
|
* Set/Get times that can be used to track when a set of
|
|
* uniforms was last updated. This can be used to reduce
|
|
* redundant SetUniformCalls
|
|
*/
|
|
enum UniformGroups
|
|
{
|
|
CameraGroup,
|
|
LightingGroup,
|
|
UserGroup, // always will be last
|
|
};
|
|
void SetUniformGroupUpdateTime(int, vtkMTimeType tm);
|
|
vtkMTimeType GetUniformGroupUpdateTime(int);
|
|
//@}
|
|
|
|
// returns the location for a uniform or attribute in
|
|
// this program. Is cached for performance.
|
|
int FindUniform(const char* name);
|
|
int FindAttributeArray(const char* name);
|
|
|
|
protected:
|
|
vtkShaderProgram();
|
|
~vtkShaderProgram() override;
|
|
|
|
/***************************************************************
|
|
* The following functions are only for use by the shader cache
|
|
* which is why they are protected and that class is a friend
|
|
* you need to use the shader cache to compile/link/bind your shader
|
|
* do not try to do it yourself as it will screw up the cache
|
|
***************************************************************/
|
|
friend class vtkOpenGLShaderCache;
|
|
|
|
/**
|
|
* Attach the supplied shader to this program.
|
|
* @note A maximum of one Vertex shader and one Fragment shader can be
|
|
* attached to a shader program.
|
|
* @return true on success.
|
|
*/
|
|
bool AttachShader(const vtkShader* shader);
|
|
|
|
/** Detach the supplied shader from this program.
|
|
* @note A maximum of one Vertex shader and one Fragment shader can be
|
|
* attached to a shader program.
|
|
* @return true on success.
|
|
*/
|
|
bool DetachShader(const vtkShader* shader);
|
|
|
|
/**
|
|
* Compile this shader program and attached shaders
|
|
*/
|
|
virtual int CompileShader();
|
|
|
|
/**
|
|
* Attempt to link the shader program.
|
|
* @return false on failure. Query error to get the reason.
|
|
* @note The shaders attached to the program must have been compiled.
|
|
*/
|
|
bool Link();
|
|
|
|
/**
|
|
* Bind the program in order to use it. If the program has not been linked
|
|
* then link() will be called.
|
|
*/
|
|
bool Bind();
|
|
|
|
/** Releases the shader program from the current context. */
|
|
void Release();
|
|
|
|
/************* end **************************************/
|
|
|
|
vtkShader* VertexShader;
|
|
vtkShader* FragmentShader;
|
|
vtkShader* GeometryShader;
|
|
vtkTransformFeedback* TransformFeedback;
|
|
|
|
// hash of the shader program
|
|
std::string MD5Hash;
|
|
|
|
bool SetAttributeArrayInternal(
|
|
const char* name, void* buffer, int type, int tupleSize, NormalizeOption normalize);
|
|
int Handle;
|
|
int VertexShaderHandle;
|
|
int FragmentShaderHandle;
|
|
int GeometryShaderHandle;
|
|
|
|
bool Linked;
|
|
bool Bound;
|
|
bool Compiled;
|
|
|
|
// for glsl 1.5 or later, how many outputs
|
|
// does this shader create
|
|
// they will be bound in order to
|
|
// fragOutput0 fragOutput1 etc...
|
|
unsigned int NumberOfOutputs;
|
|
|
|
std::string Error;
|
|
|
|
// since we are using const char * arrays we have to
|
|
// free our memory :-)
|
|
void ClearMaps();
|
|
std::map<const char*, int, cmp_str> AttributeLocs;
|
|
std::map<const char*, int, cmp_str> UniformLocs;
|
|
|
|
std::map<int, vtkMTimeType> UniformGroupMTimes;
|
|
|
|
friend class VertexArrayObject;
|
|
|
|
private:
|
|
vtkShaderProgram(const vtkShaderProgram&) = delete;
|
|
void operator=(const vtkShaderProgram&) = delete;
|
|
|
|
char* FileNamePrefixForDebugging;
|
|
};
|
|
|
|
#endif
|