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