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 if (!hasARBTesselationShader) 36 throw new Exception( 37 "Tried to create a TESS_CONTROL_SHADER without GL_ARB_tessellation_shader extension being available"); 38 39 _id = glCreateShader(GL_TESS_CONTROL_SHADER); 40 break; 41 case ShaderType.TessEvaluation: 42 if (!hasARBTesselationShader) 43 throw new Exception( 44 "Tried to create a TESS_EVALUATION_SHADER without GL_ARB_tessellation_shader extension being available"); 45 46 _id = glCreateShader(GL_TESS_EVALUATION_SHADER); 47 break; 48 case ShaderType.Geometry: 49 _id = glCreateShader(GL_GEOMETRY_SHADER); 50 break; 51 case ShaderType.Fragment: 52 _id = glCreateShader(GL_FRAGMENT_SHADER); 53 break; 54 default: 55 throw new Exception("ShaderType " ~ type.to!string ~ " is not defined!"); 56 } 57 58 const int len = cast(const(int)) content.length; 59 60 glShaderSource(_id, 1, [content.ptr].ptr, &len); 61 return true; 62 } 63 64 /// Creates a shader, loads the content and compiles it in one function. 65 static Shader create(ShaderType type, string content) 66 { 67 Shader shader = new Shader(); 68 shader.load(type, content); 69 shader.compile(); 70 return shader; 71 } 72 73 /// Compiles the shader and throws an Exception if an error occured. 74 /// Will automatically be called when attaching the shader to a ShaderProgram instance. 75 public bool compile() 76 { 77 if (compiled) 78 return true; 79 glCompileShader(_id); 80 int success = 0; 81 glGetShaderiv(_id, GL_COMPILE_STATUS, &success); 82 83 if (success == 0) 84 { 85 int logSize = 0; 86 glGetShaderiv(_id, GL_INFO_LOG_LENGTH, &logSize); 87 88 char* log = new char[logSize].ptr; 89 glGetShaderInfoLog(_id, logSize, &logSize, &log[0]); 90 91 throw new Exception(cast(string) log[0 .. logSize]); 92 } 93 compiled = true; 94 return true; 95 } 96 97 /// The OpenGL id of this shader. 98 public @property uint id() 99 { 100 return _id; 101 } 102 103 /// Checks if this shader is valid. 104 public @property bool valid() 105 { 106 return _id > 0; 107 } 108 109 private uint _id = 0; 110 private string content; 111 private bool compiled = false; 112 }