#pragma once
#include "ofConstants.h"
#include "ofFileUtils.h"
#include "glm/fwd.hpp"
#include <unordered_map>
#include <map>
class ofTexture;
class ofMatrix3x3;
class ofParameterGroup;
class ofBufferObject;
class ofBaseHasTexture;
template<typename T>
class ofColor_;
typedef ofColor_<float> ofFloatColor;
enum ofLogLevel: short;
struct ofShaderSettings {
std::map<GLuint, std::filesystem::path> shaderFiles;
std::map<GLuint, std::string> shaderSources;
std::map<std::string, int> intDefines;
std::map<std::string, float> floatDefines;
std::filesystem::path sourceDirectoryPath;
bool bindDefaults = true;
};
class ofShader {
struct Source{
Source(GLuint type, const std::string & source, const std::filesystem::path & directoryPath)
:type(type)
,source(source)
,directoryPath(directoryPath){}
Source(){}
GLuint type;
std::string source;
std::string expandedSource;
std::filesystem::path directoryPath;
std::map<std::string, int> intDefines;
std::map<std::string, float> floatDefines;
};
public:
ofShader();
~ofShader();
ofShader(const ofShader & shader);
ofShader & operator=(const ofShader & shader);
ofShader(ofShader && shader);
ofShader & operator=(ofShader && shader);
bool load(const std::filesystem::path& shaderName);
bool load(const std::filesystem::path& vertName, const std::filesystem::path& fragName, const std::filesystem::path& geomName="");
#if !defined(TARGET_OPENGLES) && defined(glDispatchCompute)
bool loadCompute(const std::filesystem::path& shaderName);
#endif
#if !defined(TARGET_OPENGLES)
struct TransformFeedbackSettings {
std::map<GLuint, std::filesystem::path> shaderFiles;
std::map<GLuint, std::string> shaderSources;
std::vector<std::string> varyingsToCapture;
std::map<std::string, int> intDefines;
std::map<std::string, float> floatDefines;
std::filesystem::path sourceDirectoryPath;
bool bindDefaults = true;
GLuint bufferMode = GL_INTERLEAVED_ATTRIBS;
};
struct TransformFeedbackRangeBinding {
TransformFeedbackRangeBinding(const ofBufferObject & buffer, GLuint offset, GLuint size);
GLuint index = 0;
GLuint offset = 0;
GLuint size;
private:
const ofBufferObject & buffer;
friend class ofShader;
};
struct TransformFeedbackBaseBinding {
TransformFeedbackBaseBinding(const ofBufferObject & buffer);
GLuint index = 0;
private:
const ofBufferObject & buffer;
friend class ofShader;
};
#endif
bool setup(const ofShaderSettings & settings);
#if !defined(TARGET_OPENGLES)
bool setup(const TransformFeedbackSettings & settings);
#endif
void setGeometryInputType(GLenum type);
void setGeometryOutputType(GLenum type);
void setGeometryOutputCount(int count);
int getGeometryMaxOutputCount() const;
void unload();
bool isLoaded() const;
void begin() const;
void end() const;
#if !defined(TARGET_OPENGLES)
void beginTransformFeedback(GLenum mode) const;
void beginTransformFeedback(GLenum mode, const TransformFeedbackRangeBinding & binding) const;
void beginTransformFeedback(GLenum mode, const std::vector<TransformFeedbackRangeBinding> & binding) const;
void beginTransformFeedback(GLenum mode, const TransformFeedbackBaseBinding & binding) const;
void beginTransformFeedback(GLenum mode, const std::vector<TransformFeedbackBaseBinding> & binding) const;
void endTransformFeedback() const;
void endTransformFeedback(const TransformFeedbackRangeBinding & binding) const;
void endTransformFeedback(const std::vector<TransformFeedbackRangeBinding> & binding) const;
void endTransformFeedback(const TransformFeedbackBaseBinding & binding) const;
void endTransformFeedback(const std::vector<TransformFeedbackBaseBinding> & binding) const;
#endif
#if !defined(TARGET_OPENGLES) && defined(glDispatchCompute)
void dispatchCompute(GLuint x, GLuint y, GLuint z) const;
#endif
void setUniformTexture(const std::string & name, const ofBaseHasTexture& img, int textureLocation) const;
void setUniformTexture(const std::string & name, const ofTexture& img, int textureLocation) const;
void setUniformTexture(const std::string & name, int textureTarget, GLint textureID, int textureLocation) const;
void setUniform1i(const std::string & name, int v1) const;
void setUniform2i(const std::string & name, int v1, int v2) const;
void setUniform3i(const std::string & name, int v1, int v2, int v3) const;
void setUniform4i(const std::string & name, int v1, int v2, int v3, int v4) const;
void setUniform1f(const std::string & name, float v1) const;
void setUniform2f(const std::string & name, float v1, float v2) const;
void setUniform3f(const std::string & name, float v1, float v2, float v3) const;
void setUniform4f(const std::string & name, float v1, float v2, float v3, float v4) const;
void setUniform2f(const std::string & name, const glm::vec2 & v) const;
void setUniform3f(const std::string & name, const glm::vec3 & v) const;
void setUniform4f(const std::string & name, const glm::vec4 & v) const;
void setUniform4f(const std::string & name, const ofFloatColor & v) const;
void setUniform1iv(const std::string & name, const int* v, int count = 1) const;
void setUniform2iv(const std::string & name, const int* v, int count = 1) const;
void setUniform3iv(const std::string & name, const int* v, int count = 1) const;
void setUniform4iv(const std::string & name, const int* v, int count = 1) const;
void setUniform1fv(const std::string & name, const float* v, int count = 1) const;
void setUniform2fv(const std::string & name, const float* v, int count = 1) const;
void setUniform3fv(const std::string & name, const float* v, int count = 1) const;
void setUniform4fv(const std::string & name, const float* v, int count = 1) const;
void setUniforms(const ofParameterGroup & parameters) const;
void setUniformMatrix3f(const std::string & name, const glm::mat3 & m, int count = 1) const;
void setUniformMatrix4f(const std::string & name, const glm::mat4 & m, int count = 1) const;
GLint getUniformLocation(const std::string & name) const;
GLint getAttributeLocation(const std::string & name) const;
#ifndef TARGET_OPENGLES
#ifdef GLEW_ARB_uniform_buffer_object
GLint getUniformBlockIndex(const std::string & name) const;
GLint getUniformBlockBinding(const std::string & name) const;
void bindUniformBlock(GLuint bindind, const std::string & name) const;
void printActiveUniformBlocks() const;
#endif
#endif
#ifndef TARGET_OPENGLES
void setAttribute1s(GLint location, short v1) const;
void setAttribute2s(GLint location, short v1, short v2) const;
void setAttribute3s(GLint location, short v1, short v2, short v3) const;
void setAttribute4s(GLint location, short v1, short v2, short v3, short v4) const;
#endif
void setAttribute1f(GLint location, float v1) const;
void setAttribute2f(GLint location, float v1, float v2) const;
void setAttribute3f(GLint location, float v1, float v2, float v3) const;
void setAttribute4f(GLint location, float v1, float v2, float v3, float v4) const;
#ifndef TARGET_OPENGLES
void setAttribute1d(GLint location, double v1) const;
void setAttribute2d(GLint location, double v1, double v2) const;
void setAttribute3d(GLint location, double v1, double v2, double v3) const;
void setAttribute4d(GLint location, double v1, double v2, double v3, double v4) const;
#endif
void setAttribute1fv(const std::string & name, const float* v, GLsizei stride=sizeof(float)) const;
void setAttribute2fv(const std::string & name, const float* v, GLsizei stride=sizeof(float)*2) const;
void setAttribute3fv(const std::string & name, const float* v, GLsizei stride=sizeof(float)*3) const;
void setAttribute4fv(const std::string & name, const float* v, GLsizei stride=sizeof(float)*4) const;
void bindAttribute(GLuint location, const std::string & name) const;
void printActiveUniforms() const;
void printActiveAttributes() const;
bool setupShaderFromSource(GLenum type, std::string source, std::string sourceDirectoryPath = "");
bool setupShaderFromFile(GLenum type, const std::filesystem::path& filename);
bool linkProgram();
bool bindDefaults();
GLuint getProgram() const;
GLuint getShader(GLenum type) const;
bool operator==(const ofShader & other) const;
bool operator!=(const ofShader & other) const;
enum defaultAttributes{
POSITION_ATTRIBUTE=0,
COLOR_ATTRIBUTE,
NORMAL_ATTRIBUTE,
TEXCOORD_ATTRIBUTE,
INDEX_ATTRIBUTE
};
std::string getShaderSource(GLenum type) const;
private:
GLuint program = 0;
bool bLoaded = false;
struct Shader{
GLuint id;
Source source;
};
std::unordered_map<GLenum, Shader> shaders;
std::unordered_map<std::string, GLint> uniformsCache;
mutable std::unordered_map<std::string, GLint> attributesBindingsCache;
#ifndef TARGET_OPENGLES
std::unordered_map<std::string, GLint> uniformBlocksCache;
#endif
bool setupShaderFromSource(Source && source);
ofShader::Source sourceFromFile(GLenum type, const std::filesystem::path& filename);
void checkProgramInfoLog();
bool checkProgramLinkStatus();
void checkShaderInfoLog(GLuint shader, GLenum type, ofLogLevel logLevel);
template<typename T>
void setDefineConstantTemp(const std::string & name, T value);
template<typename T>
void setConstantTemp(const std::string & name, const std::string & type, T value);
static std::string nameForType(GLenum type);
static std::string parseForIncludes( const std::string& source, const std::filesystem::path& sourceDirectoryPath = "");
static std::string parseForIncludes( const std::string& source, std::vector<std::string>& included, int level = 0, const std::filesystem::path& sourceDirectoryPath = "");
void checkAndCreateProgram();
#ifdef TARGET_ANDROID
void unloadGL();
void reloadGL();
#endif
};
Comments