From 23a37b2cdd8ffde8bb85a4159888bf3a7ec35966 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Mon, 4 Nov 2019 00:50:45 +0100 Subject: Use external shaders instead of generating shader code from c++ code... --- src/RenderBackend/OpenGL/CommonShader.cpp | 20 --- src/RenderBackend/OpenGL/CompiledShader.cpp | 40 ------ src/RenderBackend/OpenGL/DeviceFrame.cpp | 9 +- src/RenderBackend/OpenGL/DeviceMemory.cpp | 10 +- src/RenderBackend/OpenGL/PixelShader.cpp | 47 ------- src/RenderBackend/OpenGL/Shader.cpp | 198 ++++++---------------------- src/RenderBackend/OpenGL/ShaderProgram.cpp | 116 ++++++++-------- src/RenderBackend/OpenGL/ShaderVec.cpp | 69 ---------- src/RenderBackend/OpenGL/VertexShader.cpp | 45 ------- 9 files changed, 103 insertions(+), 451 deletions(-) delete mode 100644 src/RenderBackend/OpenGL/CommonShader.cpp delete mode 100644 src/RenderBackend/OpenGL/CompiledShader.cpp delete mode 100644 src/RenderBackend/OpenGL/PixelShader.cpp delete mode 100644 src/RenderBackend/OpenGL/ShaderVec.cpp delete mode 100644 src/RenderBackend/OpenGL/VertexShader.cpp (limited to 'src/RenderBackend/OpenGL') diff --git a/src/RenderBackend/OpenGL/CommonShader.cpp b/src/RenderBackend/OpenGL/CommonShader.cpp deleted file mode 100644 index ea88f62..0000000 --- a/src/RenderBackend/OpenGL/CommonShader.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#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 deleted file mode 100644 index f4a1fec..0000000 --- a/src/RenderBackend/OpenGL/CompiledShader.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include "../../../include/RenderBackend/OpenGL/CompiledShader.hpp" -#include "../../../include/RenderBackend/OpenGL/opengl.hpp" - -using namespace std; - -namespace amalgine -{ - CompiledVertexShader::CompiledVertexShader(u32 _shaderId) : - shaderId(_shaderId) - { - - } - - CompiledVertexShader::~CompiledVertexShader() - { - glDeleteShader(shaderId); - } - - u32 CompiledVertexShader::getShaderId() const - { - return shaderId; - } - - CompiledPixelShader::CompiledPixelShader(u32 _shaderId, unordered_map &&_pixelAttributes) : - shaderId(_shaderId), - pixelAttributes(_pixelAttributes) - { - - } - - CompiledPixelShader::~CompiledPixelShader() - { - glDeleteShader(shaderId); - } - - u32 CompiledPixelShader::getShaderId() const - { - return shaderId; - } -} diff --git a/src/RenderBackend/OpenGL/DeviceFrame.cpp b/src/RenderBackend/OpenGL/DeviceFrame.cpp index e79dfa1..2132f83 100644 --- a/src/RenderBackend/OpenGL/DeviceFrame.cpp +++ b/src/RenderBackend/OpenGL/DeviceFrame.cpp @@ -1,6 +1,7 @@ #include "../../../include/RenderBackend/OpenGL/DeviceFrame.hpp" #include "../../../include/RenderBackend/OpenGL/DeviceMemory.hpp" #include "../../../include/RenderBackend/OpenGL/opengl.hpp" +#include "../../../include/RenderBackend/OpenGL/ShaderProgram.hpp" namespace amalgine { @@ -26,13 +27,13 @@ namespace amalgine return deviceMemory; } - void DeviceFrame::draw() - { - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + void DeviceFrame::draw(ShaderProgram *shader) { + shader->use(); + //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); for(DeviceMemory *deviceMemory : buffers) { deviceMemory->draw(); } - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } } diff --git a/src/RenderBackend/OpenGL/DeviceMemory.cpp b/src/RenderBackend/OpenGL/DeviceMemory.cpp index 0dd3e89..2d40569 100644 --- a/src/RenderBackend/OpenGL/DeviceMemory.cpp +++ b/src/RenderBackend/OpenGL/DeviceMemory.cpp @@ -33,7 +33,7 @@ namespace amalgine } } - DeviceMemory::DeviceMemory() : primitiveType(0), numVertices(0) + DeviceMemory::DeviceMemory() : primitiveType(0), numVertices(0), type(DeviceMemoryType::NONE) { glGenBuffers(1, &vertexBufferObjectId); } @@ -43,11 +43,6 @@ namespace amalgine glDeleteBuffers(1, &vertexBufferObjectId); } - void DeviceMemory::operator delete(void *data) - { - free(data); - } - void DeviceMemory::use() const { // TODO: Bind vao here? @@ -68,12 +63,11 @@ namespace amalgine glBufferData(GL_ARRAY_BUFFER, triangles.getByteSize(), triangles.data, getOpenglStorageType(storageType)); primitiveType = GL_TRIANGLES; numVertices = triangles.size * 3; + type = DeviceMemoryType::VEC2; } void DeviceMemory::draw() { - if(primitiveType == 0) - throw DeviceMemoryEmpty("Unable to draw buffer as no data has been copied to device memory"); glDrawArrays(primitiveType, 0, numVertices); } } diff --git a/src/RenderBackend/OpenGL/PixelShader.cpp b/src/RenderBackend/OpenGL/PixelShader.cpp deleted file mode 100644 index e6006f2..0000000 --- a/src/RenderBackend/OpenGL/PixelShader.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include "../../../include/RenderBackend/OpenGL/PixelShader.hpp" -#include "../../../include/RenderBackend/OpenGL/opengl.hpp" -#include "../../../include/RenderBackend/OpenGL/CompiledShader.hpp" - -namespace amalgine -{ - PixelShader::PixelShader() - { - glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxAttribs); - } - - void PixelShader::defineMain(PixelShaderMainFunc mainFunc) - { - if(mainFuncDefined) - throw ShaderFunctionAlreadyDefined("main"); - - writeBody("void main() {\n"); - mainFunc(); - mainFuncDefined = true; - writeBody("}\n\n"); - } - - Result PixelShader::compile() - { - if(!mainFuncDefined) - return Result::Err("main function not defined (defineMain not called)"); - - GLuint fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER); - std::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); - std::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, move(inputAttributes))); - } - else - return Result::Err(compileLog); - } -} diff --git a/src/RenderBackend/OpenGL/Shader.cpp b/src/RenderBackend/OpenGL/Shader.cpp index fad1702..3b6563f 100644 --- a/src/RenderBackend/OpenGL/Shader.cpp +++ b/src/RenderBackend/OpenGL/Shader.cpp @@ -1,169 +1,55 @@ #include "../../../include/RenderBackend/OpenGL/Shader.hpp" #include "../../../include/RenderBackend/OpenGL/opengl.hpp" -#include "../../../include/RenderBackend/OpenGL/CompiledShader.hpp" -#include - -using namespace std; namespace amalgine { - ShaderTooManyAttributes::ShaderTooManyAttributes(i32 maxAttributes) : - runtime_error(string("Attempting to define more than ") + to_string(maxAttributes) + " attributes") - { - - } - - ShaderAttributeAlreadyDefined::ShaderAttributeAlreadyDefined(const std::string &attributeName) : - runtime_error(string("An attribute with the name ") + attributeName + " has already been defined") - { - - } - - ShaderInvalidAttributeName::ShaderInvalidAttributeName(const std::string &attributeName) : - runtime_error(string("Attribute name ") + attributeName + " is invalid") - { - - } - - ShaderFunctionAlreadyDefined::ShaderFunctionAlreadyDefined(const std::string &funcName) : - runtime_error(string("Shader function already defined: ") + funcName) - { - - } - - Shader::Shader() : inputLocationCounter(0), outputLocationCounter(0), mainFuncDefined(false) - { - writeHeader("#version 330 core\n\n"); - } - - const string& Shader::getOutputAttributeName(i32 attributeIndex) - { - assert(attributeIndex < (i32)outputAttributeNames.size()); - return outputAttributeNames[attributeIndex].name; + static GLuint to_opengl_shader_type(Shader::Type type) { + switch(type) { + case Shader::Type::VERTEX: + return GL_VERTEX_SHADER; + case Shader::Type::PIXEL: + return GL_FRAGMENT_SHADER; + } + assert(false); } - const string& Shader::getInputAttributeName(i32 attributeIndex) const - { - assert(attributeIndex < (i32)inputAttributeNames.size()); - return inputAttributeNames[attributeIndex].name; - } - - AttributeType Shader::getInputAttributeType(i32 attributeIndex) const - { - assert(attributeIndex < (i32)inputAttributeNames.size()); - return getAttributeTypeByName(inputAttributeNames[attributeIndex].typeName); - } - - ShaderOutputVec4 Shader::defineOutputVec4(const std::string &name) - { - i32 attributeIndex = defineOutputVariable(name, "vec4"); - return ShaderOutputVec4(this, attributeIndex); - } - - // TODO: Generate warning if global variable is defined but not assigned to? - ShaderGlobalVec3 Shader::defineGlobalVec3(const std::string &name) - { - if(!isShaderVariableNameValid(name.c_str())) - throw ShaderInvalidAttributeName(name); - - if(uniforms.find(name) != uniforms.end()) - throw ShaderAttributeAlreadyDefined(name); - - writeHeader("uniform vec3 "); - writeHeader(name); - writeHeader(";\n"); - - ShaderGlobalVec3 globalVec(name); - uniforms[name] = globalVec.getVecObject(); - return ShaderGlobalVec3(globalVec); - } - - i32 Shader::defineOutputVariable(const string &variableName, const char *typeName) - { - if(!isShaderVariableNameValid(variableName.c_str())) - throw ShaderInvalidAttributeName(variableName); - - if(outputLocationCounter + 1 > maxAttribs) - throw ShaderTooManyAttributes(maxAttribs); - - if(outputAttributes.find(variableName) != outputAttributes.end()) - throw ShaderAttributeAlreadyDefined(variableName); - - i32 attributeIndex = outputLocationCounter; - outputAttributes[variableName] = outputLocationCounter; - writeHeader("out "); - writeHeader(typeName); - writeHeader(" "); - writeHeader(variableName); - writeHeader(";\n"); - - ShaderAttribute shaderAttribute; - shaderAttribute.name = variableName; - shaderAttribute.typeName = typeName; - outputAttributeNames.push_back(shaderAttribute); - ++outputLocationCounter; - return attributeIndex; - } - - ShaderInputVec2 Shader::defineInputVec2(const std::string &name) - { - i32 attributeIndex = defineInputVariable(name, "vec2"); - return ShaderInputVec2(this, attributeIndex); - } - - i32 Shader::defineInputVariable(const string &variableName, const char *typeName) - { - if(!isShaderVariableNameValid(variableName.c_str())) - throw ShaderInvalidAttributeName(variableName); - - if(inputLocationCounter + 1 > maxAttribs) - throw ShaderTooManyAttributes(maxAttribs); - - if(inputAttributes.find(variableName) != inputAttributes.end()) - throw ShaderAttributeAlreadyDefined(variableName); - - i32 attributeIndex = inputLocationCounter; - inputAttributes[variableName] = inputLocationCounter; - ShaderAttribute shaderAttribute; - shaderAttribute.name = variableName; - shaderAttribute.typeName = typeName; - inputAttributeNames.push_back(shaderAttribute); - - writeHeader("layout(location = "); - writeHeader(to_string(inputLocationCounter)); - ++inputLocationCounter; - writeHeader(") in "); - writeHeader(typeName); - writeHeader(" "); - writeHeader(variableName); - writeHeader(";\n"); - return attributeIndex; - } - - void Shader::assign(const ShaderOutputVec4 &lhsVariable, const ShaderVec4 &rhsVariable) - { - writeBody(lhsVariable.getName()); - writeBody(" = "); - writeBody(rhsVariable.getOutput()); - writeBody(";\n"); - } - - string Shader::build() const + static std::string get_shader_compile_log(GLuint shaderId) { std::string result; - result.reserve(header.size() + 2 + body.size()); - result += header; - result += "\n"; - result += body; + GLint shaderLogLength; + glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &shaderLogLength); + if(shaderLogLength > 0) { + result.resize(shaderLogLength); + glGetShaderInfoLog(shaderId, shaderLogLength, NULL, &result[0]); + } return result; } - - void Shader::writeHeader(const string &code) - { - header += code; + + Shader::Shader(u32 shader_id) : id(shader_id) { + } - - void Shader::writeBody(const string &code) - { - body += code; + + Shader::~Shader() { + glDeleteShader(id); + } + + // static + Result> Shader::compile(Type type, const char *str, int size) { + GLuint shader_id = glCreateShader(to_opengl_shader_type(type)); + GLint shader_lengths[1] = { size }; + glShaderSource(shader_id, 1, &str, shader_lengths); + glCompileShader(shader_id); + + GLint status; + glGetShaderiv(shader_id, GL_COMPILE_STATUS, &status); + std::string compileLog = get_shader_compile_log(shader_id); + if(status == GL_TRUE) { + if(!compileLog.empty()) + fprintf(stderr, "Shader compile log:\n%s", compileLog.c_str()); + std::unique_ptr shader; + shader.reset(new Shader(shader_id)); + return Result>::Ok(std::move(shader)); + } + else + return Result>::Err(compileLog); } } diff --git a/src/RenderBackend/OpenGL/ShaderProgram.cpp b/src/RenderBackend/OpenGL/ShaderProgram.cpp index aceda3b..e613668 100644 --- a/src/RenderBackend/OpenGL/ShaderProgram.cpp +++ b/src/RenderBackend/OpenGL/ShaderProgram.cpp @@ -1,56 +1,34 @@ #include "../../../include/RenderBackend/OpenGL/ShaderProgram.hpp" + +#include "../../../include/RenderBackend/OpenGL/Shader.hpp" #include "../../../include/RenderBackend/OpenGL/opengl.hpp" -#include "../../../include/RenderBackend/OpenGL/CompiledShader.hpp" using namespace std; -namespace amalgine -{ - ShaderProgramUsedBeforeBuilt::ShaderProgramUsedBeforeBuilt() : - runtime_error("Shader program was used before it was built") - { +namespace amalgine { + ShaderProgram::ShaderProgram(u32 shader_program_id) : program_id(shader_program_id) { } - ShaderProgramNonExistingGlobalVariable::ShaderProgramNonExistingGlobalVariable(const char *variableName) : - runtime_error(string("There is no shader global variable with the name '") + variableName + "'") - { - - } - - ShaderProgram::ShaderProgram() : built(false) - { - shaderProgramId = glCreateProgram(); - } - ShaderProgram::~ShaderProgram() { GLint numAttachedShaders; - glGetProgramiv(shaderProgramId, GL_ATTACHED_SHADERS, &numAttachedShaders); + glGetProgramiv(program_id, GL_ATTACHED_SHADERS, &numAttachedShaders); GLuint *attachedShaders = new GLuint[numAttachedShaders]; - glGetAttachedShaders(shaderProgramId, numAttachedShaders, nullptr, attachedShaders); + glGetAttachedShaders(program_id, numAttachedShaders, nullptr, attachedShaders); for(int i = 0; i < numAttachedShaders; ++i) { GLuint attachedShaderId = attachedShaders[i]; - glDetachShader(shaderProgramId, attachedShaderId); + glDetachShader(program_id, attachedShaderId); } - glDeleteProgram(shaderProgramId); - } - - // TODO: Before adding shader to program, check if it has already been added - - bool ShaderProgram::setVertexShader(CompiledVertexShader *vertexShader) - { - if(!vertexShader) return false; - - // TODO: Do not allow adding shader if the program has already been built - glAttachShader(shaderProgramId, vertexShader->getShaderId()); - return true; + glDeleteProgram(program_id); + delete []attachedShaders; } + #if 0 bool ShaderProgram::setPixelShader(CompiledPixelShader *pixelShader) { if(!pixelShader) return false; @@ -68,41 +46,55 @@ namespace amalgine return true; } + #endif - Result ShaderProgram::build() - { - if(built) - return Result::Err("Shader program already built"); + // static + Result> ShaderProgram::build(const std::vector &shaders) { + u32 shader_program_id = glCreateProgram(); + if(shader_program_id == 0) + return Result>::Err("Failed to create shader program"); - glLinkProgram(shaderProgramId); - built = true; - return Result::Ok(true); - } - - void ShaderProgram::use() - { - if(built) - { - glUseProgram(shaderProgramId); - } - else - { - throw ShaderProgramUsedBeforeBuilt(); + for(Shader *shader : shaders) { + glAttachShader(shader_program_id, shader->id); } + + glLinkProgram(shader_program_id); + std::unique_ptr shader_program; + shader_program.reset(new ShaderProgram(shader_program_id)); + return Result>::Ok(std::move(shader_program)); } - - ShaderProgramGlobalVec3 ShaderProgram::getGlobalVec3(const char *name) - { - if(built) - { - GLint uniformId = glGetUniformLocation(shaderProgramId, name); - if(uniformId == -1) - throw ShaderProgramNonExistingGlobalVariable(name); - return ShaderProgramGlobalVec3(this, uniformId); + + int ShaderProgram::set_uniform(const char *name, const vec3f &value) { + GLint uniformId = glGetUniformLocation(program_id, name); + if(uniformId == -1) + return -1; + use(); + glUniform3f(uniformId, value.x, value.y, value.z); + return 0; + } + + int ShaderProgram::set_vertex_input(const char *name, const DeviceMemory &data) { + GLint attrib_location = glGetAttribLocation(program_id, name); + if(attrib_location == -1) { + fprintf(stderr, "No such attribute in shader: %s\n", name); + return -1; } - else - { - throw ShaderProgramUsedBeforeBuilt(); + + data.use(); + switch(data.get_type()) { + case DeviceMemoryType::NONE: + return -1; + case DeviceMemoryType::VEC2: { + glVertexAttribPointer(attrib_location, 2, GL_FLOAT, GL_FALSE, 0, 0); + break; + } + case DeviceMemoryType::VEC3: assert(false); return -1; } + glEnableVertexAttribArray(attrib_location); + return 0; + } + + void ShaderProgram::use() { + glUseProgram(program_id); } } diff --git a/src/RenderBackend/OpenGL/ShaderVec.cpp b/src/RenderBackend/OpenGL/ShaderVec.cpp deleted file mode 100644 index 8897b84..0000000 --- a/src/RenderBackend/OpenGL/ShaderVec.cpp +++ /dev/null @@ -1,69 +0,0 @@ -#include "../../../include/RenderBackend/OpenGL/ShaderVec.hpp" -#include "../../../include/RenderBackend/OpenGL/Shader.hpp" -#include "../../../include/RenderBackend/OpenGL/ShaderProgram.hpp" -#include "../../../include/RenderBackend/OpenGL/opengl.hpp" -#include -#include - -using namespace std; - -namespace amalgine -{ - AttributeType getAttributeTypeByName(const char *attributeName) - { - if(strncmp(attributeName, "vec2", 4) == 0) - { - return AttributeType::VEC2; - } - else if(strncmp(attributeName, "vec3", 4) == 0) - { - return AttributeType::VEC3; - } - else if(strncmp(attributeName, "vec4", 4) == 0) - { - return AttributeType::VEC4; - } - - assert(false); - return AttributeType::NONE; - } - - void ShaderProgramGlobalVec3::set(f32 x, f32 y, f32 z) - { - shaderProgram->use(); - glUniform3f(uniformId, x, y, z); - } - - const string& ShaderInputVec2::getName() const - { - return shader->getInputAttributeName(attributeIndex); - } - - void ShaderInputVec2::setData(const DeviceMemory &data) - { - data.use(); - AttributeType attributeType = shader->getInputAttributeType(attributeIndex); - switch(attributeType) - { - case AttributeType::VEC2: - { - glVertexAttribPointer(attributeIndex, 2, GL_FLOAT, GL_FALSE, 0, 0); - break; - } - default: - assert(false); - break; - } - glEnableVertexAttribArray(attributeIndex); - } - - const string& ShaderOutputVec4::getName() const - { - return shader->getOutputAttributeName(attributeIndex); - } - - void ShaderOutputVec4::operator=(const ShaderVec4 &shaderVec4) - { - shader->assign(*this, shaderVec4); - } -} diff --git a/src/RenderBackend/OpenGL/VertexShader.cpp b/src/RenderBackend/OpenGL/VertexShader.cpp deleted file mode 100644 index 19705b6..0000000 --- a/src/RenderBackend/OpenGL/VertexShader.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include "../../../include/RenderBackend/OpenGL/VertexShader.hpp" -#include "../../../include/RenderBackend/OpenGL/opengl.hpp" -#include "../../../include/RenderBackend/OpenGL/CompiledShader.hpp" - -namespace amalgine { - VertexShader::VertexShader() - { - glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxAttribs); - } - - void VertexShader::defineMain(VertexShaderMainFunc mainFunc) - { - if(mainFuncDefined) - throw ShaderFunctionAlreadyDefined("main"); - - writeBody("void main() {\n"); - ShaderVec4 glPosition = mainFunc(); - mainFuncDefined = true; - writeBody("gl_Position = "); - writeBody(glPosition.getOutput()); - writeBody(";\n}\n\n"); - } - - Result VertexShader::compile() - { - GLuint vertexShaderId = glCreateShader(GL_VERTEX_SHADER); - std::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); - std::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