summaryrefslogtreecommitdiff
path: root/gfx/gl
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2022-11-03 19:47:46 +0000
committerDan Goodliffe <dan@randomdan.homeip.net>2022-11-03 19:48:31 +0000
commitc3eea71370eb94cff1fd96185458643fab6eb2c5 (patch)
treecb331dd81d9cb36d69e1b659353796ec170a78e4 /gfx/gl
parentRename Shader to SceneShader (diff)
downloadilt-c3eea71370eb94cff1fd96185458643fab6eb2c5.tar.bz2
ilt-c3eea71370eb94cff1fd96185458643fab6eb2c5.tar.xz
ilt-c3eea71370eb94cff1fd96185458643fab6eb2c5.zip
Restructure how shaders are worked with
Needs a tidy-up
Diffstat (limited to 'gfx/gl')
-rw-r--r--gfx/gl/program.cpp35
-rw-r--r--gfx/gl/program.h46
-rw-r--r--gfx/gl/programHandle.cpp14
-rw-r--r--gfx/gl/programHandle.h13
-rw-r--r--gfx/gl/sceneShader.cpp135
-rw-r--r--gfx/gl/sceneShader.h81
-rw-r--r--gfx/gl/shader.cpp (renamed from gfx/gl/glSource.cpp)19
-rw-r--r--gfx/gl/shader.h (renamed from gfx/gl/glSource.h)15
-rw-r--r--gfx/gl/uiShader.cpp31
-rw-r--r--gfx/gl/uiShader.h37
10 files changed, 255 insertions, 171 deletions
diff --git a/gfx/gl/program.cpp b/gfx/gl/program.cpp
new file mode 100644
index 0000000..c36cc80
--- /dev/null
+++ b/gfx/gl/program.cpp
@@ -0,0 +1,35 @@
+#include "program.h"
+#include "shader.h"
+#include <glm/gtc/type_ptr.hpp>
+#include <glm/gtx/transform.hpp>
+#include <location.hpp>
+#include <maths.h>
+
+void
+Program::linkAndValidate() const
+{
+ glLinkProgram(m_program);
+ Shader::CheckShaderError(m_program, GL_LINK_STATUS, true, "Error linking shader program");
+
+ glValidateProgram(m_program);
+ Shader::CheckShaderError(m_program, GL_VALIDATE_STATUS, true, "Invalid shader program");
+}
+
+void
+Program::use() const
+{
+ glUseProgram(m_program);
+}
+
+Program::UniformLocation::UniformLocation(GLuint program, const char * name) :
+ location {glGetUniformLocation(program, name)}
+{
+}
+
+Program::RequiredUniformLocation::RequiredUniformLocation(GLuint program, const char * name) :
+ UniformLocation {program, name}
+{
+ if (location < 0) {
+ throw std::logic_error("Required uniform does not exist");
+ }
+}
diff --git a/gfx/gl/program.h b/gfx/gl/program.h
new file mode 100644
index 0000000..711a26d
--- /dev/null
+++ b/gfx/gl/program.h
@@ -0,0 +1,46 @@
+#pragma once
+
+#include "shader.h"
+#include <GL/glew.h>
+#include <glRef.hpp>
+#include <glm/mat4x4.hpp>
+
+class Location;
+
+class Program {
+public:
+ template<typename... S> Program(const S &... srcs)
+ {
+ (glAttachShader(m_program, srcs), ...);
+ linkAndValidate();
+ }
+ virtual ~Program() = default;
+
+ class UniformLocation {
+ public:
+ UniformLocation(GLuint prog, const char * name);
+ operator auto() const
+ {
+ return location;
+ }
+
+ protected:
+ GLint location;
+ };
+
+ class RequiredUniformLocation : public UniformLocation {
+ public:
+ RequiredUniformLocation(GLuint prog, const char * name);
+ };
+
+ operator GLuint() const
+ {
+ return m_program;
+ }
+
+protected:
+ void use() const;
+ using ProgramRef = glRef<GLuint, &__glewCreateProgram, &__glewDeleteProgram>;
+ void linkAndValidate() const;
+ ProgramRef m_program;
+};
diff --git a/gfx/gl/programHandle.cpp b/gfx/gl/programHandle.cpp
deleted file mode 100644
index bfe06f2..0000000
--- a/gfx/gl/programHandle.cpp
+++ /dev/null
@@ -1,14 +0,0 @@
-#include "programHandle.h"
-#include "glSource.h"
-
-ProgramHandleBase::ProgramHandleBase(GLuint vs, GLuint fs) : viewProjection_uniform {}, model_uniform {}
-{
- glAttachShader(m_program, vs);
- glAttachShader(m_program, fs);
-
- glLinkProgram(m_program);
- GLsource::CheckShaderError(m_program, GL_LINK_STATUS, true, "Error linking shader program");
-
- glValidateProgram(m_program);
- GLsource::CheckShaderError(m_program, GL_VALIDATE_STATUS, true, "Invalid shader program");
-}
diff --git a/gfx/gl/programHandle.h b/gfx/gl/programHandle.h
deleted file mode 100644
index a2a7a2d..0000000
--- a/gfx/gl/programHandle.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#pragma once
-
-#include <GL/glew.h>
-#include <glRef.hpp>
-
-class ProgramHandleBase {
-public:
- ProgramHandleBase(GLuint, GLuint);
- using ProgramRef = glRef<GLuint, &__glewCreateProgram, &__glewDeleteProgram>;
-
- ProgramRef m_program;
- GLint viewProjection_uniform, model_uniform;
-};
diff --git a/gfx/gl/sceneShader.cpp b/gfx/gl/sceneShader.cpp
index 48c0f42..bec6553 100644
--- a/gfx/gl/sceneShader.cpp
+++ b/gfx/gl/sceneShader.cpp
@@ -1,77 +1,58 @@
-#include "sceneShader.h"
-#include "gfx/gl/glSource.h"
-#include <array>
-#include <cstddef>
-#include <gfx/gl/programHandle.h>
-#include <gfx/gl/shaders/fs-basicShader.h>
-#include <gfx/gl/shaders/fs-landmassShader.h>
-#include <gfx/gl/shaders/fs-waterShader.h>
-#include <gfx/gl/shaders/vs-basicShader.h>
-#include <gfx/gl/shaders/vs-landmassShader.h>
-#include <gfx/gl/shaders/vs-waterShader.h>
-#include <glm/glm.hpp>
-#include <glm/gtc/type_ptr.hpp>
-#include <glm/gtx/transform.hpp>
-#include <location.hpp>
-#include <maths.h>
-
-SceneShader::ProgramHandle::ProgramHandle(GLuint vs, GLuint fs) : ProgramHandleBase {vs, fs}
-{
- glBindAttribLocation(m_program, 0, "position");
- glBindAttribLocation(m_program, 1, "texCoord");
- glBindAttribLocation(m_program, 2, "normal");
-
- viewProjection_uniform = glGetUniformLocation(m_program, "viewProjection");
- model_uniform = glGetUniformLocation(m_program, "model");
-}
-
-SceneShader::SceneShader() :
- programs {{{
- basicShader_vs.compile(),
- basicShader_fs.compile(),
- },
- {
- waterShader_vs.compile(),
- waterShader_fs.compile(),
- },
- {
- landmassShader_vs.compile(),
- landmassShader_fs.compile(),
- },
- {
- landmassShader_vs.compile(),
- basicShader_fs.compile(),
- }}}
-{
-}
-
-void
-SceneShader::setView(glm::mat4 proj) const
-{
- for (const auto & prog : programs) {
- glUseProgram(prog.m_program);
- glUniformMatrix4fv(prog.viewProjection_uniform, 1, GL_FALSE, glm::value_ptr(proj));
- }
-}
-
-void
-SceneShader::setUniform(const GLchar * uniform, glm::vec3 v) const
-{
- for (const auto & prog : programs) {
- if (auto loc = glGetUniformLocation(prog.m_program, uniform); loc >= 0) {
- glUseProgram(prog.m_program);
- glUniform3fv(loc, 1, glm::value_ptr(v));
- }
- }
-}
-
-void
-SceneShader::setModel(const Location & loc, Program pid) const
-{
- auto & prog = programs[static_cast<std::size_t>(pid)];
- glUseProgram(prog.m_program);
- if (prog.model_uniform >= 0) {
- const auto model {glm::translate(loc.pos) * rotate_ypr(loc.rot)};
- glUniformMatrix4fv(prog.model_uniform, 1, GL_FALSE, glm::value_ptr(model));
- }
-}
+#include "sceneShader.h"
+#include <array>
+#include <gfx/gl/shaders/fs-basicShader.h>
+#include <gfx/gl/shaders/fs-landmassShader.h>
+#include <gfx/gl/shaders/fs-waterShader.h>
+#include <gfx/gl/shaders/vs-basicShader.h>
+#include <gfx/gl/shaders/vs-landmassShader.h>
+#include <gfx/gl/shaders/vs-waterShader.h>
+#include <glm/gtc/type_ptr.hpp>
+#include <glm/gtx/transform.hpp>
+#include <location.hpp>
+#include <maths.h>
+
+SceneShader::SceneShader() :
+ landmass {landmassShader_vs, landmassShader_fs}, absolute {landmassShader_vs, basicShader_fs}
+{
+}
+
+void
+SceneShader::setView(glm::mat4 proj) const
+{
+ for (const auto & prog : std::array<const SceneProgram *, 4> {&basic, &water, &landmass, &absolute}) {
+ prog->setView(proj);
+ }
+}
+
+void
+SceneShader::SceneProgram::setView(const glm::mat4 & viewProjection) const
+{
+ glUseProgram(*this);
+ glUniformMatrix4fv(viewProjectionLoc, 1, GL_FALSE, glm::value_ptr(viewProjection));
+}
+
+SceneShader::BasicProgram::BasicProgram() : SceneProgram {basicShader_vs, basicShader_fs}, modelLoc {*this, "model"} { }
+
+void
+SceneShader::BasicProgram::setModel(Location const & location) const
+{
+ const auto model {glm::translate(location.pos) * rotate_ypr(location.rot)};
+ glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
+}
+
+void
+SceneShader::BasicProgram::use(Location const & location) const
+{
+ Program::use();
+ setModel(location);
+}
+
+SceneShader::WaterProgram::WaterProgram() : SceneProgram {waterShader_vs, waterShader_fs}, waveLoc {*this, "waves"} { }
+
+void
+SceneShader::WaterProgram::use(float waveCycle) const
+{
+ Program::use();
+ glm::vec3 waves {waveCycle, 0.F, 0.F};
+ glUniform3fv(waveLoc, 1, glm::value_ptr(waves));
+}
diff --git a/gfx/gl/sceneShader.h b/gfx/gl/sceneShader.h
index 61c159b..a85e55b 100644
--- a/gfx/gl/sceneShader.h
+++ b/gfx/gl/sceneShader.h
@@ -1,27 +1,54 @@
-#pragma once
-
-#include "programHandle.h"
-#include <GL/glew.h>
-#include <array>
-#include <glm/glm.hpp>
-
-class Location;
-
-class SceneShader {
-public:
- enum class Program { Basic = 0, Water = 1, LandMass = 2, StaticPos = 3 };
-
- SceneShader();
-
- void setView(glm::mat4 view) const;
- void setModel(const Location &, Program = Program::Basic) const;
- void setUniform(const GLchar *, glm::vec3 dir) const;
-
-private:
- class ProgramHandle : public ProgramHandleBase {
- public:
- ProgramHandle(GLuint, GLuint);
- };
-
- std::array<ProgramHandle, 4> programs;
-};
+#pragma once
+
+#include "program.h"
+
+class Location;
+
+struct SceneShader {
+ class SceneProgram : public Program {
+ public:
+ template<typename... S>
+ inline SceneProgram(const S &... srcs) : Program {srcs...}, viewProjectionLoc {*this, "viewProjection"}
+ {
+ }
+
+ void setView(const glm::mat4 &) const;
+
+ private:
+ RequiredUniformLocation viewProjectionLoc;
+ };
+
+ class BasicProgram : public SceneProgram {
+ public:
+ BasicProgram();
+ void setModel(const Location &) const;
+ void use(const Location &) const;
+
+ private:
+ RequiredUniformLocation modelLoc;
+ };
+
+ class AbsolutePosProgram : public SceneProgram {
+ public:
+ using Program::use;
+ using SceneProgram::SceneProgram;
+ };
+
+ class WaterProgram : public SceneProgram {
+ public:
+ public:
+ WaterProgram();
+ void use(float waveCycle) const;
+
+ private:
+ RequiredUniformLocation waveLoc;
+ };
+
+ SceneShader();
+
+ BasicProgram basic;
+ WaterProgram water;
+ AbsolutePosProgram landmass, absolute;
+
+ void setView(glm::mat4 proj) const;
+};
diff --git a/gfx/gl/glSource.cpp b/gfx/gl/shader.cpp
index 962d096..8b0f614 100644
--- a/gfx/gl/glSource.cpp
+++ b/gfx/gl/shader.cpp
@@ -1,21 +1,22 @@
-#include "glSource.h"
+#include "shader.h"
#include <array>
#include <stdexcept>
#include <string>
-GLsource::ShaderRef
-GLsource::compile() const
+Shader::operator GLuint() const
{
- ShaderRef id {type};
- glShaderSource(id, 1, &text, &len);
- glCompileShader(id);
+ if (!shader) {
+ shader.emplace(type);
+ glShaderSource(*shader, 1, &text, &len);
+ glCompileShader(*shader);
- CheckShaderError(id, GL_COMPILE_STATUS, false, "Error compiling shader!");
- return id;
+ CheckShaderError(*shader, GL_COMPILE_STATUS, false, "Error compiling shader!");
+ }
+ return *shader;
}
void
-GLsource::CheckShaderError(GLuint shader, GLuint flag, bool isProgram, std::string_view errorMessage)
+Shader::CheckShaderError(GLuint shader, GLuint flag, bool isProgram, std::string_view errorMessage)
{
GLint success = 0;
diff --git a/gfx/gl/glSource.h b/gfx/gl/shader.h
index c6b1f41..1a8ddef 100644
--- a/gfx/gl/glSource.h
+++ b/gfx/gl/shader.h
@@ -2,15 +2,20 @@
#include <GL/glew.h>
#include <glRef.hpp>
+#include <optional>
#include <string_view>
-struct GLsource {
- using ShaderRef = glRef<GLuint, &__glewCreateShader, &__glewDeleteShader>;
+class Shader {
+public:
+ constexpr Shader(const GLchar * text, GLint len, GLuint type) : text {text}, len {len}, type {type} { }
+
+ operator GLuint() const;
+ static void CheckShaderError(GLuint shader, GLuint flag, bool isProgram, std::string_view errorMessage);
+private:
+ using ShaderRef = glRef<GLuint, &__glewCreateShader, &__glewDeleteShader>;
const GLchar * text;
GLint len;
GLuint type;
-
- [[nodiscard]] ShaderRef compile() const;
- static void CheckShaderError(GLuint shader, GLuint flag, bool isProgram, std::string_view errorMessage);
+ mutable std::optional<ShaderRef> shader {};
};
diff --git a/gfx/gl/uiShader.cpp b/gfx/gl/uiShader.cpp
index fbcdd15..78e0064 100644
--- a/gfx/gl/uiShader.cpp
+++ b/gfx/gl/uiShader.cpp
@@ -1,6 +1,6 @@
#include "uiShader.h"
-#include <gfx/gl/glSource.h>
-#include <gfx/gl/programHandle.h>
+#include <gfx/gl/program.h>
+#include <gfx/gl/shader.h>
#include <gfx/gl/shaders/fs-uiShader.h>
#include <gfx/gl/shaders/fs-uiShaderFont.h>
#include <gfx/gl/shaders/vs-uiShader.h>
@@ -8,30 +8,21 @@
#include <glm/gtc/type_ptr.hpp>
#include <initializer_list>
-UIShader::UIShader(size_t width, size_t height) :
- progDefault {uiShader_vs.compile(), uiShader_fs.compile()}, progText {uiShader_vs.compile(),
- uiShaderFont_fs.compile()}
+UIShader::IconProgram::IconProgram(const glm::mat4 & vp) : UIProgram {vp, uiShader_vs, uiShader_fs} { }
+UIShader::TextProgram::TextProgram(const glm::mat4 & vp) :
+ UIProgram {vp, uiShader_vs, uiShaderFont_fs}, colorLoc {*this, "colour"}
{
- for (const auto prog : {&progDefault, &progText}) {
- if (auto loc = glGetUniformLocation(prog->m_program, "uiProjection"); loc >= 0) {
- glUseProgram(prog->m_program);
- const auto uiProjection = glm::ortho<float>(0, static_cast<float>(width), 0, static_cast<float>(height));
- glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(uiProjection));
- }
- }
}
-void
-UIShader::useDefault() const
+UIShader::UIShader(size_t width, size_t height) :
+ UIShader {glm::ortho<float>(0, static_cast<float>(width), 0, static_cast<float>(height))}
{
- glUseProgram(progDefault.m_program);
}
+UIShader::UIShader(const glm::mat4 & viewProjection) : icon {viewProjection}, text {viewProjection} { }
void
-UIShader::useText(glm::vec3 colour) const
+UIShader::TextProgram::use(const glm::vec3 & colour) const
{
- glUseProgram(progText.m_program);
- if (auto loc = glGetUniformLocation(progText.m_program, "colour"); loc >= 0) {
- glUniform3fv(loc, 1, glm::value_ptr(colour));
- }
+ Program::use();
+ glUniform3fv(colorLoc, 1, glm::value_ptr(colour));
}
diff --git a/gfx/gl/uiShader.h b/gfx/gl/uiShader.h
index ea5bf25..ee44af7 100644
--- a/gfx/gl/uiShader.h
+++ b/gfx/gl/uiShader.h
@@ -1,19 +1,44 @@
#pragma once
-#include "programHandle.h"
+#include "program.h"
#include <GL/glew.h>
#include <cstddef>
#include <glm/glm.hpp>
+#include <glm/gtc/type_ptr.hpp>
class UIShader {
public:
UIShader(std::size_t width, std::size_t height);
- void useDefault() const;
- void useText(glm::vec3) const;
private:
- class UIProgramHandle : public ProgramHandleBase {
- using ProgramHandleBase::ProgramHandleBase;
+ explicit UIShader(const glm::mat4 & viewProjection);
+
+ class UIProgram : public Program {
+ public:
+ template<typename... S> UIProgram(const glm::mat4 & vp, S &&... srcs) : Program {std::forward<S>(srcs)...}
+ {
+ RequiredUniformLocation uiProjectionLoc {*this, "uiProjection"};
+ glUseProgram(*this);
+ glUniformMatrix4fv(uiProjectionLoc, 1, GL_FALSE, glm::value_ptr(vp));
+ }
+ };
+
+ class IconProgram : public UIProgram {
+ public:
+ explicit IconProgram(const glm::mat4 & vp);
+ using Program::use;
+ };
+
+ class TextProgram : public UIProgram {
+ public:
+ explicit TextProgram(const glm::mat4 & vp);
+ void use(const glm::vec3 & colour) const;
+
+ private:
+ RequiredUniformLocation colorLoc;
};
- UIProgramHandle progDefault, progText;
+
+public:
+ IconProgram icon;
+ TextProgram text;
};