aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md5
-rw-r--r--include/RenderBackend/OpenGL/CommonShader.hpp11
-rw-r--r--include/RenderBackend/OpenGL/CompiledShader.hpp30
-rw-r--r--include/RenderBackend/OpenGL/DeviceMemory.hpp7
-rw-r--r--include/RenderBackend/OpenGL/PixelShader.hpp23
-rw-r--r--include/RenderBackend/OpenGL/ShaderProgram.hpp40
-rw-r--r--include/RenderBackend/OpenGL/ShaderVec.hpp8
-rw-r--r--include/RenderBackend/OpenGL/VertexShader.hpp9
-rw-r--r--include/Result.hpp11
-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
17 files changed, 402 insertions, 144 deletions
diff --git a/README.md b/README.md
index caca64d..ed3496f 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,5 @@
## Prerequisite
-Install glfw3 and glew
+glfw3
+glew
+glm
+sibs (https://github.com/DEC05EBA/sibs)
diff --git a/include/RenderBackend/OpenGL/CommonShader.hpp b/include/RenderBackend/OpenGL/CommonShader.hpp
index a67aa68..80e63a9 100644
--- a/include/RenderBackend/OpenGL/CommonShader.hpp
+++ b/include/RenderBackend/OpenGL/CommonShader.hpp
@@ -1,7 +1,16 @@
#pragma once
+#include "../../types.hpp"
+#include <string>
+
namespace amalgine
{
+ struct ShaderAttribute
+ {
+ std::string name;
+ const char *typeName;
+ };
+
static bool isAlpha(char c)
{
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
@@ -30,4 +39,6 @@ namespace amalgine
return false;
}
+
+ std::string getShaderCompileLog(u32 shaderId);
}
diff --git a/include/RenderBackend/OpenGL/CompiledShader.hpp b/include/RenderBackend/OpenGL/CompiledShader.hpp
new file mode 100644
index 0000000..67e6418
--- /dev/null
+++ b/include/RenderBackend/OpenGL/CompiledShader.hpp
@@ -0,0 +1,30 @@
+#pragma once
+
+#include "../../types.hpp"
+
+namespace amalgine
+{
+ class CompiledVertexShader
+ {
+ friend class VertexShader;
+ public:
+ ~CompiledVertexShader();
+ u32 getShaderId() const;
+ private:
+ CompiledVertexShader(u32 _shaderId);
+ private:
+ u32 shaderId;
+ };
+
+ class CompiledPixelShader
+ {
+ friend class PixelShader;
+ public:
+ ~CompiledPixelShader();
+ u32 getShaderId() const;
+ private:
+ CompiledPixelShader(u32 _shaderId);
+ private:
+ u32 shaderId;
+ };
+}
diff --git a/include/RenderBackend/OpenGL/DeviceMemory.hpp b/include/RenderBackend/OpenGL/DeviceMemory.hpp
index 706529e..974c7cf 100644
--- a/include/RenderBackend/OpenGL/DeviceMemory.hpp
+++ b/include/RenderBackend/OpenGL/DeviceMemory.hpp
@@ -10,15 +10,16 @@ namespace amalgine
DISABLE_COPY(DeviceMemory)
public:
DeviceMemory();
+ ~DeviceMemory();
// Uploaded once, drawn many times
- void copyStatic(const DataView<f32> &data);
+ void copyAsStatic(const DataView<f32> &data);
// Created once, changed from time to time but drawn many times more than that
- void copyDynamic(const DataView<f32> &data);
+ void copyAsDynamic(const DataView<f32> &data);
// Uploaded once, drawn once (for example data that is changed every frame)
- void copyStream(const DataView<f32> &data);
+ void copyAsStream(const DataView<f32> &data);
private:
void copy(const DataView<f32> &data, i32 storageType);
private:
diff --git a/include/RenderBackend/OpenGL/PixelShader.hpp b/include/RenderBackend/OpenGL/PixelShader.hpp
index b869a8f..e025c6f 100644
--- a/include/RenderBackend/OpenGL/PixelShader.hpp
+++ b/include/RenderBackend/OpenGL/PixelShader.hpp
@@ -1,6 +1,9 @@
#pragma once
#include "../../DataView.hpp"
+#include "../../utils.hpp"
+#include "../../Result.hpp"
+#include "CommonShader.hpp"
#include "ShaderVec.hpp"
#include <string>
#include <unordered_map>
@@ -40,20 +43,38 @@ namespace amalgine
* Using the same PixelShader instance in multiple threads to define data is not thread safe.
* All get*** functions are thread safe.
*/
+ class CompiledPixelShader;
+
class PixelShader
{
+ DISABLE_COPY(PixelShader)
+ friend class ShaderProgram;
public:
PixelShader();
+ const std::string& getOutputAttributeName(i32 attributeIndex);
+ ShaderOutputVec4 defineOutputVec4(const std::string &name);
+
void defineMain(PixelShaderMainFunc mainFunc);
void assign(const ShaderOutputVec4 &lhsVariable, const ShaderVec4 &rhsVariable);
- std::string build() const;
+ Result<CompiledPixelShader*> compile();
private:
void writeHeader(const std::string &code);
void writeBody(const std::string &code);
+ std::string build() const;
+
+ /*
+ * Throws PixelShaderTooManyAttributes if too many pixel attributes are defined for the platform.
+ * Throws PixelShaderAttributeAlreadyDefined if a pixel attribute with the same name has already been defined.
+ */
+ i32 defineOutputVariable(const std::string &variableName, const char *typeName);
private:
std::string header;
std::string body;
+ int locationCounter;
+ i32 maxPixelAttribs; // Could make this static
+ std::unordered_map<std::string, i32> pixelAttributes;
+ std::vector<ShaderAttribute> pixelAttributeNames;
bool mainFuncDefined;
};
}
diff --git a/include/RenderBackend/OpenGL/ShaderProgram.hpp b/include/RenderBackend/OpenGL/ShaderProgram.hpp
index efeae5b..a3e8a0f 100644
--- a/include/RenderBackend/OpenGL/ShaderProgram.hpp
+++ b/include/RenderBackend/OpenGL/ShaderProgram.hpp
@@ -1,34 +1,38 @@
#pragma once
-#include "VertexShader.hpp"
-#include "PixelShader.hpp"
#include "../../Result.hpp"
#include "../../types.hpp"
+#include "../../utils.hpp"
#include <vector>
+#include <stdexcept>
namespace amalgine
{
+ class CompiledVertexShader;
+ class CompiledPixelShader;
+
+ class ShaderProgramUsedBeforeBuilt : public std::runtime_error
+ {
+ public:
+ // TODO: Add name to ShaderProgram so we know which shader has issue when
+ // an exception is thrown?
+ ShaderProgramUsedBeforeBuilt();
+ };
+
class ShaderProgram
{
+ DISABLE_COPY(ShaderProgram)
public:
ShaderProgram();
+ ~ShaderProgram();
- const std::string& getOutputAttributeName(i32 attributeIndex);
- ShaderOutputVec4 defineOutputVec4(const std::string &name);
- //Result<std::string> addVertexShader(const VertexShader &vertexShader);
- //Result<std::string> addPixelShader(const PixelShader &pixelShader);
- //void build();
- private:
- /*
- * Throws PixelShaderTooManyAttributes if too many pixel attributes are defined for the platform.
- * Throws PixelShaderAttributeAlreadyDefined if a pixel attribute with the same name has already been defined.
- */
- i32 defineOutputVariable(const std::string &variableName, const char *typeName);
+ bool addVertexShader(CompiledVertexShader *vertexShader);
+ bool addPixelShader(CompiledPixelShader *pixelShader);
+
+ Result<bool> build();
+ void use();
private:
- int locationCounter;
- i32 maxPixelAttribs; // Could make this static
- std::unordered_map<std::string, i32> pixelAttributes;
- std::vector<std::string> pixelAttributeNames;
- std::vector<u32> shaderIds;
+ u32 shaderProgramId;
+ bool built;
};
}
diff --git a/include/RenderBackend/OpenGL/ShaderVec.hpp b/include/RenderBackend/OpenGL/ShaderVec.hpp
index 0c0a88a..10e628c 100644
--- a/include/RenderBackend/OpenGL/ShaderVec.hpp
+++ b/include/RenderBackend/OpenGL/ShaderVec.hpp
@@ -6,7 +6,7 @@
namespace amalgine
{
class VertexShader;
- class ShaderProgram;
+ class PixelShader;
class ShaderInputVec2
{
@@ -62,20 +62,20 @@ namespace amalgine
class ShaderOutputVec4
{
- friend class ShaderProgram;
+ friend class PixelShader;
public:
const std::string& getName() const;
void operator=(const ShaderVec4 &shaderVec4);
private:
- ShaderOutputVec4(ShaderProgram *_pixelShader, i32 _attributeIndex) :
+ ShaderOutputVec4(PixelShader *_pixelShader, i32 _attributeIndex) :
pixelShader(_pixelShader),
attributeIndex(_attributeIndex)
{
}
private:
- ShaderProgram *shaderProgram;
+ PixelShader *pixelShader;
i32 attributeIndex;
};
}
diff --git a/include/RenderBackend/OpenGL/VertexShader.hpp b/include/RenderBackend/OpenGL/VertexShader.hpp
index 3239be2..43a5dd8 100644
--- a/include/RenderBackend/OpenGL/VertexShader.hpp
+++ b/include/RenderBackend/OpenGL/VertexShader.hpp
@@ -1,6 +1,8 @@
#pragma once
#include "../../DataView.hpp"
+#include "../../utils.hpp"
+#include "../../Result.hpp"
#include "ShaderVec.hpp"
#include <string>
#include <unordered_map>
@@ -40,18 +42,23 @@ namespace amalgine
* Using the same VertexShader instance in multiple threads to define data is not thread safe.
* All get*** functions are thread safe.
*/
+ class CompiledVertexShader;
+
class VertexShader
{
+ DISABLE_COPY(VertexShader)
+ friend class ShaderProgram;
public:
VertexShader();
const std::string& getInputAttributeName(i32 attributeIndex);
ShaderInputVec2 defineInputVec2(const std::string &name);
void defineMain(VertexShaderMainFunc mainFunc);
- std::string build() const;
+ Result<CompiledVertexShader*> compile();
private:
void writeHeader(const std::string &code);
void writeBody(const std::string &code);
+ std::string build() const;
/*
* Throws VertexShaderTooManyInputAttributes if too many vertex attributes are defined for the platform.
diff --git a/include/Result.hpp b/include/Result.hpp
index 316e45a..749d381 100644
--- a/include/Result.hpp
+++ b/include/Result.hpp
@@ -1,6 +1,7 @@
#pragma once
#include <string>
+#include <cassert>
namespace amalgine
{
@@ -28,16 +29,22 @@ namespace amalgine
static Result<T> Err(const Result<OtherType> &otherResult)
{
Result<T> result;
- result.errorMsg = otherResult.errorMsg;
- result.errorCode = otherResult.errorCode;
+ result.errorMsg = otherResult.getErrorMsg();
+ result.errorCode = otherResult.getErrorCode();
return result;
}
bool isOk() const { return errorCode == 0; }
bool isErr() const { return !isOk(); }
operator bool() const { return isOk(); }
+ T& unwrap()
+ {
+ assert(isOk());
+ return data;
+ }
const std::string& getErrorMsg() const { return errorMsg; }
+ int getErrorCode() const { return errorCode; }
private:
Result(){}
private:
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();
}