diff options
author | Dan Goodliffe <dan@randomdan.homeip.net> | 2022-11-03 19:47:46 +0000 |
---|---|---|
committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2022-11-03 19:48:31 +0000 |
commit | c3eea71370eb94cff1fd96185458643fab6eb2c5 (patch) | |
tree | cb331dd81d9cb36d69e1b659353796ec170a78e4 /gfx/gl | |
parent | Rename Shader to SceneShader (diff) | |
download | ilt-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.cpp | 35 | ||||
-rw-r--r-- | gfx/gl/program.h | 46 | ||||
-rw-r--r-- | gfx/gl/programHandle.cpp | 14 | ||||
-rw-r--r-- | gfx/gl/programHandle.h | 13 | ||||
-rw-r--r-- | gfx/gl/sceneShader.cpp | 135 | ||||
-rw-r--r-- | gfx/gl/sceneShader.h | 81 | ||||
-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.cpp | 31 | ||||
-rw-r--r-- | gfx/gl/uiShader.h | 37 |
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; }; |