diff options
-rw-r--r-- | include/RenderBackend/OpenGL/PixelShader.hpp | 14 | ||||
-rw-r--r-- | include/RenderBackend/OpenGL/ShaderProgram.hpp | 34 | ||||
-rw-r--r-- | include/RenderBackend/OpenGL/ShaderVec.hpp | 8 | ||||
-rw-r--r-- | include/RenderBackend/OpenGL/VertexShader.hpp | 2 | ||||
-rw-r--r-- | include/Result.hpp | 48 | ||||
-rw-r--r-- | src/RenderBackend/OpenGL/PixelShader.cpp | 44 | ||||
-rw-r--r-- | src/RenderBackend/OpenGL/ShaderProgram.cpp | 103 | ||||
-rw-r--r-- | src/RenderBackend/OpenGL/VertexShader.cpp | 3 | ||||
-rw-r--r-- | src/main.cpp | 5 |
9 files changed, 198 insertions, 63 deletions
diff --git a/include/RenderBackend/OpenGL/PixelShader.hpp b/include/RenderBackend/OpenGL/PixelShader.hpp index 3d33155..b869a8f 100644 --- a/include/RenderBackend/OpenGL/PixelShader.hpp +++ b/include/RenderBackend/OpenGL/PixelShader.hpp @@ -45,27 +45,15 @@ namespace amalgine 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(); + std::string build() const; 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<std::string, i32> pixelAttributes; - std::vector<std::string> pixelAttributeNames; bool mainFuncDefined; }; } diff --git a/include/RenderBackend/OpenGL/ShaderProgram.hpp b/include/RenderBackend/OpenGL/ShaderProgram.hpp new file mode 100644 index 0000000..efeae5b --- /dev/null +++ b/include/RenderBackend/OpenGL/ShaderProgram.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include "VertexShader.hpp" +#include "PixelShader.hpp" +#include "../../Result.hpp" +#include "../../types.hpp" +#include <vector> + +namespace amalgine +{ + class ShaderProgram + { + public: + ShaderProgram(); + + const std::string& getOutputAttributeName(i32 attributeIndex); + ShaderOutputVec4 defineOutputVec4(const std::string &name); + //Result<std::string> addVertexShader(const VertexShader &vertexShader); + //Result<std::string> addPixelShader(const PixelShader &pixelShader); + //void build(); + private: + /* + * 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: + int locationCounter; + i32 maxPixelAttribs; // Could make this static + std::unordered_map<std::string, i32> pixelAttributes; + std::vector<std::string> pixelAttributeNames; + std::vector<u32> shaderIds; + }; +} diff --git a/include/RenderBackend/OpenGL/ShaderVec.hpp b/include/RenderBackend/OpenGL/ShaderVec.hpp index 10e628c..0c0a88a 100644 --- a/include/RenderBackend/OpenGL/ShaderVec.hpp +++ b/include/RenderBackend/OpenGL/ShaderVec.hpp @@ -6,7 +6,7 @@ namespace amalgine { class VertexShader; - class PixelShader; + class ShaderProgram; class ShaderInputVec2 { @@ -62,20 +62,20 @@ namespace amalgine class ShaderOutputVec4 { - friend class PixelShader; + friend class ShaderProgram; public: const std::string& getName() const; void operator=(const ShaderVec4 &shaderVec4); private: - ShaderOutputVec4(PixelShader *_pixelShader, i32 _attributeIndex) : + ShaderOutputVec4(ShaderProgram *_pixelShader, i32 _attributeIndex) : pixelShader(_pixelShader), attributeIndex(_attributeIndex) { } private: - PixelShader *pixelShader; + ShaderProgram *shaderProgram; i32 attributeIndex; }; } diff --git a/include/RenderBackend/OpenGL/VertexShader.hpp b/include/RenderBackend/OpenGL/VertexShader.hpp index ec8be22..3239be2 100644 --- a/include/RenderBackend/OpenGL/VertexShader.hpp +++ b/include/RenderBackend/OpenGL/VertexShader.hpp @@ -48,7 +48,7 @@ namespace amalgine const std::string& getInputAttributeName(i32 attributeIndex); ShaderInputVec2 defineInputVec2(const std::string &name); void defineMain(VertexShaderMainFunc mainFunc); - std::string build(); + std::string build() const; private: void writeHeader(const std::string &code); void writeBody(const std::string &code); diff --git a/include/Result.hpp b/include/Result.hpp new file mode 100644 index 0000000..316e45a --- /dev/null +++ b/include/Result.hpp @@ -0,0 +1,48 @@ +#pragma once + +#include <string> + +namespace amalgine +{ + template <typename T> + class Result + { + public: + static Result<T> Ok(const T &data) + { + Result<T> result; + result.data = data; + result.errorCode = 0; + return result; + } + + static Result<T> Err(const std::string &errorMsg, int errorCode = -1) + { + Result<T> result; + result.errorMsg = errorMsg; + result.errorCode = errorCode; + return result; + } + + template <typename OtherType> + static Result<T> Err(const Result<OtherType> &otherResult) + { + Result<T> result; + result.errorMsg = otherResult.errorMsg; + result.errorCode = otherResult.errorCode; + return result; + } + + bool isOk() const { return errorCode == 0; } + bool isErr() const { return !isOk(); } + operator bool() const { return isOk(); } + + const std::string& getErrorMsg() const { return errorMsg; } + private: + Result(){} + private: + T data; + int errorCode; + std::string errorMsg; + }; +} diff --git a/src/RenderBackend/OpenGL/PixelShader.cpp b/src/RenderBackend/OpenGL/PixelShader.cpp index cbdc842..2a7c913 100644 --- a/src/RenderBackend/OpenGL/PixelShader.cpp +++ b/src/RenderBackend/OpenGL/PixelShader.cpp @@ -1,7 +1,4 @@ #include "../../../include/RenderBackend/OpenGL/PixelShader.hpp" -#include "../../../include/RenderBackend/OpenGL/CommonShader.hpp" -#include "../../../include/RenderBackend/OpenGL/opengl.hpp" -#include <cassert> using namespace std; @@ -31,24 +28,11 @@ namespace amalgine } - PixelShader::PixelShader() : locationCounter(0), mainFuncDefined(false) + PixelShader::PixelShader() : mainFuncDefined(false) { - glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxPixelAttribs); writeHeader("#version 330 core\n\n"); } - const string& PixelShader::getOutputAttributeName(i32 attributeIndex) - { - assert(attributeIndex < pixelAttributeNames.size()); - return pixelAttributeNames[attributeIndex]; - } - - ShaderOutputVec4 PixelShader::defineOutputVec4(const std::string &name) - { - i32 attributeIndex = defineOutputVariable(name, "vec4"); - return ShaderOutputVec4(this, attributeIndex); - } - void PixelShader::defineMain(PixelShaderMainFunc mainFunc) { if(mainFuncDefined) @@ -68,31 +52,7 @@ namespace amalgine writeBody(";\n"); } - i32 PixelShader::defineOutputVariable(const string &variableName, const char *typeName) - { - if(!isShaderVariableNameValid(variableName.c_str())) - throw PixelShaderInvalidAttributeName(variableName); - - if(locationCounter + 1 > maxPixelAttribs) - throw PixelShaderTooManyAttributes(maxPixelAttribs); - - if(pixelAttributes.find(variableName) != pixelAttributes.end()) - throw PixelShaderAttributeAlreadyDefined(variableName); - - i32 attributeIndex = locationCounter; - pixelAttributes[variableName] = locationCounter; - pixelAttributeNames.push_back(variableName); - - ++locationCounter; - writeHeader("out "); - writeHeader(typeName); - writeHeader(" "); - writeHeader(variableName); - writeHeader(";\n"); - return attributeIndex; - } - - string PixelShader::build() + string PixelShader::build() const { std::string result; result.reserve(header.size() + 2 + body.size()); diff --git a/src/RenderBackend/OpenGL/ShaderProgram.cpp b/src/RenderBackend/OpenGL/ShaderProgram.cpp new file mode 100644 index 0000000..892f45e --- /dev/null +++ b/src/RenderBackend/OpenGL/ShaderProgram.cpp @@ -0,0 +1,103 @@ +#include "../../../include/RenderBackend/OpenGL/ShaderProgram.hpp" +#include "../../../include/RenderBackend/OpenGL/CommonShader.hpp" +#include "../../../include/RenderBackend/OpenGL/opengl.hpp" + +using namespace std; + +namespace amalgine +{ + string getShaderCompileLog(GLuint shaderId) + { + string result; + GLint shaderLogLength; + glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &shaderLogLength); + if(shaderLogLength > 0) + { + result.resize(shaderLogLength); + glGetShaderInfoLog(shaderId, shaderLogLength, NULL, &result[0]); + } + return result; + } + + ShaderProgram::ShaderProgram() : locationCounter(0) + { + glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxPixelAttribs); + } + + const string& ShaderProgram::getOutputAttributeName(i32 attributeIndex) + { + assert(attributeIndex < pixelAttributeNames.size()); + return pixelAttributeNames[attributeIndex]; + } + + ShaderOutputVec4 ShaderProgram::defineOutputVec4(const std::string &name) + { + i32 attributeIndex = defineOutputVariable(name, "vec4"); + return ShaderOutputVec4(this, attributeIndex); + } + + i32 ShaderProgram::defineOutputVariable(const string &variableName, const char *typeName) + { + if(!isShaderVariableNameValid(variableName.c_str())) + throw PixelShaderInvalidAttributeName(variableName); + + if(locationCounter + 1 > maxPixelAttribs) + throw PixelShaderTooManyAttributes(maxPixelAttribs); + + if(pixelAttributes.find(variableName) != pixelAttributes.end()) + throw PixelShaderAttributeAlreadyDefined(variableName); + + i32 attributeIndex = locationCounter; + pixelAttributes[variableName] = locationCounter; + pixelAttributeNames.push_back(variableName); + ++locationCounter; + return attributeIndex; + } + + /* + Result<string> ShaderProgram::addVertexShader(const VertexShader &vertexShader) + { + GLuint vertexShaderId = glCreateShader(GL_VERTEX_SHADER); + string verterShaderSource = vertexShader.build(); + const char *verterShaderSourcePtr = verterShaderSource.c_str(); + glShaderSource(vertexShaderId, 1, &verterShaderSourcePtr, NULL); + glCompileShader(vertexShaderId); + shaderIds.push_back(vertexShaderId); + + GLint status; + glGetShaderiv(vertexShaderId, GL_COMPILE_STATUS, &status); + string compileLog = getShaderCompileLog(vertexShaderId); + if(status == GL_TRUE) + return Result<string>::Ok(compileLog); + else + return Result<string>::Err(compileLog); + } + + Result<string> ShaderProgram::addPixelShader(const PixelShader &pixelShader) + { + GLuint fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER); + string fragmentShaderSource = pixelShader.build(); + const char *fragmentShaderSourcePtr = fragmentShaderSource.c_str(); + glShaderSource(fragmentShaderId, 1, &fragmentShaderSourcePtr, NULL); + glCompileShader(fragmentShaderId); + shaderIds.push_back(fragmentShaderId); + + GLint status; + glGetShaderiv(fragmentShaderId, GL_COMPILE_STATUS, &status); + string compileLog = getShaderCompileLog(fragmentShaderId); + if(status == GL_TRUE) + return Result<string>::Ok(compileLog); + else + return Result<string>::Err(compileLog); + } + + void ShaderProgram::build() + { + GLuint shaderProgramId = glCreateProgram(); + for(u32 shaderId : shaderIds) + { + glAttachShader(shaderProgramId, shaderId); + } + } + */ +} diff --git a/src/RenderBackend/OpenGL/VertexShader.cpp b/src/RenderBackend/OpenGL/VertexShader.cpp index b869624..04bf863 100644 --- a/src/RenderBackend/OpenGL/VertexShader.cpp +++ b/src/RenderBackend/OpenGL/VertexShader.cpp @@ -1,7 +1,6 @@ #include "../../../include/RenderBackend/OpenGL/VertexShader.hpp" #include "../../../include/RenderBackend/OpenGL/CommonShader.hpp" #include "../../../include/RenderBackend/OpenGL/opengl.hpp" -#include <cassert> using namespace std; @@ -88,7 +87,7 @@ namespace amalgine return attributeIndex; } - string VertexShader::build() + string VertexShader::build() const { std::string result; result.reserve(header.size() + 2 + body.size()); diff --git a/src/main.cpp b/src/main.cpp index fe48ddf..03222f1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,6 +4,7 @@ #include <glm/glm.hpp> #include "../include/RenderBackend/OpenGL/VertexShader.hpp" #include "../include/RenderBackend/OpenGL/PixelShader.hpp" +#include "../include/RenderBackend/OpenGL/ShaderProgram.hpp" #include "../include/RenderBackend/OpenGL/DeviceMemory.hpp" using namespace amalgine; @@ -54,6 +55,8 @@ int main() DeviceMemory triangle; triangle.copyStatic(vertices); + ShaderProgram shaderProgram; + VertexShader vertexShader; ShaderInputVec2 inputPosition = vertexShader.defineInputVec2("position"); @@ -63,7 +66,7 @@ int main() }); PixelShader pixelShader; - ShaderOutputVec4 outColor = pixelShader.defineOutputVec4("outColor"); + ShaderOutputVec4 outColor = shaderProgram.defineOutputVec4("outColor"); pixelShader.defineMain([&outColor]() { |