From fbd2e5d9a802db4fb5e056705ec599ac423e09be Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sun, 27 Oct 2019 01:30:34 +0200 Subject: Create Shader class as a base for vertex and pixel shader --- src/RenderBackend/OpenGL/Shader.cpp | 169 ++++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 src/RenderBackend/OpenGL/Shader.cpp (limited to 'src/RenderBackend/OpenGL/Shader.cpp') diff --git a/src/RenderBackend/OpenGL/Shader.cpp b/src/RenderBackend/OpenGL/Shader.cpp new file mode 100644 index 0000000..fad1702 --- /dev/null +++ b/src/RenderBackend/OpenGL/Shader.cpp @@ -0,0 +1,169 @@ +#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; + } + + 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 + { + std::string result; + result.reserve(header.size() + 2 + body.size()); + result += header; + result += "\n"; + result += body; + return result; + } + + void Shader::writeHeader(const string &code) + { + header += code; + } + + void Shader::writeBody(const string &code) + { + body += code; + } +} -- cgit v1.2.3