#pragma once #ifndef _NB_SHADER #define _NB_SHADER #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace NB { typedef std::pair FileLocation; FileLocation get_file_path(std::string); class ShaderPreprocessorError : public std::runtime_error { public: enum Codes : unsigned char { NONE, FILE_NOT_FOUND, BUILTIN_NOT_FOUND, CUSTOM, UNDEFINED }; const Codes code; ShaderPreprocessorError(const std::string&, const std::string& file="", int line=-1); ShaderPreprocessorError(Codes, const std::string& arg="", const std::string& file="", int line=-1); protected: static std::string errorCodeParser(Codes, const std::string& arg=""); }; class ShaderError : public std::runtime_error { public: ShaderError(const std::string&, const char* shad=nullptr, const std::string& file="", int line=-1); protected: std::string formatString(const std::string&, const char* shad=nullptr, const std::string& file="", int line=-1); }; struct File { FileLocation loc; std::stringstream src; std::map> include_map; }; class ShaderPreprocessor; struct ShaderUnit { friend ShaderPreprocessor; File file; std::stringstream preprocSource; std::map defines; uint8_t vMajor=0, vMinor=0; }; void preprocessor_include(const ShaderPreprocessor&, ShaderUnit&, unsigned int, const std::string&); void preprocessor_define(const ShaderPreprocessor&, ShaderUnit&, unsigned int, const std::string&); void preprocessor_version(const ShaderPreprocessor&, ShaderUnit&, unsigned int, const std::string&); class ShaderPreprocessor { public: typedef ShaderPreprocessorError::Codes Codes; typedef void (*PreprocFunc)(const ShaderPreprocessor&, ShaderUnit&, unsigned int, const std::string&); std::vector AcceptedExtensions = {"frag", "vert", "tess", "geom", "comp", "shad", "glsl"}; std::vector Directories; std::map BuiltIns; std::map Keywords = { {"#include", preprocessor_include}, {"#define", preprocessor_define}, {"#version", preprocessor_version}, {"#ifdef", nullptr}, {"#ifndef", nullptr}, {"#endif", nullptr} }; ShaderPreprocessor(); std::stringstream load(const std::string&) const; std::stringstream loadFromRelative(const std::string&, const std::string& base="") const; std::stringstream loadFromDirectory(const std::string&) const; std::stringstream loadFromBuiltIn(const std::string&) const; void process(std::stringstream&, ShaderUnit&) const; ShaderUnit process(std::stringstream&) const; }; class Shader { public: Shader(const std::stringstream&, const std::stringstream&); Shader(); Shader(const Shader&); Shader& operator=(const Shader&); void use() const; void setBool(const std::string& name, bool value) const; void setInt(const std::string& name, int value) const; void setFloat(const std::string& name, float value) const; void setMat4(const std::string& name, glm::mat4& value) const; unsigned int id; private: }; } #endif