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 ++++++++++++++++++++++++++++ src/main.cpp | 88 +++++++++++++++++++++++ 5 files changed, 366 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 create mode 100644 src/main.cpp (limited to 'src') 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; + } +} diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..fe48ddf --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,88 @@ +#include +#include +#include +#include +#include "../include/RenderBackend/OpenGL/VertexShader.hpp" +#include "../include/RenderBackend/OpenGL/PixelShader.hpp" +#include "../include/RenderBackend/OpenGL/DeviceMemory.hpp" + +using namespace amalgine; +using namespace std; + +int main() +{ + if(!glfwInit()) + { + fprintf(stderr, "Failed to initialize GLFW\n"); + return -1; + } + + glfwWindowHint(GLFW_SAMPLES, 4); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5); + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); + + GLFWwindow *window = glfwCreateWindow(1920, 1080, "Amalgine", nullptr, nullptr); + if(!window) + { + fprintf(stderr, "Failed to open GLFW window\n"); + glfwTerminate(); + return -1; + } + + glfwMakeContextCurrent(window); + glewExperimental = true; + if(glewInit() != GLEW_OK) + { + fprintf(stderr, "Failed to initialize GLEW\n"); + glfwTerminate(); + return -1; + } + + glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE); + + + f32 verticesRaw[] = + { + 0.0f, 0.5f, + 0.5f, -0.5f, + -0.5f, -0.5f + }; + DataView vertices(verticesRaw, 6); + DeviceMemory triangle; + triangle.copyStatic(vertices); + + VertexShader vertexShader; + ShaderInputVec2 inputPosition = vertexShader.defineInputVec2("position"); + + vertexShader.defineMain([&inputPosition]() + { + return ShaderVec4(inputPosition, 0.0f, 1.0f); + }); + + PixelShader pixelShader; + ShaderOutputVec4 outColor = pixelShader.defineOutputVec4("outColor"); + + pixelShader.defineMain([&outColor]() + { + outColor = ShaderVec4(1.0f, 1.0f, 1.0f, 1.0f); + }); + + string vertexShaderSource = vertexShader.build(); + printf("Vertex shader source:\n%s", vertexShaderSource.c_str()); + string pixelShaderSource = pixelShader.build(); + printf("Pixel shader source:\n%s", pixelShaderSource.c_str()); + + while(!glfwWindowShouldClose(window)) + { + if(glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS) + glfwSetWindowShouldClose(window, GL_TRUE); + + glfwSwapBuffers(window); + glfwPollEvents(); + } + + return 0; +} -- cgit v1.2.3