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 deprecated("Use .destroy instead") void close(){} 47 48 /// Load source code for this shader. 49 /// Throws: $(D OpenGLException) on error. 50 void load(string[] lines) 51 { 52 size_t lineCount = lines.length; 53 54 auto lengths = new GLint[lineCount]; 55 auto addresses = new immutable(GLchar)*[lineCount]; 56 auto localLines = new string[lineCount]; 57 58 for (size_t i = 0; i < lineCount; ++i) 59 { 60 localLines[i] = lines[i] ~ "\n"; 61 lengths[i] = cast(GLint)(localLines[i].length); 62 addresses[i] = localLines[i].ptr; 63 } 64 65 glShaderSource(_shader, 66 cast(GLint)lineCount, 67 cast(const(char)**)addresses.ptr, 68 cast(const(int)*)(lengths.ptr)); 69 _gl.runtimeCheck(); 70 } 71 72 /// Compile this OpenGL shader. 73 /// Throws: $(D OpenGLException) on compilation error. 74 void compile() 75 { 76 glCompileShader(_shader); 77 _gl.runtimeCheck(); 78 79 // print info log 80 const(char)[] infoLog = getInfoLog(); 81 if (infoLog != null) 82 _gl._logger.info(infoLog); 83 84 GLint compiled; 85 glGetShaderiv(_shader, GL_COMPILE_STATUS, &compiled); 86 87 if (compiled != GL_TRUE) 88 throw new OpenGLException("shader did not compile"); 89 } 90 91 /// Gets the compiling report. 92 /// Returns: Log output of the GLSL compiler. Can return null! 93 /// Throws: $(D OpenGLException) on error. 94 const(char)[] getInfoLog() 95 { 96 GLint logLength; 97 glGetShaderiv(_shader, GL_INFO_LOG_LENGTH, &logLength); 98 if (logLength <= 0) // "If shader has no information log, a value of 0 is returned." 99 return null; 100 101 char[] log = new char[logLength]; 102 GLint dummy; 103 glGetShaderInfoLog(_shader, logLength, &dummy, log.ptr); 104 _gl.runtimeCheck(); 105 return fromStringz(log.ptr); 106 } 107 } 108 109 package 110 { 111 GLuint _shader; 112 } 113 114 private 115 { 116 OpenGL _gl; 117 bool _initialized; 118 } 119 } 120 121