diff options
-rw-r--r-- | README.md | 5 | ||||
-rw-r--r-- | include/RenderBackend/OpenGL/CommonShader.hpp | 11 | ||||
-rw-r--r-- | include/RenderBackend/OpenGL/CompiledShader.hpp | 30 | ||||
-rw-r--r-- | include/RenderBackend/OpenGL/DeviceMemory.hpp | 7 | ||||
-rw-r--r-- | include/RenderBackend/OpenGL/PixelShader.hpp | 23 | ||||
-rw-r--r-- | include/RenderBackend/OpenGL/ShaderProgram.hpp | 40 | ||||
-rw-r--r-- | include/RenderBackend/OpenGL/ShaderVec.hpp | 8 | ||||
-rw-r--r-- | include/RenderBackend/OpenGL/VertexShader.hpp | 9 | ||||
-rw-r--r-- | include/Result.hpp | 11 | ||||
-rw-r--r-- | src/RenderBackend/OpenGL/CommonShader.cpp | 20 | ||||
-rw-r--r-- | src/RenderBackend/OpenGL/CompiledShader.cpp | 37 | ||||
-rw-r--r-- | src/RenderBackend/OpenGL/DeviceMemory.cpp | 11 | ||||
-rw-r--r-- | src/RenderBackend/OpenGL/PixelShader.cpp | 67 | ||||
-rw-r--r-- | src/RenderBackend/OpenGL/ShaderProgram.cpp | 113 | ||||
-rw-r--r-- | src/RenderBackend/OpenGL/ShaderVec.cpp | 3 | ||||
-rw-r--r-- | src/RenderBackend/OpenGL/VertexShader.cpp | 23 | ||||
-rw-r--r-- | src/main.cpp | 128 |
17 files changed, 402 insertions, 144 deletions
@@ -1,2 +1,5 @@ ## Prerequisite -Install glfw3 and glew +glfw3 +glew +glm +sibs (https://github.com/DEC05EBA/sibs) diff --git a/include/RenderBackend/OpenGL/CommonShader.hpp b/include/RenderBackend/OpenGL/CommonShader.hpp index a67aa68..80e63a9 100644 --- a/include/RenderBackend/OpenGL/CommonShader.hpp +++ b/include/RenderBackend/OpenGL/CommonShader.hpp @@ -1,7 +1,16 @@ #pragma once +#include "../../types.hpp" +#include <string> + namespace amalgine { + struct ShaderAttribute + { + std::string name; + const char *typeName; + }; + static bool isAlpha(char c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); @@ -30,4 +39,6 @@ namespace amalgine return false; } + + std::string getShaderCompileLog(u32 shaderId); } diff --git a/include/RenderBackend/OpenGL/CompiledShader.hpp b/include/RenderBackend/OpenGL/CompiledShader.hpp new file mode 100644 index 0000000..67e6418 --- /dev/null +++ b/include/RenderBackend/OpenGL/CompiledShader.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include "../../types.hpp" + +namespace amalgine +{ + class CompiledVertexShader + { + friend class VertexShader; + public: + ~CompiledVertexShader(); + u32 getShaderId() const; + private: + CompiledVertexShader(u32 _shaderId); + private: + u32 shaderId; + }; + + class CompiledPixelShader + { + friend class PixelShader; + public: + ~CompiledPixelShader(); + u32 getShaderId() const; + private: + CompiledPixelShader(u32 _shaderId); + private: + u32 shaderId; + }; +} diff --git a/include/RenderBackend/OpenGL/DeviceMemory.hpp b/include/RenderBackend/OpenGL/DeviceMemory.hpp index 706529e..974c7cf 100644 --- a/include/RenderBackend/OpenGL/DeviceMemory.hpp +++ b/include/RenderBackend/OpenGL/DeviceMemory.hpp @@ -10,15 +10,16 @@ namespace amalgine DISABLE_COPY(DeviceMemory) public: DeviceMemory(); + ~DeviceMemory(); // Uploaded once, drawn many times - void copyStatic(const DataView<f32> &data); + void copyAsStatic(const DataView<f32> &data); // Created once, changed from time to time but drawn many times more than that - void copyDynamic(const DataView<f32> &data); + void copyAsDynamic(const DataView<f32> &data); // Uploaded once, drawn once (for example data that is changed every frame) - void copyStream(const DataView<f32> &data); + void copyAsStream(const DataView<f32> &data); private: void copy(const DataView<f32> &data, i32 storageType); private: diff --git a/include/RenderBackend/OpenGL/PixelShader.hpp b/include/RenderBackend/OpenGL/PixelShader.hpp index b869a8f..e025c6f 100644 --- a/include/RenderBackend/OpenGL/PixelShader.hpp +++ b/include/RenderBackend/OpenGL/PixelShader.hpp @@ -1,6 +1,9 @@ #pragma once #include "../../DataView.hpp" +#include "../../utils.hpp" +#include "../../Result.hpp" +#include "CommonShader.hpp" #include "ShaderVec.hpp" #include <string> #include <unordered_map> @@ -40,20 +43,38 @@ namespace amalgine * Using the same PixelShader instance in multiple threads to define data is not thread safe. * All get*** functions are thread safe. */ + class CompiledPixelShader; + class PixelShader { + DISABLE_COPY(PixelShader) + friend class ShaderProgram; 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() const; + Result<CompiledPixelShader*> compile(); private: void writeHeader(const std::string &code); void writeBody(const std::string &code); + std::string build() const; + + /* + * 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<ShaderAttribute> pixelAttributeNames; bool mainFuncDefined; }; } diff --git a/include/RenderBackend/OpenGL/ShaderProgram.hpp b/include/RenderBackend/OpenGL/ShaderProgram.hpp index efeae5b..a3e8a0f 100644 --- a/include/RenderBackend/OpenGL/ShaderProgram.hpp +++ b/include/RenderBackend/OpenGL/ShaderProgram.hpp @@ -1,34 +1,38 @@ #pragma once -#include "VertexShader.hpp" -#include "PixelShader.hpp" #include "../../Result.hpp" #include "../../types.hpp" +#include "../../utils.hpp" #include <vector> +#include <stdexcept> namespace amalgine { + class CompiledVertexShader; + class CompiledPixelShader; + + class ShaderProgramUsedBeforeBuilt : public std::runtime_error + { + public: + // TODO: Add name to ShaderProgram so we know which shader has issue when + // an exception is thrown? + ShaderProgramUsedBeforeBuilt(); + }; + class ShaderProgram { + DISABLE_COPY(ShaderProgram) public: ShaderProgram(); + ~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); + bool addVertexShader(CompiledVertexShader *vertexShader); + bool addPixelShader(CompiledPixelShader *pixelShader); + + Result<bool> build(); + void use(); 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; + u32 shaderProgramId; + bool built; }; } diff --git a/include/RenderBackend/OpenGL/ShaderVec.hpp b/include/RenderBackend/OpenGL/ShaderVec.hpp index 0c0a88a..10e628c 100644 --- a/include/RenderBackend/OpenGL/ShaderVec.hpp +++ b/include/RenderBackend/OpenGL/ShaderVec.hpp @@ -6,7 +6,7 @@ namespace amalgine { class VertexShader; - class ShaderProgram; + class PixelShader; class ShaderInputVec2 { @@ -62,20 +62,20 @@ namespace amalgine class ShaderOutputVec4 { - friend class ShaderProgram; + friend class PixelShader; public: const std::string& getName() const; void operator=(const ShaderVec4 &shaderVec4); private: - ShaderOutputVec4(ShaderProgram *_pixelShader, i32 _attributeIndex) : + ShaderOutputVec4(PixelShader *_pixelShader, i32 _attributeIndex) : pixelShader(_pixelShader), attributeIndex(_attributeIndex) { } private: - ShaderProgram *shaderProgram; + PixelShader *pixelShader; i32 attributeIndex; }; } diff --git a/include/RenderBackend/OpenGL/VertexShader.hpp b/include/RenderBackend/OpenGL/VertexShader.hpp index 3239be2..43a5dd8 100644 --- a/include/RenderBackend/OpenGL/VertexShader.hpp +++ b/include/RenderBackend/OpenGL/VertexShader.hpp @@ -1,6 +1,8 @@ #pragma once #include "../../DataView.hpp" +#include "../../utils.hpp" +#include "../../Result.hpp" #include "ShaderVec.hpp" #include <string> #include <unordered_map> @@ -40,18 +42,23 @@ namespace amalgine * Using the same VertexShader instance in multiple threads to define data is not thread safe. * All get*** functions are thread safe. */ + class CompiledVertexShader; + class VertexShader { + DISABLE_COPY(VertexShader) + friend class ShaderProgram; public: VertexShader(); const std::string& getInputAttributeName(i32 attributeIndex); ShaderInputVec2 defineInputVec2(const std::string &name); void defineMain(VertexShaderMainFunc mainFunc); - std::string build() const; + Result<CompiledVertexShader*> compile(); private: void writeHeader(const std::string &code); void writeBody(const std::string &code); + std::string build() const; /* * Throws VertexShaderTooManyInputAttributes if too many vertex attributes are defined for the platform. diff --git a/include/Result.hpp b/include/Result.hpp index 316e45a..749d381 100644 --- a/include/Result.hpp +++ b/include/Result.hpp @@ -1,6 +1,7 @@ #pragma once #include <string> +#include <cassert> namespace amalgine { @@ -28,16 +29,22 @@ namespace amalgine static Result<T> Err(const Result<OtherType> &otherResult) { Result<T> result; - result.errorMsg = otherResult.errorMsg; - result.errorCode = otherResult.errorCode; + result.errorMsg = otherResult.getErrorMsg(); + result.errorCode = otherResult.getErrorCode(); return result; } bool isOk() const { return errorCode == 0; } bool isErr() const { return !isOk(); } operator bool() const { return isOk(); } + T& unwrap() + { + assert(isOk()); + return data; + } const std::string& getErrorMsg() const { return errorMsg; } + int getErrorCode() const { return errorCode; } private: Result(){} private: diff --git a/src/RenderBackend/OpenGL/CommonShader.cpp b/src/RenderBackend/OpenGL/CommonShader.cpp new file mode 100644 index 0000000..ea88f62 --- /dev/null +++ b/src/RenderBackend/OpenGL/CommonShader.cpp @@ -0,0 +1,20 @@ +#include "../../../include/RenderBackend/OpenGL/CommonShader.hpp" +#include "../../../include/RenderBackend/OpenGL/opengl.hpp" + +using namespace std; + +namespace amalgine +{ + string getShaderCompileLog(u32 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; + } +} diff --git a/src/RenderBackend/OpenGL/CompiledShader.cpp b/src/RenderBackend/OpenGL/CompiledShader.cpp new file mode 100644 index 0000000..6707b7a --- /dev/null +++ b/src/RenderBackend/OpenGL/CompiledShader.cpp @@ -0,0 +1,37 @@ +#include "../../../include/RenderBackend/OpenGL/CompiledShader.hpp" +#include "../../../include/RenderBackend/OpenGL/opengl.hpp" + +namespace amalgine +{ + CompiledVertexShader::CompiledVertexShader(u32 _shaderId) : + shaderId(_shaderId) + { + + } + + CompiledVertexShader::~CompiledVertexShader() + { + glDeleteShader(shaderId); + } + + u32 CompiledVertexShader::getShaderId() const + { + return shaderId; + } + + CompiledPixelShader::CompiledPixelShader(u32 _shaderId) : + shaderId(_shaderId) + { + + } + + CompiledPixelShader::~CompiledPixelShader() + { + glDeleteShader(shaderId); + } + + u32 CompiledPixelShader::getShaderId() const + { + return shaderId; + } +} diff --git a/src/RenderBackend/OpenGL/DeviceMemory.cpp b/src/RenderBackend/OpenGL/DeviceMemory.cpp index f166666..9e33ac9 100644 --- a/src/RenderBackend/OpenGL/DeviceMemory.cpp +++ b/src/RenderBackend/OpenGL/DeviceMemory.cpp @@ -8,17 +8,22 @@ namespace amalgine glGenBuffers(1, &vertexBufferObjectId); } - void DeviceMemory::copyStatic(const DataView<f32> &data) + DeviceMemory::~DeviceMemory() + { + glDeleteBuffers(1, &vertexBufferObjectId); + } + + void DeviceMemory::copyAsStatic(const DataView<f32> &data) { copy(data, GL_STATIC_DRAW); } - void DeviceMemory::copyDynamic(const DataView<f32> &data) + void DeviceMemory::copyAsDynamic(const DataView<f32> &data) { copy(data, GL_DYNAMIC_DRAW); } - void DeviceMemory::copyStream(const DataView<f32> &data) + void DeviceMemory::copyAsStream(const DataView<f32> &data) { copy(data, GL_STREAM_DRAW); } diff --git a/src/RenderBackend/OpenGL/PixelShader.cpp b/src/RenderBackend/OpenGL/PixelShader.cpp index 2a7c913..2af68e5 100644 --- a/src/RenderBackend/OpenGL/PixelShader.cpp +++ b/src/RenderBackend/OpenGL/PixelShader.cpp @@ -1,4 +1,7 @@ #include "../../../include/RenderBackend/OpenGL/PixelShader.hpp" +#include "../../../include/RenderBackend/OpenGL/opengl.hpp" +#include "../../../include/RenderBackend/OpenGL/CompiledShader.hpp" +#include <cassert> using namespace std; @@ -28,11 +31,51 @@ namespace amalgine } - PixelShader::PixelShader() : mainFuncDefined(false) + PixelShader::PixelShader() : locationCounter(0), 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].name; + } + + ShaderOutputVec4 PixelShader::defineOutputVec4(const std::string &name) + { + i32 attributeIndex = defineOutputVariable(name, "vec4"); + return ShaderOutputVec4(this, attributeIndex); + } + + 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; + writeHeader("out "); + writeHeader(typeName); + writeHeader(" "); + writeHeader(variableName); + writeHeader(";\n"); + + ShaderAttribute shaderAttribute; + shaderAttribute.name = variableName; + shaderAttribute.typeName = typeName; + pixelAttributeNames.push_back(shaderAttribute); + ++locationCounter; + return attributeIndex; + } + void PixelShader::defineMain(PixelShaderMainFunc mainFunc) { if(mainFuncDefined) @@ -71,4 +114,26 @@ namespace amalgine { body += code; } + + Result<CompiledPixelShader*> PixelShader::compile() + { + GLuint fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER); + string verterShaderSource = build(); + const char *verterShaderSourcePtr = verterShaderSource.c_str(); + printf("Vertex shader:\n%s\n", verterShaderSourcePtr); + glShaderSource(fragmentShaderId, 1, &verterShaderSourcePtr, NULL); + glCompileShader(fragmentShaderId); + + GLint status; + glGetShaderiv(fragmentShaderId, GL_COMPILE_STATUS, &status); + string compileLog = getShaderCompileLog((u32)fragmentShaderId); + if(status == GL_TRUE) + { + if(!compileLog.empty()) + printf("Pixel shader compile log:\n%s", compileLog.c_str()); + return Result<CompiledPixelShader*>::Ok(new CompiledPixelShader(fragmentShaderId)); + } + else + return Result<CompiledPixelShader*>::Err(compileLog); + } } diff --git a/src/RenderBackend/OpenGL/ShaderProgram.cpp b/src/RenderBackend/OpenGL/ShaderProgram.cpp index 892f45e..f76903e 100644 --- a/src/RenderBackend/OpenGL/ShaderProgram.cpp +++ b/src/RenderBackend/OpenGL/ShaderProgram.cpp @@ -1,103 +1,74 @@ #include "../../../include/RenderBackend/OpenGL/ShaderProgram.hpp" -#include "../../../include/RenderBackend/OpenGL/CommonShader.hpp" #include "../../../include/RenderBackend/OpenGL/opengl.hpp" +#include "../../../include/RenderBackend/OpenGL/CompiledShader.hpp" using namespace std; namespace amalgine { - string getShaderCompileLog(GLuint shaderId) + ShaderProgramUsedBeforeBuilt::ShaderProgramUsedBeforeBuilt() : + runtime_error("Shader program was used before it was built") { - 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) + ShaderProgram::ShaderProgram() : built(false) { - glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxPixelAttribs); + shaderProgramId = glCreateProgram(); } - const string& ShaderProgram::getOutputAttributeName(i32 attributeIndex) + ShaderProgram::~ShaderProgram() { - assert(attributeIndex < pixelAttributeNames.size()); - return pixelAttributeNames[attributeIndex]; + GLint numAttachedShaders; + glGetProgramiv(shaderProgramId, GL_ATTACHED_SHADERS, &numAttachedShaders); + + GLuint *attachedShaders = new GLuint[numAttachedShaders]; + glGetAttachedShaders(shaderProgramId, numAttachedShaders, nullptr, attachedShaders); + + for(int i = 0; i < numAttachedShaders; ++i) + { + GLuint attachedShaderId = attachedShaders[i]; + glDetachShader(shaderProgramId, attachedShaderId); + } + + glDeleteProgram(shaderProgramId); } - ShaderOutputVec4 ShaderProgram::defineOutputVec4(const std::string &name) - { - i32 attributeIndex = defineOutputVariable(name, "vec4"); - return ShaderOutputVec4(this, attributeIndex); - } + // TODO: Before adding shader to program, check if it has already been added - i32 ShaderProgram::defineOutputVariable(const string &variableName, const char *typeName) + bool ShaderProgram::addVertexShader(CompiledVertexShader *vertexShader) { - 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; + // TODO: Do not allow adding shader if the program has already been built + glAttachShader(shaderProgramId, vertexShader->getShaderId()); + return true; } - /* - Result<string> ShaderProgram::addVertexShader(const VertexShader &vertexShader) + bool ShaderProgram::addPixelShader(CompiledPixelShader *pixelShader) { - 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); + // TODO: Do not allow adding shader if the program has already been built + glAttachShader(shaderProgramId, pixelShader->getShaderId()); + return true; } - Result<string> ShaderProgram::addPixelShader(const PixelShader &pixelShader) + Result<bool> ShaderProgram::build() { - 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); + if(built) + return Result<bool>::Err("Shader program already built"); - 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); + glLinkProgram(shaderProgramId); + built = true; + return Result<bool>::Ok(true); } - void ShaderProgram::build() + void ShaderProgram::use() { - GLuint shaderProgramId = glCreateProgram(); - for(u32 shaderId : shaderIds) + if(built) + { + glUseProgram(shaderProgramId); + } + else { - glAttachShader(shaderProgramId, shaderId); + throw ShaderProgramUsedBeforeBuilt(); } } - */ } diff --git a/src/RenderBackend/OpenGL/ShaderVec.cpp b/src/RenderBackend/OpenGL/ShaderVec.cpp index 0dfb4c6..6411650 100644 --- a/src/RenderBackend/OpenGL/ShaderVec.cpp +++ b/src/RenderBackend/OpenGL/ShaderVec.cpp @@ -1,11 +1,12 @@ #include "../../../include/RenderBackend/OpenGL/ShaderVec.hpp" #include "../../../include/RenderBackend/OpenGL/VertexShader.hpp" #include "../../../include/RenderBackend/OpenGL/PixelShader.hpp" +#include "../../../include/RenderBackend/OpenGL/ShaderProgram.hpp" using namespace std; namespace amalgine -{ +{ const string& ShaderInputVec2::getName() const { return vertexShader->getInputAttributeName(attributeIndex); diff --git a/src/RenderBackend/OpenGL/VertexShader.cpp b/src/RenderBackend/OpenGL/VertexShader.cpp index 04bf863..1505ff4 100644 --- a/src/RenderBackend/OpenGL/VertexShader.cpp +++ b/src/RenderBackend/OpenGL/VertexShader.cpp @@ -1,6 +1,7 @@ #include "../../../include/RenderBackend/OpenGL/VertexShader.hpp" #include "../../../include/RenderBackend/OpenGL/CommonShader.hpp" #include "../../../include/RenderBackend/OpenGL/opengl.hpp" +#include "../../../include/RenderBackend/OpenGL/CompiledShader.hpp" using namespace std; @@ -106,4 +107,26 @@ namespace amalgine { body += code; } + + Result<CompiledVertexShader*> VertexShader::compile() + { + GLuint vertexShaderId = glCreateShader(GL_VERTEX_SHADER); + string verterShaderSource = build(); + const char *verterShaderSourcePtr = verterShaderSource.c_str(); + printf("Vertex shader:\n%s\n", verterShaderSourcePtr); + glShaderSource(vertexShaderId, 1, &verterShaderSourcePtr, NULL); + glCompileShader(vertexShaderId); + + GLint status; + glGetShaderiv(vertexShaderId, GL_COMPILE_STATUS, &status); + string compileLog = getShaderCompileLog((u32)vertexShaderId); + if(status == GL_TRUE) + { + if(!compileLog.empty()) + printf("Vertex shader compile log:\n%s", compileLog.c_str()); + return Result<CompiledVertexShader*>::Ok(new CompiledVertexShader(vertexShaderId)); + } + else + return Result<CompiledVertexShader*>::Err(compileLog); + } } diff --git a/src/main.cpp b/src/main.cpp index 03222f1..b1a0d62 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -10,12 +10,61 @@ using namespace amalgine; using namespace std; +void initGlfw(); +void initGlew(); +GLFWwindow *createWindow(); + +CompiledVertexShader* createVertexShader(); +CompiledPixelShader* createPixelShader(); + int main() { + initGlfw(); + GLFWwindow *window = createWindow(); + + f32 verticesRaw[] = + { + 0.0f, 0.5f, + 0.5f, -0.5f, + -0.5f, -0.5f + }; + DataView<f32> vertices(verticesRaw, 6); + DeviceMemory triangle; + triangle.copyAsStatic(vertices); + + CompiledVertexShader *vertexShader = createVertexShader(); + CompiledPixelShader *pixelShader = createPixelShader(); + + ShaderProgram shaderProgram; + shaderProgram.addVertexShader(vertexShader); + shaderProgram.addPixelShader(pixelShader); + Result<bool> shaderBuildResult = shaderProgram.build(); + if(!shaderBuildResult) + { + fprintf(stderr, "Failed to build shader program: %s\n", shaderBuildResult.getErrorMsg().c_str()); + exit(20); + } + + while(!glfwWindowShouldClose(window)) + { + glfwPollEvents(); + if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) + glfwSetWindowShouldClose(window, GL_TRUE); + + shaderProgram.use(); + glfwSwapBuffers(window); + } + + glfwTerminate(); + return 0; +} + +void initGlfw() +{ if(!glfwInit()) { fprintf(stderr, "Failed to initialize GLFW\n"); - return -1; + exit(-1); } glfwWindowHint(GLFW_SAMPLES, 4); @@ -24,39 +73,37 @@ int main() glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); +} - GLFWwindow *window = glfwCreateWindow(1920, 1080, "Amalgine", nullptr, nullptr); - if(!window) +void initGlew() +{ + glewExperimental = true; + if(glewInit() != GLEW_OK) { - fprintf(stderr, "Failed to open GLFW window\n"); + fprintf(stderr, "Failed to initialize GLEW\n"); glfwTerminate(); - return -1; + exit(-1); } +} - glfwMakeContextCurrent(window); - glewExperimental = true; - if(glewInit() != GLEW_OK) +GLFWwindow* createWindow() +{ + GLFWwindow *window = glfwCreateWindow(1280, 720, "Amalgine", nullptr, nullptr); + if(!window) { - fprintf(stderr, "Failed to initialize GLEW\n"); + fprintf(stderr, "Failed to open GLFW window\n"); glfwTerminate(); - return -1; + exit(10); } glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE); - - - f32 verticesRaw[] = - { - 0.0f, 0.5f, - 0.5f, -0.5f, - -0.5f, -0.5f - }; - DataView<f32> vertices(verticesRaw, 6); - DeviceMemory triangle; - triangle.copyStatic(vertices); - - ShaderProgram shaderProgram; - + glfwMakeContextCurrent(window); + initGlew(); + return window; +} + +CompiledVertexShader* createVertexShader() +{ VertexShader vertexShader; ShaderInputVec2 inputPosition = vertexShader.defineInputVec2("position"); @@ -65,27 +112,32 @@ int main() return ShaderVec4(inputPosition, 0.0f, 1.0f); }); + Result<CompiledVertexShader*> compiledVertexShader = vertexShader.compile(); + if(!compiledVertexShader) + { + fprintf(stderr, "Failed to compile vertex shader:\n%s", compiledVertexShader.getErrorMsg().c_str()); + exit(2); + } + + return compiledVertexShader.unwrap(); +} + +CompiledPixelShader* createPixelShader() +{ PixelShader pixelShader; - ShaderOutputVec4 outColor = shaderProgram.defineOutputVec4("outColor"); + ShaderOutputVec4 outColor = pixelShader.defineOutputVec4("outColor"); pixelShader.defineMain([&outColor]() { outColor = ShaderVec4(1.0f, 1.0f, 1.0f, 1.0f); }); - string vertexShaderSource = vertexShader.build(); - printf("Vertex shader source:\n%s", vertexShaderSource.c_str()); - string pixelShaderSource = pixelShader.build(); - printf("Pixel shader source:\n%s", pixelShaderSource.c_str()); - - while(!glfwWindowShouldClose(window)) + Result<CompiledPixelShader*> compiledPixelShader = pixelShader.compile(); + if(!compiledPixelShader) { - if(glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS) - glfwSetWindowShouldClose(window, GL_TRUE); - - glfwSwapBuffers(window); - glfwPollEvents(); + fprintf(stderr, "Failed to compile pixel shader:\n%s", compiledPixelShader.getErrorMsg().c_str()); + exit(2); } - - return 0; + + return compiledPixelShader.unwrap(); } |