aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/RenderBackend/OpenGL/PixelShader.hpp2
-rw-r--r--include/RenderBackend/OpenGL/ShaderProgram.hpp8
-rw-r--r--include/RenderBackend/OpenGL/ShaderVec.hpp56
-rw-r--r--src/RenderBackend/OpenGL/PixelShader.cpp18
-rw-r--r--src/RenderBackend/OpenGL/ShaderProgram.cpp21
-rw-r--r--src/RenderBackend/OpenGL/ShaderVec.cpp6
-rw-r--r--src/main.cpp28
7 files changed, 133 insertions, 6 deletions
diff --git a/include/RenderBackend/OpenGL/PixelShader.hpp b/include/RenderBackend/OpenGL/PixelShader.hpp
index e025c6f..6794fb1 100644
--- a/include/RenderBackend/OpenGL/PixelShader.hpp
+++ b/include/RenderBackend/OpenGL/PixelShader.hpp
@@ -54,6 +54,7 @@ namespace amalgine
const std::string& getOutputAttributeName(i32 attributeIndex);
ShaderOutputVec4 defineOutputVec4(const std::string &name);
+ ShaderGlobalVec3 defineGlobalVec3(const std::string &name);
void defineMain(PixelShaderMainFunc mainFunc);
void assign(const ShaderOutputVec4 &lhsVariable, const ShaderVec4 &rhsVariable);
@@ -75,6 +76,7 @@ namespace amalgine
i32 maxPixelAttribs; // Could make this static
std::unordered_map<std::string, i32> pixelAttributes;
std::vector<ShaderAttribute> pixelAttributeNames;
+ std::unordered_map<std::string, ShaderGlobalVec> globalAttributes;
bool mainFuncDefined;
};
}
diff --git a/include/RenderBackend/OpenGL/ShaderProgram.hpp b/include/RenderBackend/OpenGL/ShaderProgram.hpp
index 2b1c5b4..c8740f8 100644
--- a/include/RenderBackend/OpenGL/ShaderProgram.hpp
+++ b/include/RenderBackend/OpenGL/ShaderProgram.hpp
@@ -3,6 +3,7 @@
#include "../../Result.hpp"
#include "../../types.hpp"
#include "../../utils.hpp"
+#include "ShaderVec.hpp"
#include <vector>
#include <stdexcept>
@@ -19,6 +20,12 @@ namespace amalgine
ShaderProgramUsedBeforeBuilt();
};
+ class ShaderProgramNonExistingGlobalVariable : public std::runtime_error
+ {
+ public:
+ ShaderProgramNonExistingGlobalVariable(const char *variableName);
+ };
+
class ShaderProgram
{
DISABLE_COPY(ShaderProgram)
@@ -31,6 +38,7 @@ namespace amalgine
Result<bool> build();
void use();
+ ShaderProgramGlobalVec3 getGlobalVec3(const char *name);
private:
u32 shaderProgramId;
bool built;
diff --git a/include/RenderBackend/OpenGL/ShaderVec.hpp b/include/RenderBackend/OpenGL/ShaderVec.hpp
index a5163ba..7c14af1 100644
--- a/include/RenderBackend/OpenGL/ShaderVec.hpp
+++ b/include/RenderBackend/OpenGL/ShaderVec.hpp
@@ -8,15 +8,60 @@ namespace amalgine
{
class VertexShader;
class PixelShader;
+ class ShaderProgram;
enum class AttributeType
{
NONE,
- VEC2
+ VEC2,
+ VEC3,
+ VEC4
};
AttributeType getAttributeTypeByName(const char *attributeName);
+ class ShaderGlobalVec
+ {
+ friend class VertexShader;
+ friend class PixelShader;
+ friend class ShaderGlobalVec3;
+ public:
+ ShaderGlobalVec() : attributeType(AttributeType::NONE) {}
+ const std::string& getName() const { return name; }
+ AttributeType getAttributeType() const { return attributeType; }
+ protected:
+ ShaderGlobalVec(const std::string &_name, AttributeType _attributeType) : name(_name), attributeType(_attributeType) {}
+ private:
+ std::string name;
+ AttributeType attributeType;
+ };
+
+ class ShaderGlobalVec3
+ {
+ friend class VertexShader;
+ friend class PixelShader;
+ public:
+ const std::string& getName() const { return globalVec.getName(); }
+ AttributeType getAttributeType() const { return globalVec.getAttributeType(); }
+ ShaderGlobalVec getVecObject() const { return globalVec; }
+ private:
+ ShaderGlobalVec3(const std::string &_name) : globalVec(_name, AttributeType::VEC3) {}
+ private:
+ ShaderGlobalVec globalVec;
+ };
+
+ class ShaderProgramGlobalVec3
+ {
+ friend class ShaderProgram;
+ public:
+ void set(f32 x = 0.0f, f32 y = 0.0f, f32 z = 0.0f);
+ private:
+ ShaderProgramGlobalVec3(ShaderProgram *_shaderProgram, i32 _uniformId) : shaderProgram(_shaderProgram), uniformId(_uniformId){}
+ private:
+ ShaderProgram *shaderProgram;
+ i32 uniformId;
+ };
+
class ShaderInputVec2
{
friend class VertexShader;
@@ -62,6 +107,15 @@ namespace amalgine
result += ")";
}
+ ShaderVec4(const ShaderGlobalVec3 &vec3, f32 w = 0.0f)
+ {
+ result = "vec4(";
+ result += vec3.getName();
+ result += ", ";
+ result += std::to_string(w);
+ result += ")";
+ }
+
const std::string& getOutput() const
{
return result;
diff --git a/src/RenderBackend/OpenGL/PixelShader.cpp b/src/RenderBackend/OpenGL/PixelShader.cpp
index 8aa4d9a..f263513 100644
--- a/src/RenderBackend/OpenGL/PixelShader.cpp
+++ b/src/RenderBackend/OpenGL/PixelShader.cpp
@@ -49,6 +49,24 @@ namespace amalgine
return ShaderOutputVec4(this, attributeIndex);
}
+ // TODO: Generate warning if global variable is defined but not assigned to?
+ ShaderGlobalVec3 PixelShader::defineGlobalVec3(const std::string &name)
+ {
+ if(!isShaderVariableNameValid(name.c_str()))
+ throw PixelShaderInvalidAttributeName(name);
+
+ if(globalAttributes.find(name) != globalAttributes.end())
+ throw PixelShaderAttributeAlreadyDefined(name);
+
+ writeHeader("uniform vec3 ");
+ writeHeader(name);
+ writeHeader(";\n");
+
+ ShaderGlobalVec3 globalVec(name);
+ globalAttributes[name] = globalVec.getVecObject();
+ return ShaderGlobalVec3(globalVec);
+ }
+
i32 PixelShader::defineOutputVariable(const string &variableName, const char *typeName)
{
if(!isShaderVariableNameValid(variableName.c_str()))
diff --git a/src/RenderBackend/OpenGL/ShaderProgram.cpp b/src/RenderBackend/OpenGL/ShaderProgram.cpp
index 40f5b6c..aceda3b 100644
--- a/src/RenderBackend/OpenGL/ShaderProgram.cpp
+++ b/src/RenderBackend/OpenGL/ShaderProgram.cpp
@@ -12,6 +12,12 @@ namespace amalgine
}
+ ShaderProgramNonExistingGlobalVariable::ShaderProgramNonExistingGlobalVariable(const char *variableName) :
+ runtime_error(string("There is no shader global variable with the name '") + variableName + "'")
+ {
+
+ }
+
ShaderProgram::ShaderProgram() : built(false)
{
shaderProgramId = glCreateProgram();
@@ -84,4 +90,19 @@ namespace amalgine
throw ShaderProgramUsedBeforeBuilt();
}
}
+
+ ShaderProgramGlobalVec3 ShaderProgram::getGlobalVec3(const char *name)
+ {
+ if(built)
+ {
+ GLint uniformId = glGetUniformLocation(shaderProgramId, name);
+ if(uniformId == -1)
+ throw ShaderProgramNonExistingGlobalVariable(name);
+ return ShaderProgramGlobalVec3(this, uniformId);
+ }
+ else
+ {
+ throw ShaderProgramUsedBeforeBuilt();
+ }
+ }
}
diff --git a/src/RenderBackend/OpenGL/ShaderVec.cpp b/src/RenderBackend/OpenGL/ShaderVec.cpp
index 3bbe0be..dd3bbe5 100644
--- a/src/RenderBackend/OpenGL/ShaderVec.cpp
+++ b/src/RenderBackend/OpenGL/ShaderVec.cpp
@@ -20,6 +20,12 @@ namespace amalgine
return AttributeType::NONE;
}
+ void ShaderProgramGlobalVec3::set(f32 x, f32 y, f32 z)
+ {
+ shaderProgram->use();
+ glUniform3f(uniformId, x, y, z);
+ }
+
const string& ShaderInputVec2::getName() const
{
return vertexShader->getInputAttributeName(attributeIndex);
diff --git a/src/main.cpp b/src/main.cpp
index a04fb99..ada75e2 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -16,6 +16,7 @@
using namespace amalgine;
using namespace std;
+void glfwErrorHandler(int errorCode, const char *errorDescription);
void initGlfw();
void initGlew();
GLFWwindow *createWindow();
@@ -26,6 +27,7 @@ CompiledPixelShader* createPixelShader();
int main()
{
initGlfw();
+ glfwSetErrorCallback(glfwErrorHandler);
GLFWwindow *window = createWindow();
DeviceFrame frame;
@@ -35,10 +37,9 @@ int main()
Vertex2D(0.5f, -0.5f),
Vertex2D(-0.5f, -0.5f)
);
-
+ DataView<Triangle2D> cpuTriangles(&cpuTriangle, 1);
DeviceMemory *gpuTriangle = frame.alloc();
- DataView<Triangle2D> triangles(&cpuTriangle, 1);
- gpuTriangle->copy(triangles, DeviceMemory::StorageType::STATIC);
+ gpuTriangle->copy(cpuTriangles, DeviceMemory::StorageType::STATIC);
CompiledVertexShader *vertexShader = createVertexShader(*gpuTriangle);
CompiledPixelShader *pixelShader = createPixelShader();
@@ -46,7 +47,13 @@ int main()
ShaderProgram shaderProgram;
shaderProgram.setVertexShader(vertexShader);
shaderProgram.setPixelShader(pixelShader);
+ // Make ShaderProgram.build return an object which we can do things on? since some operations
+ // require the shader to be built to be used
Result<bool> shaderBuildResult = shaderProgram.build();
+
+ ShaderProgramGlobalVec3 triangleColor = shaderProgram.getGlobalVec3("triangleColor");
+ triangleColor.set(1.0f, 0.0f, 0.0f);
+
if(!shaderBuildResult)
{
fprintf(stderr, "Failed to build shader program: %s\n", shaderBuildResult.getErrorMsg().c_str());
@@ -59,6 +66,10 @@ int main()
if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
+ // Set color for clearing
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ // Do the actual screen clearing, using the color set using glClearColor
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
shaderProgram.use();
frame.draw();
glfwSwapBuffers(window);
@@ -68,6 +79,11 @@ int main()
return 0;
}
+void glfwErrorHandler(int errorCode, const char *errorDescription)
+{
+ printf("GLFW error code: %d, description: %s\n", errorCode, errorDescription);
+}
+
void initGlfw()
{
if(!glfwInit())
@@ -107,6 +123,7 @@ GLFWwindow* createWindow()
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
glfwMakeContextCurrent(window);
+ glfwSwapInterval(0);
initGlew();
return window;
}
@@ -135,11 +152,12 @@ CompiledVertexShader* createVertexShader(const DeviceMemory &inputData)
CompiledPixelShader* createPixelShader()
{
PixelShader pixelShader;
+ ShaderGlobalVec3 triangleColor = pixelShader.defineGlobalVec3("triangleColor");
ShaderOutputVec4 outColor = pixelShader.defineOutputVec4("outColor");
- pixelShader.defineMain([&outColor]()
+ pixelShader.defineMain([&triangleColor, &outColor]()
{
- outColor = ShaderVec4(1.0f, 1.0f, 1.0f, 1.0f);
+ outColor = ShaderVec4(triangleColor, 1.0f);
});
Result<CompiledPixelShader*> compiledPixelShader = pixelShader.compile();