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 ++++++ 7 files changed, 198 insertions(+), 76 deletions(-) create mode 100644 src/RenderBackend/OpenGL/CommonShader.cpp create mode 100644 src/RenderBackend/OpenGL/CompiledShader.cpp (limited to 'src/RenderBackend') 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); + } } -- cgit v1.2.3