aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2017-12-20 20:55:05 +0100
committerdec05eba <dec05eba@protonmail.com>2021-11-18 15:21:46 +0100
commitca92d8c90f7103db6d7cae4cef49b278d804b474 (patch)
treebaf44e42fcc1cf7e871a7b2f1d3d92f680f3a845 /src
parent3d7f123c0fc0af4b8df3ad791b264d22268bd423 (diff)
Create shader using c++ code
Diffstat (limited to 'src')
-rw-r--r--src/RenderBackend/OpenGL/DeviceMemory.cpp31
-rw-r--r--src/RenderBackend/OpenGL/PixelShader.cpp114
-rw-r--r--src/RenderBackend/OpenGL/ShaderVec.cpp23
-rw-r--r--src/RenderBackend/OpenGL/VertexShader.cpp110
-rw-r--r--src/main.cpp88
5 files changed, 366 insertions, 0 deletions
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<f32> &data)
+ {
+ copy(data, GL_STATIC_DRAW);
+ }
+
+ void DeviceMemory::copyDynamic(const DataView<f32> &data)
+ {
+ copy(data, GL_DYNAMIC_DRAW);
+ }
+
+ void DeviceMemory::copyStream(const DataView<f32> &data)
+ {
+ copy(data, GL_STREAM_DRAW);
+ }
+
+ void DeviceMemory::copy(const DataView<f32> &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 <cassert>
+
+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 <cassert>
+
+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 <cstdio>
+#include <GL/glew.h>
+#include <GLFW/glfw3.h>
+#include <glm/glm.hpp>
+#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<f32> 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;
+}