aboutsummaryrefslogtreecommitdiff
path: root/source/Shader.hpp
blob: b481bd60c0fc9b1f5218513ede8a587a1419feec (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
#pragma once

#include "RcPtr.hpp"

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

class ShaderDetails : public RefCounted {
public:
};

class Shader : public RefCounted {
private:
	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);

	struct ShaderFilePaths {
		const char* vertex = nullptr;
		const char* geometry = nullptr;
		const char* tessControl = nullptr;
		const char* tessEval = nullptr;
		const char* fragment = nullptr;
	};

	/// Create shader by loading each specified file and combining them together to form a shader object.
	/// Use the mental model that this function simply loads the files from disk (synchronously) and then
	/// passing them to `FromSource(const ShaderSources& source)`.
	ErrorCode InitFromFiles(const ShaderFilePaths& files);

	/// 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);

	/// Create shader by loading the file at the `file`, and then giving the contents to
	/// `FromSource(std::string_view source)`.
	ErrorCode InitFromFile(const char* file);

	GLuint GetProgram() const;

	bool IsValid() const;
};