aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/RenderBackend/OpenGL/CompiledShader.hpp9
-rw-r--r--include/RenderBackend/OpenGL/DeviceFrame.hpp24
-rw-r--r--include/RenderBackend/OpenGL/DeviceMemory.hpp42
-rw-r--r--include/RenderBackend/OpenGL/ShaderProgram.hpp4
-rw-r--r--include/RenderBackend/OpenGL/ShaderVec.hpp10
-rw-r--r--include/RenderBackend/OpenGL/VertexShader.hpp6
-rw-r--r--src/RenderBackend/OpenGL/CompiledShader.cpp7
-rw-r--r--src/RenderBackend/OpenGL/DeviceFrame.cpp36
-rw-r--r--src/RenderBackend/OpenGL/DeviceMemory.cpp51
-rw-r--r--src/RenderBackend/OpenGL/PixelShader.cpp2
-rw-r--r--src/RenderBackend/OpenGL/ShaderProgram.cpp17
-rw-r--r--src/RenderBackend/OpenGL/ShaderVec.cpp31
-rw-r--r--src/RenderBackend/OpenGL/VertexShader.cpp16
-rw-r--r--src/main.cpp29
14 files changed, 240 insertions, 44 deletions
diff --git a/include/RenderBackend/OpenGL/CompiledShader.hpp b/include/RenderBackend/OpenGL/CompiledShader.hpp
index 67e6418..8d2ee84 100644
--- a/include/RenderBackend/OpenGL/CompiledShader.hpp
+++ b/include/RenderBackend/OpenGL/CompiledShader.hpp
@@ -1,6 +1,8 @@
#pragma once
#include "../../types.hpp"
+#include <unordered_map>
+#include <string>
namespace amalgine
{
@@ -22,9 +24,14 @@ namespace amalgine
public:
~CompiledPixelShader();
u32 getShaderId() const;
+ const auto& getPixelAttributes() const
+ {
+ return pixelAttributes;
+ }
private:
- CompiledPixelShader(u32 _shaderId);
+ CompiledPixelShader(u32 _shaderId, std::unordered_map<std::string, i32> &&_pixelAttributes);
private:
u32 shaderId;
+ std::unordered_map<std::string, i32> pixelAttributes;
};
}
diff --git a/include/RenderBackend/OpenGL/DeviceFrame.hpp b/include/RenderBackend/OpenGL/DeviceFrame.hpp
new file mode 100644
index 0000000..12e578a
--- /dev/null
+++ b/include/RenderBackend/OpenGL/DeviceFrame.hpp
@@ -0,0 +1,24 @@
+#pragma once
+
+#include "../../types.hpp"
+#include "../../utils.hpp"
+#include <vector>
+
+namespace amalgine
+{
+ class DeviceMemory;
+
+ class DeviceFrame
+ {
+ DISABLE_COPY(DeviceFrame)
+ public:
+ DeviceFrame();
+ ~DeviceFrame();
+
+ DeviceMemory* alloc();
+ void draw();
+ private:
+ u32 vertexArrayObjectId;
+ std::vector<DeviceMemory*> buffers;
+ };
+}
diff --git a/include/RenderBackend/OpenGL/DeviceMemory.hpp b/include/RenderBackend/OpenGL/DeviceMemory.hpp
index 974c7cf..163b0ad 100644
--- a/include/RenderBackend/OpenGL/DeviceMemory.hpp
+++ b/include/RenderBackend/OpenGL/DeviceMemory.hpp
@@ -2,27 +2,49 @@
#include "../../DataView.hpp"
#include "../../utils.hpp"
+#include <stdexcept>
namespace amalgine
{
+ class DeviceMemoryEmpty : public std::runtime_error
+ {
+ public:
+ DeviceMemoryEmpty(const std::string &errMsg) : std::runtime_error(errMsg) {}
+ };
+
class DeviceMemory
{
DISABLE_COPY(DeviceMemory)
+ friend class DeviceFrame;
+ friend class ShaderInputVec4;
public:
- DeviceMemory();
- ~DeviceMemory();
-
- // Uploaded once, drawn many times
- void copyAsStatic(const DataView<f32> &data);
+ enum class StorageType
+ {
+ // Uploaded once, drawn many times
+ STATIC,
+
+ // Created once, changed from time to time but drawn many times more than that
+ DYNAMIC,
+
+ // Uploaded once, drawn once (for example data that is changed every frame)
+ STREAM
+ };
- // Created once, changed from time to time but drawn many times more than that
- void copyAsDynamic(const DataView<f32> &data);
+ enum class PrimitiveType
+ {
+ TRIANGLE
+ };
- // Uploaded once, drawn once (for example data that is changed every frame)
- void copyAsStream(const DataView<f32> &data);
+ ~DeviceMemory();
+ void copy(const DataView<f32> &data, StorageType storageType, PrimitiveType primitiveType = PrimitiveType::TRIANGLE);
+ void draw();
private:
- void copy(const DataView<f32> &data, i32 storageType);
+ DeviceMemory();
+ void operator delete(void *data);
+ void use() const;
private:
u32 vertexBufferObjectId;
+ u32 primitiveType;
+ u32 numVertices;
};
}
diff --git a/include/RenderBackend/OpenGL/ShaderProgram.hpp b/include/RenderBackend/OpenGL/ShaderProgram.hpp
index a3e8a0f..2b1c5b4 100644
--- a/include/RenderBackend/OpenGL/ShaderProgram.hpp
+++ b/include/RenderBackend/OpenGL/ShaderProgram.hpp
@@ -26,8 +26,8 @@ namespace amalgine
ShaderProgram();
~ShaderProgram();
- bool addVertexShader(CompiledVertexShader *vertexShader);
- bool addPixelShader(CompiledPixelShader *pixelShader);
+ bool setVertexShader(CompiledVertexShader *vertexShader);
+ bool setPixelShader(CompiledPixelShader *pixelShader);
Result<bool> build();
void use();
diff --git a/include/RenderBackend/OpenGL/ShaderVec.hpp b/include/RenderBackend/OpenGL/ShaderVec.hpp
index 10e628c..a5163ba 100644
--- a/include/RenderBackend/OpenGL/ShaderVec.hpp
+++ b/include/RenderBackend/OpenGL/ShaderVec.hpp
@@ -1,6 +1,7 @@
#pragma once
#include "../../types.hpp"
+#include "../../RenderBackend/OpenGL/DeviceMemory.hpp"
#include <string>
namespace amalgine
@@ -8,11 +9,20 @@ namespace amalgine
class VertexShader;
class PixelShader;
+ enum class AttributeType
+ {
+ NONE,
+ VEC2
+ };
+
+ AttributeType getAttributeTypeByName(const char *attributeName);
+
class ShaderInputVec2
{
friend class VertexShader;
public:
const std::string& getName() const;
+ void setData(const DeviceMemory &data);
private:
ShaderInputVec2(VertexShader *_vertexShader, i32 _attributeIndex) :
vertexShader(_vertexShader),
diff --git a/include/RenderBackend/OpenGL/VertexShader.hpp b/include/RenderBackend/OpenGL/VertexShader.hpp
index 43a5dd8..aaf8b24 100644
--- a/include/RenderBackend/OpenGL/VertexShader.hpp
+++ b/include/RenderBackend/OpenGL/VertexShader.hpp
@@ -3,6 +3,7 @@
#include "../../DataView.hpp"
#include "../../utils.hpp"
#include "../../Result.hpp"
+#include "CommonShader.hpp"
#include "ShaderVec.hpp"
#include <string>
#include <unordered_map>
@@ -51,7 +52,8 @@ namespace amalgine
public:
VertexShader();
- const std::string& getInputAttributeName(i32 attributeIndex);
+ const std::string& getInputAttributeName(i32 attributeIndex) const;
+ AttributeType getInputAttributeType(i32 attributeIndex) const;
ShaderInputVec2 defineInputVec2(const std::string &name);
void defineMain(VertexShaderMainFunc mainFunc);
Result<CompiledVertexShader*> compile();
@@ -71,7 +73,7 @@ namespace amalgine
int locationCounter;
i32 maxVertexAttribs; // Could make this static
std::unordered_map<std::string, i32> vertexAttributes;
- std::vector<std::string> vertexAttributeNames;
+ std::vector<ShaderAttribute> vertexAttributeNames;
bool mainFuncDefined;
};
}
diff --git a/src/RenderBackend/OpenGL/CompiledShader.cpp b/src/RenderBackend/OpenGL/CompiledShader.cpp
index 6707b7a..f4a1fec 100644
--- a/src/RenderBackend/OpenGL/CompiledShader.cpp
+++ b/src/RenderBackend/OpenGL/CompiledShader.cpp
@@ -1,6 +1,8 @@
#include "../../../include/RenderBackend/OpenGL/CompiledShader.hpp"
#include "../../../include/RenderBackend/OpenGL/opengl.hpp"
+using namespace std;
+
namespace amalgine
{
CompiledVertexShader::CompiledVertexShader(u32 _shaderId) :
@@ -19,8 +21,9 @@ namespace amalgine
return shaderId;
}
- CompiledPixelShader::CompiledPixelShader(u32 _shaderId) :
- shaderId(_shaderId)
+ CompiledPixelShader::CompiledPixelShader(u32 _shaderId, unordered_map<string, i32> &&_pixelAttributes) :
+ shaderId(_shaderId),
+ pixelAttributes(_pixelAttributes)
{
}
diff --git a/src/RenderBackend/OpenGL/DeviceFrame.cpp b/src/RenderBackend/OpenGL/DeviceFrame.cpp
new file mode 100644
index 0000000..9d60597
--- /dev/null
+++ b/src/RenderBackend/OpenGL/DeviceFrame.cpp
@@ -0,0 +1,36 @@
+#include "../../../include/RenderBackend/OpenGL/DeviceFrame.hpp"
+#include "../../../include/RenderBackend/OpenGL/DeviceMemory.hpp"
+#include "../../../include/RenderBackend/OpenGL/opengl.hpp"
+
+namespace amalgine
+{
+ DeviceFrame::DeviceFrame()
+ {
+ glGenVertexArrays(1, &vertexArrayObjectId);
+ }
+
+ DeviceFrame::~DeviceFrame()
+ {
+ for(DeviceMemory *deviceMemory : buffers)
+ {
+ delete deviceMemory;
+ }
+ glDeleteVertexArrays(1, &vertexArrayObjectId);
+ }
+
+ DeviceMemory* DeviceFrame::alloc()
+ {
+ glBindVertexArray(vertexArrayObjectId);
+ DeviceMemory *deviceMemory = new DeviceMemory();
+ buffers.push_back(deviceMemory);
+ return deviceMemory;
+ }
+
+ void DeviceFrame::draw()
+ {
+ for(DeviceMemory *deviceMemory : buffers)
+ {
+ deviceMemory->draw();
+ }
+ }
+}
diff --git a/src/RenderBackend/OpenGL/DeviceMemory.cpp b/src/RenderBackend/OpenGL/DeviceMemory.cpp
index 9e33ac9..faf2943 100644
--- a/src/RenderBackend/OpenGL/DeviceMemory.cpp
+++ b/src/RenderBackend/OpenGL/DeviceMemory.cpp
@@ -3,7 +3,33 @@
namespace amalgine
{
- DeviceMemory::DeviceMemory()
+ u32 getOpenglStorageType(DeviceMemory::StorageType storageType)
+ {
+ switch(storageType)
+ {
+ case DeviceMemory::StorageType::STATIC: return GL_STATIC_DRAW;
+ case DeviceMemory::StorageType::DYNAMIC: return GL_DYNAMIC_DRAW;
+ case DeviceMemory::StorageType::STREAM: return GL_STREAM_DRAW;
+ }
+ }
+
+ u32 getOpenglPrimitiveType(DeviceMemory::PrimitiveType primitiveType)
+ {
+ switch(primitiveType)
+ {
+ case DeviceMemory::PrimitiveType::TRIANGLE: return GL_TRIANGLES;
+ }
+ }
+
+ u32 getPrimitiveTypePointsPerVertices(DeviceMemory::PrimitiveType primitiveType)
+ {
+ switch(primitiveType)
+ {
+ case DeviceMemory::PrimitiveType::TRIANGLE: return 3;
+ }
+ }
+
+ DeviceMemory::DeviceMemory() : primitiveType(0), numVertices(0)
{
glGenBuffers(1, &vertexBufferObjectId);
}
@@ -13,24 +39,29 @@ namespace amalgine
glDeleteBuffers(1, &vertexBufferObjectId);
}
- void DeviceMemory::copyAsStatic(const DataView<f32> &data)
+ void DeviceMemory::operator delete(void *data)
{
- copy(data, GL_STATIC_DRAW);
+ free(data);
}
- void DeviceMemory::copyAsDynamic(const DataView<f32> &data)
+ void DeviceMemory::use() const
{
- copy(data, GL_DYNAMIC_DRAW);
+ // TODO: Bind vao here?
+ glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObjectId);
}
- void DeviceMemory::copyAsStream(const DataView<f32> &data)
+ void DeviceMemory::copy(const DataView<f32> &data, StorageType storageType, PrimitiveType primitiveType)
{
- copy(data, GL_STREAM_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObjectId);
+ glBufferData(GL_ARRAY_BUFFER, data.getByteSize(), data.data, getOpenglStorageType(storageType));
+ this->primitiveType = getOpenglPrimitiveType(primitiveType);
+ numVertices = getPrimitiveTypePointsPerVertices(primitiveType);
}
- void DeviceMemory::copy(const DataView<f32> &data, i32 storageType)
+ void DeviceMemory::draw()
{
- glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObjectId);
- glBufferData(GL_ARRAY_BUFFER, data.getByteSize(), data.data, storageType);
+ if(primitiveType == 0)
+ throw DeviceMemoryEmpty("Unable to draw buffer as no data has been copied to device memory");
+ glDrawArrays(primitiveType, 0, 3);
}
}
diff --git a/src/RenderBackend/OpenGL/PixelShader.cpp b/src/RenderBackend/OpenGL/PixelShader.cpp
index 2af68e5..8aa4d9a 100644
--- a/src/RenderBackend/OpenGL/PixelShader.cpp
+++ b/src/RenderBackend/OpenGL/PixelShader.cpp
@@ -131,7 +131,7 @@ namespace amalgine
{
if(!compileLog.empty())
printf("Pixel shader compile log:\n%s", compileLog.c_str());
- return Result<CompiledPixelShader*>::Ok(new CompiledPixelShader(fragmentShaderId));
+ return Result<CompiledPixelShader*>::Ok(new CompiledPixelShader(fragmentShaderId, move(pixelAttributes)));
}
else
return Result<CompiledPixelShader*>::Err(compileLog);
diff --git a/src/RenderBackend/OpenGL/ShaderProgram.cpp b/src/RenderBackend/OpenGL/ShaderProgram.cpp
index f76903e..40f5b6c 100644
--- a/src/RenderBackend/OpenGL/ShaderProgram.cpp
+++ b/src/RenderBackend/OpenGL/ShaderProgram.cpp
@@ -36,17 +36,30 @@ namespace amalgine
// TODO: Before adding shader to program, check if it has already been added
- bool ShaderProgram::addVertexShader(CompiledVertexShader *vertexShader)
+ bool ShaderProgram::setVertexShader(CompiledVertexShader *vertexShader)
{
+ if(!vertexShader) return false;
+
// TODO: Do not allow adding shader if the program has already been built
glAttachShader(shaderProgramId, vertexShader->getShaderId());
return true;
}
- bool ShaderProgram::addPixelShader(CompiledPixelShader *pixelShader)
+ bool ShaderProgram::setPixelShader(CompiledPixelShader *pixelShader)
{
+ if(!pixelShader) return false;
+
// TODO: Do not allow adding shader if the program has already been built
glAttachShader(shaderProgramId, pixelShader->getShaderId());
+
+ const auto &pixelAttributes = pixelShader->getPixelAttributes();
+ for(const auto &pixelAttribute : pixelAttributes)
+ {
+ const string &attributeName = pixelAttribute.first;
+ i32 attributeLocation = pixelAttribute.second;
+ glBindFragDataLocation(shaderProgramId, attributeLocation, attributeName.c_str());
+ }
+
return true;
}
diff --git a/src/RenderBackend/OpenGL/ShaderVec.cpp b/src/RenderBackend/OpenGL/ShaderVec.cpp
index 6411650..3bbe0be 100644
--- a/src/RenderBackend/OpenGL/ShaderVec.cpp
+++ b/src/RenderBackend/OpenGL/ShaderVec.cpp
@@ -2,16 +2,47 @@
#include "../../../include/RenderBackend/OpenGL/VertexShader.hpp"
#include "../../../include/RenderBackend/OpenGL/PixelShader.hpp"
#include "../../../include/RenderBackend/OpenGL/ShaderProgram.hpp"
+#include "../../../include/RenderBackend/OpenGL/opengl.hpp"
+#include <cstring>
+#include <cassert>
using namespace std;
namespace amalgine
{
+ AttributeType getAttributeTypeByName(const char *attributeName)
+ {
+ if(strncmp(attributeName, "vec2", 4) == 0)
+ {
+ return AttributeType::VEC2;
+ }
+
+ return AttributeType::NONE;
+ }
+
const string& ShaderInputVec2::getName() const
{
return vertexShader->getInputAttributeName(attributeIndex);
}
+ void ShaderInputVec2::setData(const DeviceMemory &data)
+ {
+ data.use();
+ AttributeType attributeType = vertexShader->getInputAttributeType(attributeIndex);
+ switch(attributeType)
+ {
+ case AttributeType::VEC2:
+ {
+ glVertexAttribPointer(attributeIndex, 2, GL_FLOAT, GL_FALSE, 0, 0);
+ break;
+ }
+ default:
+ assert(false);
+ break;
+ }
+ glEnableVertexAttribArray(attributeIndex);
+ }
+
const string& ShaderOutputVec4::getName() const
{
return pixelShader->getOutputAttributeName(attributeIndex);
diff --git a/src/RenderBackend/OpenGL/VertexShader.cpp b/src/RenderBackend/OpenGL/VertexShader.cpp
index 1505ff4..ac9a159 100644
--- a/src/RenderBackend/OpenGL/VertexShader.cpp
+++ b/src/RenderBackend/OpenGL/VertexShader.cpp
@@ -1,5 +1,4 @@
#include "../../../include/RenderBackend/OpenGL/VertexShader.hpp"
-#include "../../../include/RenderBackend/OpenGL/CommonShader.hpp"
#include "../../../include/RenderBackend/OpenGL/opengl.hpp"
#include "../../../include/RenderBackend/OpenGL/CompiledShader.hpp"
@@ -37,10 +36,16 @@ namespace amalgine
writeHeader("#version 330 core\n\n");
}
- const string& VertexShader::getInputAttributeName(i32 attributeIndex)
+ const string& VertexShader::getInputAttributeName(i32 attributeIndex) const
{
assert(attributeIndex < vertexAttributeNames.size());
- return vertexAttributeNames[attributeIndex];
+ return vertexAttributeNames[attributeIndex].name;
+ }
+
+ AttributeType VertexShader::getInputAttributeType(i32 attributeIndex) const
+ {
+ assert(attributeIndex < vertexAttributeNames.size());
+ return getAttributeTypeByName(vertexAttributeNames[attributeIndex].typeName);
}
ShaderInputVec2 VertexShader::defineInputVec2(const std::string &name)
@@ -75,7 +80,10 @@ namespace amalgine
i32 attributeIndex = locationCounter;
vertexAttributes[variableName] = locationCounter;
- vertexAttributeNames.push_back(variableName);
+ ShaderAttribute shaderAttribute;
+ shaderAttribute.name = variableName;
+ shaderAttribute.typeName = typeName;
+ vertexAttributeNames.push_back(shaderAttribute);
writeHeader("layout(location = ");
writeHeader(to_string(locationCounter));
diff --git a/src/main.cpp b/src/main.cpp
index b1a0d62..0e72df0 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,11 +1,16 @@
#include <cstdio>
-#include <GL/glew.h>
-#include <GLFW/glfw3.h>
-#include <glm/glm.hpp>
+#include "../include/RenderBackend/OpenGL/opengl.hpp"
#include "../include/RenderBackend/OpenGL/VertexShader.hpp"
#include "../include/RenderBackend/OpenGL/PixelShader.hpp"
#include "../include/RenderBackend/OpenGL/ShaderProgram.hpp"
#include "../include/RenderBackend/OpenGL/DeviceMemory.hpp"
+#include "../include/RenderBackend/OpenGL/DeviceFrame.hpp"
+
+// TODO: Disallow shader variables that begin with "gl_" as reserved variables
+// start with that. What about hlsl?
+
+// TODO: Creating buffers etc should be somehow created/drawn using the window object, since they are associated with the window
+// opengl context
using namespace amalgine;
using namespace std;
@@ -14,7 +19,7 @@ void initGlfw();
void initGlew();
GLFWwindow *createWindow();
-CompiledVertexShader* createVertexShader();
+CompiledVertexShader* createVertexShader(const DeviceMemory &inputData);
CompiledPixelShader* createPixelShader();
int main()
@@ -22,22 +27,24 @@ int main()
initGlfw();
GLFWwindow *window = createWindow();
+ DeviceFrame frame;
+
f32 verticesRaw[] =
{
0.0f, 0.5f,
0.5f, -0.5f,
-0.5f, -0.5f
};
+ DeviceMemory *triangle = frame.alloc();
DataView<f32> vertices(verticesRaw, 6);
- DeviceMemory triangle;
- triangle.copyAsStatic(vertices);
+ triangle->copy(vertices, DeviceMemory::StorageType::STATIC);
- CompiledVertexShader *vertexShader = createVertexShader();
+ CompiledVertexShader *vertexShader = createVertexShader(*triangle);
CompiledPixelShader *pixelShader = createPixelShader();
ShaderProgram shaderProgram;
- shaderProgram.addVertexShader(vertexShader);
- shaderProgram.addPixelShader(pixelShader);
+ shaderProgram.setVertexShader(vertexShader);
+ shaderProgram.setPixelShader(pixelShader);
Result<bool> shaderBuildResult = shaderProgram.build();
if(!shaderBuildResult)
{
@@ -52,6 +59,7 @@ int main()
glfwSetWindowShouldClose(window, GL_TRUE);
shaderProgram.use();
+ frame.draw();
glfwSwapBuffers(window);
}
@@ -102,10 +110,11 @@ GLFWwindow* createWindow()
return window;
}
-CompiledVertexShader* createVertexShader()
+CompiledVertexShader* createVertexShader(const DeviceMemory &inputData)
{
VertexShader vertexShader;
ShaderInputVec2 inputPosition = vertexShader.defineInputVec2("position");
+ inputPosition.setData(inputData);
vertexShader.defineMain([&inputPosition]()
{