diff options
Diffstat (limited to 'src/RenderBackend/OpenGL/Shader.cpp')
-rw-r--r-- | src/RenderBackend/OpenGL/Shader.cpp | 198 |
1 files changed, 42 insertions, 156 deletions
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 <cassert> - -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<std::unique_ptr<Shader>> 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; + shader.reset(new Shader(shader_id)); + return Result<std::unique_ptr<Shader>>::Ok(std::move(shader)); + } + else + return Result<std::unique_ptr<Shader>>::Err(compileLog); } } |