1 module D2DGame.Rendering.Shader;
2 
3 import D2D;
4 
5 /// All valid types of shaders for the `Shader` class.
6 enum ShaderType : ubyte
7 {
8 	/// Vertex Shader
9 	Vertex,
10 	/// Tessellation Control Shader
11 	TessControl,
12 	/// Tessellation Evaluation Shader
13 	TessEvaluation,
14 	/// Geometry Shader
15 	Geometry,
16 	/// Fragment/Pixel Shader
17 	Fragment
18 }
19 
20 /// Class containing a single shader for combining in a ShaderProgram.
21 class Shader : IVerifiable
22 {
23 	/// Loads the shader content into memory.
24 	public bool load(ShaderType type, string content)
25 	{
26 		this.content = content;
27 		switch (type)
28 		{
29 		case ShaderType.Vertex:
30 			_id = glCreateShader(GL_VERTEX_SHADER);
31 			break;
32 		case ShaderType.TessControl:
33 			_id = glCreateShader(GL_TESS_CONTROL_SHADER);
34 			break;
35 		case ShaderType.TessEvaluation:
36 			_id = glCreateShader(GL_TESS_EVALUATION_SHADER);
37 			break;
38 		case ShaderType.Geometry:
39 			_id = glCreateShader(GL_GEOMETRY_SHADER);
40 			break;
41 		case ShaderType.Fragment:
42 			_id = glCreateShader(GL_FRAGMENT_SHADER);
43 			break;
44 		default:
45 			throw new Exception("ShaderType " ~ to!string(type) ~ " is not defined!");
46 		}
47 
48 		const int len = cast(const(int)) content.length;
49 
50 		glShaderSource(_id, 1, [content.ptr].ptr, &len);
51 		return true;
52 	}
53 
54 	/// Creates a shader, loads the content and compiles it in one function.
55 	static Shader create(ShaderType type, string content)
56 	{
57 		Shader shader = new Shader();
58 		shader.load(type, content);
59 		shader.compile();
60 		return shader;
61 	}
62 
63 	/// Compiles the shader and throws an Exception if an error occured.
64 	/// Will automatically be called when attaching the shader to a ShaderProgram instance.
65 	public bool compile()
66 	{
67 		if (compiled)
68 			return true;
69 		glCompileShader(_id);
70 		int success = 0;
71 		glGetShaderiv(_id, GL_COMPILE_STATUS, &success);
72 
73 		if (success == 0)
74 		{
75 			int logSize = 0;
76 			glGetShaderiv(_id, GL_INFO_LOG_LENGTH, &logSize);
77 
78 			char* log = new char[logSize].ptr;
79 			glGetShaderInfoLog(_id, logSize, &logSize, &log[0]);
80 
81 			throw new Exception(cast(string) log[0 .. logSize]);
82 		}
83 		compiled = true;
84 		return true;
85 	}
86 
87 	/// The OpenGL id of this shader.
88 	public @property uint id()
89 	{
90 		return _id;
91 	}
92 
93 	/// Checks if this shader is valid.
94 	public @property bool valid()
95 	{
96 		return _id > 0;
97 	}
98 
99 	private uint   _id = 0;
100 	private string content;
101 	private bool   compiled = false;
102 }