1 module gfm.opengl.shader; 2 3 import std.string, 4 std.conv; 5 6 import derelict.opengl3.gl3; 7 8 import gfm.opengl.opengl; 9 10 11 /// OpenGL Shader wrapper. 12 final class GLShader 13 { 14 public 15 { 16 /// Creates a shader devoid of source code. 17 /// Throws: $(D OpenGLException) on error. 18 this(OpenGL gl, GLenum shaderType) 19 { 20 _gl = gl; 21 _shader = glCreateShader(shaderType); 22 if (_shader == 0) 23 throw new OpenGLException("glCreateShader failed"); 24 _initialized = true; 25 } 26 27 /// Creates a shader with source code and compiles it. 28 /// Throws: $(D OpenGLException) on error. 29 this(OpenGL gl, GLenum shaderType, string[] lines) 30 { 31 this(gl, shaderType); 32 load(lines); 33 compile(); 34 } 35 36 /// Releases the OpenGL shader resource. 37 ~this() 38 { 39 if (_initialized) 40 { 41 debug ensureNotInGC("GLShader"); 42 glDeleteShader(_shader); 43 _initialized = false; 44 } 45 } 46 47 /// Load source code for this shader. 48 /// Throws: $(D OpenGLException) on error. 49 void load(string[] lines) 50 { 51 size_t lineCount = lines.length; 52 53 auto lengths = new GLint[lineCount]; 54 auto addresses = new immutable(GLchar)*[lineCount]; 55 auto localLines = new string[lineCount]; 56 57 for (size_t i = 0; i < lineCount; ++i) 58 { 59 localLines[i] = lines[i] ~ "\n"; 60 lengths[i] = cast(GLint)(localLines[i].length); 61 addresses[i] = localLines[i].ptr; 62 } 63 64 glShaderSource(_shader, 65 cast(GLint)lineCount, 66 cast(const(char)**)addresses.ptr, 67 cast(const(int)*)(lengths.ptr)); 68 _gl.runtimeCheck(); 69 } 70 71 /// Compile this OpenGL shader. 72 /// Throws: $(D OpenGLException) on compilation error. 73 void compile() 74 { 75 glCompileShader(_shader); 76 _gl.runtimeCheck(); 77 78 // print info log 79 const(char)[] infoLog = getInfoLog(); 80 if (infoLog != null) 81 _gl._logger.info(infoLog); 82 83 GLint compiled; 84 glGetShaderiv(_shader, GL_COMPILE_STATUS, &compiled); 85 86 if (compiled != GL_TRUE) 87 throw new OpenGLException("shader did not compile"); 88 } 89 90 /// Gets the compiling report. 91 /// Returns: Log output of the GLSL compiler. Can return null! 92 /// Throws: $(D OpenGLException) on error. 93 const(char)[] getInfoLog() 94 { 95 GLint logLength; 96 glGetShaderiv(_shader, GL_INFO_LOG_LENGTH, &logLength); 97 if (logLength <= 0) // "If shader has no information log, a value of 0 is returned." 98 return null; 99 100 char[] log = new char[logLength]; 101 GLint dummy; 102 glGetShaderInfoLog(_shader, logLength, &dummy, log.ptr); 103 _gl.runtimeCheck(); 104 return fromStringz(log.ptr); 105 } 106 } 107 108 package 109 { 110 GLuint _shader; 111 } 112 113 private 114 { 115 OpenGL _gl; 116 bool _initialized; 117 } 118 } 119 120