From ca92d8c90f7103db6d7cae4cef49b278d804b474 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Wed, 20 Dec 2017 20:55:05 +0100 Subject: Create shader using c++ code --- src/RenderBackend/OpenGL/DeviceMemory.cpp | 31 ++++++++ src/RenderBackend/OpenGL/PixelShader.cpp | 114 ++++++++++++++++++++++++++++++ src/RenderBackend/OpenGL/ShaderVec.cpp | 23 ++++++ src/RenderBackend/OpenGL/VertexShader.cpp | 110 ++++++++++++++++++++++++++++ 4 files changed, 278 insertions(+) create mode 100644 src/RenderBackend/OpenGL/DeviceMemory.cpp create mode 100644 src/RenderBackend/OpenGL/PixelShader.cpp create mode 100644 src/RenderBackend/OpenGL/ShaderVec.cpp create mode 100644 src/RenderBackend/OpenGL/VertexShader.cpp (limited to 'src/RenderBackend/OpenGL') diff --git a/src/RenderBackend/OpenGL/DeviceMemory.cpp b/src/RenderBackend/OpenGL/DeviceMemory.cpp new file mode 100644 index 0000000..f166666 --- /dev/null +++ b/src/RenderBackend/OpenGL/DeviceMemory.cpp @@ -0,0 +1,31 @@ +#include "../../../include/RenderBackend/OpenGL/DeviceMemory.hpp" +#include "../../../include/RenderBackend/OpenGL/opengl.hpp" + +namespace amalgine +{ + DeviceMemory::DeviceMemory() + { + glGenBuffers(1, &vertexBufferObjectId); + } + + void DeviceMemory::copyStatic(const DataView &data) + { + copy(data, GL_STATIC_DRAW); + } + + void DeviceMemory::copyDynamic(const DataView &data) + { + copy(data, GL_DYNAMIC_DRAW); + } + + void DeviceMemory::copyStream(const DataView &data) + { + copy(data, GL_STREAM_DRAW); + } + + void DeviceMemory::copy(const DataView &data, i32 storageType) + { + glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObjectId); + glBufferData(GL_ARRAY_BUFFER, data.getByteSize(), data.data, storageType); + } +} diff --git a/src/RenderBackend/OpenGL/PixelShader.cpp b/src/RenderBackend/OpenGL/PixelShader.cpp new file mode 100644 index 0000000..cbdc842 --- /dev/null +++ b/src/RenderBackend/OpenGL/PixelShader.cpp @@ -0,0 +1,114 @@ +#include "../../../include/RenderBackend/OpenGL/PixelShader.hpp" +#include "../../../include/RenderBackend/OpenGL/CommonShader.hpp" +#include "../../../include/RenderBackend/OpenGL/opengl.hpp" +#include + +using namespace std; + +namespace amalgine +{ + PixelShaderTooManyAttributes::PixelShaderTooManyAttributes(i32 maxPixelAttributes) : + runtime_error(string("Attempting to define more than ") + to_string(maxPixelAttributes) + " pixel attributes") + { + + } + + PixelShaderAttributeAlreadyDefined::PixelShaderAttributeAlreadyDefined(const std::string &attributeName) : + runtime_error(string("A pixel attribute with the name ") + attributeName + " has already been defined") + { + + } + + PixelShaderInvalidAttributeName::PixelShaderInvalidAttributeName(const std::string &attributeName) : + runtime_error(string("Pixel attribute name ") + attributeName + " is invalid") + { + + } + + PixelShaderFunctionAlreadyDefined::PixelShaderFunctionAlreadyDefined(const std::string &funcName) : + runtime_error(string("Pixel shader function already defined: ") + funcName) + { + + } + + 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]; + } + + ShaderOutputVec4 PixelShader::defineOutputVec4(const std::string &name) + { + i32 attributeIndex = defineOutputVariable(name, "vec4"); + return ShaderOutputVec4(this, attributeIndex); + } + + void PixelShader::defineMain(PixelShaderMainFunc mainFunc) + { + if(mainFuncDefined) + throw PixelShaderFunctionAlreadyDefined("main"); + + writeBody("void main() {\n"); + mainFunc(); + mainFuncDefined = true; + writeBody("}\n\n"); + } + + void PixelShader::assign(const ShaderOutputVec4 &lhsVariable, const ShaderVec4 &rhsVariable) + { + writeBody(lhsVariable.getName()); + writeBody(" = "); + writeBody(rhsVariable.getOutput()); + writeBody(";\n"); + } + + 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; + pixelAttributeNames.push_back(variableName); + + ++locationCounter; + writeHeader("out "); + writeHeader(typeName); + writeHeader(" "); + writeHeader(variableName); + writeHeader(";\n"); + return attributeIndex; + } + + string PixelShader::build() + { + std::string result; + result.reserve(header.size() + 2 + body.size()); + result += header; + result += "\n"; + result += body; + return result; + } + + void PixelShader::writeHeader(const string &code) + { + header += code; + } + + void PixelShader::writeBody(const string &code) + { + body += code; + } +} diff --git a/src/RenderBackend/OpenGL/ShaderVec.cpp b/src/RenderBackend/OpenGL/ShaderVec.cpp new file mode 100644 index 0000000..0dfb4c6 --- /dev/null +++ b/src/RenderBackend/OpenGL/ShaderVec.cpp @@ -0,0 +1,23 @@ +#include "../../../include/RenderBackend/OpenGL/ShaderVec.hpp" +#include "../../../include/RenderBackend/OpenGL/VertexShader.hpp" +#include "../../../include/RenderBackend/OpenGL/PixelShader.hpp" + +using namespace std; + +namespace amalgine +{ + const string& ShaderInputVec2::getName() const + { + return vertexShader->getInputAttributeName(attributeIndex); + } + + const string& ShaderOutputVec4::getName() const + { + return pixelShader->getOutputAttributeName(attributeIndex); + } + + void ShaderOutputVec4::operator=(const ShaderVec4 &shaderVec4) + { + pixelShader->assign(*this, shaderVec4); + } +} diff --git a/src/RenderBackend/OpenGL/VertexShader.cpp b/src/RenderBackend/OpenGL/VertexShader.cpp new file mode 100644 index 0000000..b869624 --- /dev/null +++ b/src/RenderBackend/OpenGL/VertexShader.cpp @@ -0,0 +1,110 @@ +#include "../../../include/RenderBackend/OpenGL/VertexShader.hpp" +#include "../../../include/RenderBackend/OpenGL/CommonShader.hpp" +#include "../../../include/RenderBackend/OpenGL/opengl.hpp" +#include + +using namespace std; + +namespace amalgine +{ + VertexShaderTooManyAttributes::VertexShaderTooManyAttributes(i32 maxVertexAttributes) : + runtime_error(string("Attempting to define more than ") + to_string(maxVertexAttributes) + " vertex attributes") + { + + } + + VertexShaderAttributeAlreadyDefined::VertexShaderAttributeAlreadyDefined(const std::string &attributeName) : + runtime_error(string("A vertex attribute with the name ") + attributeName + " has already been defined") + { + + } + + VertexShaderInvalidAttributeName::VertexShaderInvalidAttributeName(const std::string &attributeName) : + runtime_error(string("Vertex attribute name ") + attributeName + " is invalid") + { + + } + + VertexShaderFunctionAlreadyDefined::VertexShaderFunctionAlreadyDefined(const std::string &funcName) : + runtime_error(string("Vertex shader function already defined: ") + funcName) + { + + } + + VertexShader::VertexShader() : locationCounter(0), mainFuncDefined(false) + { + glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs); + writeHeader("#version 330 core\n\n"); + } + + const string& VertexShader::getInputAttributeName(i32 attributeIndex) + { + assert(attributeIndex < vertexAttributeNames.size()); + return vertexAttributeNames[attributeIndex]; + } + + ShaderInputVec2 VertexShader::defineInputVec2(const std::string &name) + { + i32 attributeIndex = defineInputVariable(name, "vec2"); + return ShaderInputVec2(this, attributeIndex); + } + + void VertexShader::defineMain(VertexShaderMainFunc mainFunc) + { + if(mainFuncDefined) + throw VertexShaderFunctionAlreadyDefined("main"); + + writeBody("void main() {\n"); + ShaderVec4 glPosition = mainFunc(); + mainFuncDefined = true; + writeBody("gl_Position = "); + writeBody(glPosition.getOutput()); + writeBody(";\n}\n\n"); + } + + i32 VertexShader::defineInputVariable(const string &variableName, const char *typeName) + { + if(!isShaderVariableNameValid(variableName.c_str())) + throw VertexShaderInvalidAttributeName(variableName); + + if(locationCounter + 1 > maxVertexAttribs) + throw VertexShaderTooManyAttributes(maxVertexAttribs); + + if(vertexAttributes.find(variableName) != vertexAttributes.end()) + throw VertexShaderAttributeAlreadyDefined(variableName); + + i32 attributeIndex = locationCounter; + vertexAttributes[variableName] = locationCounter; + vertexAttributeNames.push_back(variableName); + + writeHeader("layout(location = "); + writeHeader(to_string(locationCounter)); + ++locationCounter; + writeHeader(") in "); + writeHeader(typeName); + writeHeader(" "); + writeHeader(variableName); + writeHeader(";\n"); + return attributeIndex; + } + + string VertexShader::build() + { + std::string result; + result.reserve(header.size() + 2 + body.size()); + result += header; + result += "\n"; + result += body; + return result; + } + + void VertexShader::writeHeader(const string &code) + { + header += code; + } + + void VertexShader::writeBody(const string &code) + { + body += code; + } +} -- cgit v1.2.3