aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/RenderBackend/OpenGL/CommonShader.cpp20
-rw-r--r--src/RenderBackend/OpenGL/CompiledShader.cpp37
-rw-r--r--src/RenderBackend/OpenGL/DeviceMemory.cpp11
-rw-r--r--src/RenderBackend/OpenGL/PixelShader.cpp67
-rw-r--r--src/RenderBackend/OpenGL/ShaderProgram.cpp113
-rw-r--r--src/RenderBackend/OpenGL/ShaderVec.cpp3
-rw-r--r--src/RenderBackend/OpenGL/VertexShader.cpp23
-rw-r--r--src/main.cpp128
8 files changed, 288 insertions, 114 deletions
diff --git a/src/RenderBackend/OpenGL/CommonShader.cpp b/src/RenderBackend/OpenGL/CommonShader.cpp
new file mode 100644
index 0000000..ea88f62
--- /dev/null
+++ b/src/RenderBackend/OpenGL/CommonShader.cpp
@@ -0,0 +1,20 @@
+#include "../../../include/RenderBackend/OpenGL/CommonShader.hpp"
+#include "../../../include/RenderBackend/OpenGL/opengl.hpp"
+
+using namespace std;
+
+namespace amalgine
+{
+ string getShaderCompileLog(u32 shaderId)
+ {
+ string result;
+ GLint shaderLogLength;
+ glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &shaderLogLength);
+ if(shaderLogLength > 0)
+ {
+ result.resize(shaderLogLength);
+ glGetShaderInfoLog(shaderId, shaderLogLength, NULL, &result[0]);
+ }
+ return result;
+ }
+}
diff --git a/src/RenderBackend/OpenGL/CompiledShader.cpp b/src/RenderBackend/OpenGL/CompiledShader.cpp
new file mode 100644
index 0000000..6707b7a
--- /dev/null
+++ b/src/RenderBackend/OpenGL/CompiledShader.cpp
@@ -0,0 +1,37 @@
+#include "../../../include/RenderBackend/OpenGL/CompiledShader.hpp"
+#include "../../../include/RenderBackend/OpenGL/opengl.hpp"
+
+namespace amalgine
+{
+ CompiledVertexShader::CompiledVertexShader(u32 _shaderId) :
+ shaderId(_shaderId)
+ {
+
+ }
+
+ CompiledVertexShader::~CompiledVertexShader()
+ {
+ glDeleteShader(shaderId);
+ }
+
+ u32 CompiledVertexShader::getShaderId() const
+ {
+ return shaderId;
+ }
+
+ CompiledPixelShader::CompiledPixelShader(u32 _shaderId) :
+ shaderId(_shaderId)
+ {
+
+ }
+
+ CompiledPixelShader::~CompiledPixelShader()
+ {
+ glDeleteShader(shaderId);
+ }
+
+ u32 CompiledPixelShader::getShaderId() const
+ {
+ return shaderId;
+ }
+}
diff --git a/src/RenderBackend/OpenGL/DeviceMemory.cpp b/src/RenderBackend/OpenGL/DeviceMemory.cpp
index f166666..9e33ac9 100644
--- a/src/RenderBackend/OpenGL/DeviceMemory.cpp
+++ b/src/RenderBackend/OpenGL/DeviceMemory.cpp
@@ -8,17 +8,22 @@ namespace amalgine
glGenBuffers(1, &vertexBufferObjectId);
}
- void DeviceMemory::copyStatic(const DataView<f32> &data)
+ DeviceMemory::~DeviceMemory()
+ {
+ glDeleteBuffers(1, &vertexBufferObjectId);
+ }
+
+ void DeviceMemory::copyAsStatic(const DataView<f32> &data)
{
copy(data, GL_STATIC_DRAW);
}
- void DeviceMemory::copyDynamic(const DataView<f32> &data)
+ void DeviceMemory::copyAsDynamic(const DataView<f32> &data)
{
copy(data, GL_DYNAMIC_DRAW);
}
- void DeviceMemory::copyStream(const DataView<f32> &data)
+ void DeviceMemory::copyAsStream(const DataView<f32> &data)
{
copy(data, GL_STREAM_DRAW);
}
diff --git a/src/RenderBackend/OpenGL/PixelShader.cpp b/src/RenderBackend/OpenGL/PixelShader.cpp
index 2a7c913..2af68e5 100644
--- a/src/RenderBackend/OpenGL/PixelShader.cpp
+++ b/src/RenderBackend/OpenGL/PixelShader.cpp
@@ -1,4 +1,7 @@
#include "../../../include/RenderBackend/OpenGL/PixelShader.hpp"
+#include "../../../include/RenderBackend/OpenGL/opengl.hpp"
+#include "../../../include/RenderBackend/OpenGL/CompiledShader.hpp"
+#include <cassert>
using namespace std;
@@ -28,11 +31,51 @@ namespace amalgine
}
- PixelShader::PixelShader() : mainFuncDefined(false)
+ 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].name;
+ }
+
+ ShaderOutputVec4 PixelShader::defineOutputVec4(const std::string &name)
+ {
+ i32 attributeIndex = defineOutputVariable(name, "vec4");
+ return ShaderOutputVec4(this, attributeIndex);
+ }
+
+ 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;
+ writeHeader("out ");
+ writeHeader(typeName);
+ writeHeader(" ");
+ writeHeader(variableName);
+ writeHeader(";\n");
+
+ ShaderAttribute shaderAttribute;
+ shaderAttribute.name = variableName;
+ shaderAttribute.typeName = typeName;
+ pixelAttributeNames.push_back(shaderAttribute);
+ ++locationCounter;
+ return attributeIndex;
+ }
+
void PixelShader::defineMain(PixelShaderMainFunc mainFunc)
{
if(mainFuncDefined)
@@ -71,4 +114,26 @@ namespace amalgine
{
body += code;
}
+
+ Result<CompiledPixelShader*> PixelShader::compile()
+ {
+ GLuint fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER);
+ string verterShaderSource = build();
+ const char *verterShaderSourcePtr = verterShaderSource.c_str();
+ printf("Vertex shader:\n%s\n", verterShaderSourcePtr);
+ glShaderSource(fragmentShaderId, 1, &verterShaderSourcePtr, NULL);
+ glCompileShader(fragmentShaderId);
+
+ GLint status;
+ glGetShaderiv(fragmentShaderId, GL_COMPILE_STATUS, &status);
+ string compileLog = getShaderCompileLog((u32)fragmentShaderId);
+ if(status == GL_TRUE)
+ {
+ if(!compileLog.empty())
+ printf("Pixel shader compile log:\n%s", compileLog.c_str());
+ return Result<CompiledPixelShader*>::Ok(new CompiledPixelShader(fragmentShaderId));
+ }
+ else
+ return Result<CompiledPixelShader*>::Err(compileLog);
+ }
}
diff --git a/src/RenderBackend/OpenGL/ShaderProgram.cpp b/src/RenderBackend/OpenGL/ShaderProgram.cpp
index 892f45e..f76903e 100644
--- a/src/RenderBackend/OpenGL/ShaderProgram.cpp
+++ b/src/RenderBackend/OpenGL/ShaderProgram.cpp
@@ -1,103 +1,74 @@
#include "../../../include/RenderBackend/OpenGL/ShaderProgram.hpp"
-#include "../../../include/RenderBackend/OpenGL/CommonShader.hpp"
#include "../../../include/RenderBackend/OpenGL/opengl.hpp"
+#include "../../../include/RenderBackend/OpenGL/CompiledShader.hpp"
using namespace std;
namespace amalgine
{
- string getShaderCompileLog(GLuint shaderId)
+ ShaderProgramUsedBeforeBuilt::ShaderProgramUsedBeforeBuilt() :
+ runtime_error("Shader program was used before it was built")
{
- string result;
- GLint shaderLogLength;
- glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &shaderLogLength);
- if(shaderLogLength > 0)
- {
- result.resize(shaderLogLength);
- glGetShaderInfoLog(shaderId, shaderLogLength, NULL, &result[0]);
- }
- return result;
+
}
- ShaderProgram::ShaderProgram() : locationCounter(0)
+ ShaderProgram::ShaderProgram() : built(false)
{
- glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxPixelAttribs);
+ shaderProgramId = glCreateProgram();
}
- const string& ShaderProgram::getOutputAttributeName(i32 attributeIndex)
+ ShaderProgram::~ShaderProgram()
{
- assert(attributeIndex < pixelAttributeNames.size());
- return pixelAttributeNames[attributeIndex];
+ GLint numAttachedShaders;
+ glGetProgramiv(shaderProgramId, GL_ATTACHED_SHADERS, &numAttachedShaders);
+
+ GLuint *attachedShaders = new GLuint[numAttachedShaders];
+ glGetAttachedShaders(shaderProgramId, numAttachedShaders, nullptr, attachedShaders);
+
+ for(int i = 0; i < numAttachedShaders; ++i)
+ {
+ GLuint attachedShaderId = attachedShaders[i];
+ glDetachShader(shaderProgramId, attachedShaderId);
+ }
+
+ glDeleteProgram(shaderProgramId);
}
- ShaderOutputVec4 ShaderProgram::defineOutputVec4(const std::string &name)
- {
- i32 attributeIndex = defineOutputVariable(name, "vec4");
- return ShaderOutputVec4(this, attributeIndex);
- }
+ // TODO: Before adding shader to program, check if it has already been added
- i32 ShaderProgram::defineOutputVariable(const string &variableName, const char *typeName)
+ bool ShaderProgram::addVertexShader(CompiledVertexShader *vertexShader)
{
- 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;
- return attributeIndex;
+ // TODO: Do not allow adding shader if the program has already been built
+ glAttachShader(shaderProgramId, vertexShader->getShaderId());
+ return true;
}
- /*
- Result<string> ShaderProgram::addVertexShader(const VertexShader &vertexShader)
+ bool ShaderProgram::addPixelShader(CompiledPixelShader *pixelShader)
{
- GLuint vertexShaderId = glCreateShader(GL_VERTEX_SHADER);
- string verterShaderSource = vertexShader.build();
- const char *verterShaderSourcePtr = verterShaderSource.c_str();
- glShaderSource(vertexShaderId, 1, &verterShaderSourcePtr, NULL);
- glCompileShader(vertexShaderId);
- shaderIds.push_back(vertexShaderId);
-
- GLint status;
- glGetShaderiv(vertexShaderId, GL_COMPILE_STATUS, &status);
- string compileLog = getShaderCompileLog(vertexShaderId);
- if(status == GL_TRUE)
- return Result<string>::Ok(compileLog);
- else
- return Result<string>::Err(compileLog);
+ // TODO: Do not allow adding shader if the program has already been built
+ glAttachShader(shaderProgramId, pixelShader->getShaderId());
+ return true;
}
- Result<string> ShaderProgram::addPixelShader(const PixelShader &pixelShader)
+ Result<bool> ShaderProgram::build()
{
- GLuint fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER);
- string fragmentShaderSource = pixelShader.build();
- const char *fragmentShaderSourcePtr = fragmentShaderSource.c_str();
- glShaderSource(fragmentShaderId, 1, &fragmentShaderSourcePtr, NULL);
- glCompileShader(fragmentShaderId);
- shaderIds.push_back(fragmentShaderId);
+ if(built)
+ return Result<bool>::Err("Shader program already built");
- GLint status;
- glGetShaderiv(fragmentShaderId, GL_COMPILE_STATUS, &status);
- string compileLog = getShaderCompileLog(fragmentShaderId);
- if(status == GL_TRUE)
- return Result<string>::Ok(compileLog);
- else
- return Result<string>::Err(compileLog);
+ glLinkProgram(shaderProgramId);
+ built = true;
+ return Result<bool>::Ok(true);
}
- void ShaderProgram::build()
+ void ShaderProgram::use()
{
- GLuint shaderProgramId = glCreateProgram();
- for(u32 shaderId : shaderIds)
+ if(built)
+ {
+ glUseProgram(shaderProgramId);
+ }
+ else
{
- glAttachShader(shaderProgramId, shaderId);
+ throw ShaderProgramUsedBeforeBuilt();
}
}
- */
}
diff --git a/src/RenderBackend/OpenGL/ShaderVec.cpp b/src/RenderBackend/OpenGL/ShaderVec.cpp
index 0dfb4c6..6411650 100644
--- a/src/RenderBackend/OpenGL/ShaderVec.cpp
+++ b/src/RenderBackend/OpenGL/ShaderVec.cpp
@@ -1,11 +1,12 @@
#include "../../../include/RenderBackend/OpenGL/ShaderVec.hpp"
#include "../../../include/RenderBackend/OpenGL/VertexShader.hpp"
#include "../../../include/RenderBackend/OpenGL/PixelShader.hpp"
+#include "../../../include/RenderBackend/OpenGL/ShaderProgram.hpp"
using namespace std;
namespace amalgine
-{
+{
const string& ShaderInputVec2::getName() const
{
return vertexShader->getInputAttributeName(attributeIndex);
diff --git a/src/RenderBackend/OpenGL/VertexShader.cpp b/src/RenderBackend/OpenGL/VertexShader.cpp
index 04bf863..1505ff4 100644
--- a/src/RenderBackend/OpenGL/VertexShader.cpp
+++ b/src/RenderBackend/OpenGL/VertexShader.cpp
@@ -1,6 +1,7 @@
#include "../../../include/RenderBackend/OpenGL/VertexShader.hpp"
#include "../../../include/RenderBackend/OpenGL/CommonShader.hpp"
#include "../../../include/RenderBackend/OpenGL/opengl.hpp"
+#include "../../../include/RenderBackend/OpenGL/CompiledShader.hpp"
using namespace std;
@@ -106,4 +107,26 @@ namespace amalgine
{
body += code;
}
+
+ Result<CompiledVertexShader*> VertexShader::compile()
+ {
+ GLuint vertexShaderId = glCreateShader(GL_VERTEX_SHADER);
+ string verterShaderSource = build();
+ const char *verterShaderSourcePtr = verterShaderSource.c_str();
+ printf("Vertex shader:\n%s\n", verterShaderSourcePtr);
+ glShaderSource(vertexShaderId, 1, &verterShaderSourcePtr, NULL);
+ glCompileShader(vertexShaderId);
+
+ GLint status;
+ glGetShaderiv(vertexShaderId, GL_COMPILE_STATUS, &status);
+ string compileLog = getShaderCompileLog((u32)vertexShaderId);
+ if(status == GL_TRUE)
+ {
+ if(!compileLog.empty())
+ printf("Vertex shader compile log:\n%s", compileLog.c_str());
+ return Result<CompiledVertexShader*>::Ok(new CompiledVertexShader(vertexShaderId));
+ }
+ else
+ return Result<CompiledVertexShader*>::Err(compileLog);
+ }
}
diff --git a/src/main.cpp b/src/main.cpp
index 03222f1..b1a0d62 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -10,12 +10,61 @@
using namespace amalgine;
using namespace std;
+void initGlfw();
+void initGlew();
+GLFWwindow *createWindow();
+
+CompiledVertexShader* createVertexShader();
+CompiledPixelShader* createPixelShader();
+
int main()
{
+ initGlfw();
+ GLFWwindow *window = createWindow();
+
+ f32 verticesRaw[] =
+ {
+ 0.0f, 0.5f,
+ 0.5f, -0.5f,
+ -0.5f, -0.5f
+ };
+ DataView<f32> vertices(verticesRaw, 6);
+ DeviceMemory triangle;
+ triangle.copyAsStatic(vertices);
+
+ CompiledVertexShader *vertexShader = createVertexShader();
+ CompiledPixelShader *pixelShader = createPixelShader();
+
+ ShaderProgram shaderProgram;
+ shaderProgram.addVertexShader(vertexShader);
+ shaderProgram.addPixelShader(pixelShader);
+ Result<bool> shaderBuildResult = shaderProgram.build();
+ if(!shaderBuildResult)
+ {
+ fprintf(stderr, "Failed to build shader program: %s\n", shaderBuildResult.getErrorMsg().c_str());
+ exit(20);
+ }
+
+ while(!glfwWindowShouldClose(window))
+ {
+ glfwPollEvents();
+ if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
+ glfwSetWindowShouldClose(window, GL_TRUE);
+
+ shaderProgram.use();
+ glfwSwapBuffers(window);
+ }
+
+ glfwTerminate();
+ return 0;
+}
+
+void initGlfw()
+{
if(!glfwInit())
{
fprintf(stderr, "Failed to initialize GLFW\n");
- return -1;
+ exit(-1);
}
glfwWindowHint(GLFW_SAMPLES, 4);
@@ -24,39 +73,37 @@ int main()
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)
+void initGlew()
+{
+ glewExperimental = true;
+ if(glewInit() != GLEW_OK)
{
- fprintf(stderr, "Failed to open GLFW window\n");
+ fprintf(stderr, "Failed to initialize GLEW\n");
glfwTerminate();
- return -1;
+ exit(-1);
}
+}
- glfwMakeContextCurrent(window);
- glewExperimental = true;
- if(glewInit() != GLEW_OK)
+GLFWwindow* createWindow()
+{
+ GLFWwindow *window = glfwCreateWindow(1280, 720, "Amalgine", nullptr, nullptr);
+ if(!window)
{
- fprintf(stderr, "Failed to initialize GLEW\n");
+ fprintf(stderr, "Failed to open GLFW window\n");
glfwTerminate();
- return -1;
+ exit(10);
}
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);
-
- ShaderProgram shaderProgram;
-
+ glfwMakeContextCurrent(window);
+ initGlew();
+ return window;
+}
+
+CompiledVertexShader* createVertexShader()
+{
VertexShader vertexShader;
ShaderInputVec2 inputPosition = vertexShader.defineInputVec2("position");
@@ -65,27 +112,32 @@ int main()
return ShaderVec4(inputPosition, 0.0f, 1.0f);
});
+ Result<CompiledVertexShader*> compiledVertexShader = vertexShader.compile();
+ if(!compiledVertexShader)
+ {
+ fprintf(stderr, "Failed to compile vertex shader:\n%s", compiledVertexShader.getErrorMsg().c_str());
+ exit(2);
+ }
+
+ return compiledVertexShader.unwrap();
+}
+
+CompiledPixelShader* createPixelShader()
+{
PixelShader pixelShader;
- ShaderOutputVec4 outColor = shaderProgram.defineOutputVec4("outColor");
+ 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))
+ Result<CompiledPixelShader*> compiledPixelShader = pixelShader.compile();
+ if(!compiledPixelShader)
{
- if(glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS)
- glfwSetWindowShouldClose(window, GL_TRUE);
-
- glfwSwapBuffers(window);
- glfwPollEvents();
+ fprintf(stderr, "Failed to compile pixel shader:\n%s", compiledPixelShader.getErrorMsg().c_str());
+ exit(2);
}
-
- return 0;
+
+ return compiledPixelShader.unwrap();
}