From b5f06b6c4cd07f3073897af32626b9b21a4d2ef8 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Fri, 22 Dec 2017 17:34:55 +0100 Subject: Fix vertex and pixel shader Remove pixel shader code from shader program --- src/RenderBackend/OpenGL/CommonShader.cpp | 20 +++++ src/RenderBackend/OpenGL/CompiledShader.cpp | 37 ++++++++ src/RenderBackend/OpenGL/DeviceMemory.cpp | 11 ++- src/RenderBackend/OpenGL/PixelShader.cpp | 67 ++++++++++++++- src/RenderBackend/OpenGL/ShaderProgram.cpp | 113 +++++++++--------------- src/RenderBackend/OpenGL/ShaderVec.cpp | 3 +- src/RenderBackend/OpenGL/VertexShader.cpp | 23 +++++ src/main.cpp | 128 +++++++++++++++++++--------- 8 files changed, 288 insertions(+), 114 deletions(-) create mode 100644 src/RenderBackend/OpenGL/CommonShader.cpp create mode 100644 src/RenderBackend/OpenGL/CompiledShader.cpp (limited to 'src') 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 &data) + DeviceMemory::~DeviceMemory() + { + glDeleteBuffers(1, &vertexBufferObjectId); + } + + void DeviceMemory::copyAsStatic(const DataView &data) { copy(data, GL_STATIC_DRAW); } - void DeviceMemory::copyDynamic(const DataView &data) + void DeviceMemory::copyAsDynamic(const DataView &data) { copy(data, GL_DYNAMIC_DRAW); } - void DeviceMemory::copyStream(const DataView &data) + void DeviceMemory::copyAsStream(const DataView &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 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 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::Ok(new CompiledPixelShader(fragmentShaderId)); + } + else + return Result::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 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::Ok(compileLog); - else - return Result::Err(compileLog); + // TODO: Do not allow adding shader if the program has already been built + glAttachShader(shaderProgramId, pixelShader->getShaderId()); + return true; } - Result ShaderProgram::addPixelShader(const PixelShader &pixelShader) + Result 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::Err("Shader program already built"); - GLint status; - glGetShaderiv(fragmentShaderId, GL_COMPILE_STATUS, &status); - string compileLog = getShaderCompileLog(fragmentShaderId); - if(status == GL_TRUE) - return Result::Ok(compileLog); - else - return Result::Err(compileLog); + glLinkProgram(shaderProgramId); + built = true; + return Result::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 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::Ok(new CompiledVertexShader(vertexShaderId)); + } + else + return Result::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 vertices(verticesRaw, 6); + DeviceMemory triangle; + triangle.copyAsStatic(vertices); + + CompiledVertexShader *vertexShader = createVertexShader(); + CompiledPixelShader *pixelShader = createPixelShader(); + + ShaderProgram shaderProgram; + shaderProgram.addVertexShader(vertexShader); + shaderProgram.addPixelShader(pixelShader); + Result 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 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 = 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 = 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(); } -- cgit v1.2.3