1 module Engine.Shader; 2 3 import std.stdio; 4 import derelict.opengl3.gl; 5 import Engine.Batch; 6 import gl3n.linalg; 7 8 9 class Shader 10 { 11 immutable GLuint Program; 12 package static GLuint currentProgram = -1; 13 Attribute[string] attributes; 14 15 @property const(Attribute[string]) Attributes() { 16 return attributes; 17 } 18 19 this(immutable string vertexShaderSource,immutable string fregmentShaderSource) 20 { 21 auto vertexShader = glCreateShader(GL_VERTEX_SHADER); 22 23 auto vertexSourcePtr = cast(const char*)vertexShaderSource.ptr; 24 glShaderSource(vertexShader, 1, &vertexSourcePtr , null); 25 glCompileShader(vertexShader); 26 27 int result = 0; 28 glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &result); 29 if (result != GL_TRUE) { 30 int InfoLogLength = 0; 31 glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &InfoLogLength); 32 if ( InfoLogLength > 0 ){ 33 char[] message = new char[InfoLogLength]; 34 scope( exit ) destroy(message); 35 glGetShaderInfoLog(vertexShader, InfoLogLength, null, cast( char*)&message[0]); 36 throw new Exception(cast(string)message); 37 } 38 } 39 40 auto fregmentShader = glCreateShader(GL_FRAGMENT_SHADER); 41 42 auto fregmentShaderPtr = cast(const char*)fregmentShaderSource.ptr; 43 glShaderSource(fregmentShader, 1, &fregmentShaderPtr , null); 44 glCompileShader(fregmentShader); 45 46 result = 0; 47 glGetShaderiv(fregmentShader, GL_COMPILE_STATUS, &result); 48 if (result != GL_TRUE) { 49 int InfoLogLength = 0; 50 glGetShaderiv(fregmentShader, GL_INFO_LOG_LENGTH, &InfoLogLength); 51 if ( InfoLogLength > 0 ){ 52 char[] message = new char[InfoLogLength]; 53 scope( exit ) destroy(message) ; 54 glGetShaderInfoLog(fregmentShader, InfoLogLength, null, cast( char*)&message[0]); 55 throw new Exception(cast(string)message); 56 } 57 } 58 59 auto program = glCreateProgram(); 60 glAttachShader(program, vertexShader); 61 glAttachShader(program, fregmentShader); 62 glLinkProgram(program); 63 64 result = 0; 65 glGetProgramiv(program, GL_LINK_STATUS, &result); 66 if (result != GL_TRUE) { 67 int InfoLogLength = 0; 68 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &InfoLogLength); 69 if ( InfoLogLength > 0 ){ 70 char[] message = new char[InfoLogLength]; 71 scope( exit ) destroy(message) ; 72 glGetProgramInfoLog(program, InfoLogLength, null, cast( char*)&message[0]); 73 throw new Exception(cast(string)message); 74 } 75 } 76 77 int attribs = 0; 78 glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &attribs); 79 int maxAttribLen = 0; 80 glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxAttribLen); 81 82 83 for (int i =0;i<attribs;i++) { 84 int len = 0; 85 int attribSize = 0; 86 GLenum type = 0; 87 char[] message = new char[maxAttribLen]; 88 glGetActiveAttrib(program,i,maxAttribLen,&len,&attribSize,&type,cast( char*)&message[0]); 89 message = message[0..len]; 90 auto location = glGetAttribLocation(program, cast( char*)&message[0]); 91 this.attributes[cast(string)(message)] = new Attribute(i,location,cast(string)(message),type); 92 } 93 94 attribs = 0; 95 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &attribs); 96 maxAttribLen = 0; 97 glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxAttribLen); 98 99 for (int i =0;i<attribs;i++) { 100 int len = 0; 101 int attribSize = 0; 102 GLenum type = 0; 103 char[] message = new char[maxAttribLen]; 104 glGetActiveUniform(program,i,maxAttribLen,&len,&attribSize,&type,cast( char*)&message[0]); 105 message = message[0..len]; 106 auto location = glGetUniformLocation(program, cast( char*)&message[0]); 107 this.attributes[cast(string)(message)] = new Attribute(i,location,cast(string)(message),type); 108 } 109 110 111 112 113 Program = program; 114 } 115 116 public void Use() { 117 if (Program != currentProgram) { 118 currentProgram = Program; 119 glUseProgram(Program); 120 } 121 } 122 } 123 124 125 126 class Attribute { 127 package this(int index, uint location, string name, GLenum type) { 128 this.index = index; 129 this.location = location; 130 this.name = name; 131 this.type = type; 132 } 133 134 immutable int index; 135 immutable uint location; 136 immutable string name; 137 immutable GLenum type; 138 139 final void Set(vec4 v) const { 140 glUniform4f(location, v.x,v.y,v.z,v.w); 141 } 142 143 final void Set(vec3 v) const { 144 glUniform3f(location, v.x,v.y,v.z); 145 } 146 147 final void Set(vec2 v) const { 148 glUniform2f(location, v.x,v.y); 149 } 150 151 final void Set(float v) const { 152 glUniform1f(location, v); 153 } 154 155 final void Set(vec4d v) const { 156 glUniform4d(location, v.x,v.y,v.z,v.w); 157 } 158 159 final void Set(vec3d v) const { 160 glUniform3d(location, v.x,v.y,v.z); 161 } 162 163 final void Set(vec2d v) const { 164 glUniform2d(location, v.x,v.y); 165 } 166 167 final void Set(double v) const { 168 glUniform1d(location, v); 169 } 170 171 final void Set(vec4i v) const { 172 glUniform4i(location, v.x,v.y,v.z,v.w); 173 } 174 175 final void Set(vec3i v) const { 176 glUniform3i(location, v.x,v.y,v.z); 177 } 178 179 final void Set(vec2i v) const { 180 glUniform2i(location, v.x,v.y); 181 } 182 183 final void Set(int v) const { 184 glUniform1i(location, v); 185 } 186 187 final void Set(bool v) const { 188 glUniform1i(location, cast(bool)v); 189 } 190 191 final void Set(ref mat4 m) const { 192 glUniformMatrix4fv(location, 1, GL_TRUE, m.value_ptr); 193 } 194 195 final void Set(mat4 m) const { 196 glUniformMatrix4fv(location, 1, GL_TRUE, m.value_ptr); 197 } 198 } 199