From ca92d8c90f7103db6d7cae4cef49b278d804b474 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Wed, 20 Dec 2017 20:55:05 +0100 Subject: Create shader using c++ code --- include/RenderBackend/OpenGL/CommonShader.hpp | 33 +++++++++++ include/RenderBackend/OpenGL/DeviceMemory.hpp | 27 +++++++++ include/RenderBackend/OpenGL/PixelShader.hpp | 71 +++++++++++++++++++++++ include/RenderBackend/OpenGL/ShaderVec.hpp | 81 +++++++++++++++++++++++++++ include/RenderBackend/OpenGL/VertexShader.hpp | 70 +++++++++++++++++++++++ include/RenderBackend/OpenGL/opengl.hpp | 5 ++ 6 files changed, 287 insertions(+) create mode 100644 include/RenderBackend/OpenGL/CommonShader.hpp create mode 100644 include/RenderBackend/OpenGL/DeviceMemory.hpp create mode 100644 include/RenderBackend/OpenGL/PixelShader.hpp create mode 100644 include/RenderBackend/OpenGL/ShaderVec.hpp create mode 100644 include/RenderBackend/OpenGL/VertexShader.hpp create mode 100644 include/RenderBackend/OpenGL/opengl.hpp (limited to 'include/RenderBackend/OpenGL') diff --git a/include/RenderBackend/OpenGL/CommonShader.hpp b/include/RenderBackend/OpenGL/CommonShader.hpp new file mode 100644 index 0000000..a67aa68 --- /dev/null +++ b/include/RenderBackend/OpenGL/CommonShader.hpp @@ -0,0 +1,33 @@ +#pragma once + +namespace amalgine +{ + static bool isAlpha(char c) + { + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); + } + + static bool isDigit(char c) + { + return c >= '0' && c <= '9'; + } + + static bool isShaderVariableNameValid(const char *variableName) + { + const char *p = &variableName[0]; + if(isAlpha(*p) || *p == '_') + { + ++p; + while(true) + { + char c = *p; + if(c == '\0') + return true; + else if(isAlpha(c) || isDigit(c) || c == '_') + ++p; + } + } + + return false; + } +} diff --git a/include/RenderBackend/OpenGL/DeviceMemory.hpp b/include/RenderBackend/OpenGL/DeviceMemory.hpp new file mode 100644 index 0000000..706529e --- /dev/null +++ b/include/RenderBackend/OpenGL/DeviceMemory.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include "../../DataView.hpp" +#include "../../utils.hpp" + +namespace amalgine +{ + class DeviceMemory + { + DISABLE_COPY(DeviceMemory) + public: + DeviceMemory(); + + // Uploaded once, drawn many times + void copyStatic(const DataView &data); + + // Created once, changed from time to time but drawn many times more than that + void copyDynamic(const DataView &data); + + // Uploaded once, drawn once (for example data that is changed every frame) + void copyStream(const DataView &data); + private: + void copy(const DataView &data, i32 storageType); + private: + u32 vertexBufferObjectId; + }; +} diff --git a/include/RenderBackend/OpenGL/PixelShader.hpp b/include/RenderBackend/OpenGL/PixelShader.hpp new file mode 100644 index 0000000..3d33155 --- /dev/null +++ b/include/RenderBackend/OpenGL/PixelShader.hpp @@ -0,0 +1,71 @@ +#pragma once + +#include "../../DataView.hpp" +#include "ShaderVec.hpp" +#include +#include +#include +#include +#include + +namespace amalgine +{ + class PixelShaderTooManyAttributes : public std::runtime_error + { + public: + PixelShaderTooManyAttributes(i32 maxPixelAttributes); + }; + + class PixelShaderAttributeAlreadyDefined : public std::runtime_error + { + public: + PixelShaderAttributeAlreadyDefined(const std::string &attributeName); + }; + + class PixelShaderInvalidAttributeName : public std::runtime_error + { + public: + PixelShaderInvalidAttributeName(const std::string &attributeName); + }; + + class PixelShaderFunctionAlreadyDefined : public std::runtime_error + { + public: + PixelShaderFunctionAlreadyDefined(const std::string &funcName); + }; + + using PixelShaderMainFunc = std::function; + + /* + * Using the same PixelShader instance in multiple threads to define data is not thread safe. + * All get*** functions are thread safe. + */ + class PixelShader + { + public: + PixelShader(); + + const std::string& getOutputAttributeName(i32 attributeIndex); + ShaderOutputVec4 defineOutputVec4(const std::string &name); + void defineMain(PixelShaderMainFunc mainFunc); + void assign(const ShaderOutputVec4 &lhsVariable, const ShaderVec4 &rhsVariable); + std::string build(); + private: + void writeHeader(const std::string &code); + void writeBody(const std::string &code); + + /* + * Throws PixelShaderTooManyAttributes if too many pixel attributes are defined for the platform. + * Throws PixelShaderAttributeAlreadyDefined if a pixel attribute with the same name has already been defined. + */ + i32 defineOutputVariable(const std::string &variableName, const char *typeName); + private: + std::string header; + std::string body; + int locationCounter; + i32 maxPixelAttribs; // Could make this static + std::unordered_map pixelAttributes; + std::vector pixelAttributeNames; + bool mainFuncDefined; + }; +} diff --git a/include/RenderBackend/OpenGL/ShaderVec.hpp b/include/RenderBackend/OpenGL/ShaderVec.hpp new file mode 100644 index 0000000..10e628c --- /dev/null +++ b/include/RenderBackend/OpenGL/ShaderVec.hpp @@ -0,0 +1,81 @@ +#pragma once + +#include "../../types.hpp" +#include + +namespace amalgine +{ + class VertexShader; + class PixelShader; + + class ShaderInputVec2 + { + friend class VertexShader; + public: + const std::string& getName() const; + private: + ShaderInputVec2(VertexShader *_vertexShader, i32 _attributeIndex) : + vertexShader(_vertexShader), + attributeIndex(_attributeIndex) + { + + } + private: + VertexShader *vertexShader; + i32 attributeIndex; + }; + + class ShaderVec4 + { + public: + ShaderVec4(f32 x = 0.0f, f32 y = 0.0f, f32 z = 0.0f, f32 w = 0.0f) + { + result = "vec4("; + result += std::to_string(x); + result += ", "; + result += std::to_string(y); + result += ", "; + result += std::to_string(z); + result += ", "; + result += std::to_string(w); + result += ")"; + } + + ShaderVec4(const ShaderInputVec2 &vec2, f32 z = 0.0f, f32 w = 0.0f) + { + result = "vec4("; + result += vec2.getName(); + result += ", "; + result += std::to_string(z); + result += ", "; + result += std::to_string(w); + result += ")"; + } + + const std::string& getOutput() const + { + return result; + } + private: + std::string result; + }; + + class ShaderOutputVec4 + { + friend class PixelShader; + public: + const std::string& getName() const; + + void operator=(const ShaderVec4 &shaderVec4); + private: + ShaderOutputVec4(PixelShader *_pixelShader, i32 _attributeIndex) : + pixelShader(_pixelShader), + attributeIndex(_attributeIndex) + { + + } + private: + PixelShader *pixelShader; + i32 attributeIndex; + }; +} diff --git a/include/RenderBackend/OpenGL/VertexShader.hpp b/include/RenderBackend/OpenGL/VertexShader.hpp new file mode 100644 index 0000000..ec8be22 --- /dev/null +++ b/include/RenderBackend/OpenGL/VertexShader.hpp @@ -0,0 +1,70 @@ +#pragma once + +#include "../../DataView.hpp" +#include "ShaderVec.hpp" +#include +#include +#include +#include +#include + +namespace amalgine +{ + class VertexShaderTooManyAttributes : public std::runtime_error + { + public: + VertexShaderTooManyAttributes(i32 maxVertexAttributes); + }; + + class VertexShaderAttributeAlreadyDefined : public std::runtime_error + { + public: + VertexShaderAttributeAlreadyDefined(const std::string &attributeName); + }; + + class VertexShaderInvalidAttributeName : public std::runtime_error + { + public: + VertexShaderInvalidAttributeName(const std::string &attributeName); + }; + + class VertexShaderFunctionAlreadyDefined : public std::runtime_error + { + public: + VertexShaderFunctionAlreadyDefined(const std::string &funcName); + }; + + using VertexShaderMainFunc = std::function; + + /* + * Using the same VertexShader instance in multiple threads to define data is not thread safe. + * All get*** functions are thread safe. + */ + class VertexShader + { + public: + VertexShader(); + + const std::string& getInputAttributeName(i32 attributeIndex); + ShaderInputVec2 defineInputVec2(const std::string &name); + void defineMain(VertexShaderMainFunc mainFunc); + std::string build(); + private: + void writeHeader(const std::string &code); + void writeBody(const std::string &code); + + /* + * Throws VertexShaderTooManyInputAttributes if too many vertex attributes are defined for the platform. + * Throws VertexShaderAttributeAlreadyDefined if a vertex attribute with the same name has already been defined. + */ + i32 defineInputVariable(const std::string &variableName, const char *typeName); + private: + std::string header; + std::string body; + int locationCounter; + i32 maxVertexAttribs; // Could make this static + std::unordered_map vertexAttributes; + std::vector vertexAttributeNames; + bool mainFuncDefined; + }; +} diff --git a/include/RenderBackend/OpenGL/opengl.hpp b/include/RenderBackend/OpenGL/opengl.hpp new file mode 100644 index 0000000..6ea8fcb --- /dev/null +++ b/include/RenderBackend/OpenGL/opengl.hpp @@ -0,0 +1,5 @@ +#pragma once + +#include +#include +#include -- cgit v1.2.3