aboutsummaryrefslogtreecommitdiff
path: root/source/Game/Shader.hpp
diff options
context:
space:
mode:
authorrtk0c <[email protected]>2022-06-03 23:26:44 -0700
committerrtk0c <[email protected]>2022-06-03 23:26:44 -0700
commit60ccc62f4934e44ad5b905fdbcf458302b8d8a09 (patch)
tree02ec83cc8387abfd08bd5ee7ea4e8115f1bfb8d0 /source/Game/Shader.hpp
parentc2ef7737536bf1f8c81fcfae95c0183b21c9753f (diff)
Changeset: 63 [WIP] Rename directories
Diffstat (limited to 'source/Game/Shader.hpp')
-rw-r--r--source/Game/Shader.hpp173
1 files changed, 173 insertions, 0 deletions
diff --git a/source/Game/Shader.hpp b/source/Game/Shader.hpp
new file mode 100644
index 0000000..707e6cc
--- /dev/null
+++ b/source/Game/Shader.hpp
@@ -0,0 +1,173 @@
+#pragma once
+
+#include "GraphicsTags.hpp"
+#include "Ires.hpp"
+#include "RcPtr.hpp"
+#include "Utils.hpp"
+
+#include <glad/glad.h>
+#include <robin_hood.h>
+#include <memory>
+#include <string_view>
+#include <vector>
+
+// TODO move to variable after pattern matching is in the language
+
+// Forward declarations
+class Shader;
+class IresShader;
+
+struct ShaderVariable {
+ enum Kind {
+ KD_Math,
+ KD_Sampler,
+ };
+
+ std::string name;
+ Kind kind;
+ GLuint location;
+ Tags::VertexElementSemantic semantic = Tags::VES_Generic;
+
+ virtual void ShowInfo() const = 0;
+
+protected:
+ ShaderVariable(Kind kind)
+ : kind{ kind } {}
+};
+
+struct ShaderMathVariable : public ShaderVariable {
+ GLenum scalarType;
+ int arrayLength;
+ int width;
+ int height;
+
+ ShaderMathVariable()
+ : ShaderVariable(KD_Math) {}
+
+ virtual void ShowInfo() const override;
+};
+
+struct ShaderSamplerVariable : public ShaderVariable {
+ GLenum type;
+ int arrayLength;
+
+ ShaderSamplerVariable()
+ : ShaderVariable(KD_Sampler) {}
+
+ virtual void ShowInfo() const override;
+};
+
+struct ShaderThingId {
+ enum Kind {
+ KD_Input,
+ KD_Output,
+ KD_Uniform,
+ KD_Invalid,
+ };
+
+ Kind kind = KD_Invalid;
+ int index = 0;
+
+ bool IsValid() const;
+};
+
+struct ShaderInfo {
+ robin_hood::unordered_map<std::string, ShaderThingId, StringHash, StringEqual> things;
+ std::vector<ShaderMathVariable> inputs;
+ std::vector<ShaderMathVariable> outputs;
+ std::vector<std::unique_ptr<ShaderVariable>> uniforms;
+
+ GLuint FindInputLocation(Tags::VertexElementSemantic semantic);
+ GLuint FindOutputLocation(Tags::VertexElementSemantic semantic);
+ ShaderVariable* FindVariable(const ShaderThingId& thing);
+};
+
+class Shader : public RefCounted {
+ friend class IresShader;
+
+private:
+ IresShader* mIres = nullptr;
+ ShaderInfo mInfo;
+ GLuint mProgram = 0;
+
+public:
+ GLuint autofill_Transform = Tags::kInvalidLocation;
+ GLuint autofill_Time = Tags::kInvalidLocation;
+ GLuint autofill_DeltaTime = Tags::kInvalidLocation;
+ GLuint autofill_TextureAtlas = Tags::kInvalidLocation;
+
+public:
+ Shader();
+ ~Shader();
+ Shader(const Shader&) = delete;
+ Shader& operator=(const Shader&) = delete;
+ Shader(Shader&&) = default;
+ Shader& operator=(Shader&&) = default;
+
+ enum ErrorCode {
+ EC_Success,
+ /// Generated when Init*() functions are called on an already initialized Shader object.
+ EC_AlreadyInitialized,
+ /// Generated when the one-source-file text contains invalid or duplicate shader variants.
+ EC_InvalidShaderVariant,
+ EC_FileIoFailed,
+ EC_CompilationFailed,
+ EC_LinkingFailed,
+ };
+
+ struct ShaderSources {
+ std::string_view vertex;
+ std::string_view geometry;
+ std::string_view tessControl;
+ std::string_view tessEval;
+ std::string_view fragment;
+ };
+
+ /// Create shader by compiling each shader source file separately and then combining them together
+ /// into a Shader object.
+ ErrorCode InitFromSources(const ShaderSources& sources);
+
+ /// The given text will be split into different shader sections according to #type directives,
+ /// and combined to form a Shader object.
+ /// For OpenGL, this process involves compililng each section separately and then linking them
+ /// together.
+ ///
+ /// There are a directive for each shader type
+ /// - `#type vertex`: Vertex shader
+ /// - `#type geometry`: Geometry shader
+ /// - `#type tessellation_control`: Tessellation control shader
+ /// - `#type tessellation_evaluation`: Tessellation evaluation shader
+ /// - `#type fragment`: Fragment shader
+ ErrorCode InitFromSource(std::string_view source);
+
+ /// Rebuild info object using OpenGL shader introspection API. Requires OpenGL 4.3 or above. Overrides existing info object.
+ bool GatherInfoShaderIntrospection();
+ const ShaderInfo& GetInfo() const { return mInfo; }
+ ShaderInfo& GetInfo() { return mInfo; }
+ /// If not empty, this name must not duplicate with any other shader object in the process.
+ GLuint GetProgram() const { return mProgram; }
+
+ IresShader* GetIres() const { return mIres; }
+
+ bool IsValid() const;
+};
+
+// Initialized in main()
+inline RcPtr<Shader> gDefaultShader;
+
+class IresShader : public IresObject {
+private:
+ RcPtr<Shader> mInstance;
+ std::string mSourceFile;
+
+public:
+ IresShader();
+
+ Shader* GetInstance() const;
+ void InvalidateInstance();
+
+ void ShowEditor(IEditor& editor) override;
+
+ void Write(IresWritingContext& ctx, rapidjson::Value& value, rapidjson::Document& root) const override;
+ void Read(IresLoadingContext& ctx, const rapidjson::Value& value) override;
+};