aboutsummaryrefslogtreecommitdiff
path: root/src/RenderBackend/OpenGL/Shader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/RenderBackend/OpenGL/Shader.cpp')
-rw-r--r--src/RenderBackend/OpenGL/Shader.cpp198
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);
}
}