aboutsummaryrefslogtreecommitdiff
path: root/source/Shader.hpp
blob: e7a069b63cfe3aff31537df1389433bdafcb3e3d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#pragma once

#include "EditorAttachment.hpp"
#include "EditorInspector.hpp"
#include "RcPtr.hpp"

#include <glad/glad.h>
#include <tsl/array_map.h>
#include <memory>
#include <string_view>

class ShaderDetails : public EditorAttachment, public IEditorInspectorTarget {
public:
	std::string fileName;

public:
	virtual void ShowInspector() override;
};

class Shader : public RefCounted {
private:
	std::unique_ptr<ShaderDetails> mDetails;
	std::unique_ptr<EditorAttachment> mEditorAttachment;
	GLuint mHandle = 0;

public:
	Shader() = default;
	~Shader();
	Shader(const Shader&) = delete;
	Shader& operator=(const Shader&) = delete;
	Shader(Shader&&) = default;
	Shader& operator=(Shader&&) = default;

	enum ErrorCode {
		Success,
		/// Generated when Init*() functions are called on an already initialized Shader object.
		ShaderAlreadyCreated,
		/// Generated when the one-source-file text contains invalid or duplicate shader variants.
		InvalidShaderVariant,
		FileIOFailed,
		CompilationFailed,
		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);

	EditorAttachment* GetEditorAttachment() const { return mEditorAttachment.get(); }
	void SetEditorAttachment(EditorAttachment* attachment) { mEditorAttachment.reset(attachment); }

	void GatherDetailsIfAbsent();
	const ShaderDetails* GetDetails() const;
	GLuint GetProgram() const;

	bool IsValid() const;
};

class ShaderManager {
public:
	static inline ShaderManager* instance = nullptr;

private:
	tsl::array_map<char, RcPtr<Shader>> mShaders;

public:
	void DiscoverShaders();

	const tsl::array_map<char, RcPtr<Shader>>& GetShaders() const { return mShaders; }
	Shader* FindShader(std::string_view name);
};